diff --git a/Documentation/admin-guide/cifs/changes.rst b/Documentation/admin-guide/cifs/changes.rst index 3147bbae9c43f2..8c42c4de510b10 100644 --- a/Documentation/admin-guide/cifs/changes.rst +++ b/Documentation/admin-guide/cifs/changes.rst @@ -5,5 +5,5 @@ Changes See https://wiki.samba.org/index.php/LinuxCIFSKernel for summary information about fixes/improvements to CIFS/SMB2/SMB3 support (changes to cifs.ko module) by kernel version (and cifs internal module version). -This may be easier to read than parsing the output of "git log fs/cifs" -by release. +This may be easier to read than parsing the output of +"git log fs/smb/client" by release. diff --git a/Documentation/admin-guide/cifs/usage.rst b/Documentation/admin-guide/cifs/usage.rst index 2e151cd8c2e4de..5f936b4b601881 100644 --- a/Documentation/admin-guide/cifs/usage.rst +++ b/Documentation/admin-guide/cifs/usage.rst @@ -45,7 +45,7 @@ Installation instructions If you have built the CIFS vfs as module (successfully) simply type ``make modules_install`` (or if you prefer, manually copy the file to -the modules directory e.g. /lib/modules/2.4.10-4GB/kernel/fs/cifs/cifs.ko). +the modules directory e.g. /lib/modules/6.3.0-060300-generic/kernel/fs/smb/client/cifs.ko). If you have built the CIFS vfs into the kernel itself, follow the instructions for your distribution on how to install a new kernel (usually you @@ -66,15 +66,15 @@ If cifs is built as a module, then the size and number of network buffers and maximum number of simultaneous requests to one server can be configured. Changing these from their defaults is not recommended. By executing modinfo:: - modinfo kernel/fs/cifs/cifs.ko + modinfo -on kernel/fs/cifs/cifs.ko the list of configuration changes that can be made +on kernel/fs/smb/client/cifs.ko the list of configuration changes that can be made at module initialization time (by running insmod cifs.ko) can be seen. Recommendations =============== -To improve security the SMB2.1 dialect or later (usually will get SMB3) is now +To improve security the SMB2.1 dialect or later (usually will get SMB3.1.1) is now the new default. To use old dialects (e.g. to mount Windows XP) use "vers=1.0" on mount (or vers=2.0 for Windows Vista). Note that the CIFS (vers=1.0) is much older and less secure than the default dialect SMB3 which includes diff --git a/Documentation/admin-guide/quickly-build-trimmed-linux.rst b/Documentation/admin-guide/quickly-build-trimmed-linux.rst index ff4f4cc8522bdb..f08149bc53f84d 100644 --- a/Documentation/admin-guide/quickly-build-trimmed-linux.rst +++ b/Documentation/admin-guide/quickly-build-trimmed-linux.rst @@ -215,12 +215,14 @@ again. reduce the compile time enormously, especially if you are running an universal kernel from a commodity Linux distribution. - There is a catch: the make target 'localmodconfig' will disable kernel - features you have not directly or indirectly through some program utilized - since you booted the system. You can reduce or nearly eliminate that risk by - using tricks outlined in the reference section; for quick testing purposes - that risk is often negligible, but it is an aspect you want to keep in mind - in case your kernel behaves oddly. + There is a catch: 'localmodconfig' is likely to disable kernel features you + did not use since you booted your Linux -- like drivers for currently + disconnected peripherals or a virtualization software not haven't used yet. + You can reduce or nearly eliminate that risk with tricks the reference + section outlines; but when building a kernel just for quick testing purposes + it is often negligible if such features are missing. But you should keep that + aspect in mind when using a kernel built with this make target, as it might + be the reason why something you only use occasionally stopped working. [:ref:`details`] @@ -271,6 +273,9 @@ again. does nothing at all; in that case you have to manually install your kernel, as outlined in the reference section. + If you are running a immutable Linux distribution, check its documentation + and the web to find out how to install your own kernel there. + [:ref:`details`] .. _another_sbs: @@ -291,29 +296,29 @@ again. version you care about, as git otherwise might retrieve the entire commit history:: - git fetch --shallow-exclude=v6.1 origin - - If you modified the sources (for example by applying a patch), you now need - to discard those modifications; that's because git otherwise will not be able - to switch to the sources of another version due to potential conflicting - changes:: - - git reset --hard + git fetch --shallow-exclude=v6.0 origin - Now checkout the version you are interested in, as explained above:: + Now switch to the version you are interested in -- but be aware the command + used here will discard any modifications you performed, as they would + conflict with the sources you want to checkout:: - git checkout --detach origin/master + git checkout --force --detach origin/master At this point you might want to patch the sources again or set/modify a build - tag, as explained earlier; afterwards adjust the build configuration to the - new codebase and build your next kernel:: + tag, as explained earlier. Afterwards adjust the build configuration to the + new codebase using olddefconfig, which will now adjust the configuration file + you prepared earlier using localmodconfig (~/linux/.config) for your next + kernel:: # reminder: if you want to apply patches, do it at this point # reminder: you might want to update your build tag at this point make olddefconfig + + Now build your kernel:: + make -j $(nproc --all) - Install the kernel as outlined above:: + Afterwards install the kernel as outlined above:: command -v installkernel && sudo make modules_install install @@ -584,11 +589,11 @@ versions and individual commits at hand at any time:: curl -L \ https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/clone.bundle \ -o linux-stable.git.bundle - git clone clone.bundle ~/linux/ + git clone linux-stable.git.bundle ~/linux/ rm linux-stable.git.bundle cd ~/linux/ - git remote set-url origin - https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git + git remote set-url origin \ + https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git git fetch origin git checkout --detach origin/master diff --git a/Documentation/admin-guide/sysctl/net.rst b/Documentation/admin-guide/sysctl/net.rst index 466c560b0c3044..4877563241f3bd 100644 --- a/Documentation/admin-guide/sysctl/net.rst +++ b/Documentation/admin-guide/sysctl/net.rst @@ -386,8 +386,8 @@ Default : 0 (for compatibility reasons) txrehash -------- -Controls default hash rethink behaviour on listening socket when SO_TXREHASH -option is set to SOCK_TXREHASH_DEFAULT (i. e. not overridden by setsockopt). +Controls default hash rethink behaviour on socket when SO_TXREHASH option is set +to SOCK_TXREHASH_DEFAULT (i. e. not overridden by setsockopt). If set to 1 (default), hash rethink is performed on listening socket. If set to 0, hash rethink is not performed. diff --git a/Documentation/bpf/instruction-set.rst b/Documentation/bpf/instruction-set.rst index 492980ece1abe9..6644842cd3ea1a 100644 --- a/Documentation/bpf/instruction-set.rst +++ b/Documentation/bpf/instruction-set.rst @@ -163,13 +163,13 @@ BPF_MUL 0x20 dst \*= src BPF_DIV 0x30 dst = (src != 0) ? (dst / src) : 0 BPF_OR 0x40 dst \|= src BPF_AND 0x50 dst &= src -BPF_LSH 0x60 dst <<= src -BPF_RSH 0x70 dst >>= src +BPF_LSH 0x60 dst <<= (src & mask) +BPF_RSH 0x70 dst >>= (src & mask) BPF_NEG 0x80 dst = ~src BPF_MOD 0x90 dst = (src != 0) ? (dst % src) : dst BPF_XOR 0xa0 dst ^= src BPF_MOV 0xb0 dst = src -BPF_ARSH 0xc0 sign extending shift right +BPF_ARSH 0xc0 sign extending dst >>= (src & mask) BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below) ======== ===== ========================================================== @@ -204,6 +204,9 @@ for ``BPF_ALU64``, 'imm' is first sign extended to 64 bits and the result interpreted as an unsigned 64-bit value. There are no instructions for signed division or modulo. +Shift operations use a mask of 0x3F (63) for 64-bit operations and 0x1F (31) +for 32-bit operations. + Byte swap instructions ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/Documentation/cdrom/index.rst b/Documentation/cdrom/index.rst index e87a8785bc1a71..e9b022d7093957 100644 --- a/Documentation/cdrom/index.rst +++ b/Documentation/cdrom/index.rst @@ -1,8 +1,8 @@ .. SPDX-License-Identifier: GPL-2.0 -===== -cdrom -===== +====== +CD-ROM +====== .. toctree:: :maxdepth: 1 diff --git a/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml b/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml index 9b31f864e071ee..71364c6081ff50 100644 --- a/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml +++ b/Documentation/devicetree/bindings/ata/ceva,ahci-1v84.yaml @@ -32,7 +32,7 @@ properties: maxItems: 1 iommus: - maxItems: 1 + maxItems: 4 power-domains: maxItems: 1 diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml index e6c1ebfe8a3247..130e16d025bcf8 100644 --- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml +++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml @@ -82,6 +82,18 @@ properties: Indicates if the DSI controller is driving a panel which needs 2 DSI links. + qcom,master-dsi: + type: boolean + description: | + Indicates if the DSI controller is the master DSI controller when + qcom,dual-dsi-mode enabled. + + qcom,sync-dual-dsi: + type: boolean + description: | + Indicates if the DSI controller needs to sync the other DSI controller + with MIPI DCS commands when qcom,dual-dsi-mode enabled. + assigned-clocks: minItems: 2 maxItems: 4 diff --git a/Documentation/devicetree/bindings/fpga/lattice,sysconfig.yaml b/Documentation/devicetree/bindings/fpga/lattice,sysconfig.yaml index 4fb05eb84e2af4..164331eb627502 100644 --- a/Documentation/devicetree/bindings/fpga/lattice,sysconfig.yaml +++ b/Documentation/devicetree/bindings/fpga/lattice,sysconfig.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Lattice Slave SPI sysCONFIG FPGA manager maintainers: - - Ivan Bornyakov + - Vladimir Georgiev description: | Lattice sysCONFIG port, which is used for FPGA configuration, among others, diff --git a/Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml b/Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml index 527532f039ceca..a157eecfb5fc33 100644 --- a/Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml +++ b/Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Microchip Polarfire FPGA manager. maintainers: - - Ivan Bornyakov + - Vladimir Georgiev description: Device Tree Bindings for Microchip Polarfire FPGA Manager using slave SPI to diff --git a/Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml b/Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml index 63369ba388e473..0a192ca192c5b3 100644 --- a/Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/nxp,imx8qxp-adc.yaml @@ -39,6 +39,12 @@ properties: power-domains: maxItems: 1 + vref-supply: + description: | + External ADC reference voltage supply on VREFH pad. If VERID[MVI] is + set, there are additional, internal reference voltages selectable. + VREFH1 is always from VREFH pad. + "#io-channel-cells": const: 1 @@ -72,6 +78,7 @@ examples: assigned-clocks = <&clk IMX_SC_R_ADC_0>; assigned-clock-rates = <24000000>; power-domains = <&pd IMX_SC_R_ADC_0>; + vref-supply = <®_1v8>; #io-channel-cells = <1>; }; }; diff --git a/Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml b/Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml index 1c7aee5ed3e0bf..36dff3250ea76f 100644 --- a/Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/renesas,rcar-gyroadc.yaml @@ -90,7 +90,7 @@ patternProperties: of the MAX chips to the GyroADC, while MISO line of each Maxim ADC connects to a shared input pin of the GyroADC. enum: - - adi,7476 + - adi,ad7476 - fujitsu,mb88101a - maxim,max1162 - maxim,max11100 diff --git a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml index 92117261e1e1d0..39e64c7f6360ca 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml @@ -166,6 +166,12 @@ properties: resets: maxItems: 1 + mediatek,broken-save-restore-fw: + type: boolean + description: + Asserts that the firmware on this device has issues saving and restoring + GICR registers when the GIC redistributors are powered off. + dependencies: mbi-ranges: [ msi-controller ] msi-controller: [ mbi-ranges ] diff --git a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml index 3bd912ed7c7ead..23e92be33ac860 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml +++ b/Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Allwinner A20 GMAC allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# maintainers: - Chen-Yu Tsai diff --git a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml index 47bc2057e6292a..4bfac91868863f 100644 --- a/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml +++ b/Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml @@ -63,7 +63,7 @@ required: - syscon allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml index a2c51a84efa555..ee7a65b528cdac 100644 --- a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml @@ -27,7 +27,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# - if: properties: compatible: diff --git a/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml b/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml index 0e5e5db32fafdd..7c90a43905319b 100644 --- a/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml +++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml @@ -55,7 +55,7 @@ properties: patternProperties: "^mdio@[0-9a-f]+$": type: object - $ref: "brcm,unimac-mdio.yaml" + $ref: brcm,unimac-mdio.yaml description: GENET internal UniMAC MDIO bus diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt index 2363b412410c37..33726134f5c969 100644 --- a/Documentation/devicetree/bindings/net/dsa/marvell.txt +++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt @@ -20,7 +20,7 @@ which is at a different MDIO base address in different switch families. 6171, 6172, 6175, 6176, 6185, 6240, 6320, 6321, 6341, 6350, 6351, 6352 - "marvell,mv88e6190" : Switch has base address 0x00. Use with models: - 6190, 6190X, 6191, 6290, 6390, 6390X + 6163, 6190, 6190X, 6191, 6290, 6390, 6390X - "marvell,mv88e6250" : Switch has base address 0x08 or 0x18. Use with model: 6220, 6250 diff --git a/Documentation/devicetree/bindings/net/ethernet-phy.yaml b/Documentation/devicetree/bindings/net/ethernet-phy.yaml index 4f574532ee13cc..c1241c8a3b779f 100644 --- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml @@ -93,6 +93,12 @@ properties: the turn around line low at end of the control phase of the MDIO transaction. + clocks: + maxItems: 1 + description: + External clock connected to the PHY. If not specified it is assumed + that the PHY uses a fixed crystal or an internal oscillator. + enet-phy-lane-swap: $ref: /schemas/types.yaml#/definitions/flag description: diff --git a/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml b/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml index d23fa3771210a0..42a0bc94312c3c 100644 --- a/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml +++ b/Documentation/devicetree/bindings/net/intel,dwmac-plat.yaml @@ -19,7 +19,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml b/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml index 0fa2132fa4f4d1..08d74ca0769c30 100644 --- a/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/mediatek-dwmac.yaml @@ -25,7 +25,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml b/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml index 63409cbff5ad1d..4c01cae7c93a77 100644 --- a/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml +++ b/Documentation/devicetree/bindings/net/nxp,dwmac-imx.yaml @@ -24,7 +24,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml index b110abb42597e6..2d382faca0e6d1 100644 --- a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml +++ b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml @@ -16,7 +16,7 @@ maintainers: properties: $nodename: - pattern: "^ethernet-pse(@.*)?$" + pattern: "^ethernet-pse(@.*|-([0-9]|[1-9][0-9]+))?$" "#pse-cells": description: diff --git a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml index 2a21bbe0289216..176ea5f90251af 100644 --- a/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/rockchip-dwmac.yaml @@ -32,7 +32,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml index 395a4650e28528..c9c25132d1544a 100644 --- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml +++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml @@ -168,14 +168,14 @@ properties: patternProperties: "^mdio@[0-9a-f]+$": type: object - $ref: "ti,davinci-mdio.yaml#" + $ref: ti,davinci-mdio.yaml# description: CPSW MDIO bus. "^cpts@[0-9a-f]+": type: object - $ref: "ti,k3-am654-cpts.yaml#" + $ref: ti,k3-am654-cpts.yaml# description: CPSW Common Platform Time Sync (CPTS) module. diff --git a/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml b/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml index 474fa8bcf302ca..052f636158b3f1 100644 --- a/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml +++ b/Documentation/devicetree/bindings/net/toshiba,visconti-dwmac.yaml @@ -19,7 +19,7 @@ select: - compatible allOf: - - $ref: "snps,dwmac.yaml#" + - $ref: snps,dwmac.yaml# properties: compatible: diff --git a/Documentation/devicetree/bindings/net/xilinx_axienet.txt b/Documentation/devicetree/bindings/net/xilinx_axienet.txt deleted file mode 100644 index 80e505a2fda162..00000000000000 --- a/Documentation/devicetree/bindings/net/xilinx_axienet.txt +++ /dev/null @@ -1,101 +0,0 @@ -XILINX AXI ETHERNET Device Tree Bindings --------------------------------------------------------- - -Also called AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core -provides connectivity to an external ethernet PHY supporting different -interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two -segments of memory for buffering TX and RX, as well as the capability of -offloading TX/RX checksum calculation off the processor. - -Management configuration is done through the AXI interface, while payload is -sent and received through means of an AXI DMA controller. This driver -includes the DMA driver code, so this driver is incompatible with AXI DMA -driver. - -For more details about mdio please refer phy.txt file in the same directory. - -Required properties: -- compatible : Must be one of "xlnx,axi-ethernet-1.00.a", - "xlnx,axi-ethernet-1.01.a", "xlnx,axi-ethernet-2.01.a" -- reg : Address and length of the IO space, as well as the address - and length of the AXI DMA controller IO space, unless - axistream-connected is specified, in which case the reg - attribute of the node referenced by it is used. -- interrupts : Should be a list of 2 or 3 interrupts: TX DMA, RX DMA, - and optionally Ethernet core. If axistream-connected is - specified, the TX/RX DMA interrupts should be on that node - instead, and only the Ethernet core interrupt is optionally - specified here. -- phy-handle : Should point to the external phy device if exists. Pointing - this to the PCS/PMA PHY is deprecated and should be avoided. - See ethernet.txt file in the same directory. -- xlnx,rxmem : Set to allocated memory buffer for Rx/Tx in the hardware - -Optional properties: -- phy-mode : See ethernet.txt -- xlnx,phy-type : Deprecated, do not use, but still accepted in preference - to phy-mode. -- xlnx,txcsum : 0 or empty for disabling TX checksum offload, - 1 to enable partial TX checksum offload, - 2 to enable full TX checksum offload -- xlnx,rxcsum : Same values as xlnx,txcsum but for RX checksum offload -- xlnx,switch-x-sgmii : Boolean to indicate the Ethernet core is configured to - support both 1000BaseX and SGMII modes. If set, the phy-mode - should be set to match the mode selected on core reset (i.e. - by the basex_or_sgmii core input line). -- clock-names: Tuple listing input clock names. Possible clocks: - s_axi_lite_clk: Clock for AXI register slave interface - axis_clk: AXI4-Stream clock for TXD RXD TXC and RXS interfaces - ref_clk: Ethernet reference clock, used by signal delay - primitives and transceivers - mgt_clk: MGT reference clock (used by optional internal - PCS/PMA PHY) - - Note that if s_axi_lite_clk is not specified by name, the - first clock of any name is used for this. If that is also not - specified, the clock rate is auto-detected from the CPU clock - (but only on platforms where this is possible). New device - trees should specify all applicable clocks by name - the - fallbacks to an unnamed clock or to CPU clock are only for - backward compatibility. -- clocks: Phandles to input clocks matching clock-names. Refer to common - clock bindings. -- axistream-connected: Reference to another node which contains the resources - for the AXI DMA controller used by this device. - If this is specified, the DMA-related resources from that - device (DMA registers and DMA TX/RX interrupts) rather - than this one will be used. - - mdio : Child node for MDIO bus. Must be defined if PHY access is - required through the core's MDIO interface (i.e. always, - unless the PHY is accessed through a different bus). - Non-standard MDIO bus frequency is supported via - "clock-frequency", see mdio.yaml. - - - pcs-handle: Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X - modes, where "pcs-handle" should be used to point - to the PCS/PMA PHY, and "phy-handle" should point to an - external PHY if exists. - -Example: - axi_ethernet_eth: ethernet@40c00000 { - compatible = "xlnx,axi-ethernet-1.00.a"; - device_type = "network"; - interrupt-parent = <µblaze_0_axi_intc>; - interrupts = <2 0 1>; - clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk"; - clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>; - phy-mode = "mii"; - reg = <0x40c00000 0x40000 0x50c00000 0x40000>; - xlnx,rxcsum = <0x2>; - xlnx,rxmem = <0x800>; - xlnx,txcsum = <0x2>; - phy-handle = <&phy0>; - axi_ethernetlite_0_mdio: mdio { - #address-cells = <1>; - #size-cells = <0>; - phy0: phy@0 { - device_type = "ethernet-phy"; - reg = <1>; - }; - }; - }; diff --git a/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml new file mode 100644 index 00000000000000..1d33d80af11c3c --- /dev/null +++ b/Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml @@ -0,0 +1,183 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/net/xlnx,axi-ethernet.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: AXI 1G/2.5G Ethernet Subsystem + +description: | + Also called AXI 1G/2.5G Ethernet Subsystem, the xilinx axi ethernet IP core + provides connectivity to an external ethernet PHY supporting different + interfaces: MII, GMII, RGMII, SGMII, 1000BaseX. It also includes two + segments of memory for buffering TX and RX, as well as the capability of + offloading TX/RX checksum calculation off the processor. + + Management configuration is done through the AXI interface, while payload is + sent and received through means of an AXI DMA controller. This driver + includes the DMA driver code, so this driver is incompatible with AXI DMA + driver. + +maintainers: + - Radhey Shyam Pandey + +properties: + compatible: + enum: + - xlnx,axi-ethernet-1.00.a + - xlnx,axi-ethernet-1.01.a + - xlnx,axi-ethernet-2.01.a + + reg: + description: + Address and length of the IO space, as well as the address + and length of the AXI DMA controller IO space, unless + axistream-connected is specified, in which case the reg + attribute of the node referenced by it is used. + maxItems: 2 + + interrupts: + items: + - description: Ethernet core interrupt + - description: Tx DMA interrupt + - description: Rx DMA interrupt + description: + Ethernet core interrupt is optional. If axistream-connected property is + present DMA node should contains TX/RX DMA interrupts else DMA interrupt + resources are mentioned on ethernet node. + minItems: 1 + + phy-handle: true + + xlnx,rxmem: + description: + Set to allocated memory buffer for Rx/Tx in the hardware. + $ref: /schemas/types.yaml#/definitions/uint32 + + phy-mode: + enum: + - mii + - gmii + - rgmii + - sgmii + - 1000BaseX + + xlnx,phy-type: + description: + Do not use, but still accepted in preference to phy-mode. + deprecated: true + $ref: /schemas/types.yaml#/definitions/uint32 + + xlnx,txcsum: + description: + TX checksum offload. 0 or empty for disabling TX checksum offload, + 1 to enable partial TX checksum offload and 2 to enable full TX + checksum offload. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + xlnx,rxcsum: + description: + RX checksum offload. 0 or empty for disabling RX checksum offload, + 1 to enable partial RX checksum offload and 2 to enable full RX + checksum offload. + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [0, 1, 2] + + xlnx,switch-x-sgmii: + type: boolean + description: + Indicate the Ethernet core is configured to support both 1000BaseX and + SGMII modes. If set, the phy-mode should be set to match the mode + selected on core reset (i.e. by the basex_or_sgmii core input line). + + clocks: + items: + - description: Clock for AXI register slave interface. + - description: AXI4-Stream clock for TXD RXD TXC and RXS interfaces. + - description: Ethernet reference clock, used by signal delay primitives + and transceivers. + - description: MGT reference clock (used by optional internal PCS/PMA PHY) + + clock-names: + items: + - const: s_axi_lite_clk + - const: axis_clk + - const: ref_clk + - const: mgt_clk + + axistream-connected: + $ref: /schemas/types.yaml#/definitions/phandle + description: Phandle of AXI DMA controller which contains the resources + used by this device. If this is specified, the DMA-related resources + from that device (DMA registers and DMA TX/RX interrupts) rather than + this one will be used. + + mdio: + type: object + + pcs-handle: + description: Phandle to the internal PCS/PMA PHY in SGMII or 1000Base-X + modes, where "pcs-handle" should be used to point to the PCS/PMA PHY, + and "phy-handle" should point to an external PHY if exists. + maxItems: 1 + +required: + - compatible + - interrupts + - reg + - xlnx,rxmem + - phy-handle + +allOf: + - $ref: /schemas/net/ethernet-controller.yaml# + +additionalProperties: false + +examples: + - | + axi_ethernet_eth: ethernet@40c00000 { + compatible = "xlnx,axi-ethernet-1.00.a"; + interrupts = <2 0 1>; + clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk"; + clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>; + phy-mode = "mii"; + reg = <0x40c00000 0x40000>,<0x50c00000 0x40000>; + xlnx,rxcsum = <0x2>; + xlnx,rxmem = <0x800>; + xlnx,txcsum = <0x2>; + phy-handle = <&phy0>; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy0: ethernet-phy@1 { + device_type = "ethernet-phy"; + reg = <1>; + }; + }; + }; + + - | + axi_ethernet_eth1: ethernet@40000000 { + compatible = "xlnx,axi-ethernet-1.00.a"; + interrupts = <0>; + clock-names = "s_axi_lite_clk", "axis_clk", "ref_clk", "mgt_clk"; + clocks = <&axi_clk>, <&axi_clk>, <&pl_enet_ref_clk>, <&mgt_clk>; + phy-mode = "mii"; + reg = <0x00 0x40000000 0x00 0x40000>; + xlnx,rxcsum = <0x2>; + xlnx,rxmem = <0x800>; + xlnx,txcsum = <0x2>; + phy-handle = <&phy1>; + axistream-connected = <&dma>; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + phy1: ethernet-phy@1 { + device_type = "ethernet-phy"; + reg = <1>; + }; + }; + }; diff --git a/Documentation/devicetree/bindings/serial/8250_omap.yaml b/Documentation/devicetree/bindings/serial/8250_omap.yaml index eb3488d8f9ee61..6a7be42da523c6 100644 --- a/Documentation/devicetree/bindings/serial/8250_omap.yaml +++ b/Documentation/devicetree/bindings/serial/8250_omap.yaml @@ -70,6 +70,7 @@ properties: dsr-gpios: true rng-gpios: true dcd-gpios: true + rs485-rts-active-high: true rts-gpio: true power-domains: true clock-frequency: true diff --git a/Documentation/devicetree/bindings/sound/tas2562.yaml b/Documentation/devicetree/bindings/sound/tas2562.yaml index a5bb561bfcfbaf..31a3024ea7898e 100644 --- a/Documentation/devicetree/bindings/sound/tas2562.yaml +++ b/Documentation/devicetree/bindings/sound/tas2562.yaml @@ -55,7 +55,9 @@ properties: description: TDM TX current sense time slot. '#sound-dai-cells': - const: 1 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward + # compatibility but is deprecated. + enum: [0, 1] required: - compatible @@ -72,7 +74,7 @@ examples: codec: codec@4c { compatible = "ti,tas2562"; reg = <0x4c>; - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; interrupt-parent = <&gpio1>; interrupts = <14>; shutdown-gpios = <&gpio1 15 0>; diff --git a/Documentation/devicetree/bindings/sound/tas2770.yaml b/Documentation/devicetree/bindings/sound/tas2770.yaml index 26088adb9dc240..8908bf1122e965 100644 --- a/Documentation/devicetree/bindings/sound/tas2770.yaml +++ b/Documentation/devicetree/bindings/sound/tas2770.yaml @@ -57,7 +57,9 @@ properties: - 1 # Falling edge '#sound-dai-cells': - const: 1 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward + # compatibility but is deprecated. + enum: [0, 1] required: - compatible @@ -74,7 +76,7 @@ examples: codec: codec@41 { compatible = "ti,tas2770"; reg = <0x41>; - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; interrupt-parent = <&gpio1>; interrupts = <14>; reset-gpio = <&gpio1 15 0>; diff --git a/Documentation/devicetree/bindings/sound/tas27xx.yaml b/Documentation/devicetree/bindings/sound/tas27xx.yaml index 8cba01316855d4..a876545ec87d8c 100644 --- a/Documentation/devicetree/bindings/sound/tas27xx.yaml +++ b/Documentation/devicetree/bindings/sound/tas27xx.yaml @@ -50,7 +50,9 @@ properties: description: TDM TX voltage sense time slot. '#sound-dai-cells': - const: 1 + # The codec has a single DAI, the #sound-dai-cells=<1>; case is left in for backward + # compatibility but is deprecated. + enum: [0, 1] required: - compatible @@ -67,7 +69,7 @@ examples: codec: codec@38 { compatible = "ti,tas2764"; reg = <0x38>; - #sound-dai-cells = <1>; + #sound-dai-cells = <0>; interrupt-parent = <&gpio1>; interrupts = <14>; reset-gpios = <&gpio1 15 0>; diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt index f59125bc79d1bf..0b4e21bde5bc1c 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt @@ -8,7 +8,7 @@ Required properties: "ti,tlv320aic32x6" TLV320AIC3206, TLV320AIC3256 "ti,tas2505" TAS2505, TAS2521 - reg: I2C slave address - - supply-*: Required supply regulators are: + - *-supply: Required supply regulators are: "iov" - digital IO power supply "ldoin" - LDO power supply "dv" - Digital core power supply diff --git a/Documentation/devicetree/bindings/usb/cdns,usb3.yaml b/Documentation/devicetree/bindings/usb/cdns,usb3.yaml index cae46c4982adf6..69a93a0722f07f 100644 --- a/Documentation/devicetree/bindings/usb/cdns,usb3.yaml +++ b/Documentation/devicetree/bindings/usb/cdns,usb3.yaml @@ -64,7 +64,7 @@ properties: description: size of memory intended as internal memory for endpoints buffers expressed in KB - $ref: /schemas/types.yaml#/definitions/uint32 + $ref: /schemas/types.yaml#/definitions/uint16 cdns,phyrst-a-enable: description: Enable resetting of PHY if Rx fail is detected diff --git a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml index 50edc4da780e9c..4f7625955ccccc 100644 --- a/Documentation/devicetree/bindings/usb/snps,dwc3.yaml +++ b/Documentation/devicetree/bindings/usb/snps,dwc3.yaml @@ -287,7 +287,7 @@ properties: description: High-Speed PHY interface selection between UTMI+ and ULPI when the DWC_USB3_HSPHY_INTERFACE has value 3. - $ref: /schemas/types.yaml#/definitions/uint8 + $ref: /schemas/types.yaml#/definitions/string enum: [utmi, ulpi] snps,quirk-frame-length-adjustment: diff --git a/Documentation/filesystems/index.rst b/Documentation/filesystems/index.rst index fbb2b5ada95b38..eb252fc972aa95 100644 --- a/Documentation/filesystems/index.rst +++ b/Documentation/filesystems/index.rst @@ -72,7 +72,6 @@ Documentation for filesystem implementations. befs bfs btrfs - cifs/index ceph coda configfs @@ -111,6 +110,7 @@ Documentation for filesystem implementations. ramfs-rootfs-initramfs relay romfs + smb/index spufs/index squashfs sysfs diff --git a/Documentation/filesystems/ramfs-rootfs-initramfs.rst b/Documentation/filesystems/ramfs-rootfs-initramfs.rst index 164960631925d0..447f767c646276 100644 --- a/Documentation/filesystems/ramfs-rootfs-initramfs.rst +++ b/Documentation/filesystems/ramfs-rootfs-initramfs.rst @@ -6,8 +6,7 @@ Ramfs, rootfs and initramfs October 17, 2005 -Rob Landley -============================= +:Author: Rob Landley What is ramfs? -------------- diff --git a/Documentation/filesystems/sharedsubtree.rst b/Documentation/filesystems/sharedsubtree.rst index d83395354250d9..1cf56489ed484d 100644 --- a/Documentation/filesystems/sharedsubtree.rst +++ b/Documentation/filesystems/sharedsubtree.rst @@ -147,6 +147,7 @@ replicas continue to be exactly same. 3) Setting mount states +----------------------- The mount command (util-linux package) can be used to set mount states:: @@ -612,6 +613,7 @@ replicas continue to be exactly same. 6) Quiz +------- A. What is the result of the following command sequence? @@ -673,6 +675,7 @@ replicas continue to be exactly same. /mnt/1/test be? 7) FAQ +------ Q1. Why is bind mount needed? How is it different from symbolic links? symbolic links can get stale if the destination mount gets @@ -841,6 +844,7 @@ replicas continue to be exactly same. tmp usr tmp usr tmp usr 8) Implementation +----------------- 8A) Datastructure diff --git a/Documentation/filesystems/cifs/cifsroot.rst b/Documentation/filesystems/smb/cifsroot.rst similarity index 97% rename from Documentation/filesystems/cifs/cifsroot.rst rename to Documentation/filesystems/smb/cifsroot.rst index 4930bb443134ae..bf2d9db3acb924 100644 --- a/Documentation/filesystems/cifs/cifsroot.rst +++ b/Documentation/filesystems/smb/cifsroot.rst @@ -59,7 +59,7 @@ the root file system via SMB protocol. Enables the kernel to mount the root file system via SMB that are located in the and specified in this option. -The default mount options are set in fs/cifs/cifsroot.c. +The default mount options are set in fs/smb/client/cifsroot.c. server-ip IPv4 address of the server. diff --git a/Documentation/filesystems/cifs/index.rst b/Documentation/filesystems/smb/index.rst similarity index 100% rename from Documentation/filesystems/cifs/index.rst rename to Documentation/filesystems/smb/index.rst diff --git a/Documentation/filesystems/cifs/ksmbd.rst b/Documentation/filesystems/smb/ksmbd.rst similarity index 100% rename from Documentation/filesystems/cifs/ksmbd.rst rename to Documentation/filesystems/smb/ksmbd.rst diff --git a/Documentation/fpga/index.rst b/Documentation/fpga/index.rst index f80f95667ca217..43c968871d995a 100644 --- a/Documentation/fpga/index.rst +++ b/Documentation/fpga/index.rst @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: GPL-2.0 ==== -fpga +FPGA ==== .. toctree:: diff --git a/Documentation/leds/leds-class.rst b/Documentation/leds/leds-class.rst index cd155ead8703d1..5db620ed27aa2e 100644 --- a/Documentation/leds/leds-class.rst +++ b/Documentation/leds/leds-class.rst @@ -169,6 +169,87 @@ Setting the brightness to zero with brightness_set() callback function should completely turn off the LED and cancel the previously programmed hardware blinking function, if any. +Hardware driven LEDs +==================== + +Some LEDs can be programmed to be driven by hardware. This is not +limited to blink but also to turn off or on autonomously. +To support this feature, a LED needs to implement various additional +ops and needs to declare specific support for the supported triggers. + +With hw control we refer to the LED driven by hardware. + +LED driver must define the following value to support hw control: + + - hw_control_trigger: + unique trigger name supported by the LED in hw control + mode. + +LED driver must implement the following API to support hw control: + - hw_control_is_supported: + check if the flags passed by the supported trigger can + be parsed and activate hw control on the LED. + + Return 0 if the passed flags mask is supported and + can be set with hw_control_set(). + + If the passed flags mask is not supported -EOPNOTSUPP + must be returned, the LED trigger will use software + fallback in this case. + + Return a negative error in case of any other error like + device not ready or timeouts. + + - hw_control_set: + activate hw control. LED driver will use the provided + flags passed from the supported trigger, parse them to + a set of mode and setup the LED to be driven by hardware + following the requested modes. + + Set LED_OFF via the brightness_set to deactivate hw control. + + Return 0 on success, a negative error number on failing to + apply flags. + + - hw_control_get: + get active modes from a LED already in hw control, parse + them and set in flags the current active flags for the + supported trigger. + + Return 0 on success, a negative error number on failing + parsing the initial mode. + Error from this function is NOT FATAL as the device may + be in a not supported initial state by the attached LED + trigger. + + - hw_control_get_device: + return the device associated with the LED driver in + hw control. A trigger might use this to match the + returned device from this function with a configured + device for the trigger as the source for blinking + events and correctly enable hw control. + (example a netdev trigger configured to blink for a + particular dev match the returned dev from get_device + to set hw control) + + Returns a pointer to a struct device or NULL if nothing + is currently attached. + +LED driver can activate additional modes by default to workaround the +impossibility of supporting each different mode on the supported trigger. +Examples are hardcoding the blink speed to a set interval, enable special +feature like bypassing blink if some requirements are not met. + +A trigger should first check if the hw control API are supported by the LED +driver and check if the trigger is supported to verify if hw control is possible, +use hw_control_is_supported to check if the flags are supported and only at +the end use hw_control_set to activate hw control. + +A trigger can use hw_control_get to check if a LED is already in hw control +and init their flags. + +When the LED is in hw control, no software blink is possible and doing so +will effectively disable hw control. Known Issues ============ diff --git a/Documentation/locking/index.rst b/Documentation/locking/index.rst index 7003bd5aeff4cf..6a9ea96c8bcb70 100644 --- a/Documentation/locking/index.rst +++ b/Documentation/locking/index.rst @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: GPL-2.0 ======= -locking +Locking ======= .. toctree:: diff --git a/Documentation/mm/page_table_check.rst b/Documentation/mm/page_table_check.rst index cfd8f4117cf3e9..c12838ce6b8de2 100644 --- a/Documentation/mm/page_table_check.rst +++ b/Documentation/mm/page_table_check.rst @@ -52,3 +52,22 @@ Build kernel with: Optionally, build kernel with PAGE_TABLE_CHECK_ENFORCED in order to have page table support without extra kernel parameter. + +Implementation notes +==================== + +We specifically decided not to use VMA information in order to avoid relying on +MM states (except for limited "struct page" info). The page table check is a +separate from Linux-MM state machine that verifies that the user accessible +pages are not falsely shared. + +PAGE_TABLE_CHECK depends on EXCLUSIVE_SYSTEM_RAM. The reason is that without +EXCLUSIVE_SYSTEM_RAM, users are allowed to map arbitrary physical memory +regions into the userspace via /dev/mem. At the same time, pages may change +their properties (e.g., from anonymous pages to named pages) while they are +still being mapped in the userspace, leading to "corruption" detected by the +page table check. + +Even with EXCLUSIVE_SYSTEM_RAM, I/O pages may be still allowed to be mapped via +/dev/mem. However, these pages are always considered as named pages, so they +won't break the logic used in the page table check. diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml index 8e8c17b0a6c654..0519c257ecf41a 100644 --- a/Documentation/netlink/genetlink-c.yaml +++ b/Documentation/netlink/genetlink-c.yaml @@ -195,6 +195,10 @@ properties: description: Max length for a string or a binary attribute. $ref: '#/$defs/len-or-define' sub-type: *attr-type + # Start genetlink-c + name-prefix: + type: string + # End genetlink-c # Make sure name-prefix does not appear in subsets (subsets inherit naming) dependencies: diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml index b33541a51d6bb4..b474889b49ffb7 100644 --- a/Documentation/netlink/genetlink-legacy.yaml +++ b/Documentation/netlink/genetlink-legacy.yaml @@ -122,6 +122,14 @@ properties: enum: [ u8, u16, u32, u64, s8, s16, s32, s64, string ] len: $ref: '#/$defs/len-or-define' + byte-order: + enum: [ little-endian, big-endian ] + doc: + description: Documentation for the struct member attribute. + type: string + enum: + description: Name of the enum type used for the attribute. + type: string # End genetlink-legacy attribute-sets: @@ -218,6 +226,10 @@ properties: description: Max length for a string or a binary attribute. $ref: '#/$defs/len-or-define' sub-type: *attr-type + # Start genetlink-c + name-prefix: + type: string + # End genetlink-c # Start genetlink-legacy struct: description: Name of the struct type used for the attribute. diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 90641668232e35..5d46ca96697923 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -9,6 +9,7 @@ doc: Partial family for Devlink. attribute-sets: - name: devlink + name-prefix: devlink-attr- attributes: - name: bus-name @@ -95,10 +96,12 @@ attribute-sets: - name: reload-action-info type: nest + multi-attr: true nested-attributes: dl-reload-act-info - name: reload-action-stats type: nest + multi-attr: true nested-attributes: dl-reload-act-stats - name: dl-dev-stats @@ -196,3 +199,8 @@ operations: attributes: - bus-name - dev-name + - info-driver-name + - info-serial-number + - info-version-fixed + - info-version-running + - info-version-stored diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml index 129f413ea3496f..837b565577ca6a 100644 --- a/Documentation/netlink/specs/ethtool.yaml +++ b/Documentation/netlink/specs/ethtool.yaml @@ -9,8 +9,13 @@ doc: Partial family for Ethtool Netlink. definitions: - name: udp-tunnel-type + enum-name: type: enum entries: [ vxlan, geneve, vxlan-gpe ] + - + name: stringset + type: enum + entries: [] attribute-sets: - @@ -60,22 +65,6 @@ attribute-sets: type: nest nested-attributes: bitset-bits - - - name: u64-array - attributes: - - - name: u64 - type: nest - multi-attr: true - nested-attributes: u64 - - - name: s32-array - attributes: - - - name: s32 - type: nest - multi-attr: true - nested-attributes: s32 - name: string attributes: @@ -239,7 +228,7 @@ attribute-sets: name: tx-min-frag-size type: u32 - - name: tx-min-frag-size + name: rx-min-frag-size type: u32 - name: verify-enabled @@ -310,7 +299,7 @@ attribute-sets: name: master-slave-state type: u8 - - name: master-slave-lanes + name: lanes type: u32 - name: rate-matching @@ -338,7 +327,7 @@ attribute-sets: name: ext-substate type: u8 - - name: down-cnt + name: ext-down-cnt type: u32 - name: debug @@ -513,7 +502,7 @@ attribute-sets: attributes: - name: pad - type: u32 + type: pad - name: tx-frames type: u64 @@ -593,7 +582,7 @@ attribute-sets: name: phc-index type: u32 - - name: cable-test-nft-nest-result + name: cable-result attributes: - name: pair @@ -602,7 +591,7 @@ attribute-sets: name: code type: u8 - - name: cable-test-nft-nest-fault-length + name: cable-fault-length attributes: - name: pair @@ -611,18 +600,25 @@ attribute-sets: name: cm type: u32 - - name: cable-test-nft-nest + name: cable-nest attributes: - name: result type: nest - nested-attributes: cable-test-nft-nest-result + nested-attributes: cable-result - name: fault-length type: nest - nested-attributes: cable-test-nft-nest-fault-length + nested-attributes: cable-fault-length - name: cable-test + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: cable-test-ntf attributes: - name: header @@ -634,7 +630,7 @@ attribute-sets: - name: nest type: nest - nested-attributes: cable-test-nft-nest + nested-attributes: cable-nest - name: cable-test-tdr-cfg attributes: @@ -648,8 +644,22 @@ attribute-sets: name: step type: u32 - - name: pari + name: pair + type: u8 + - + name: cable-test-tdr-ntf + attributes: + - + name: header + type: nest + nested-attributes: header + - + name: status type: u8 + - + name: nest + type: nest + nested-attributes: cable-nest - name: cable-test-tdr attributes: @@ -662,7 +672,7 @@ attribute-sets: type: nest nested-attributes: cable-test-tdr-cfg - - name: tunnel-info-udp-entry + name: tunnel-udp-entry attributes: - name: port @@ -673,7 +683,7 @@ attribute-sets: type: u32 enum: udp-tunnel-type - - name: tunnel-info-udp-table + name: tunnel-udp-table attributes: - name: size @@ -683,9 +693,17 @@ attribute-sets: type: nest nested-attributes: bitset - - name: udp-ports + name: entry type: nest - nested-attributes: tunnel-info-udp-entry + multi-attr: true + nested-attributes: tunnel-udp-entry + - + name: tunnel-udp + attributes: + - + name: table + type: nest + nested-attributes: tunnel-udp-table - name: tunnel-info attributes: @@ -696,25 +714,25 @@ attribute-sets: - name: udp-ports type: nest - nested-attributes: tunnel-info-udp-table + nested-attributes: tunnel-udp - name: fec-stat attributes: - name: pad - type: u8 + type: pad - name: corrected - type: nest - nested-attributes: u64-array + type: binary + sub-type: u64 - name: uncorr - type: nest - nested-attributes: u64-array + type: binary + sub-type: u64 - name: corr-bits - type: nest - nested-attributes: u64-array + type: binary + sub-type: u64 - name: fec attributes: @@ -766,7 +784,7 @@ attribute-sets: attributes: - name: pad - type: u32 + type: pad - name: id type: u32 @@ -775,16 +793,16 @@ attribute-sets: type: u32 - name: stat - type: nest - nested-attributes: u64 + type: u64 + type-value: [ id ] - name: hist-rx type: nest - nested-attributes: u64 + nested-attributes: stats-grp-hist - name: hist-tx type: nest - nested-attributes: u64 + nested-attributes: stats-grp-hist - name: hist-bkt-low type: u32 @@ -792,14 +810,27 @@ attribute-sets: name: hist-bkt-hi type: u32 - - name: hist-bkt-val + name: hist-val + type: u64 + - + name: stats-grp-hist + subset-of: stats-grp + attributes: + - + name: hist-bkt-low + type: u32 + - + name: hist-bkt-hi + type: u32 + - + name: hist-val type: u64 - name: stats attributes: - name: pad - type: u32 + type: pad - name: header type: nest @@ -827,8 +858,8 @@ attribute-sets: type: u32 - name: index - type: nest - nested-attributes: s32-array + type: binary + sub-type: s32 - name: module attributes: @@ -852,12 +883,15 @@ attribute-sets: - name: admin-state type: u32 + name-prefix: ethtool-a-podl-pse- - name: admin-control type: u32 + name-prefix: ethtool-a-podl-pse- - name: pw-d-status type: u32 + name-prefix: ethtool-a-podl-pse- - name: rss attributes: @@ -911,6 +945,7 @@ attribute-sets: operations: enum-model: directional + name-prefix: ethtool-msg- list: - name: strset-get @@ -981,7 +1016,7 @@ operations: - duplex - master-slave-cfg - master-slave-state - - master-slave-lanes + - lanes - rate-matching dump: *linkmodes-get-op - @@ -1015,7 +1050,7 @@ operations: - sqi-max - ext-state - ext-substate - - down-cnt + - ext-down-cnt dump: *linkstate-get-op - name: debug-get @@ -1364,10 +1399,16 @@ operations: request: attributes: - header - reply: - attributes: - - header - - cable-test-nft-nest + - + name: cable-test-ntf + doc: Cable test notification. + + attribute-set: cable-test-ntf + + event: + attributes: + - header + - status - name: cable-test-tdr-act doc: Cable test TDR. @@ -1378,10 +1419,17 @@ operations: request: attributes: - header - reply: - attributes: - - header - - cable-test-tdr-cfg + - + name: cable-test-tdr-ntf + doc: Cable test TDR notification. + + attribute-set: cable-test-tdr-ntf + + event: + attributes: + - header + - status + - nest - name: tunnel-info-get doc: Get tsinfo params. @@ -1555,7 +1603,7 @@ operations: - hkey dump: *rss-get-op - - name: plca-get + name: plca-get-cfg doc: Get PLCA params. attribute-set: plca @@ -1577,7 +1625,7 @@ operations: - burst-tmr dump: *plca-get-op - - name: plca-set + name: plca-set-cfg doc: Set PLCA params. attribute-set: plca @@ -1601,7 +1649,7 @@ operations: - name: plca-ntf doc: Notification for change in PLCA params. - notify: plca-get + notify: plca-get-cfg - name: mm-get doc: Get MAC Merge configuration and state diff --git a/Documentation/netlink/specs/ovs_flow.yaml b/Documentation/netlink/specs/ovs_flow.yaml new file mode 100644 index 00000000000000..3b0624c870740a --- /dev/null +++ b/Documentation/netlink/specs/ovs_flow.yaml @@ -0,0 +1,831 @@ +# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) + +name: ovs_flow +version: 1 +protocol: genetlink-legacy + +doc: + OVS flow configuration over generic netlink. + +definitions: + - + name: ovs-header + type: struct + doc: | + Header for OVS Generic Netlink messages. + members: + - + name: dp-ifindex + type: u32 + doc: | + ifindex of local port for datapath (0 to make a request not specific + to a datapath). + - + name: ovs-flow-stats + type: struct + members: + - + name: n-packets + type: u64 + doc: Number of matched packets. + - + name: n-bytes + type: u64 + doc: Number of matched bytes. + - + name: ovs-key-mpls + type: struct + members: + - + name: mpls-lse + type: u32 + byte-order: big-endian + - + name: ovs-key-ipv4 + type: struct + members: + - + name: ipv4-src + type: u32 + byte-order: big-endian + - + name: ipv4-dst + type: u32 + byte-order: big-endian + - + name: ipv4-proto + type: u8 + - + name: ipv4-tos + type: u8 + - + name: ipv4-ttl + type: u8 + - + name: ipv4-frag + type: u8 + enum: ovs-frag-type + - + name: ovs-frag-type + type: enum + entries: + - + name: none + doc: Packet is not a fragment. + - + name: first + doc: Packet is a fragment with offset 0. + - + name: later + doc: Packet is a fragment with nonzero offset. + - + name: any + value: 255 + - + name: ovs-key-tcp + type: struct + members: + - + name: tcp-src + type: u16 + byte-order: big-endian + - + name: tcp-dst + type: u16 + byte-order: big-endian + - + name: ovs-key-udp + type: struct + members: + - + name: udp-src + type: u16 + byte-order: big-endian + - + name: udp-dst + type: u16 + byte-order: big-endian + - + name: ovs-key-sctp + type: struct + members: + - + name: sctp-src + type: u16 + byte-order: big-endian + - + name: sctp-dst + type: u16 + byte-order: big-endian + - + name: ovs-key-icmp + type: struct + members: + - + name: icmp-type + type: u8 + - + name: icmp-code + type: u8 + - + name: ovs-key-ct-tuple-ipv4 + type: struct + members: + - + name: ipv4-src + type: u32 + byte-order: big-endian + - + name: ipv4-dst + type: u32 + byte-order: big-endian + - + name: src-port + type: u16 + byte-order: big-endian + - + name: dst-port + type: u16 + byte-order: big-endian + - + name: ipv4-proto + type: u8 + - + name: ovs-action-push-vlan + type: struct + members: + - + name: vlan_tpid + type: u16 + byte-order: big-endian + doc: Tag protocol identifier (TPID) to push. + - + name: vlan_tci + type: u16 + byte-order: big-endian + doc: Tag control identifier (TCI) to push. + - + name: ovs-ufid-flags + type: flags + entries: + - omit-key + - omit-mask + - omit-actions + - + name: ovs-action-hash + type: struct + members: + - + name: hash-algorithm + type: u32 + doc: Algorithm used to compute hash prior to recirculation. + - + name: hash-basis + type: u32 + doc: Basis used for computing hash. + - + name: ovs-hash-alg + type: enum + doc: | + Data path hash algorithm for computing Datapath hash. The algorithm type only specifies + the fields in a flow will be used as part of the hash. Each datapath is free to use its + own hash algorithm. The hash value will be opaque to the user space daemon. + entries: + - ovs-hash-alg-l4 + + - + name: ovs-action-push-mpls + type: struct + members: + - + name: lse + type: u32 + byte-order: big-endian + doc: | + MPLS label stack entry to push + - + name: ethertype + type: u32 + byte-order: big-endian + doc: | + Ethertype to set in the encapsulating ethernet frame. The only values + ethertype should ever be given are ETH_P_MPLS_UC and ETH_P_MPLS_MC, + indicating MPLS unicast or multicast. Other are rejected. + - + name: ovs-action-add-mpls + type: struct + members: + - + name: lse + type: u32 + byte-order: big-endian + doc: | + MPLS label stack entry to push + - + name: ethertype + type: u32 + byte-order: big-endian + doc: | + Ethertype to set in the encapsulating ethernet frame. The only values + ethertype should ever be given are ETH_P_MPLS_UC and ETH_P_MPLS_MC, + indicating MPLS unicast or multicast. Other are rejected. + - + name: tun-flags + type: u16 + doc: | + MPLS tunnel attributes. + - + name: ct-state-flags + type: flags + entries: + - + name: new + doc: Beginning of a new connection. + - + name: established + doc: Part of an existing connenction + - + name: related + doc: Related to an existing connection. + - + name: reply-dir + doc: Flow is in the reply direction. + - + name: invalid + doc: Could not track the connection. + - + name: tracked + doc: Conntrack has occurred. + - + name: src-nat + doc: Packet's source address/port was mangled by NAT. + - + name: dst-nat + doc: Packet's destination address/port was mangled by NAT. + +attribute-sets: + - + name: flow-attrs + attributes: + - + name: key + type: nest + nested-attributes: key-attrs + doc: | + Nested attributes specifying the flow key. Always present in + notifications. Required for all requests (except dumps). + - + name: actions + type: nest + nested-attributes: action-attrs + doc: | + Nested attributes specifying the actions to take for packets that + match the key. Always present in notifications. Required for + OVS_FLOW_CMD_NEW requests, optional for OVS_FLOW_CMD_SET requests. An + OVS_FLOW_CMD_SET without OVS_FLOW_ATTR_ACTIONS will not modify the + actions. To clear the actions, an OVS_FLOW_ATTR_ACTIONS without any + nested attributes must be given. + - + name: stats + type: binary + struct: ovs-flow-stats + doc: | + Statistics for this flow. Present in notifications if the stats would + be nonzero. Ignored in requests. + - + name: tcp-flags + type: u8 + doc: | + An 8-bit value giving the ORed value of all of the TCP flags seen on + packets in this flow. Only present in notifications for TCP flows, and + only if it would be nonzero. Ignored in requests. + - + name: used + type: u64 + doc: | + A 64-bit integer giving the time, in milliseconds on the system + monotonic clock, at which a packet was last processed for this + flow. Only present in notifications if a packet has been processed for + this flow. Ignored in requests. + - + name: clear + type: flag + doc: | + If present in a OVS_FLOW_CMD_SET request, clears the last-used time, + accumulated TCP flags, and statistics for this flow. Otherwise + ignored in requests. Never present in notifications. + - + name: mask + type: nest + nested-attributes: key-attrs + doc: | + Nested attributes specifying the mask bits for wildcarded flow + match. Mask bit value '1' specifies exact match with corresponding + flow key bit, while mask bit value '0' specifies a wildcarded + match. Omitting attribute is treated as wildcarding all corresponding + fields. Optional for all requests. If not present, all flow key bits + are exact match bits. + - + name: probe + type: binary + doc: | + Flow operation is a feature probe, error logging should be suppressed. + - + name: ufid + type: binary + doc: | + A value between 1-16 octets specifying a unique identifier for the + flow. Causes the flow to be indexed by this value rather than the + value of the OVS_FLOW_ATTR_KEY attribute. Optional for all + requests. Present in notifications if the flow was created with this + attribute. + - + name: ufid-flags + type: u32 + enum: ovs-ufid-flags + doc: | + A 32-bit value of ORed flags that provide alternative semantics for + flow installation and retrieval. Optional for all requests. + - + name: pad + type: binary + + - + name: key-attrs + attributes: + - + name: encap + type: nest + nested-attributes: key-attrs + - + name: priority + type: u32 + - + name: in-port + type: u32 + - + name: ethernet + type: binary + doc: struct ovs_key_ethernet + - + name: vlan + type: u16 + byte-order: big-endian + - + name: ethertype + type: u16 + byte-order: big-endian + - + name: ipv4 + type: binary + struct: ovs-key-ipv4 + - + name: ipv6 + type: binary + doc: struct ovs_key_ipv6 + - + name: tcp + type: binary + struct: ovs-key-tcp + - + name: udp + type: binary + struct: ovs-key-udp + - + name: icmp + type: binary + struct: ovs-key-icmp + - + name: icmpv6 + type: binary + struct: ovs-key-icmp + - + name: arp + type: binary + doc: struct ovs_key_arp + - + name: nd + type: binary + doc: struct ovs_key_nd + - + name: skb-mark + type: u32 + - + name: tunnel + type: nest + nested-attributes: tunnel-key-attrs + - + name: sctp + type: binary + struct: ovs-key-sctp + - + name: tcp-flags + type: u16 + byte-order: big-endian + - + name: dp-hash + type: u32 + doc: Value 0 indicates the hash is not computed by the datapath. + - + name: recirc-id + type: u32 + - + name: mpls + type: binary + struct: ovs-key-mpls + - + name: ct-state + type: u32 + enum: ct-state-flags + enum-as-flags: true + - + name: ct-zone + type: u16 + doc: connection tracking zone + - + name: ct-mark + type: u32 + doc: connection tracking mark + - + name: ct-labels + type: binary + doc: 16-octet connection tracking label + - + name: ct-orig-tuple-ipv4 + type: binary + struct: ovs-key-ct-tuple-ipv4 + - + name: ct-orig-tuple-ipv6 + type: binary + doc: struct ovs_key_ct_tuple_ipv6 + - + name: nsh + type: nest + nested-attributes: ovs-nsh-key-attrs + - + name: packet-type + type: u32 + byte-order: big-endian + doc: Should not be sent to the kernel + - + name: nd-extensions + type: binary + doc: Should not be sent to the kernel + - + name: tunnel-info + type: binary + doc: struct ip_tunnel_info + - + name: ipv6-exthdrs + type: binary + doc: struct ovs_key_ipv6_exthdr + - + name: action-attrs + attributes: + - + name: output + type: u32 + doc: ovs port number in datapath + - + name: userspace + type: nest + nested-attributes: userspace-attrs + - + name: set + type: nest + nested-attributes: key-attrs + doc: Replaces the contents of an existing header. The single nested attribute specifies a header to modify and its value. + - + name: push-vlan + type: binary + struct: ovs-action-push-vlan + doc: Push a new outermost 802.1Q or 802.1ad header onto the packet. + - + name: pop-vlan + type: flag + doc: Pop the outermost 802.1Q or 802.1ad header from the packet. + - + name: sample + type: nest + nested-attributes: sample-attrs + doc: | + Probabilistically executes actions, as specified in the nested attributes. + - + name: recirc + type: u32 + doc: recirc id + - + name: hash + type: binary + struct: ovs-action-hash + - + name: push-mpls + type: binary + struct: ovs-action-push-mpls + doc: | + Push a new MPLS label stack entry onto the top of the packets MPLS + label stack. Set the ethertype of the encapsulating frame to either + ETH_P_MPLS_UC or ETH_P_MPLS_MC to indicate the new packet contents. + - + name: pop-mpls + type: u16 + byte-order: big-endian + doc: ethertype + - + name: set-masked + type: nest + nested-attributes: key-attrs + doc: | + Replaces the contents of an existing header. A nested attribute + specifies a header to modify, its value, and a mask. For every bit set + in the mask, the corresponding bit value is copied from the value to + the packet header field, rest of the bits are left unchanged. The + non-masked value bits must be passed in as zeroes. Masking is not + supported for the OVS_KEY_ATTR_TUNNEL attribute. + - + name: ct + type: nest + nested-attributes: ct-attrs + doc: | + Track the connection. Populate the conntrack-related entries + in the flow key. + - + name: trunc + type: u32 + doc: struct ovs_action_trunc is a u32 max length + - + name: push-eth + type: binary + doc: struct ovs_action_push_eth + - + name: pop-eth + type: flag + - + name: ct-clear + type: flag + - + name: push-nsh + type: nest + nested-attributes: ovs-nsh-key-attrs + doc: | + Push NSH header to the packet. + - + name: pop-nsh + type: flag + doc: | + Pop the outermost NSH header off the packet. + - + name: meter + type: u32 + doc: | + Run packet through a meter, which may drop the packet, or modify the + packet (e.g., change the DSCP field) + - + name: clone + type: nest + nested-attributes: action-attrs + doc: | + Make a copy of the packet and execute a list of actions without + affecting the original packet and key. + - + name: check-pkt-len + type: nest + nested-attributes: check-pkt-len-attrs + doc: | + Check the packet length and execute a set of actions if greater than + the specified packet length, else execute another set of actions. + - + name: add-mpls + type: binary + struct: ovs-action-add-mpls + doc: | + Push a new MPLS label stack entry at the start of the packet or at the + start of the l3 header depending on the value of l3 tunnel flag in the + tun_flags field of this OVS_ACTION_ATTR_ADD_MPLS argument. + - + name: dec-ttl + type: nest + nested-attributes: dec-ttl-attrs + - + name: tunnel-key-attrs + attributes: + - + name: id + type: u64 + byte-order: big-endian + value: 0 + - + name: ipv4-src + type: u32 + byte-order: big-endian + - + name: ipv4-dst + type: u32 + byte-order: big-endian + - + name: tos + type: u8 + - + name: ttl + type: u8 + - + name: dont-fragment + type: flag + - + name: csum + type: flag + - + name: oam + type: flag + - + name: geneve-opts + type: binary + sub-type: u32 + - + name: tp-src + type: u16 + byte-order: big-endian + - + name: tp-dst + type: u16 + byte-order: big-endian + - + name: vxlan-opts + type: nest + nested-attributes: vxlan-ext-attrs + - + name: ipv6-src + type: binary + doc: | + struct in6_addr source IPv6 address + - + name: ipv6-dst + type: binary + doc: | + struct in6_addr destination IPv6 address + - + name: pad + type: binary + - + name: erspan-opts + type: binary + doc: | + struct erspan_metadata + - + name: ipv4-info-bridge + type: flag + - + name: check-pkt-len-attrs + attributes: + - + name: pkt-len + type: u16 + - + name: actions-if-greater + type: nest + nested-attributes: action-attrs + - + name: actions-if-less-equal + type: nest + nested-attributes: action-attrs + - + name: sample-attrs + attributes: + - + name: probability + type: u32 + - + name: actions + type: nest + nested-attributes: action-attrs + - + name: userspace-attrs + attributes: + - + name: pid + type: u32 + - + name: userdata + type: binary + - + name: egress-tun-port + type: u32 + - + name: actions + type: flag + - + name: ovs-nsh-key-attrs + attributes: + - + name: base + type: binary + - + name: md1 + type: binary + - + name: md2 + type: binary + - + name: ct-attrs + attributes: + - + name: commit + type: flag + - + name: zone + type: u16 + - + name: mark + type: binary + - + name: labels + type: binary + - + name: helper + type: string + - + name: nat + type: nest + nested-attributes: nat-attrs + - + name: force-commit + type: flag + - + name: eventmask + type: u32 + - + name: timeout + type: string + - + name: nat-attrs + attributes: + - + name: src + type: binary + - + name: dst + type: binary + - + name: ip-min + type: binary + - + name: ip-max + type: binary + - + name: proto-min + type: binary + - + name: proto-max + type: binary + - + name: persistent + type: binary + - + name: proto-hash + type: binary + - + name: proto-random + type: binary + - + name: dec-ttl-attrs + attributes: + - + name: action + type: nest + nested-attributes: action-attrs + - + name: vxlan-ext-attrs + attributes: + - + name: gbp + type: u32 + +operations: + fixed-header: ovs-header + list: + - + name: flow-get + doc: Get / dump OVS flow configuration and state + value: 3 + attribute-set: flow-attrs + do: &flow-get-op + request: + attributes: + - dp-ifindex + - key + - ufid + - ufid-flags + reply: + attributes: + - dp-ifindex + - key + - ufid + - mask + - stats + - actions + dump: *flow-get-op + +mcast-groups: + list: + - + name: ovs_flow diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst index 3a7a714cc08f0a..a4edf908b707c2 100644 --- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst +++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/devlink.rst @@ -40,6 +40,7 @@ flow_steering_mode: Device flow steering mode --------------------------------------------- The flow steering mode parameter controls the flow steering mode of the driver. Two modes are supported: + 1. 'dmfs' - Device managed flow steering. 2. 'smfs' - Software/Driver managed flow steering. @@ -99,6 +100,7 @@ between representors and stacked devices. By default metadata is enabled on the supported devices in E-switch. Metadata is applicable only for E-switch in switchdev mode and users may disable it when NONE of the below use cases will be in use: + 1. HCA is in Dual/multi-port RoCE mode. 2. VF/SF representor bonding (Usually used for Live migration) 3. Stacked devices @@ -180,7 +182,8 @@ User commands examples: $ devlink health diagnose pci/0000:82:00.0 reporter tx -NOTE: This command has valid output only when interface is up, otherwise the command has empty output. +.. note:: + This command has valid output only when interface is up, otherwise the command has empty output. - Show number of tx errors indicated, number of recover flows ended successfully, is autorecover enabled and graceful period from last recover:: @@ -232,8 +235,9 @@ User commands examples: $ devlink health dump show pci/0000:82:00.0 reporter fw -NOTE: This command can run only on the PF which has fw tracer ownership, -running it on other PF or any VF will return "Operation not permitted". +.. note:: + This command can run only on the PF which has fw tracer ownership, + running it on other PF or any VF will return "Operation not permitted". fw fatal reporter ----------------- @@ -256,7 +260,8 @@ User commands examples: $ devlink health dump show pci/0000:82:00.1 reporter fw_fatal -NOTE: This command can run only on PF. +.. note:: + This command can run only on PF. vnic reporter ------------- @@ -265,28 +270,44 @@ It is responsible for querying the vnic diagnostic counters from fw and displayi them in realtime. Description of the vnic counters: -total_q_under_processor_handle: number of queues in an error state due to -an async error or errored command. -send_queue_priority_update_flow: number of QP/SQ priority/SL update -events. -cq_overrun: number of times CQ entered an error state due to an -overflow. -async_eq_overrun: number of times an EQ mapped to async events was -overrun. -comp_eq_overrun: number of times an EQ mapped to completion events was -overrun. -quota_exceeded_command: number of commands issued and failed due to quota -exceeded. -invalid_command: number of commands issued and failed dues to any reason -other than quota exceeded. -nic_receive_steering_discard: number of packets that completed RX flow -steering but were discarded due to a mismatch in flow table. + +- total_q_under_processor_handle + number of queues in an error state due to + an async error or errored command. +- send_queue_priority_update_flow + number of QP/SQ priority/SL update events. +- cq_overrun + number of times CQ entered an error state due to an overflow. +- async_eq_overrun + number of times an EQ mapped to async events was overrun. + comp_eq_overrun number of times an EQ mapped to completion events was + overrun. +- quota_exceeded_command + number of commands issued and failed due to quota exceeded. +- invalid_command + number of commands issued and failed dues to any reason other than quota + exceeded. +- nic_receive_steering_discard + number of packets that completed RX flow + steering but were discarded due to a mismatch in flow table. +- generated_pkt_steering_fail + number of packets generated by the VNIC experiencing unexpected steering + failure (at any point in steering flow). +- handled_pkt_steering_fail + number of packets handled by the VNIC experiencing unexpected steering + failure (at any point in steering flow owned by the VNIC, including the FDB + for the eswitch owner). User commands examples: -- Diagnose PF/VF vnic counters + +- Diagnose PF/VF vnic counters:: + $ devlink health diagnose pci/0000:82:00.1 reporter vnic + - Diagnose representor vnic counters (performed by supplying devlink port of the - representor, which can be obtained via devlink port command) + representor, which can be obtained via devlink port command):: + $ devlink health diagnose pci/0000:82:00.1/65537 reporter vnic -NOTE: This command can run over all interfaces such as PF/VF and representor ports. +.. note:: + This command can run over all interfaces such as PF/VF and representor ports. diff --git a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst index 01deedb7159755..db62187eebcecd 100644 --- a/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst +++ b/Documentation/networking/device_drivers/ethernet/mellanox/mlx5/switchdev.rst @@ -45,6 +45,26 @@ Following bridge VLAN functions are supported by mlx5: Subfunction =========== +Subfunction which are spawned over the E-switch are created only with devlink +device, and by default all the SF auxiliary devices are disabled. +This will allow user to configure the SF before the SF have been fully probed, +which will save time. + +Usage example: +Create SF: +$ devlink port add pci/0000:08:00.0 flavour pcisf pfnum 0 sfnum 11 +$ devlink port function set pci/0000:08:00.0/32768 \ + hw_addr 00:00:00:00:00:11 state active + +Enable ETH auxiliary device: +$ devlink dev param set auxiliary/mlx5_core.sf.1 \ + name enable_eth value true cmode driverinit + +Now, in order to fully probe the SF, use devlink reload: +$ devlink dev reload auxiliary/mlx5_core.sf.1 + +mlx5 supports ETH,rdma and vdpa (vnet) auxiliary devices devlink params (see :ref:`Documentation/networking/devlink/devlink-params.rst`) + mlx5 supports subfunction management using devlink port (see :ref:`Documentation/networking/devlink/devlink-port.rst `) interface. A subfunction has its own function capabilities and its own resources. This diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst index 3f6d3d5f5626a4..366e2a5097d9ef 100644 --- a/Documentation/networking/ip-sysctl.rst +++ b/Documentation/networking/ip-sysctl.rst @@ -1363,8 +1363,8 @@ ping_group_range - 2 INTEGERS Restrict ICMP_PROTO datagram sockets to users in the group range. The default is "1 0", meaning, that nobody (not even root) may create ping sockets. Setting it to "100 100" would grant permissions - to the single group. "0 4294967295" would enable it for the world, "100 - 4294967295" would enable it for the users, but not daemons. + to the single group. "0 4294967294" would enable it for the world, "100 + 4294967294" would enable it for the users, but not daemons. tcp_early_demux - BOOLEAN Enable early demux for established TCP sockets. diff --git a/Documentation/networking/page_pool.rst b/Documentation/networking/page_pool.rst index 873efd97f82280..df3e28728008df 100644 --- a/Documentation/networking/page_pool.rst +++ b/Documentation/networking/page_pool.rst @@ -4,12 +4,28 @@ Page Pool API ============= -The page_pool allocator is optimized for the XDP mode that uses one frame -per-page, but it can fallback on the regular page allocator APIs. - -Basic use involves replacing alloc_pages() calls with the -page_pool_alloc_pages() call. Drivers should use page_pool_dev_alloc_pages() -replacing dev_alloc_pages(). +The page_pool allocator is optimized for recycling page or page frag used by skb +packet and xdp frame. + +Basic use involves replacing alloc_pages() calls with different page pool +allocator API based on different use case: +1. page_pool_alloc_pages(): allocate memory without page splitting when driver + knows that the memory it need is always bigger than half of the page + allocated from page pool. There is no cache line dirtying for 'struct page' + when a page is recycled back to the page pool. + +2. page_pool_alloc_frag(): allocate memory with page splitting when driver knows + that the memory it need is always smaller than or equal to half of the page + allocated from page pool. Page splitting enables memory saving and thus avoid + TLB/cache miss for data access, but there also is some cost to implement page + splitting, mainly some cache line dirtying/bouncing for 'struct page' and + atomic operation for page->pp_frag_count. + +3. page_pool_alloc(): allocate memory with or without page splitting depending + on the requested memory size when driver doesn't know the size of memory it + need beforehand. It is a mix of the above two case, so it is a wrapper of the + above API to simplify driver's interface for memory allocation with least + memory utilization and performance penalty. API keeps track of in-flight pages, in order to let API user know when it is safe to free a page_pool object. Thus, API users @@ -93,6 +109,12 @@ a page will cause no race conditions is enough. * page_pool_dev_alloc_pages(): Get a page from the page allocator or page_pool caches. +* page_pool_dev_alloc_frag(): Get a page frag from the page allocator or + page_pool caches. + +* page_pool_dev_alloc(): Get a page or page frag from the page allocator or + page_pool caches. + * page_pool_get_dma_addr(): Retrieve the stored DMA address. * page_pool_get_dma_dir(): Retrieve the stored DMA direction. diff --git a/Documentation/pcmcia/index.rst b/Documentation/pcmcia/index.rst index 7ae1f62fca14f8..8067236c51ab42 100644 --- a/Documentation/pcmcia/index.rst +++ b/Documentation/pcmcia/index.rst @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: GPL-2.0 ====== -pcmcia +PCMCIA ====== .. toctree:: diff --git a/Documentation/process/maintainer-netdev.rst b/Documentation/process/maintainer-netdev.rst index f73ac9e175a8dd..83614cec9328b6 100644 --- a/Documentation/process/maintainer-netdev.rst +++ b/Documentation/process/maintainer-netdev.rst @@ -127,13 +127,32 @@ the value of ``Message-ID`` to the URL above. Updating patch status ~~~~~~~~~~~~~~~~~~~~~ -It may be tempting to help the maintainers and update the state of your -own patches when you post a new version or spot a bug. Please **do not** -do that. -Interfering with the patch status on patchwork will only cause confusion. Leave -it to the maintainer to figure out what is the most recent and current -version that should be applied. If there is any doubt, the maintainer -will reply and ask what should be done. +Contributors and reviewers do not have the permissions to update patch +state directly in patchwork. Patchwork doesn't expose much information +about the history of the state of patches, therefore having multiple +people update the state leads to confusion. + +Instead of delegating patchwork permissions netdev uses a simple mail +bot which looks for special commands/lines within the emails sent to +the mailing list. For example to mark a series as Changes Requested +one needs to send the following line anywhere in the email thread:: + + pw-bot: changes-requested + +As a result the bot will set the entire series to Changes Requested. +This may be useful when author discovers a bug in their own series +and wants to prevent it from getting applied. + +The use of the bot is entirely optional, if in doubt ignore its existence +completely. Maintainers will classify and update the state of the patches +themselves. No email should ever be sent to the list with the main purpose +of communicating with the bot, the bot commands should be seen as metadata. + +The use of the bot is restricted to authors of the patches (the ``From:`` +header on patch submission and command must match!), maintainers themselves +and a handful of senior reviewers. Bot records its activity here: + + https://patchwork.hopto.org/pw-bot.html Review timelines ~~~~~~~~~~~~~~~~ diff --git a/Documentation/s390/vfio-ap.rst b/Documentation/s390/vfio-ap.rst index d46e98c7c1ec6c..bb3f4c4e288563 100644 --- a/Documentation/s390/vfio-ap.rst +++ b/Documentation/s390/vfio-ap.rst @@ -551,7 +551,6 @@ These are the steps: * IOMMU_SUPPORT * S390 * ZCRYPT - * S390_AP_IOMMU * VFIO * KVM diff --git a/Documentation/staging/crc32.rst b/Documentation/staging/crc32.rst index 8a6860f33b4e76..7542220967cb4c 100644 --- a/Documentation/staging/crc32.rst +++ b/Documentation/staging/crc32.rst @@ -1,5 +1,5 @@ ================================= -brief tutorial on CRC computation +Brief tutorial on CRC computation ================================= A CRC is a long-division remainder. You add the CRC to the message, diff --git a/Documentation/timers/index.rst b/Documentation/timers/index.rst index df510ad0c989be..983f91f8f023e0 100644 --- a/Documentation/timers/index.rst +++ b/Documentation/timers/index.rst @@ -1,7 +1,7 @@ .. SPDX-License-Identifier: GPL-2.0 ====== -timers +Timers ====== .. toctree:: diff --git a/Documentation/trace/histogram.rst b/Documentation/trace/histogram.rst index 479c9eac633522..3c9b263de9c24f 100644 --- a/Documentation/trace/histogram.rst +++ b/Documentation/trace/histogram.rst @@ -35,7 +35,7 @@ Documentation written by Tom Zanussi in place of an explicit value field - this is simply a count of event hits. If 'values' isn't specified, an implicit 'hitcount' value will be automatically created and used as the only value. - Keys can be any field, or the special string 'stacktrace', which + Keys can be any field, or the special string 'common_stacktrace', which will use the event's kernel stacktrace as the key. The keywords 'keys' or 'key' can be used to specify keys, and the keywords 'values', 'vals', or 'val' can be used to specify values. Compound @@ -54,7 +54,7 @@ Documentation written by Tom Zanussi 'compatible' if the fields named in the trigger share the same number and type of fields and those fields also have the same names. Note that any two events always share the compatible 'hitcount' and - 'stacktrace' fields and can therefore be combined using those + 'common_stacktrace' fields and can therefore be combined using those fields, however pointless that may be. 'hist' triggers add a 'hist' file to each event's subdirectory. @@ -547,9 +547,9 @@ Extended error information the hist trigger display symbolic call_sites, we can have the hist trigger additionally display the complete set of kernel stack traces that led to each call_site. To do that, we simply use the special - value 'stacktrace' for the key parameter:: + value 'common_stacktrace' for the key parameter:: - # echo 'hist:keys=stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \ + # echo 'hist:keys=common_stacktrace:values=bytes_req,bytes_alloc:sort=bytes_alloc' > \ /sys/kernel/tracing/events/kmem/kmalloc/trigger The above trigger will use the kernel stack trace in effect when an @@ -561,9 +561,9 @@ Extended error information every callpath to a kmalloc for a kernel compile):: # cat /sys/kernel/tracing/events/kmem/kmalloc/hist - # trigger info: hist:keys=stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active] + # trigger info: hist:keys=common_stacktrace:vals=bytes_req,bytes_alloc:sort=bytes_alloc:size=2048 [active] - { stacktrace: + { common_stacktrace: __kmalloc_track_caller+0x10b/0x1a0 kmemdup+0x20/0x50 hidraw_report_event+0x8a/0x120 [hid] @@ -581,7 +581,7 @@ Extended error information cpu_startup_entry+0x315/0x3e0 rest_init+0x7c/0x80 } hitcount: 3 bytes_req: 21 bytes_alloc: 24 - { stacktrace: + { common_stacktrace: __kmalloc_track_caller+0x10b/0x1a0 kmemdup+0x20/0x50 hidraw_report_event+0x8a/0x120 [hid] @@ -596,7 +596,7 @@ Extended error information do_IRQ+0x5a/0xf0 ret_from_intr+0x0/0x30 } hitcount: 3 bytes_req: 21 bytes_alloc: 24 - { stacktrace: + { common_stacktrace: kmem_cache_alloc_trace+0xeb/0x150 aa_alloc_task_context+0x27/0x40 apparmor_cred_prepare+0x1f/0x50 @@ -608,7 +608,7 @@ Extended error information . . . - { stacktrace: + { common_stacktrace: __kmalloc+0x11b/0x1b0 i915_gem_execbuffer2+0x6c/0x2c0 [i915] drm_ioctl+0x349/0x670 [drm] @@ -616,7 +616,7 @@ Extended error information SyS_ioctl+0x81/0xa0 system_call_fastpath+0x12/0x6a } hitcount: 17726 bytes_req: 13944120 bytes_alloc: 19593808 - { stacktrace: + { common_stacktrace: __kmalloc+0x11b/0x1b0 load_elf_phdrs+0x76/0xa0 load_elf_binary+0x102/0x1650 @@ -625,7 +625,7 @@ Extended error information SyS_execve+0x3a/0x50 return_from_execve+0x0/0x23 } hitcount: 33348 bytes_req: 17152128 bytes_alloc: 20226048 - { stacktrace: + { common_stacktrace: kmem_cache_alloc_trace+0xeb/0x150 apparmor_file_alloc_security+0x27/0x40 security_file_alloc+0x16/0x20 @@ -636,7 +636,7 @@ Extended error information SyS_open+0x1e/0x20 system_call_fastpath+0x12/0x6a } hitcount: 4766422 bytes_req: 9532844 bytes_alloc: 38131376 - { stacktrace: + { common_stacktrace: __kmalloc+0x11b/0x1b0 seq_buf_alloc+0x1b/0x50 seq_read+0x2cc/0x370 @@ -1026,7 +1026,7 @@ Extended error information First we set up an initially paused stacktrace trigger on the netif_receive_skb event:: - # echo 'hist:key=stacktrace:vals=len:pause' > \ + # echo 'hist:key=common_stacktrace:vals=len:pause' > \ /sys/kernel/tracing/events/net/netif_receive_skb/trigger Next, we set up an 'enable_hist' trigger on the sched_process_exec @@ -1060,9 +1060,9 @@ Extended error information $ wget https://www.kernel.org/pub/linux/kernel/v3.x/patch-3.19.xz # cat /sys/kernel/tracing/events/net/netif_receive_skb/hist - # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused] + # trigger info: hist:keys=common_stacktrace:vals=len:sort=hitcount:size=2048 [paused] - { stacktrace: + { common_stacktrace: __netif_receive_skb_core+0x46d/0x990 __netif_receive_skb+0x18/0x60 netif_receive_skb_internal+0x23/0x90 @@ -1079,7 +1079,7 @@ Extended error information kthread+0xd2/0xf0 ret_from_fork+0x42/0x70 } hitcount: 85 len: 28884 - { stacktrace: + { common_stacktrace: __netif_receive_skb_core+0x46d/0x990 __netif_receive_skb+0x18/0x60 netif_receive_skb_internal+0x23/0x90 @@ -1097,7 +1097,7 @@ Extended error information irq_thread+0x11f/0x150 kthread+0xd2/0xf0 } hitcount: 98 len: 664329 - { stacktrace: + { common_stacktrace: __netif_receive_skb_core+0x46d/0x990 __netif_receive_skb+0x18/0x60 process_backlog+0xa8/0x150 @@ -1115,7 +1115,7 @@ Extended error information inet_sendmsg+0x64/0xa0 sock_sendmsg+0x3d/0x50 } hitcount: 115 len: 13030 - { stacktrace: + { common_stacktrace: __netif_receive_skb_core+0x46d/0x990 __netif_receive_skb+0x18/0x60 netif_receive_skb_internal+0x23/0x90 @@ -1142,14 +1142,14 @@ Extended error information into the histogram. In order to avoid having to set everything up again, we can just clear the histogram first:: - # echo 'hist:key=stacktrace:vals=len:clear' >> \ + # echo 'hist:key=common_stacktrace:vals=len:clear' >> \ /sys/kernel/tracing/events/net/netif_receive_skb/trigger Just to verify that it is in fact cleared, here's what we now see in the hist file:: # cat /sys/kernel/tracing/events/net/netif_receive_skb/hist - # trigger info: hist:keys=stacktrace:vals=len:sort=hitcount:size=2048 [paused] + # trigger info: hist:keys=common_stacktrace:vals=len:sort=hitcount:size=2048 [paused] Totals: Hits: 0 @@ -1485,12 +1485,12 @@ Extended error information And here's an example that shows how to combine histogram data from any two events even if they don't share any 'compatible' fields - other than 'hitcount' and 'stacktrace'. These commands create a + other than 'hitcount' and 'common_stacktrace'. These commands create a couple of triggers named 'bar' using those fields:: - # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \ + # echo 'hist:name=bar:key=common_stacktrace:val=hitcount' > \ /sys/kernel/tracing/events/sched/sched_process_fork/trigger - # echo 'hist:name=bar:key=stacktrace:val=hitcount' > \ + # echo 'hist:name=bar:key=common_stacktrace:val=hitcount' > \ /sys/kernel/tracing/events/net/netif_rx/trigger And displaying the output of either shows some interesting if @@ -1501,16 +1501,16 @@ Extended error information # event histogram # - # trigger info: hist:name=bar:keys=stacktrace:vals=hitcount:sort=hitcount:size=2048 [active] + # trigger info: hist:name=bar:keys=common_stacktrace:vals=hitcount:sort=hitcount:size=2048 [active] # - { stacktrace: + { common_stacktrace: kernel_clone+0x18e/0x330 kernel_thread+0x29/0x30 kthreadd+0x154/0x1b0 ret_from_fork+0x3f/0x70 } hitcount: 1 - { stacktrace: + { common_stacktrace: netif_rx_internal+0xb2/0xd0 netif_rx_ni+0x20/0x70 dev_loopback_xmit+0xaa/0xd0 @@ -1528,7 +1528,7 @@ Extended error information call_cpuidle+0x3b/0x60 cpu_startup_entry+0x22d/0x310 } hitcount: 1 - { stacktrace: + { common_stacktrace: netif_rx_internal+0xb2/0xd0 netif_rx_ni+0x20/0x70 dev_loopback_xmit+0xaa/0xd0 @@ -1543,7 +1543,7 @@ Extended error information SyS_sendto+0xe/0x10 entry_SYSCALL_64_fastpath+0x12/0x6a } hitcount: 2 - { stacktrace: + { common_stacktrace: netif_rx_internal+0xb2/0xd0 netif_rx+0x1c/0x60 loopback_xmit+0x6c/0xb0 @@ -1561,7 +1561,7 @@ Extended error information sock_sendmsg+0x38/0x50 ___sys_sendmsg+0x14e/0x270 } hitcount: 76 - { stacktrace: + { common_stacktrace: netif_rx_internal+0xb2/0xd0 netif_rx+0x1c/0x60 loopback_xmit+0x6c/0xb0 @@ -1579,7 +1579,7 @@ Extended error information sock_sendmsg+0x38/0x50 ___sys_sendmsg+0x269/0x270 } hitcount: 77 - { stacktrace: + { common_stacktrace: netif_rx_internal+0xb2/0xd0 netif_rx+0x1c/0x60 loopback_xmit+0x6c/0xb0 @@ -1597,7 +1597,7 @@ Extended error information sock_sendmsg+0x38/0x50 SYSC_sendto+0xef/0x170 } hitcount: 88 - { stacktrace: + { common_stacktrace: kernel_clone+0x18e/0x330 SyS_clone+0x19/0x20 entry_SYSCALL_64_fastpath+0x12/0x6a @@ -1949,7 +1949,7 @@ uninterruptible state:: # cd /sys/kernel/tracing # echo 's:block_lat pid_t pid; u64 delta; unsigned long[] stack;' > dynamic_events - # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=stacktrace if prev_state == 2' >> events/sched/sched_switch/trigger + # echo 'hist:keys=next_pid:ts=common_timestamp.usecs,st=common_stacktrace if prev_state == 2' >> events/sched/sched_switch/trigger # echo 'hist:keys=prev_pid:delta=common_timestamp.usecs-$ts,s=$st:onmax($delta).trace(block_lat,prev_pid,$delta,$s)' >> events/sched/sched_switch/trigger # echo 1 > events/synthetic/block_lat/enable # cat trace diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 176e8fc3f31b93..4f7b23faebb98c 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -363,7 +363,7 @@ Code Seq# Include File Comments 0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver 0xCD 01 linux/reiserfs_fs.h 0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices -0xCF 02 fs/cifs/ioctl.c +0xCF 02 fs/smb/client/cifs_ioctl.h 0xDB 00-0F drivers/char/mwave/mwavepub.h 0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ diff --git a/Documentation/userspace-api/netlink/intro-specs.rst b/Documentation/userspace-api/netlink/intro-specs.rst index a3b847eafff711..bada89699455c8 100644 --- a/Documentation/userspace-api/netlink/intro-specs.rst +++ b/Documentation/userspace-api/netlink/intro-specs.rst @@ -78,3 +78,82 @@ to see other examples. The code generation itself is performed by ``tools/net/ynl/ynl-gen-c.py`` but it takes a few arguments so calling it directly for each file quickly becomes tedious. + +YNL lib +======= + +``tools/net/ynl/lib/`` contains an implementation of a C library +(based on libmnl) which integrates with code generated by +``tools/net/ynl/ynl-gen-c.py`` to create easy to use netlink wrappers. + +YNL basics +---------- + +The YNL library consists of two parts - the generic code (functions +prefix by ``ynl_``) and per-family auto-generated code (prefixed +with the name of the family). + +To create a YNL socket call ynl_sock_create() passing the family +struct (family structs are exported by the auto-generated code). +ynl_sock_destroy() closes the socket. + +YNL requests +------------ + +Steps for issuing YNL requests are best explained on an example. +All the functions and types in this example come from the auto-generated +code (for the netdev family in this case): + +.. code-block:: c + + // 0. Request and response pointers + struct netdev_dev_get_req *req; + struct netdev_dev_get_rsp *d; + + // 1. Allocate a request + req = netdev_dev_get_req_alloc(); + // 2. Set request parameters (as needed) + netdev_dev_get_req_set_ifindex(req, ifindex); + + // 3. Issues the request + d = netdev_dev_get(ys, req); + // 4. Free the request arguments + netdev_dev_get_req_free(req); + // 5. Error check (the return value from step 3) + if (!d) { + // 6. Print the YNL-generated error + fprintf(stderr, "YNL: %s\n", ys->err.msg); + return -1; + } + + // ... do stuff with the response @d + + // 7. Free response + netdev_dev_get_rsp_free(d); + +YNL dumps +--------- + +Performing dumps follows similar pattern as requests. +Dumps return a list of objects terminated by a special marker, +or NULL on error. Use ``ynl_dump_foreach()`` to iterate over +the result. + +YNL notifications +----------------- + +YNL lib supports using the same socket for notifications and +requests. In case notifications arrive during processing of a request +they are queued internally and can be retrieved at a later time. + +To subscribed to notifications use ``ynl_subscribe()``. +The notifications have to be read out from the socket, +``ynl_socket_get_fd()`` returns the underlying socket fd which can +be plugged into appropriate asynchronous IO API like ``poll``, +or ``select``. + +Notifications can be retrieved using ``ynl_ntf_dequeue()`` and have +to be freed using ``ynl_ntf_free()``. Since we don't know the notification +type upfront the notifications are returned as ``struct ynl_ntf_base_type *`` +and user is expected to cast them to the appropriate full type based +on the ``cmd`` member. diff --git a/MAINTAINERS b/MAINTAINERS index c25172d6471a24..f04ff8fa7f0419 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -909,13 +909,6 @@ L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/altera/ -ALTERA TSE PCS -M: Maxime Chevallier -L: netdev@vger.kernel.org -S: Supported -F: drivers/net/pcs/pcs-altera-tse.c -F: include/linux/pcs-altera-tse.h - ALTERA UART/JTAG UART SERIAL DRIVERS M: Tobias Klauser L: linux-serial@vger.kernel.org @@ -956,7 +949,8 @@ F: Documentation/networking/device_drivers/ethernet/amazon/ena.rst F: drivers/net/ethernet/amazon/ AMAZON RDMA EFA DRIVER -M: Gal Pressman +M: Michael Margolin +R: Gal Pressman R: Yossi Leybovich L: linux-rdma@vger.kernel.org S: Supported @@ -1600,7 +1594,7 @@ F: drivers/media/i2c/ar0521.c ARASAN NAND CONTROLLER DRIVER M: Miquel Raynal -M: Naga Sureshkumar Relli +R: Michal Simek L: linux-mtd@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/mtd/arasan,nand-controller.yaml @@ -1677,10 +1671,7 @@ F: drivers/power/reset/arm-versatile-reboot.c F: drivers/soc/versatile/ ARM KOMEDA DRM-KMS DRIVER -M: James (Qian) Wang M: Liviu Dudau -M: Mihail Atanassov -L: Mali DP Maintainers S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/devicetree/bindings/display/arm,komeda.yaml @@ -1701,8 +1692,6 @@ F: include/uapi/drm/panfrost_drm.h ARM MALI-DP DRM DRIVER M: Liviu Dudau -M: Brian Starkey -L: Mali DP Maintainers S: Supported T: git git://anongit.freedesktop.org/drm/drm-misc F: Documentation/devicetree/bindings/display/arm,malidp.yaml @@ -1768,7 +1757,7 @@ F: include/linux/amba/mmci.h ARM PRIMECELL PL35X NAND CONTROLLER DRIVER M: Miquel Raynal -M: Naga Sureshkumar Relli +R: Michal Simek L: linux-mtd@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/mtd/arm,pl353-nand-r2p1.yaml @@ -1776,7 +1765,7 @@ F: drivers/mtd/nand/raw/pl35x-nand-controller.c ARM PRIMECELL PL35X SMC DRIVER M: Miquel Raynal -M: Naga Sureshkumar Relli +R: Michal Simek L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/memory-controllers/arm,pl35x-smc.yaml @@ -2434,6 +2423,15 @@ X: drivers/net/wireless/atmel/ N: at91 N: atmel +ARM/MICROCHIP (ARM64) SoC support +M: Conor Dooley +M: Nicolas Ferre +M: Claudiu Beznea +L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) +S: Supported +T: git https://git.kernel.org/pub/scm/linux/kernel/git/at91/linux.git +F: arch/arm64/boot/dts/microchip/ + ARM/Microchip Sparx5 SoC support M: Lars Povlsen M: Steen Hegelund @@ -2441,8 +2439,7 @@ M: Daniel Machon M: UNGLinuxDriver@microchip.com L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported -T: git git://github.com/microchip-ung/linux-upstream.git -F: arch/arm64/boot/dts/microchip/ +F: arch/arm64/boot/dts/microchip/sparx* F: drivers/net/ethernet/microchip/vcap/ F: drivers/pinctrl/pinctrl-microchip-sgpio.c N: sparx5 @@ -3541,7 +3538,7 @@ F: Documentation/filesystems/befs.rst F: fs/befs/ BFQ I/O SCHEDULER -M: Paolo Valente +M: Paolo Valente M: Jens Axboe L: linux-block@vger.kernel.org S: Maintained @@ -4914,7 +4911,6 @@ F: drivers/media/cec/i2c/ch7322.c CIRRUS LOGIC AUDIO CODEC DRIVERS M: James Schulman M: David Rhodes -M: Lucas Tanure M: Richard Fitzgerald L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: patches@opensource.cirrus.com @@ -5136,7 +5132,7 @@ X: drivers/clk/clkdev.c COMMON INTERNET FILE SYSTEM CLIENT (CIFS and SMB3) M: Steve French -R: Paulo Alcantara (DFS, global name space) +R: Paulo Alcantara (DFS, global name space) R: Ronnie Sahlberg (directory leases, sparse files) R: Shyam Prasad N (multichannel) R: Tom Talpey (RDMA, smbdirect) @@ -5146,8 +5142,8 @@ S: Supported W: https://wiki.samba.org/index.php/LinuxCIFS T: git git://git.samba.org/sfrench/cifs-2.6.git F: Documentation/admin-guide/cifs/ -F: fs/cifs/ -F: fs/smbfs_common/ +F: fs/smb/client/ +F: fs/smb/common/ F: include/uapi/linux/cifs COMPACTPCI HOTPLUG CORE @@ -5725,6 +5721,14 @@ F: include/linux/tfrc.h F: include/uapi/linux/dccp.h F: net/dccp/ +DEBUGOBJECTS: +M: Thomas Gleixner +L: linux-kernel@vger.kernel.org +S: Maintained +T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git core/debugobjects +F: lib/debugobjects.c +F: include/linux/debugobjects.h + DECSTATION PLATFORM SUPPORT M: "Maciej W. Rozycki" L: linux-mips@vger.kernel.org @@ -6012,7 +6016,7 @@ W: http://www.dialog-semiconductor.com/products F: Documentation/devicetree/bindings/input/da90??-onkey.txt F: Documentation/devicetree/bindings/input/dlg,da72??.txt F: Documentation/devicetree/bindings/mfd/da90*.txt -F: Documentation/devicetree/bindings/mfd/da90*.yaml +F: Documentation/devicetree/bindings/mfd/dlg,da90*.yaml F: Documentation/devicetree/bindings/regulator/da92*.txt F: Documentation/devicetree/bindings/regulator/dlg,da9*.yaml F: Documentation/devicetree/bindings/regulator/slg51000.txt @@ -8165,6 +8169,7 @@ F: include/linux/spi/spi-fsl-dspi.h FREESCALE ENETC ETHERNET DRIVERS M: Claudiu Manoil +M: Vladimir Oltean L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/freescale/enetc/ @@ -9346,7 +9351,7 @@ F: include/linux/hisi_acc_qm.h HISILICON ROCE DRIVER M: Haoyue Xu -M: Wenpeng Liang +M: Junxian Huang L: linux-rdma@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/infiniband/hisilicon-hns-roce.txt @@ -10117,7 +10122,7 @@ S: Maintained F: Documentation/process/kernel-docs.rst INDUSTRY PACK SUBSYSTEM (IPACK) -M: Samuel Iglesias Gonsalvez +M: Vaibhav Gupta M: Jens Taprogge M: Greg Kroah-Hartman L: industrypack-devel@lists.sourceforge.net @@ -10345,7 +10350,8 @@ F: Documentation/networking/device_drivers/ethernet/intel/ F: drivers/net/ethernet/intel/ F: drivers/net/ethernet/intel/*/ F: include/linux/avf/virtchnl.h -F: include/linux/net/intel/iidc.h +F: include/linux/net/intel/ +F: include/linux/net/intel/*/ INTEL ETHERNET PROTOCOL DRIVER FOR RDMA M: Mustafa Ismail @@ -11311,9 +11317,9 @@ R: Tom Talpey L: linux-cifs@vger.kernel.org S: Maintained T: git git://git.samba.org/ksmbd.git -F: Documentation/filesystems/cifs/ksmbd.rst -F: fs/ksmbd/ -F: fs/smbfs_common/ +F: Documentation/filesystems/smb/ksmbd.rst +F: fs/smb/common/ +F: fs/smb/server/ KERNEL UNIT TESTING FRAMEWORK (KUnit) M: Brendan Higgins @@ -12840,6 +12846,13 @@ F: Documentation/devicetree/bindings/net/ieee802154/mcr20a.txt F: drivers/net/ieee802154/mcr20a.c F: drivers/net/ieee802154/mcr20a.h +MDIO REGMAP DRIVER +M: Maxime Chevallier +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/mdio/mdio-regmap.c +F: include/linux/mdio/mdio-regmap.h + MEASUREMENT COMPUTING CIO-DAC IIO DRIVER M: William Breathitt Gray L: linux-iio@vger.kernel.org @@ -13139,6 +13152,15 @@ S: Maintained F: drivers/net/pcs/pcs-mtk-lynxi.c F: include/linux/pcs/pcs-mtk-lynxi.h +MEDIATEK ETHERNET PHY DRIVERS +M: Daniel Golle +M: Qingfang Deng +M: SkyLake Huang +L: netdev@vger.kernel.org +S: Maintained +F: drivers/net/phy/mediatek-ge-soc.c +F: drivers/net/phy/mediatek-ge.c + MEDIATEK I2C CONTROLLER DRIVER M: Qii Wang L: linux-i2c@vger.kernel.org @@ -13838,7 +13860,7 @@ F: drivers/tty/serial/8250/8250_pci1xxxx.c MICROCHIP POLARFIRE FPGA DRIVERS M: Conor Dooley -R: Ivan Bornyakov +R: Vladimir Georgiev L: linux-fpga@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/fpga/microchip,mpf-spi-fpga-mgr.yaml @@ -14937,6 +14959,7 @@ F: drivers/ntb/hw/intel/ NTFS FILESYSTEM M: Anton Altaparmakov +R: Namjae Jeon L: linux-ntfs-dev@lists.sourceforge.net S: Supported W: http://www.tuxera.com/ @@ -18584,10 +18607,9 @@ F: Documentation/admin-guide/LSM/SafeSetID.rst F: security/safesetid/ SAMSUNG AUDIO (ASoC) DRIVERS -M: Krzysztof Kozlowski M: Sylwester Nawrocki L: alsa-devel@alsa-project.org (moderated for non-subscribers) -S: Supported +S: Maintained B: mailto:linux-samsung-soc@vger.kernel.org F: Documentation/devicetree/bindings/sound/samsung* F: sound/soc/samsung/ @@ -18715,7 +18737,6 @@ F: include/dt-bindings/clock/samsung,*.h F: include/linux/clk/samsung.h SAMSUNG SPI DRIVERS -M: Krzysztof Kozlowski M: Andi Shyti L: linux-spi@vger.kernel.org L: linux-samsung-soc@vger.kernel.org @@ -23133,6 +23154,7 @@ F: drivers/iio/adc/xilinx-ams.c XILINX AXI ETHERNET DRIVER M: Radhey Shyam Pandey S: Maintained +F: Documentation/devicetree/bindings/net/xlnx,axi-ethernet.yaml F: drivers/net/ethernet/xilinx/xilinx_axienet* XILINX CAN DRIVER diff --git a/Makefile b/Makefile index f836936fb4d8b9..09866a85bc2a21 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 6 PATCHLEVEL = 4 SUBLEVEL = 0 -EXTRAVERSION = -rc2 +EXTRAVERSION = -rc5 NAME = Hurr durr I'ma ninja sloth # *DOCUMENTATION* diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h index 739891b9413653..e94f621903feed 100644 --- a/arch/alpha/include/uapi/asm/socket.h +++ b/arch/alpha/include/uapi/asm/socket.h @@ -137,6 +137,9 @@ #define SO_RCVMARK 75 +#define SO_PASSPIDFD 76 +#define SO_PEERPIDFD 77 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/arm/boot/dts/imx6qdl-mba6.dtsi b/arch/arm/boot/dts/imx6qdl-mba6.dtsi index 78555a6188510f..7b7e6c2ad190c8 100644 --- a/arch/arm/boot/dts/imx6qdl-mba6.dtsi +++ b/arch/arm/boot/dts/imx6qdl-mba6.dtsi @@ -209,6 +209,7 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_pcie>; reset-gpio = <&gpio6 7 GPIO_ACTIVE_LOW>; + vpcie-supply = <®_pcie>; status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi b/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi index 5882c7565f6495..32a6022625d979 100644 --- a/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi +++ b/arch/arm/boot/dts/imx6ull-dhcor-som.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include #include "imx6ull.dtsi" / { @@ -84,16 +85,20 @@ regulators { vdd_soc_in_1v4: buck1 { + regulator-allowed-modes = ; /* PFM */ regulator-always-on; regulator-boot-on; + regulator-initial-mode = ; regulator-max-microvolt = <1400000>; regulator-min-microvolt = <1400000>; regulator-name = "vdd_soc_in_1v4"; }; vcc_3v3: buck2 { + regulator-allowed-modes = ; /* PWM */ regulator-always-on; regulator-boot-on; + regulator-initial-mode = ; regulator-max-microvolt = <3300000>; regulator-min-microvolt = <3300000>; regulator-name = "vcc_3v3"; @@ -106,8 +111,10 @@ * the voltage is set to 1.5V. */ vcc_ddr_1v35: buck3 { + regulator-allowed-modes = ; /* PWM */ regulator-always-on; regulator-boot-on; + regulator-initial-mode = ; regulator-max-microvolt = <1500000>; regulator-min-microvolt = <1500000>; regulator-name = "vcc_ddr_1v35"; diff --git a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts index 3b88209bacea2f..ff1f9a1bcfcfc3 100644 --- a/arch/arm/boot/dts/vexpress-v2p-ca5s.dts +++ b/arch/arm/boot/dts/vexpress-v2p-ca5s.dts @@ -132,6 +132,7 @@ reg = <0x2c0f0000 0x1000>; interrupts = <0 84 4>; cache-level = <2>; + cache-unified; }; pmu { diff --git a/arch/arm/include/asm/arm_pmuv3.h b/arch/arm/include/asm/arm_pmuv3.h index 78d3d4b82c6c25..f4db3e75d75f02 100644 --- a/arch/arm/include/asm/arm_pmuv3.h +++ b/arch/arm/include/asm/arm_pmuv3.h @@ -92,7 +92,7 @@ #define RETURN_READ_PMEVCNTRN(n) \ return read_sysreg(PMEVCNTR##n) -static unsigned long read_pmevcntrn(int n) +static inline unsigned long read_pmevcntrn(int n) { PMEVN_SWITCH(n, RETURN_READ_PMEVCNTRN); return 0; @@ -100,14 +100,14 @@ static unsigned long read_pmevcntrn(int n) #define WRITE_PMEVCNTRN(n) \ write_sysreg(val, PMEVCNTR##n) -static void write_pmevcntrn(int n, unsigned long val) +static inline void write_pmevcntrn(int n, unsigned long val) { PMEVN_SWITCH(n, WRITE_PMEVCNTRN); } #define WRITE_PMEVTYPERN(n) \ write_sysreg(val, PMEVTYPER##n) -static void write_pmevtypern(int n, unsigned long val) +static inline void write_pmevtypern(int n, unsigned long val) { PMEVN_SWITCH(n, WRITE_PMEVTYPERN); } diff --git a/arch/arm64/boot/dts/arm/foundation-v8.dtsi b/arch/arm64/boot/dts/arm/foundation-v8.dtsi index 029578072d8fb4..7b41537731a6ae 100644 --- a/arch/arm64/boot/dts/arm/foundation-v8.dtsi +++ b/arch/arm64/boot/dts/arm/foundation-v8.dtsi @@ -59,6 +59,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts index ef68f5aae7ddf7..afdf954206f1d1 100644 --- a/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts +++ b/arch/arm64/boot/dts/arm/rtsm_ve-aemv8a.dts @@ -72,6 +72,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts index 796cd7d02eb55a..7bdeb965f0a964 100644 --- a/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts +++ b/arch/arm64/boot/dts/arm/vexpress-v2f-1xv7-ca53x2.dts @@ -58,6 +58,7 @@ L2_0: l2-cache0 { compatible = "cache"; cache-level = <2>; + cache-unified; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi index 2209c1ac6e9b01..e62a43591361b3 100644 --- a/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8-ss-conn.dtsi @@ -171,6 +171,7 @@ conn_subsys: bus@5b000000 { interrupt-names = "host", "peripheral", "otg", "wakeup"; phys = <&usb3_phy>; phy-names = "cdns3,usb3-phy"; + cdns,on-chip-buff-size = /bits/ 16 <18>; status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi index 67072e6c77d5fb..cbd9d124c80d09 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi @@ -98,11 +98,17 @@ #address-cells = <1>; #size-cells = <0>; - ethphy: ethernet-phy@4 { + ethphy: ethernet-phy@4 { /* AR8033 or ADIN1300 */ compatible = "ethernet-phy-ieee802.3-c22"; reg = <4>; reset-gpios = <&gpio1 9 GPIO_ACTIVE_LOW>; reset-assert-us = <10000>; + /* + * Deassert delay: + * ADIN1300 requires 5ms. + * AR8033 requires 1ms. + */ + reset-deassert-us = <20000>; }; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mn.dtsi b/arch/arm64/boot/dts/freescale/imx8mn.dtsi index bd84db55005313..8be8f090e8b8e9 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn.dtsi @@ -1069,13 +1069,6 @@ <&clk IMX8MN_CLK_DISP_APB_ROOT>, <&clk IMX8MN_CLK_DISP_AXI_ROOT>; clock-names = "pix", "axi", "disp_axi"; - assigned-clocks = <&clk IMX8MN_CLK_DISP_PIXEL_ROOT>, - <&clk IMX8MN_CLK_DISP_AXI>, - <&clk IMX8MN_CLK_DISP_APB>; - assigned-clock-parents = <&clk IMX8MN_CLK_DISP_PIXEL>, - <&clk IMX8MN_SYS_PLL2_1000M>, - <&clk IMX8MN_SYS_PLL1_800M>; - assigned-clock-rates = <594000000>, <500000000>, <200000000>; interrupts = ; power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_LCDIF>; status = "disabled"; @@ -1093,12 +1086,6 @@ clocks = <&clk IMX8MN_CLK_DSI_CORE>, <&clk IMX8MN_CLK_DSI_PHY_REF>; clock-names = "bus_clk", "sclk_mipi"; - assigned-clocks = <&clk IMX8MN_CLK_DSI_CORE>, - <&clk IMX8MN_CLK_DSI_PHY_REF>; - assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>, - <&clk IMX8MN_CLK_24M>; - assigned-clock-rates = <266000000>, <24000000>; - samsung,pll-clock-frequency = <24000000>; interrupts = ; power-domains = <&disp_blk_ctrl IMX8MN_DISPBLK_PD_MIPI_DSI>; status = "disabled"; @@ -1142,6 +1129,21 @@ "lcdif-axi", "lcdif-apb", "lcdif-pix", "dsi-pclk", "dsi-ref", "csi-aclk", "csi-pclk"; + assigned-clocks = <&clk IMX8MN_CLK_DSI_CORE>, + <&clk IMX8MN_CLK_DSI_PHY_REF>, + <&clk IMX8MN_CLK_DISP_PIXEL>, + <&clk IMX8MN_CLK_DISP_AXI>, + <&clk IMX8MN_CLK_DISP_APB>; + assigned-clock-parents = <&clk IMX8MN_SYS_PLL1_266M>, + <&clk IMX8MN_CLK_24M>, + <&clk IMX8MN_VIDEO_PLL1_OUT>, + <&clk IMX8MN_SYS_PLL2_1000M>, + <&clk IMX8MN_SYS_PLL1_800M>; + assigned-clock-rates = <266000000>, + <24000000>, + <594000000>, + <500000000>, + <200000000>; #power-domain-cells = <1>; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi index f81391993354f4..428c60462e3d6b 100644 --- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi @@ -1211,13 +1211,6 @@ <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; clock-names = "pix", "axi", "disp_axi"; - assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX_ROOT>, - <&clk IMX8MP_CLK_MEDIA_AXI>, - <&clk IMX8MP_CLK_MEDIA_APB>; - assigned-clock-parents = <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>, - <&clk IMX8MP_SYS_PLL2_1000M>, - <&clk IMX8MP_SYS_PLL1_800M>; - assigned-clock-rates = <594000000>, <500000000>, <200000000>; interrupts = ; power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_1>; status = "disabled"; @@ -1237,11 +1230,6 @@ <&clk IMX8MP_CLK_MEDIA_APB_ROOT>, <&clk IMX8MP_CLK_MEDIA_AXI_ROOT>; clock-names = "pix", "axi", "disp_axi"; - assigned-clocks = <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>, - <&clk IMX8MP_VIDEO_PLL1>; - assigned-clock-parents = <&clk IMX8MP_VIDEO_PLL1_OUT>, - <&clk IMX8MP_VIDEO_PLL1_REF_SEL>; - assigned-clock-rates = <0>, <1039500000>; power-domains = <&media_blk_ctrl IMX8MP_MEDIABLK_PD_LCDIF_2>; status = "disabled"; @@ -1296,11 +1284,16 @@ "disp1", "disp2", "isp", "phy"; assigned-clocks = <&clk IMX8MP_CLK_MEDIA_AXI>, - <&clk IMX8MP_CLK_MEDIA_APB>; + <&clk IMX8MP_CLK_MEDIA_APB>, + <&clk IMX8MP_CLK_MEDIA_DISP1_PIX>, + <&clk IMX8MP_CLK_MEDIA_DISP2_PIX>, + <&clk IMX8MP_VIDEO_PLL1>; assigned-clock-parents = <&clk IMX8MP_SYS_PLL2_1000M>, - <&clk IMX8MP_SYS_PLL1_800M>; - assigned-clock-rates = <500000000>, <200000000>; - + <&clk IMX8MP_SYS_PLL1_800M>, + <&clk IMX8MP_VIDEO_PLL1_OUT>, + <&clk IMX8MP_VIDEO_PLL1_OUT>; + assigned-clock-rates = <500000000>, <200000000>, + <0>, <0>, <1039500000>; #power-domain-cells = <1>; lvds_bridge: bridge@5c { diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi index 7264d784ae723c..9af769ab8cebbd 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri-eval-v3.dtsi @@ -33,6 +33,12 @@ }; }; +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ext_io0>, <&pinctrl_hog0>, <&pinctrl_hog1>, + <&pinctrl_lpspi2_cs2>; +}; + /* Colibri SPI */ &lpspi2 { status = "okay"; diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi index 5f30c88855e707..f8953067bc3bb8 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri-iris.dtsi @@ -48,8 +48,7 @@ , /* SODIMM 101 */ , /* SODIMM 97 */ , /* SODIMM 85 */ - , /* SODIMM 79 */ - ; /* SODIMM 45 */ + ; /* SODIMM 79 */ }; pinctrl_uart1_forceoff: uart1forceoffgrp { diff --git a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi index 7cad79102e1afe..49d105eb476919 100644 --- a/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8x-colibri.dtsi @@ -363,10 +363,6 @@ /* TODO VPU Encoder/Decoder */ &iomuxc { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ext_io0>, <&pinctrl_hog0>, <&pinctrl_hog1>, - <&pinctrl_hog2>, <&pinctrl_lpspi2_cs2>; - /* On-module touch pen-down interrupt */ pinctrl_ad7879_int: ad7879intgrp { fsl,pins = ; @@ -499,8 +495,7 @@ }; pinctrl_hog1: hog1grp { - fsl,pins = , /* SODIMM 75 */ - ; /* SODIMM 93 */ + fsl,pins = ; /* SODIMM 93 */ }; pinctrl_hog2: hog2grp { @@ -774,3 +769,10 @@ fsl,pins = ; }; }; + +/* Delete peripherals which are not present on SOC, but are defined in imx8-ss-*.dtsi */ + +/delete-node/ &adc1; +/delete-node/ &adc1_lpcg; +/delete-node/ &dsp; +/delete-node/ &dsp_lpcg; diff --git a/arch/arm64/include/asm/arm_pmuv3.h b/arch/arm64/include/asm/arm_pmuv3.h index d6b51deb7bf0ff..18dc2fb3d7b7b2 100644 --- a/arch/arm64/include/asm/arm_pmuv3.h +++ b/arch/arm64/include/asm/arm_pmuv3.h @@ -13,7 +13,7 @@ #define RETURN_READ_PMEVCNTRN(n) \ return read_sysreg(pmevcntr##n##_el0) -static unsigned long read_pmevcntrn(int n) +static inline unsigned long read_pmevcntrn(int n) { PMEVN_SWITCH(n, RETURN_READ_PMEVCNTRN); return 0; @@ -21,14 +21,14 @@ static unsigned long read_pmevcntrn(int n) #define WRITE_PMEVCNTRN(n) \ write_sysreg(val, pmevcntr##n##_el0) -static void write_pmevcntrn(int n, unsigned long val) +static inline void write_pmevcntrn(int n, unsigned long val) { PMEVN_SWITCH(n, WRITE_PMEVCNTRN); } #define WRITE_PMEVTYPERN(n) \ write_sysreg(val, pmevtyper##n##_el0) -static void write_pmevtypern(int n, unsigned long val) +static inline void write_pmevtypern(int n, unsigned long val) { PMEVN_SWITCH(n, WRITE_PMEVTYPERN); } diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h index 683ca3af408485..5f6f84837a4903 100644 --- a/arch/arm64/include/asm/cputype.h +++ b/arch/arm64/include/asm/cputype.h @@ -126,6 +126,10 @@ #define APPLE_CPU_PART_M1_FIRESTORM_MAX 0x029 #define APPLE_CPU_PART_M2_BLIZZARD 0x032 #define APPLE_CPU_PART_M2_AVALANCHE 0x033 +#define APPLE_CPU_PART_M2_BLIZZARD_PRO 0x034 +#define APPLE_CPU_PART_M2_AVALANCHE_PRO 0x035 +#define APPLE_CPU_PART_M2_BLIZZARD_MAX 0x038 +#define APPLE_CPU_PART_M2_AVALANCHE_MAX 0x039 #define AMPERE_CPU_PART_AMPERE1 0xAC3 @@ -181,6 +185,10 @@ #define MIDR_APPLE_M1_FIRESTORM_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M1_FIRESTORM_MAX) #define MIDR_APPLE_M2_BLIZZARD MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD) #define MIDR_APPLE_M2_AVALANCHE MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE) +#define MIDR_APPLE_M2_BLIZZARD_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_PRO) +#define MIDR_APPLE_M2_AVALANCHE_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_PRO) +#define MIDR_APPLE_M2_BLIZZARD_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_BLIZZARD_MAX) +#define MIDR_APPLE_M2_AVALANCHE_MAX MIDR_CPU_MODEL(ARM_CPU_IMP_APPLE, APPLE_CPU_PART_M2_AVALANCHE_MAX) #define MIDR_AMPERE1 MIDR_CPU_MODEL(ARM_CPU_IMP_AMPERE, AMPERE_CPU_PART_AMPERE1) /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index 4cd6762bda805d..93bd0975b15f55 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -209,6 +209,7 @@ struct kvm_pgtable_visit_ctx { kvm_pte_t old; void *arg; struct kvm_pgtable_mm_ops *mm_ops; + u64 start; u64 addr; u64 end; u32 level; @@ -631,9 +632,9 @@ int kvm_pgtable_stage2_flush(struct kvm_pgtable *pgt, u64 addr, u64 size); * * The walker will walk the page-table entries corresponding to the input * address range specified, visiting entries according to the walker flags. - * Invalid entries are treated as leaf entries. Leaf entries are reloaded - * after invoking the walker callback, allowing the walker to descend into - * a newly installed table. + * Invalid entries are treated as leaf entries. The visited page table entry is + * reloaded after invoking the walker callback, allowing the walker to descend + * into a newly installed table. * * Returning a negative error code from the walker callback function will * terminate the walk immediately with the same error code. diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index e72d9aaab6b1b6..eefd712f243035 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -115,8 +115,14 @@ #define SB_BARRIER_INSN __SYS_BARRIER_INSN(0, 7, 31) #define SYS_DC_ISW sys_insn(1, 0, 7, 6, 2) +#define SYS_DC_IGSW sys_insn(1, 0, 7, 6, 4) +#define SYS_DC_IGDSW sys_insn(1, 0, 7, 6, 6) #define SYS_DC_CSW sys_insn(1, 0, 7, 10, 2) +#define SYS_DC_CGSW sys_insn(1, 0, 7, 10, 4) +#define SYS_DC_CGDSW sys_insn(1, 0, 7, 10, 6) #define SYS_DC_CISW sys_insn(1, 0, 7, 14, 2) +#define SYS_DC_CIGSW sys_insn(1, 0, 7, 14, 4) +#define SYS_DC_CIGDSW sys_insn(1, 0, 7, 14, 6) /* * Automatically generated definitions for system registers, the diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c index f5bcb0dc626738..7e89968bd28244 100644 --- a/arch/arm64/kernel/mte.c +++ b/arch/arm64/kernel/mte.c @@ -66,13 +66,10 @@ void mte_sync_tags(pte_t old_pte, pte_t pte) return; /* if PG_mte_tagged is set, tags have already been initialised */ - for (i = 0; i < nr_pages; i++, page++) { - if (!page_mte_tagged(page)) { + for (i = 0; i < nr_pages; i++, page++) + if (!page_mte_tagged(page)) mte_sync_page_tags(page, old_pte, check_swap, pte_is_tagged); - set_page_mte_tagged(page); - } - } /* ensure the tags are visible before the PTE is set */ smp_wmb(); diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index 0119dc91abb5db..d9e1355730ef58 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -288,7 +288,7 @@ static int aarch32_alloc_kuser_vdso_page(void) memcpy((void *)(vdso_page + 0x1000 - kuser_sz), __kuser_helper_start, kuser_sz); - aarch32_vectors_page = virt_to_page(vdso_page); + aarch32_vectors_page = virt_to_page((void *)vdso_page); return 0; } diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c index 1279949599b5fc..4c9dcd8fc93950 100644 --- a/arch/arm64/kvm/fpsimd.c +++ b/arch/arm64/kvm/fpsimd.c @@ -81,26 +81,34 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu) fpsimd_kvm_prepare(); + /* + * We will check TIF_FOREIGN_FPSTATE just before entering the + * guest in kvm_arch_vcpu_ctxflush_fp() and override this to + * FP_STATE_FREE if the flag set. + */ vcpu->arch.fp_state = FP_STATE_HOST_OWNED; vcpu_clear_flag(vcpu, HOST_SVE_ENABLED); if (read_sysreg(cpacr_el1) & CPACR_EL1_ZEN_EL0EN) vcpu_set_flag(vcpu, HOST_SVE_ENABLED); - /* - * We don't currently support SME guests but if we leave - * things in streaming mode then when the guest starts running - * FPSIMD or SVE code it may generate SME traps so as a - * special case if we are in streaming mode we force the host - * state to be saved now and exit streaming mode so that we - * don't have to handle any SME traps for valid guest - * operations. Do this for ZA as well for now for simplicity. - */ if (system_supports_sme()) { vcpu_clear_flag(vcpu, HOST_SME_ENABLED); if (read_sysreg(cpacr_el1) & CPACR_EL1_SMEN_EL0EN) vcpu_set_flag(vcpu, HOST_SME_ENABLED); + /* + * If PSTATE.SM is enabled then save any pending FP + * state and disable PSTATE.SM. If we leave PSTATE.SM + * enabled and the guest does not enable SME via + * CPACR_EL1.SMEN then operations that should be valid + * may generate SME traps from EL1 to EL1 which we + * can't intercept and which would confuse the guest. + * + * Do the same for PSTATE.ZA in the case where there + * is state in the registers which has not already + * been saved, this is very unlikely to happen. + */ if (read_sysreg_s(SYS_SVCR) & (SVCR_SM_MASK | SVCR_ZA_MASK)) { vcpu->arch.fp_state = FP_STATE_FREE; fpsimd_save_and_flush_cpu_state(); diff --git a/arch/arm64/kvm/hyp/include/hyp/switch.h b/arch/arm64/kvm/hyp/include/hyp/switch.h index c41166f1a1dd7d..5c15c58f90cceb 100644 --- a/arch/arm64/kvm/hyp/include/hyp/switch.h +++ b/arch/arm64/kvm/hyp/include/hyp/switch.h @@ -177,9 +177,17 @@ static bool kvm_hyp_handle_fpsimd(struct kvm_vcpu *vcpu, u64 *exit_code) sve_guest = vcpu_has_sve(vcpu); esr_ec = kvm_vcpu_trap_get_class(vcpu); - /* Don't handle SVE traps for non-SVE vcpus here: */ - if (!sve_guest && esr_ec != ESR_ELx_EC_FP_ASIMD) + /* Only handle traps the vCPU can support here: */ + switch (esr_ec) { + case ESR_ELx_EC_FP_ASIMD: + break; + case ESR_ELx_EC_SVE: + if (!sve_guest) + return false; + break; + default: return false; + } /* Valid trap. Switch the context: */ @@ -404,17 +412,21 @@ static bool kvm_hyp_handle_cp15_32(struct kvm_vcpu *vcpu, u64 *exit_code) return false; } -static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) +static bool kvm_hyp_handle_memory_fault(struct kvm_vcpu *vcpu, u64 *exit_code) { if (!__populate_fault_info(vcpu)) return true; return false; } +static bool kvm_hyp_handle_iabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) + __alias(kvm_hyp_handle_memory_fault); +static bool kvm_hyp_handle_watchpt_low(struct kvm_vcpu *vcpu, u64 *exit_code) + __alias(kvm_hyp_handle_memory_fault); static bool kvm_hyp_handle_dabt_low(struct kvm_vcpu *vcpu, u64 *exit_code) { - if (!__populate_fault_info(vcpu)) + if (kvm_hyp_handle_memory_fault(vcpu, exit_code)) return true; if (static_branch_unlikely(&vgic_v2_cpuif_trap)) { diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 2e9ec4a2a4a323..a8813b2129966d 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -575,7 +575,7 @@ struct pkvm_mem_donation { struct check_walk_data { enum pkvm_page_state desired; - enum pkvm_page_state (*get_page_state)(kvm_pte_t pte); + enum pkvm_page_state (*get_page_state)(kvm_pte_t pte, u64 addr); }; static int __check_page_state_visitor(const struct kvm_pgtable_visit_ctx *ctx, @@ -583,10 +583,7 @@ static int __check_page_state_visitor(const struct kvm_pgtable_visit_ctx *ctx, { struct check_walk_data *d = ctx->arg; - if (kvm_pte_valid(ctx->old) && !addr_is_allowed_memory(kvm_pte_to_phys(ctx->old))) - return -EINVAL; - - return d->get_page_state(ctx->old) == d->desired ? 0 : -EPERM; + return d->get_page_state(ctx->old, ctx->addr) == d->desired ? 0 : -EPERM; } static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size, @@ -601,8 +598,11 @@ static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size, return kvm_pgtable_walk(pgt, addr, size, &walker); } -static enum pkvm_page_state host_get_page_state(kvm_pte_t pte) +static enum pkvm_page_state host_get_page_state(kvm_pte_t pte, u64 addr) { + if (!addr_is_allowed_memory(addr)) + return PKVM_NOPAGE; + if (!kvm_pte_valid(pte) && pte) return PKVM_NOPAGE; @@ -709,7 +709,7 @@ static int host_complete_donation(u64 addr, const struct pkvm_mem_transition *tx return host_stage2_set_owner_locked(addr, size, host_id); } -static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte) +static enum pkvm_page_state hyp_get_page_state(kvm_pte_t pte, u64 addr) { if (!kvm_pte_valid(pte)) return PKVM_NOPAGE; diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c index 71fa16a0dc7758..77791495c9951d 100644 --- a/arch/arm64/kvm/hyp/nvhe/switch.c +++ b/arch/arm64/kvm/hyp/nvhe/switch.c @@ -186,6 +186,7 @@ static const exit_handler_fn hyp_exit_handlers[] = { [ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd, [ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low, [ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low, + [ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low, [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth, }; @@ -196,6 +197,7 @@ static const exit_handler_fn pvm_exit_handlers[] = { [ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd, [ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low, [ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low, + [ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low, [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth, }; diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 3d61bd3e591d27..95dae02ccc2e60 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -58,8 +58,9 @@ struct kvm_pgtable_walk_data { struct kvm_pgtable_walker *walker; + const u64 start; u64 addr; - u64 end; + const u64 end; }; static bool kvm_phys_is_valid(u64 phys) @@ -201,20 +202,33 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data, .old = READ_ONCE(*ptep), .arg = data->walker->arg, .mm_ops = mm_ops, + .start = data->start, .addr = data->addr, .end = data->end, .level = level, .flags = flags, }; int ret = 0; + bool reload = false; kvm_pteref_t childp; bool table = kvm_pte_table(ctx.old, level); - if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE)) + if (table && (ctx.flags & KVM_PGTABLE_WALK_TABLE_PRE)) { ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_TABLE_PRE); + reload = true; + } if (!table && (ctx.flags & KVM_PGTABLE_WALK_LEAF)) { ret = kvm_pgtable_visitor_cb(data, &ctx, KVM_PGTABLE_WALK_LEAF); + reload = true; + } + + /* + * Reload the page table after invoking the walker callback for leaf + * entries or after pre-order traversal, to allow the walker to descend + * into a newly installed or replaced table. + */ + if (reload) { ctx.old = READ_ONCE(*ptep); table = kvm_pte_table(ctx.old, level); } @@ -293,6 +307,7 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size, struct kvm_pgtable_walker *walker) { struct kvm_pgtable_walk_data walk_data = { + .start = ALIGN_DOWN(addr, PAGE_SIZE), .addr = ALIGN_DOWN(addr, PAGE_SIZE), .end = PAGE_ALIGN(walk_data.addr + size), .walker = walker, @@ -349,7 +364,7 @@ int kvm_pgtable_get_leaf(struct kvm_pgtable *pgt, u64 addr, } struct hyp_map_data { - u64 phys; + const u64 phys; kvm_pte_t attr; }; @@ -407,13 +422,12 @@ enum kvm_pgtable_prot kvm_pgtable_hyp_pte_prot(kvm_pte_t pte) static bool hyp_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx, struct hyp_map_data *data) { + u64 phys = data->phys + (ctx->addr - ctx->start); kvm_pte_t new; - u64 granule = kvm_granule_size(ctx->level), phys = data->phys; if (!kvm_block_mapping_supported(ctx, phys)) return false; - data->phys += granule; new = kvm_init_valid_leaf_pte(phys, data->attr, ctx->level); if (ctx->old == new) return true; @@ -576,7 +590,7 @@ void kvm_pgtable_hyp_destroy(struct kvm_pgtable *pgt) } struct stage2_map_data { - u64 phys; + const u64 phys; kvm_pte_t attr; u8 owner_id; @@ -794,20 +808,43 @@ static bool stage2_pte_executable(kvm_pte_t pte) return !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN); } +static u64 stage2_map_walker_phys_addr(const struct kvm_pgtable_visit_ctx *ctx, + const struct stage2_map_data *data) +{ + u64 phys = data->phys; + + /* + * Stage-2 walks to update ownership data are communicated to the map + * walker using an invalid PA. Avoid offsetting an already invalid PA, + * which could overflow and make the address valid again. + */ + if (!kvm_phys_is_valid(phys)) + return phys; + + /* + * Otherwise, work out the correct PA based on how far the walk has + * gotten. + */ + return phys + (ctx->addr - ctx->start); +} + static bool stage2_leaf_mapping_allowed(const struct kvm_pgtable_visit_ctx *ctx, struct stage2_map_data *data) { + u64 phys = stage2_map_walker_phys_addr(ctx, data); + if (data->force_pte && (ctx->level < (KVM_PGTABLE_MAX_LEVELS - 1))) return false; - return kvm_block_mapping_supported(ctx, data->phys); + return kvm_block_mapping_supported(ctx, phys); } static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx, struct stage2_map_data *data) { kvm_pte_t new; - u64 granule = kvm_granule_size(ctx->level), phys = data->phys; + u64 phys = stage2_map_walker_phys_addr(ctx, data); + u64 granule = kvm_granule_size(ctx->level); struct kvm_pgtable *pgt = data->mmu->pgt; struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops; @@ -841,8 +878,6 @@ static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx, stage2_make_pte(ctx, new); - if (kvm_phys_is_valid(phys)) - data->phys += granule; return 0; } @@ -1297,4 +1332,7 @@ void kvm_pgtable_stage2_free_removed(struct kvm_pgtable_mm_ops *mm_ops, void *pg }; WARN_ON(__kvm_pgtable_walk(&data, mm_ops, ptep, level + 1)); + + WARN_ON(mm_ops->page_count(pgtable) != 1); + mm_ops->put_page(pgtable); } diff --git a/arch/arm64/kvm/hyp/vhe/switch.c b/arch/arm64/kvm/hyp/vhe/switch.c index 3d868e84c7a0a3..7a1aa511e7da6f 100644 --- a/arch/arm64/kvm/hyp/vhe/switch.c +++ b/arch/arm64/kvm/hyp/vhe/switch.c @@ -110,6 +110,7 @@ static const exit_handler_fn hyp_exit_handlers[] = { [ESR_ELx_EC_FP_ASIMD] = kvm_hyp_handle_fpsimd, [ESR_ELx_EC_IABT_LOW] = kvm_hyp_handle_iabt_low, [ESR_ELx_EC_DABT_LOW] = kvm_hyp_handle_dabt_low, + [ESR_ELx_EC_WATCHPT_LOW] = kvm_hyp_handle_watchpt_low, [ESR_ELx_EC_PAC] = kvm_hyp_handle_ptrauth, }; diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index 64c3aec0d937c3..0bd93a5f21ce38 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -204,7 +204,7 @@ void kvm_inject_size_fault(struct kvm_vcpu *vcpu) * Size Fault at level 0, as if exceeding PARange. * * Non-LPAE guests will only get the external abort, as there - * is no way to to describe the ASF. + * is no way to describe the ASF. */ if (vcpu_el1_is_32bit(vcpu) && !(vcpu_read_sys_reg(vcpu, TCR_EL1) & TTBCR_EAE)) diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 45727d50d18dd9..491ca7eb2a4c6e 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -694,45 +694,23 @@ void kvm_host_pmu_init(struct arm_pmu *pmu) static struct arm_pmu *kvm_pmu_probe_armpmu(void) { - struct perf_event_attr attr = { }; - struct perf_event *event; - struct arm_pmu *pmu = NULL; - - /* - * Create a dummy event that only counts user cycles. As we'll never - * leave this function with the event being live, it will never - * count anything. But it allows us to probe some of the PMU - * details. Yes, this is terrible. - */ - attr.type = PERF_TYPE_RAW; - attr.size = sizeof(attr); - attr.pinned = 1; - attr.disabled = 0; - attr.exclude_user = 0; - attr.exclude_kernel = 1; - attr.exclude_hv = 1; - attr.exclude_host = 1; - attr.config = ARMV8_PMUV3_PERFCTR_CPU_CYCLES; - attr.sample_period = GENMASK(63, 0); + struct arm_pmu *tmp, *pmu = NULL; + struct arm_pmu_entry *entry; + int cpu; - event = perf_event_create_kernel_counter(&attr, -1, current, - kvm_pmu_perf_overflow, &attr); + mutex_lock(&arm_pmus_lock); - if (IS_ERR(event)) { - pr_err_once("kvm: pmu event creation failed %ld\n", - PTR_ERR(event)); - return NULL; - } + cpu = smp_processor_id(); + list_for_each_entry(entry, &arm_pmus, entry) { + tmp = entry->arm_pmu; - if (event->pmu) { - pmu = to_arm_pmu(event->pmu); - if (pmu->pmuver == ID_AA64DFR0_EL1_PMUVer_NI || - pmu->pmuver == ID_AA64DFR0_EL1_PMUVer_IMP_DEF) - pmu = NULL; + if (cpumask_test_cpu(cpu, &tmp->supported_cpus)) { + pmu = tmp; + break; + } } - perf_event_disable(event); - perf_event_release_kernel(event); + mutex_unlock(&arm_pmus_lock); return pmu; } @@ -912,7 +890,17 @@ int kvm_arm_pmu_v3_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr) return -EBUSY; if (!kvm->arch.arm_pmu) { - /* No PMU set, get the default one */ + /* + * No PMU set, get the default one. + * + * The observant among you will notice that the supported_cpus + * mask does not get updated for the default PMU even though it + * is quite possible the selected instance supports only a + * subset of cores in the system. This is intentional, and + * upholds the preexisting behavior on heterogeneous systems + * where vCPUs can be scheduled on any core but the guest + * counters could stop working. + */ kvm->arch.arm_pmu = kvm_pmu_probe_armpmu(); if (!kvm->arch.arm_pmu) return -ENODEV; diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 71b12094d61370..753aa741814977 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -211,6 +211,19 @@ static bool access_dcsw(struct kvm_vcpu *vcpu, return true; } +static bool access_dcgsw(struct kvm_vcpu *vcpu, + struct sys_reg_params *p, + const struct sys_reg_desc *r) +{ + if (!kvm_has_mte(vcpu->kvm)) { + kvm_inject_undefined(vcpu); + return false; + } + + /* Treat MTE S/W ops as we treat the classic ones: with contempt */ + return access_dcsw(vcpu, p, r); +} + static void get_access_mask(const struct sys_reg_desc *r, u64 *mask, u64 *shift) { switch (r->aarch32_map) { @@ -1756,8 +1769,14 @@ static bool access_spsr(struct kvm_vcpu *vcpu, */ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_DC_ISW), access_dcsw }, + { SYS_DESC(SYS_DC_IGSW), access_dcgsw }, + { SYS_DESC(SYS_DC_IGDSW), access_dcgsw }, { SYS_DESC(SYS_DC_CSW), access_dcsw }, + { SYS_DESC(SYS_DC_CGSW), access_dcgsw }, + { SYS_DESC(SYS_DC_CGDSW), access_dcgsw }, { SYS_DESC(SYS_DC_CISW), access_dcsw }, + { SYS_DESC(SYS_DC_CIGSW), access_dcgsw }, + { SYS_DESC(SYS_DC_CIGDSW), access_dcgsw }, DBG_BCR_BVR_WCR_WVR_EL1(0), DBG_BCR_BVR_WCR_WVR_EL1(1), diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index 9d42c7cb2b5882..6eafc2c45cfcf7 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -235,9 +235,9 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) * KVM io device for the redistributor that belongs to this VCPU. */ if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) { - mutex_lock(&vcpu->kvm->arch.config_lock); + mutex_lock(&vcpu->kvm->slots_lock); ret = vgic_register_redist_iodev(vcpu); - mutex_unlock(&vcpu->kvm->arch.config_lock); + mutex_unlock(&vcpu->kvm->slots_lock); } return ret; } @@ -406,7 +406,7 @@ void kvm_vgic_destroy(struct kvm *kvm) /** * vgic_lazy_init: Lazy init is only allowed if the GIC exposed to the guest - * is a GICv2. A GICv3 must be explicitly initialized by the guest using the + * is a GICv2. A GICv3 must be explicitly initialized by userspace using the * KVM_DEV_ARM_VGIC_GRP_CTRL KVM_DEVICE group. * @kvm: kvm struct pointer */ @@ -446,11 +446,13 @@ int vgic_lazy_init(struct kvm *kvm) int kvm_vgic_map_resources(struct kvm *kvm) { struct vgic_dist *dist = &kvm->arch.vgic; + gpa_t dist_base; int ret = 0; if (likely(vgic_ready(kvm))) return 0; + mutex_lock(&kvm->slots_lock); mutex_lock(&kvm->arch.config_lock); if (vgic_ready(kvm)) goto out; @@ -463,13 +465,26 @@ int kvm_vgic_map_resources(struct kvm *kvm) else ret = vgic_v3_map_resources(kvm); - if (ret) + if (ret) { __kvm_vgic_destroy(kvm); - else - dist->ready = true; + goto out; + } + dist->ready = true; + dist_base = dist->vgic_dist_base; + mutex_unlock(&kvm->arch.config_lock); + + ret = vgic_register_dist_iodev(kvm, dist_base, + kvm_vgic_global_state.type); + if (ret) { + kvm_err("Unable to register VGIC dist MMIO regions\n"); + kvm_vgic_destroy(kvm); + } + mutex_unlock(&kvm->slots_lock); + return ret; out: mutex_unlock(&kvm->arch.config_lock); + mutex_unlock(&kvm->slots_lock); return ret; } diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 750e51e3779a31..5fe2365a629f25 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -1936,6 +1936,7 @@ void vgic_lpi_translation_cache_destroy(struct kvm *kvm) static int vgic_its_create(struct kvm_device *dev, u32 type) { + int ret; struct vgic_its *its; if (type != KVM_DEV_TYPE_ARM_VGIC_ITS) @@ -1945,9 +1946,12 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) if (!its) return -ENOMEM; + mutex_lock(&dev->kvm->arch.config_lock); + if (vgic_initialized(dev->kvm)) { - int ret = vgic_v4_init(dev->kvm); + ret = vgic_v4_init(dev->kvm); if (ret < 0) { + mutex_unlock(&dev->kvm->arch.config_lock); kfree(its); return ret; } @@ -1960,12 +1964,10 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) /* Yep, even more trickery for lock ordering... */ #ifdef CONFIG_LOCKDEP - mutex_lock(&dev->kvm->arch.config_lock); mutex_lock(&its->cmd_lock); mutex_lock(&its->its_lock); mutex_unlock(&its->its_lock); mutex_unlock(&its->cmd_lock); - mutex_unlock(&dev->kvm->arch.config_lock); #endif its->vgic_its_base = VGIC_ADDR_UNDEF; @@ -1986,7 +1988,11 @@ static int vgic_its_create(struct kvm_device *dev, u32 type) dev->private = its; - return vgic_its_set_abi(its, NR_ITS_ABIS - 1); + ret = vgic_its_set_abi(its, NR_ITS_ABIS - 1); + + mutex_unlock(&dev->kvm->arch.config_lock); + + return ret; } static void vgic_its_destroy(struct kvm_device *kvm_dev) diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c index 35cfa268fd5de7..212b73a715c1c2 100644 --- a/arch/arm64/kvm/vgic/vgic-kvm-device.c +++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c @@ -102,7 +102,11 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri if (get_user(addr, uaddr)) return -EFAULT; - mutex_lock(&kvm->arch.config_lock); + /* + * Since we can't hold config_lock while registering the redistributor + * iodevs, take the slots_lock immediately. + */ + mutex_lock(&kvm->slots_lock); switch (attr->attr) { case KVM_VGIC_V2_ADDR_TYPE_DIST: r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); @@ -182,6 +186,7 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri if (r) goto out; + mutex_lock(&kvm->arch.config_lock); if (write) { r = vgic_check_iorange(kvm, *addr_ptr, addr, alignment, size); if (!r) @@ -189,9 +194,10 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri } else { addr = *addr_ptr; } + mutex_unlock(&kvm->arch.config_lock); out: - mutex_unlock(&kvm->arch.config_lock); + mutex_unlock(&kvm->slots_lock); if (!r && !write) r = put_user(addr, uaddr); diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index 472b18ac92a242..188d2187eede93 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -769,10 +769,13 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; struct vgic_redist_region *rdreg; gpa_t rd_base; - int ret; + int ret = 0; + + lockdep_assert_held(&kvm->slots_lock); + mutex_lock(&kvm->arch.config_lock); if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr)) - return 0; + goto out_unlock; /* * We may be creating VCPUs before having set the base address for the @@ -782,10 +785,12 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) */ rdreg = vgic_v3_rdist_free_slot(&vgic->rd_regions); if (!rdreg) - return 0; + goto out_unlock; - if (!vgic_v3_check_base(kvm)) - return -EINVAL; + if (!vgic_v3_check_base(kvm)) { + ret = -EINVAL; + goto out_unlock; + } vgic_cpu->rdreg = rdreg; vgic_cpu->rdreg_index = rdreg->free_index; @@ -799,16 +804,20 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rd_registers); rd_dev->redist_vcpu = vcpu; - mutex_lock(&kvm->slots_lock); + mutex_unlock(&kvm->arch.config_lock); + ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base, 2 * SZ_64K, &rd_dev->dev); - mutex_unlock(&kvm->slots_lock); - if (ret) return ret; + /* Protected by slots_lock */ rdreg->free_index++; return 0; + +out_unlock: + mutex_unlock(&kvm->arch.config_lock); + return ret; } static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu) @@ -834,12 +843,10 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm) /* The current c failed, so iterate over the previous ones. */ int i; - mutex_lock(&kvm->slots_lock); for (i = 0; i < c; i++) { vcpu = kvm_get_vcpu(kvm, i); vgic_unregister_redist_iodev(vcpu); } - mutex_unlock(&kvm->slots_lock); } return ret; @@ -938,7 +945,9 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count) { int ret; + mutex_lock(&kvm->arch.config_lock); ret = vgic_v3_alloc_redist_region(kvm, index, addr, count); + mutex_unlock(&kvm->arch.config_lock); if (ret) return ret; @@ -950,8 +959,10 @@ int vgic_v3_set_redist_base(struct kvm *kvm, u32 index, u64 addr, u32 count) if (ret) { struct vgic_redist_region *rdreg; + mutex_lock(&kvm->arch.config_lock); rdreg = vgic_v3_rdist_region_from_index(kvm, index); vgic_v3_free_redist_region(rdreg); + mutex_unlock(&kvm->arch.config_lock); return ret; } diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c index 1939c94e0b2488..ff558c05e990c7 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.c +++ b/arch/arm64/kvm/vgic/vgic-mmio.c @@ -1096,7 +1096,6 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address, enum vgic_type type) { struct vgic_io_device *io_device = &kvm->arch.vgic.dist_iodev; - int ret = 0; unsigned int len; switch (type) { @@ -1114,10 +1113,6 @@ int vgic_register_dist_iodev(struct kvm *kvm, gpa_t dist_base_address, io_device->iodev_type = IODEV_DIST; io_device->redist_vcpu = NULL; - mutex_lock(&kvm->slots_lock); - ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address, - len, &io_device->dev); - mutex_unlock(&kvm->slots_lock); - - return ret; + return kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, dist_base_address, + len, &io_device->dev); } diff --git a/arch/arm64/kvm/vgic/vgic-v2.c b/arch/arm64/kvm/vgic/vgic-v2.c index 645648349c99b1..7e9cdb78f7ce88 100644 --- a/arch/arm64/kvm/vgic/vgic-v2.c +++ b/arch/arm64/kvm/vgic/vgic-v2.c @@ -312,12 +312,6 @@ int vgic_v2_map_resources(struct kvm *kvm) return ret; } - ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V2); - if (ret) { - kvm_err("Unable to register VGIC MMIO regions\n"); - return ret; - } - if (!static_branch_unlikely(&vgic_v2_cpuif_trap)) { ret = kvm_phys_addr_ioremap(kvm, dist->vgic_cpu_base, kvm_vgic_global_state.vcpu_base, diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c index 469d816f356f3f..c3b8e132d59926 100644 --- a/arch/arm64/kvm/vgic/vgic-v3.c +++ b/arch/arm64/kvm/vgic/vgic-v3.c @@ -539,7 +539,6 @@ int vgic_v3_map_resources(struct kvm *kvm) { struct vgic_dist *dist = &kvm->arch.vgic; struct kvm_vcpu *vcpu; - int ret = 0; unsigned long c; kvm_for_each_vcpu(c, vcpu, kvm) { @@ -569,12 +568,6 @@ int vgic_v3_map_resources(struct kvm *kvm) return -EBUSY; } - ret = vgic_register_dist_iodev(kvm, dist->vgic_dist_base, VGIC_V3); - if (ret) { - kvm_err("Unable to register VGICv3 dist MMIO regions\n"); - return ret; - } - if (kvm_vgic_global_state.has_gicv4_1) vgic_v4_configure_vsgis(kvm); @@ -616,6 +609,10 @@ static const struct midr_range broken_seis[] = { MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX), MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD), MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE), + MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO), + MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO), + MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX), + MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX), {}, }; diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c index 3bb00347806057..c1c28fe680ba31 100644 --- a/arch/arm64/kvm/vgic/vgic-v4.c +++ b/arch/arm64/kvm/vgic/vgic-v4.c @@ -184,13 +184,14 @@ static void vgic_v4_disable_vsgis(struct kvm_vcpu *vcpu) } } -/* Must be called with the kvm lock held */ void vgic_v4_configure_vsgis(struct kvm *kvm) { struct vgic_dist *dist = &kvm->arch.vgic; struct kvm_vcpu *vcpu; unsigned long i; + lockdep_assert_held(&kvm->arch.config_lock); + kvm_arm_halt_guest(kvm); kvm_for_each_vcpu(i, vcpu, kvm) { diff --git a/arch/arm64/kvm/vmid.c b/arch/arm64/kvm/vmid.c index 08978d0672e7e9..7fe8ba1a2851c5 100644 --- a/arch/arm64/kvm/vmid.c +++ b/arch/arm64/kvm/vmid.c @@ -47,7 +47,7 @@ static void flush_context(void) int cpu; u64 vmid; - bitmap_clear(vmid_map, 0, NUM_USER_VMIDS); + bitmap_zero(vmid_map, NUM_USER_VMIDS); for_each_possible_cpu(cpu) { vmid = atomic64_xchg_relaxed(&per_cpu(active_vmids, cpu), 0); @@ -182,8 +182,7 @@ int __init kvm_arm_vmid_alloc_init(void) */ WARN_ON(NUM_USER_VMIDS - 1 <= num_possible_cpus()); atomic64_set(&vmid_generation, VMID_FIRST_VERSION); - vmid_map = kcalloc(BITS_TO_LONGS(NUM_USER_VMIDS), - sizeof(*vmid_map), GFP_KERNEL); + vmid_map = bitmap_zalloc(NUM_USER_VMIDS, GFP_KERNEL); if (!vmid_map) return -ENOMEM; @@ -192,5 +191,5 @@ int __init kvm_arm_vmid_alloc_init(void) void __init kvm_arm_vmid_alloc_free(void) { - kfree(vmid_map); + bitmap_free(vmid_map); } diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c index 4aadcfb017545d..a7bb20055ce094 100644 --- a/arch/arm64/mm/copypage.c +++ b/arch/arm64/mm/copypage.c @@ -21,9 +21,10 @@ void copy_highpage(struct page *to, struct page *from) copy_page(kto, kfrom); + if (kasan_hw_tags_enabled()) + page_kasan_tag_reset(to); + if (system_supports_mte() && page_mte_tagged(from)) { - if (kasan_hw_tags_enabled()) - page_kasan_tag_reset(to); /* It's a new page, shouldn't have been tagged yet */ WARN_ON_ONCE(!try_page_mte_tagging(to)); mte_copy_page_tags(kto, kfrom); diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 9e0db5c387e3ae..cb21ccd7940d0e 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -480,8 +480,8 @@ static void do_bad_area(unsigned long far, unsigned long esr, } } -#define VM_FAULT_BADMAP 0x010000 -#define VM_FAULT_BADACCESS 0x020000 +#define VM_FAULT_BADMAP ((__force vm_fault_t)0x010000) +#define VM_FAULT_BADACCESS ((__force vm_fault_t)0x020000) static vm_fault_t __do_page_fault(struct mm_struct *mm, unsigned long addr, unsigned int mm_flags, unsigned long vm_flags, diff --git a/arch/m68k/kernel/signal.c b/arch/m68k/kernel/signal.c index b9f6908a31bc39..ba468b5f3f0b65 100644 --- a/arch/m68k/kernel/signal.c +++ b/arch/m68k/kernel/signal.c @@ -858,11 +858,17 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs * } static inline void __user * -get_sigframe(struct ksignal *ksig, size_t frame_size) +get_sigframe(struct ksignal *ksig, struct pt_regs *tregs, size_t frame_size) { unsigned long usp = sigsp(rdusp(), ksig); + unsigned long gap = 0; - return (void __user *)((usp - frame_size) & -8UL); + if (CPU_IS_020_OR_030 && tregs->format == 0xb) { + /* USP is unreliable so use worst-case value */ + gap = 256; + } + + return (void __user *)((usp - gap - frame_size) & -8UL); } static int setup_frame(struct ksignal *ksig, sigset_t *set, @@ -880,7 +886,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, return -EFAULT; } - frame = get_sigframe(ksig, sizeof(*frame) + fsize); + frame = get_sigframe(ksig, tregs, sizeof(*frame) + fsize); if (fsize) err |= copy_to_user (frame + 1, regs + 1, fsize); @@ -952,7 +958,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, return -EFAULT; } - frame = get_sigframe(ksig, sizeof(*frame)); + frame = get_sigframe(ksig, tregs, sizeof(*frame)); if (fsize) err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize); diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index c2f5498d207fff..675a8660cb85a0 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -79,6 +79,7 @@ config MIPS select HAVE_LD_DEAD_CODE_DATA_ELIMINATION select HAVE_MOD_ARCH_SPECIFIC select HAVE_NMI + select HAVE_PATA_PLATFORM select HAVE_PERF_EVENTS select HAVE_PERF_REGS select HAVE_PERF_USER_STACK_DUMP diff --git a/arch/mips/alchemy/common/dbdma.c b/arch/mips/alchemy/common/dbdma.c index 5ab04300040929..6a3c890f7bbfed 100644 --- a/arch/mips/alchemy/common/dbdma.c +++ b/arch/mips/alchemy/common/dbdma.c @@ -30,6 +30,7 @@ * */ +#include /* for dma_default_coherent */ #include #include #include @@ -623,17 +624,18 @@ u32 au1xxx_dbdma_put_source(u32 chanid, dma_addr_t buf, int nbytes, u32 flags) dp->dscr_cmd0 &= ~DSCR_CMD0_IE; /* - * There is an errata on the Au1200/Au1550 parts that could result - * in "stale" data being DMA'ed. It has to do with the snoop logic on - * the cache eviction buffer. DMA_NONCOHERENT is on by default for - * these parts. If it is fixed in the future, these dma_cache_inv will - * just be nothing more than empty macros. See io.h. + * There is an erratum on certain Au1200/Au1550 revisions that could + * result in "stale" data being DMA'ed. It has to do with the snoop + * logic on the cache eviction buffer. dma_default_coherent is set + * to false on these parts. */ - dma_cache_wback_inv((unsigned long)buf, nbytes); + if (!dma_default_coherent) + dma_cache_wback_inv(KSEG0ADDR(buf), nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ wmb(); /* drain writebuffer */ dma_cache_wback_inv((unsigned long)dp, sizeof(*dp)); ctp->chan_ptr->ddma_dbell = 0; + wmb(); /* force doorbell write out to dma engine */ /* Get next descriptor pointer. */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); @@ -685,17 +687,18 @@ u32 au1xxx_dbdma_put_dest(u32 chanid, dma_addr_t buf, int nbytes, u32 flags) dp->dscr_source1, dp->dscr_dest0, dp->dscr_dest1); #endif /* - * There is an errata on the Au1200/Au1550 parts that could result in - * "stale" data being DMA'ed. It has to do with the snoop logic on the - * cache eviction buffer. DMA_NONCOHERENT is on by default for these - * parts. If it is fixed in the future, these dma_cache_inv will just - * be nothing more than empty macros. See io.h. + * There is an erratum on certain Au1200/Au1550 revisions that could + * result in "stale" data being DMA'ed. It has to do with the snoop + * logic on the cache eviction buffer. dma_default_coherent is set + * to false on these parts. */ - dma_cache_inv((unsigned long)buf, nbytes); + if (!dma_default_coherent) + dma_cache_inv(KSEG0ADDR(buf), nbytes); dp->dscr_cmd0 |= DSCR_CMD0_V; /* Let it rip */ wmb(); /* drain writebuffer */ dma_cache_wback_inv((unsigned long)dp, sizeof(*dp)); ctp->chan_ptr->ddma_dbell = 0; + wmb(); /* force doorbell write out to dma engine */ /* Get next descriptor pointer. */ ctp->put_ptr = phys_to_virt(DSCR_GET_NXTPTR(dp->dscr_nxtptr)); diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h index 18f3d95ecfec1d..60ebaed28a4cab 100644 --- a/arch/mips/include/uapi/asm/socket.h +++ b/arch/mips/include/uapi/asm/socket.h @@ -148,6 +148,9 @@ #define SO_RCVMARK 75 +#define SO_PASSPIDFD 76 +#define SO_PEERPIDFD 77 + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 6d15a398d389e2..e79adcb128e67d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1502,6 +1502,10 @@ static inline void cpu_probe_alchemy(struct cpuinfo_mips *c, unsigned int cpu) break; } break; + case PRID_IMP_NETLOGIC_AU13XX: + c->cputype = CPU_ALCHEMY; + __cpu_name[cpu] = "Au1300"; + break; } } @@ -1863,6 +1867,7 @@ void cpu_probe(void) cpu_probe_mips(c, cpu); break; case PRID_COMP_ALCHEMY: + case PRID_COMP_NETLOGIC: cpu_probe_alchemy(c, cpu); break; case PRID_COMP_SIBYTE: diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index febdc5564638e9..c0e65135481b74 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -158,10 +158,6 @@ static unsigned long __init init_initrd(void) pr_err("initrd start must be page aligned\n"); goto disable; } - if (initrd_start < PAGE_OFFSET) { - pr_err("initrd start < PAGE_OFFSET\n"); - goto disable; - } /* * Sanitize initrd addresses. For example firmware @@ -174,6 +170,11 @@ static unsigned long __init init_initrd(void) initrd_end = (unsigned long)__va(end); initrd_start = (unsigned long)__va(__pa(initrd_start)); + if (initrd_start < PAGE_OFFSET) { + pr_err("initrd start < PAGE_OFFSET\n"); + goto disable; + } + ROOT_DEV = Root_RAM0; return PFN_UP(end); disable: diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index 466a25525364d2..967bde65dd0ec8 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -130,6 +130,10 @@ config PM config STACKTRACE_SUPPORT def_bool y +config LOCKDEP_SUPPORT + bool + default y + config ISA_DMA_API bool diff --git a/arch/parisc/Kconfig.debug b/arch/parisc/Kconfig.debug index f66554cd5c4518..3a059cb5e112fb 100644 --- a/arch/parisc/Kconfig.debug +++ b/arch/parisc/Kconfig.debug @@ -1 +1,12 @@ # SPDX-License-Identifier: GPL-2.0 +# +config LIGHTWEIGHT_SPINLOCK_CHECK + bool "Enable lightweight spinlock checks" + depends on SMP && !DEBUG_SPINLOCK + default y + help + Add checks with low performance impact to the spinlock functions + to catch memory overwrites at runtime. For more advanced + spinlock debugging you should choose the DEBUG_SPINLOCK option + which will detect unitialized spinlocks too. + If unsure say Y here. diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index 0bdee672413206..c8b6928cee1ee4 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h @@ -48,6 +48,10 @@ void flush_dcache_page(struct page *page); #define flush_dcache_mmap_lock(mapping) xa_lock_irq(&mapping->i_pages) #define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&mapping->i_pages) +#define flush_dcache_mmap_lock_irqsave(mapping, flags) \ + xa_lock_irqsave(&mapping->i_pages, flags) +#define flush_dcache_mmap_unlock_irqrestore(mapping, flags) \ + xa_unlock_irqrestore(&mapping->i_pages, flags) #define flush_icache_page(vma,page) do { \ flush_kernel_dcache_page_addr(page_address(page)); \ diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h index a6e5d66a76562a..edfcb9858bcb7c 100644 --- a/arch/parisc/include/asm/spinlock.h +++ b/arch/parisc/include/asm/spinlock.h @@ -7,10 +7,26 @@ #include #include +#define SPINLOCK_BREAK_INSN 0x0000c006 /* break 6,6 */ + +static inline void arch_spin_val_check(int lock_val) +{ + if (IS_ENABLED(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK)) + asm volatile( "andcm,= %0,%1,%%r0\n" + ".word %2\n" + : : "r" (lock_val), "r" (__ARCH_SPIN_LOCK_UNLOCKED_VAL), + "i" (SPINLOCK_BREAK_INSN)); +} + static inline int arch_spin_is_locked(arch_spinlock_t *x) { - volatile unsigned int *a = __ldcw_align(x); - return READ_ONCE(*a) == 0; + volatile unsigned int *a; + int lock_val; + + a = __ldcw_align(x); + lock_val = READ_ONCE(*a); + arch_spin_val_check(lock_val); + return (lock_val == 0); } static inline void arch_spin_lock(arch_spinlock_t *x) @@ -18,9 +34,18 @@ static inline void arch_spin_lock(arch_spinlock_t *x) volatile unsigned int *a; a = __ldcw_align(x); - while (__ldcw(a) == 0) + do { + int lock_val_old; + + lock_val_old = __ldcw(a); + arch_spin_val_check(lock_val_old); + if (lock_val_old) + return; /* got lock */ + + /* wait until we should try to get lock again */ while (*a == 0) continue; + } while (1); } static inline void arch_spin_unlock(arch_spinlock_t *x) @@ -29,15 +54,19 @@ static inline void arch_spin_unlock(arch_spinlock_t *x) a = __ldcw_align(x); /* Release with ordered store. */ - __asm__ __volatile__("stw,ma %0,0(%1)" : : "r"(1), "r"(a) : "memory"); + __asm__ __volatile__("stw,ma %0,0(%1)" + : : "r"(__ARCH_SPIN_LOCK_UNLOCKED_VAL), "r"(a) : "memory"); } static inline int arch_spin_trylock(arch_spinlock_t *x) { volatile unsigned int *a; + int lock_val; a = __ldcw_align(x); - return __ldcw(a) != 0; + lock_val = __ldcw(a); + arch_spin_val_check(lock_val); + return lock_val != 0; } /* diff --git a/arch/parisc/include/asm/spinlock_types.h b/arch/parisc/include/asm/spinlock_types.h index ca39ee350c3f42..d65934079ebdb0 100644 --- a/arch/parisc/include/asm/spinlock_types.h +++ b/arch/parisc/include/asm/spinlock_types.h @@ -2,13 +2,17 @@ #ifndef __ASM_SPINLOCK_TYPES_H #define __ASM_SPINLOCK_TYPES_H +#define __ARCH_SPIN_LOCK_UNLOCKED_VAL 0x1a46 + typedef struct { #ifdef CONFIG_PA20 volatile unsigned int slock; -# define __ARCH_SPIN_LOCK_UNLOCKED { 1 } +# define __ARCH_SPIN_LOCK_UNLOCKED { __ARCH_SPIN_LOCK_UNLOCKED_VAL } #else volatile unsigned int lock[4]; -# define __ARCH_SPIN_LOCK_UNLOCKED { { 1, 1, 1, 1 } } +# define __ARCH_SPIN_LOCK_UNLOCKED \ + { { __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL, \ + __ARCH_SPIN_LOCK_UNLOCKED_VAL, __ARCH_SPIN_LOCK_UNLOCKED_VAL } } #endif } arch_spinlock_t; diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h index f486d3dfb6bb62..be264c2b1a1178 100644 --- a/arch/parisc/include/uapi/asm/socket.h +++ b/arch/parisc/include/uapi/asm/socket.h @@ -129,6 +129,9 @@ #define SO_RCVMARK 0x4049 +#define SO_PASSPIDFD 0x404A +#define SO_PEERPIDFD 0x404B + #if !defined(__KERNEL__) #if __BITS_PER_LONG == 64 diff --git a/arch/parisc/kernel/alternative.c b/arch/parisc/kernel/alternative.c index 66f5672c70bd46..25c4d6c3375db3 100644 --- a/arch/parisc/kernel/alternative.c +++ b/arch/parisc/kernel/alternative.c @@ -25,7 +25,7 @@ void __init_or_module apply_alternatives(struct alt_instr *start, { struct alt_instr *entry; int index = 0, applied = 0; - int num_cpus = num_online_cpus(); + int num_cpus = num_present_cpus(); u16 cond_check; cond_check = ALT_COND_ALWAYS | diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 1d3b8bc8a62336..ca4a302d4365fe 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -399,6 +399,7 @@ void flush_dcache_page(struct page *page) unsigned long offset; unsigned long addr, old_addr = 0; unsigned long count = 0; + unsigned long flags; pgoff_t pgoff; if (mapping && !mapping_mapped(mapping)) { @@ -420,7 +421,7 @@ void flush_dcache_page(struct page *page) * to flush one address here for them all to become coherent * on machines that support equivalent aliasing */ - flush_dcache_mmap_lock(mapping); + flush_dcache_mmap_lock_irqsave(mapping, flags); vma_interval_tree_foreach(mpnt, &mapping->i_mmap, pgoff, pgoff) { offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT; addr = mpnt->vm_start + offset; @@ -460,7 +461,7 @@ void flush_dcache_page(struct page *page) } WARN_ON(++count == 4096); } - flush_dcache_mmap_unlock(mapping); + flush_dcache_mmap_unlock_irqrestore(mapping, flags); } EXPORT_SYMBOL(flush_dcache_page); diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index ba87f791323be0..71ed5391f29d6f 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -446,11 +446,27 @@ void arch_dma_free(struct device *dev, size_t size, void *vaddr, void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, enum dma_data_direction dir) { + /* + * fdc: The data cache line is written back to memory, if and only if + * it is dirty, and then invalidated from the data cache. + */ flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size); } void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, enum dma_data_direction dir) { - flush_kernel_dcache_range((unsigned long)phys_to_virt(paddr), size); + unsigned long addr = (unsigned long) phys_to_virt(paddr); + + switch (dir) { + case DMA_TO_DEVICE: + case DMA_BIDIRECTIONAL: + flush_kernel_dcache_range(addr, size); + return; + case DMA_FROM_DEVICE: + purge_kernel_dcache_range_asm(addr, addr + size); + return; + default: + BUG(); + } } diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 97c6f875bd0e12..24411ab79c307d 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -122,13 +122,18 @@ void machine_power_off(void) /* It seems we have no way to power the system off via * software. The user has to press the button himself. */ - printk(KERN_EMERG "System shut down completed.\n" - "Please power this system off now."); + printk("Power off or press RETURN to reboot.\n"); /* prevent soft lockup/stalled CPU messages for endless loop. */ rcu_sysrq_start(); lockup_detector_soft_poweroff(); - for (;;); + while (1) { + /* reboot if user presses RETURN key */ + if (pdc_iodc_getc() == 13) { + printk("Rebooting...\n"); + machine_restart(NULL); + } + } } void (*pm_power_off)(void); diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index f9696fbf646c47..304eebd1c83e7d 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -47,6 +47,10 @@ #include #include +#if defined(CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK) +#include +#endif + #include "../math-emu/math-emu.h" /* for handle_fpe() */ static void parisc_show_stack(struct task_struct *task, @@ -291,24 +295,30 @@ static void handle_break(struct pt_regs *regs) } #ifdef CONFIG_KPROBES - if (unlikely(iir == PARISC_KPROBES_BREAK_INSN)) { + if (unlikely(iir == PARISC_KPROBES_BREAK_INSN && !user_mode(regs))) { parisc_kprobe_break_handler(regs); return; } - if (unlikely(iir == PARISC_KPROBES_BREAK_INSN2)) { + if (unlikely(iir == PARISC_KPROBES_BREAK_INSN2 && !user_mode(regs))) { parisc_kprobe_ss_handler(regs); return; } #endif #ifdef CONFIG_KGDB - if (unlikely(iir == PARISC_KGDB_COMPILED_BREAK_INSN || - iir == PARISC_KGDB_BREAK_INSN)) { + if (unlikely((iir == PARISC_KGDB_COMPILED_BREAK_INSN || + iir == PARISC_KGDB_BREAK_INSN)) && !user_mode(regs)) { kgdb_handle_exception(9, SIGTRAP, 0, regs); return; } #endif +#ifdef CONFIG_LIGHTWEIGHT_SPINLOCK_CHECK + if ((iir == SPINLOCK_BREAK_INSN) && !user_mode(regs)) { + die_if_kernel("Spinlock was trashed", regs, 1); + } +#endif + if (unlikely(iir != GDB_BREAK_INSN)) parisc_printk_ratelimited(0, regs, KERN_DEBUG "break %d,%d: pid=%d command='%s'\n", diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 539d1f03ff42a5..bff5820b7cda14 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -906,11 +906,17 @@ config DATA_SHIFT config ARCH_FORCE_MAX_ORDER int "Order of maximal physically contiguous allocations" + range 7 8 if PPC64 && PPC_64K_PAGES default "8" if PPC64 && PPC_64K_PAGES + range 12 12 if PPC64 && !PPC_64K_PAGES default "12" if PPC64 && !PPC_64K_PAGES + range 8 10 if PPC32 && PPC_16K_PAGES default "8" if PPC32 && PPC_16K_PAGES + range 6 10 if PPC32 && PPC_64K_PAGES default "6" if PPC32 && PPC_64K_PAGES + range 4 10 if PPC32 && PPC_256K_PAGES default "4" if PPC32 && PPC_256K_PAGES + range 10 10 default "10" help The kernel page allocator limits the size of maximal physically diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 85cde5bf04b7ae..771b79423bbc2b 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile @@ -34,8 +34,6 @@ endif BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -O2 -msoft-float -mno-altivec -mno-vsx \ - $(call cc-option,-mno-prefixed) $(call cc-option,-mno-pcrel) \ - $(call cc-option,-mno-mma) \ $(call cc-option,-mno-spe) $(call cc-option,-mspe=no) \ -pipe -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ $(LINUXINCLUDE) @@ -71,6 +69,10 @@ BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -nostdinc BOOTARFLAGS := -crD +BOOTCFLAGS += $(call cc-option,-mno-prefixed) \ + $(call cc-option,-mno-pcrel) \ + $(call cc-option,-mno-mma) + ifdef CONFIG_CC_IS_CLANG BOOTCFLAGS += $(CLANG_FLAGS) BOOTAFLAGS += $(CLANG_FLAGS) diff --git a/arch/powerpc/crypto/Kconfig b/arch/powerpc/crypto/Kconfig index 7113f9355165a6..ad1872518992e0 100644 --- a/arch/powerpc/crypto/Kconfig +++ b/arch/powerpc/crypto/Kconfig @@ -96,7 +96,7 @@ config CRYPTO_AES_PPC_SPE config CRYPTO_AES_GCM_P10 tristate "Stitched AES/GCM acceleration support on P10 or later CPU (PPC)" - depends on PPC64 && CPU_LITTLE_ENDIAN + depends on PPC64 && CPU_LITTLE_ENDIAN && VSX select CRYPTO_LIB_AES select CRYPTO_ALGAPI select CRYPTO_AEAD diff --git a/arch/powerpc/crypto/Makefile b/arch/powerpc/crypto/Makefile index 05c7486f42c587..7b4f516abec1d3 100644 --- a/arch/powerpc/crypto/Makefile +++ b/arch/powerpc/crypto/Makefile @@ -22,15 +22,15 @@ sha1-ppc-spe-y := sha1-spe-asm.o sha1-spe-glue.o sha256-ppc-spe-y := sha256-spe-asm.o sha256-spe-glue.o crc32c-vpmsum-y := crc32c-vpmsum_asm.o crc32c-vpmsum_glue.o crct10dif-vpmsum-y := crct10dif-vpmsum_asm.o crct10dif-vpmsum_glue.o -aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp8-ppc.o aesp8-ppc.o +aes-gcm-p10-crypto-y := aes-gcm-p10-glue.o aes-gcm-p10.o ghashp10-ppc.o aesp10-ppc.o quiet_cmd_perl = PERL $@ cmd_perl = $(PERL) $< $(if $(CONFIG_CPU_LITTLE_ENDIAN), linux-ppc64le, linux-ppc64) > $@ -targets += aesp8-ppc.S ghashp8-ppc.S +targets += aesp10-ppc.S ghashp10-ppc.S -$(obj)/aesp8-ppc.S $(obj)/ghashp8-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE +$(obj)/aesp10-ppc.S $(obj)/ghashp10-ppc.S: $(obj)/%.S: $(src)/%.pl FORCE $(call if_changed,perl) -OBJECT_FILES_NON_STANDARD_aesp8-ppc.o := y -OBJECT_FILES_NON_STANDARD_ghashp8-ppc.o := y +OBJECT_FILES_NON_STANDARD_aesp10-ppc.o := y +OBJECT_FILES_NON_STANDARD_ghashp10-ppc.o := y diff --git a/arch/powerpc/crypto/aes-gcm-p10-glue.c b/arch/powerpc/crypto/aes-gcm-p10-glue.c index bd3475f5348d99..4b6e899895e7be 100644 --- a/arch/powerpc/crypto/aes-gcm-p10-glue.c +++ b/arch/powerpc/crypto/aes-gcm-p10-glue.c @@ -30,15 +30,15 @@ MODULE_AUTHOR("Danny Tsen aadLen = alen; i = alen & ~0xf; if (i) { - gcm_ghash_p8(nXi, hash->Htable+32, aad, i); + gcm_ghash_p10(nXi, hash->Htable+32, aad, i); aad += i; alen -= i; } @@ -102,7 +102,7 @@ static void set_aad(struct gcm_ctx *gctx, struct Hash_ctx *hash, nXi[i] ^= aad[i]; memset(gctx->aad_hash, 0, 16); - gcm_ghash_p8(gctx->aad_hash, hash->Htable+32, nXi, 16); + gcm_ghash_p10(gctx->aad_hash, hash->Htable+32, nXi, 16); } else { memcpy(gctx->aad_hash, nXi, 16); } @@ -115,7 +115,7 @@ static void gcmp10_init(struct gcm_ctx *gctx, u8 *iv, unsigned char *rdkey, { __be32 counter = cpu_to_be32(1); - aes_p8_encrypt(hash->H, hash->H, rdkey); + aes_p10_encrypt(hash->H, hash->H, rdkey); set_subkey(hash->H); gcm_init_htable(hash->Htable+32, hash->H); @@ -126,7 +126,7 @@ static void gcmp10_init(struct gcm_ctx *gctx, u8 *iv, unsigned char *rdkey, /* * Encrypt counter vector as iv tag and increment counter. */ - aes_p8_encrypt(iv, gctx->ivtag, rdkey); + aes_p10_encrypt(iv, gctx->ivtag, rdkey); counter = cpu_to_be32(2); *((__be32 *)(iv+12)) = counter; @@ -160,7 +160,7 @@ static void finish_tag(struct gcm_ctx *gctx, struct Hash_ctx *hash, int len) /* * hash (AAD len and len) */ - gcm_ghash_p8(hash->Htable, hash->Htable+32, aclen, 16); + gcm_ghash_p10(hash->Htable, hash->Htable+32, aclen, 16); for (i = 0; i < 16; i++) hash->Htable[i] ^= gctx->ivtag[i]; @@ -192,7 +192,7 @@ static int p10_aes_gcm_setkey(struct crypto_aead *aead, const u8 *key, int ret; vsx_begin(); - ret = aes_p8_set_encrypt_key(key, keylen * 8, &ctx->enc_key); + ret = aes_p10_set_encrypt_key(key, keylen * 8, &ctx->enc_key); vsx_end(); return ret ? -EINVAL : 0; diff --git a/arch/powerpc/crypto/aesp8-ppc.pl b/arch/powerpc/crypto/aesp10-ppc.pl similarity index 99% rename from arch/powerpc/crypto/aesp8-ppc.pl rename to arch/powerpc/crypto/aesp10-ppc.pl index 1f22aec27d7997..2c06ce2a2c7c02 100644 --- a/arch/powerpc/crypto/aesp8-ppc.pl +++ b/arch/powerpc/crypto/aesp10-ppc.pl @@ -110,7 +110,7 @@ open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!"; $FRAME=8*$SIZE_T; -$prefix="aes_p8"; +$prefix="aes_p10"; $sp="r1"; $vrsave="r12"; diff --git a/arch/powerpc/crypto/ghashp8-ppc.pl b/arch/powerpc/crypto/ghashp10-ppc.pl similarity index 97% rename from arch/powerpc/crypto/ghashp8-ppc.pl rename to arch/powerpc/crypto/ghashp10-ppc.pl index b56603b4a893c7..27a6b0bec645f9 100644 --- a/arch/powerpc/crypto/ghashp8-ppc.pl +++ b/arch/powerpc/crypto/ghashp10-ppc.pl @@ -64,7 +64,7 @@ .text -.globl .gcm_init_p8 +.globl .gcm_init_p10 lis r0,0xfff0 li r8,0x10 mfspr $vrsave,256 @@ -110,7 +110,7 @@ .long 0 .byte 0,12,0x14,0,0,0,2,0 .long 0 -.size .gcm_init_p8,.-.gcm_init_p8 +.size .gcm_init_p10,.-.gcm_init_p10 .globl .gcm_init_htable lis r0,0xfff0 @@ -237,7 +237,7 @@ .long 0 .size .gcm_init_htable,.-.gcm_init_htable -.globl .gcm_gmult_p8 +.globl .gcm_gmult_p10 lis r0,0xfff8 li r8,0x10 mfspr $vrsave,256 @@ -283,9 +283,9 @@ .long 0 .byte 0,12,0x14,0,0,0,2,0 .long 0 -.size .gcm_gmult_p8,.-.gcm_gmult_p8 +.size .gcm_gmult_p10,.-.gcm_gmult_p10 -.globl .gcm_ghash_p8 +.globl .gcm_ghash_p10 lis r0,0xfff8 li r8,0x10 mfspr $vrsave,256 @@ -350,7 +350,7 @@ .long 0 .byte 0,12,0x14,0,0,0,4,0 .long 0 -.size .gcm_ghash_p8,.-.gcm_ghash_p8 +.size .gcm_ghash_p10,.-.gcm_ghash_p10 .asciz "GHASH for PowerISA 2.07, CRYPTOGAMS by " .align 2 diff --git a/arch/powerpc/include/asm/iommu.h b/arch/powerpc/include/asm/iommu.h index 678b5bdc79b1f5..34e14dfd8e042a 100644 --- a/arch/powerpc/include/asm/iommu.h +++ b/arch/powerpc/include/asm/iommu.h @@ -205,7 +205,6 @@ extern void iommu_register_group(struct iommu_table_group *table_group, int pci_domain_number, unsigned long pe_num); extern int iommu_add_device(struct iommu_table_group *table_group, struct device *dev); -extern void iommu_del_device(struct device *dev); extern long iommu_tce_xchg(struct mm_struct *mm, struct iommu_table *tbl, unsigned long entry, unsigned long *hpa, enum dma_data_direction *direction); @@ -229,10 +228,6 @@ static inline int iommu_add_device(struct iommu_table_group *table_group, { return 0; } - -static inline void iommu_del_device(struct device *dev) -{ -} #endif /* !CONFIG_IOMMU_API */ u64 dma_iommu_get_required_mask(struct device *dev); diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 038ce8d9061d16..8920862ffd7916 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c @@ -144,7 +144,7 @@ static bool dma_iommu_bypass_supported(struct device *dev, u64 mask) /* We support DMA to/from any memory page via the iommu */ int dma_iommu_dma_supported(struct device *dev, u64 mask) { - struct iommu_table *tbl = get_iommu_table_base(dev); + struct iommu_table *tbl; if (dev_is_pci(dev) && dma_iommu_bypass_supported(dev, mask)) { /* @@ -162,6 +162,8 @@ int dma_iommu_dma_supported(struct device *dev, u64 mask) return 1; } + tbl = get_iommu_table_base(dev); + if (!tbl) { dev_err(dev, "Warning: IOMMU dma not supported: mask 0x%08llx, table unavailable\n", mask); return 0; diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 0089dd49b4cbf7..67f0b01e6ff575 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -518,7 +518,7 @@ int ppc_iommu_map_sg(struct device *dev, struct iommu_table *tbl, /* Convert entry to a dma_addr_t */ entry += tbl->it_offset; dma_addr = entry << tbl->it_page_shift; - dma_addr |= (s->offset & ~IOMMU_PAGE_MASK(tbl)); + dma_addr |= (vaddr & ~IOMMU_PAGE_MASK(tbl)); DBG(" - %lu pages, entry: %lx, dma_addr: %lx\n", npages, entry, dma_addr); @@ -905,6 +905,7 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl, unsigned int order; unsigned int nio_pages, io_order; struct page *page; + int tcesize = (1 << tbl->it_page_shift); size = PAGE_ALIGN(size); order = get_order(size); @@ -931,7 +932,8 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl, memset(ret, 0, size); /* Set up tces to cover the allocated range */ - nio_pages = size >> tbl->it_page_shift; + nio_pages = IOMMU_PAGE_ALIGN(size, tbl) >> tbl->it_page_shift; + io_order = get_iommu_order(size, tbl); mapping = iommu_alloc(dev, tbl, ret, nio_pages, DMA_BIDIRECTIONAL, mask >> tbl->it_page_shift, io_order, 0); @@ -939,7 +941,8 @@ void *iommu_alloc_coherent(struct device *dev, struct iommu_table *tbl, free_pages((unsigned long)ret, order); return NULL; } - *dma_handle = mapping; + + *dma_handle = mapping | ((u64)ret & (tcesize - 1)); return ret; } @@ -950,7 +953,7 @@ void iommu_free_coherent(struct iommu_table *tbl, size_t size, unsigned int nio_pages; size = PAGE_ALIGN(size); - nio_pages = size >> tbl->it_page_shift; + nio_pages = IOMMU_PAGE_ALIGN(size, tbl) >> tbl->it_page_shift; iommu_free(tbl, dma_handle, nio_pages); size = PAGE_ALIGN(size); free_pages((unsigned long)vaddr, get_order(size)); @@ -1168,23 +1171,6 @@ int iommu_add_device(struct iommu_table_group *table_group, struct device *dev) } EXPORT_SYMBOL_GPL(iommu_add_device); -void iommu_del_device(struct device *dev) -{ - /* - * Some devices might not have IOMMU table and group - * and we needn't detach them from the associated - * IOMMU groups - */ - if (!device_iommu_mapped(dev)) { - pr_debug("iommu_tce: skipping device %s with no tbl\n", - dev_name(dev)); - return; - } - - iommu_group_remove_device(dev); -} -EXPORT_SYMBOL_GPL(iommu_del_device); - /* * A simple iommu_table_group_ops which only allows reusing the existing * iommu_table. This handles VFIO for POWER7 or the nested KVM. diff --git a/arch/powerpc/kernel/isa-bridge.c b/arch/powerpc/kernel/isa-bridge.c index 85bdd7d3652f84..48e0eaf1ad6155 100644 --- a/arch/powerpc/kernel/isa-bridge.c +++ b/arch/powerpc/kernel/isa-bridge.c @@ -93,11 +93,12 @@ static int process_ISA_OF_ranges(struct device_node *isa_node, } inval_range: - if (!phb_io_base_phys) { + if (phb_io_base_phys) { pr_err("no ISA IO ranges or unexpected isa range, mapping 64k\n"); remap_isa_base(phb_io_base_phys, 0x10000); + return 0; } - return 0; + return -EINVAL; } diff --git a/arch/powerpc/mm/book3s64/radix_pgtable.c b/arch/powerpc/mm/book3s64/radix_pgtable.c index 26245aaf12b8bd..2297aa764ecdbc 100644 --- a/arch/powerpc/mm/book3s64/radix_pgtable.c +++ b/arch/powerpc/mm/book3s64/radix_pgtable.c @@ -1040,8 +1040,8 @@ void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, pte_t entry, unsigned long address, int psize) { struct mm_struct *mm = vma->vm_mm; - unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | - _PAGE_RW | _PAGE_EXEC); + unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_SOFT_DIRTY | + _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); unsigned long change = pte_val(entry) ^ pte_val(*ptep); /* diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index e93aefcfb83f26..37043dfc1adddf 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -101,6 +101,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp) bpf_hdr = jit_data->header; proglen = jit_data->proglen; extra_pass = true; + /* During extra pass, ensure index is reset before repopulating extable entries */ + cgctx.exentry_idx = 0; goto skip_init_ctx; } diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 0d9b7609c7d562..3e2e252016f7a6 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig @@ -265,6 +265,7 @@ config CPM2 config FSL_ULI1575 bool "ULI1575 PCIe south bridge support" depends on FSL_SOC_BOOKE || PPC_86xx + depends on PCI select FSL_PCI select GENERIC_ISA_DMA help diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index 233a50e65fcedd..7725492097b627 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -865,28 +865,3 @@ void __init pnv_pci_init(void) /* Configure IOMMU DMA hooks */ set_pci_dma_ops(&dma_iommu_ops); } - -static int pnv_tce_iommu_bus_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - - switch (action) { - case BUS_NOTIFY_DEL_DEVICE: - iommu_del_device(dev); - return 0; - default: - return 0; - } -} - -static struct notifier_block pnv_tce_iommu_bus_nb = { - .notifier_call = pnv_tce_iommu_bus_notifier, -}; - -static int __init pnv_tce_iommu_bus_notifier_init(void) -{ - bus_register_notifier(&pci_bus_type, &pnv_tce_iommu_bus_nb); - return 0; -} -machine_subsys_initcall_sync(powernv, pnv_tce_iommu_bus_notifier_init); diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 7464fa6e414553..d59e8a98a20082 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -91,19 +91,24 @@ static struct iommu_table_group *iommu_pseries_alloc_group(int node) static void iommu_pseries_free_group(struct iommu_table_group *table_group, const char *node_name) { - struct iommu_table *tbl; - if (!table_group) return; - tbl = table_group->tables[0]; #ifdef CONFIG_IOMMU_API if (table_group->group) { iommu_group_put(table_group->group); BUG_ON(table_group->group); } #endif - iommu_tce_table_put(tbl); + + /* Default DMA window table is at index 0, while DDW at 1. SR-IOV + * adapters only have table on index 1. + */ + if (table_group->tables[0]) + iommu_tce_table_put(table_group->tables[0]); + + if (table_group->tables[1]) + iommu_tce_table_put(table_group->tables[1]); kfree(table_group); } @@ -312,13 +317,22 @@ static void tce_free_pSeriesLP(unsigned long liobn, long tcenum, long tceshift, static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages) { u64 rc; + long rpages = npages; + unsigned long limit; if (!firmware_has_feature(FW_FEATURE_STUFF_TCE)) return tce_free_pSeriesLP(tbl->it_index, tcenum, tbl->it_page_shift, npages); - rc = plpar_tce_stuff((u64)tbl->it_index, - (u64)tcenum << tbl->it_page_shift, 0, npages); + do { + limit = min_t(unsigned long, rpages, 512); + + rc = plpar_tce_stuff((u64)tbl->it_index, + (u64)tcenum << tbl->it_page_shift, 0, limit); + + rpages -= limit; + tcenum += limit; + } while (rpages > 0 && !rc); if (rc && printk_ratelimit()) { printk("tce_freemulti_pSeriesLP: plpar_tce_stuff failed\n"); @@ -1695,31 +1709,6 @@ static int __init disable_multitce(char *str) __setup("multitce=", disable_multitce); -static int tce_iommu_bus_notifier(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct device *dev = data; - - switch (action) { - case BUS_NOTIFY_DEL_DEVICE: - iommu_del_device(dev); - return 0; - default: - return 0; - } -} - -static struct notifier_block tce_iommu_bus_nb = { - .notifier_call = tce_iommu_bus_notifier, -}; - -static int __init tce_iommu_bus_notifier_init(void) -{ - bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb); - return 0; -} -machine_subsys_initcall_sync(pseries, tce_iommu_bus_notifier_init); - #ifdef CONFIG_SPAPR_TCE_IOMMU struct iommu_group *pSeries_pci_device_group(struct pci_controller *hose, struct pci_dev *pdev) diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index 728d3c257e4a33..70c4c59a1a8f47 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c @@ -88,7 +88,7 @@ static unsigned long ndump = 64; static unsigned long nidump = 16; static unsigned long ncsum = 4096; static int termch; -static char tmpstr[128]; +static char tmpstr[KSYM_NAME_LEN]; static int tracing_enabled; static long bus_error_jmp[JMP_BUF_LEN]; diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 348c0fa1fc8c7a..2bb0c38419ff53 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -799,8 +799,11 @@ menu "Power management options" source "kernel/power/Kconfig" +# Hibernation is only possible on systems where the SBI implementation has +# marked its reserved memory as not accessible from, or does not run +# from the same memory as, Linux config ARCH_HIBERNATION_POSSIBLE - def_bool y + def_bool NONPORTABLE config ARCH_HIBERNATION_HEADER def_bool HIBERNATION diff --git a/arch/riscv/errata/Makefile b/arch/riscv/errata/Makefile index a1055965fbee6a..7b2637c8c33265 100644 --- a/arch/riscv/errata/Makefile +++ b/arch/riscv/errata/Makefile @@ -1,2 +1,6 @@ +ifdef CONFIG_RELOCATABLE +KBUILD_CFLAGS += -fno-pie +endif + obj-$(CONFIG_ERRATA_SIFIVE) += sifive/ obj-$(CONFIG_ERRATA_THEAD) += thead/ diff --git a/arch/riscv/include/asm/hugetlb.h b/arch/riscv/include/asm/hugetlb.h index fe6f2300664162..ce1ebda1a49a79 100644 --- a/arch/riscv/include/asm/hugetlb.h +++ b/arch/riscv/include/asm/hugetlb.h @@ -36,6 +36,9 @@ int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty); +#define __HAVE_ARCH_HUGE_PTEP_GET +pte_t huge_ptep_get(pte_t *ptep); + pte_t arch_make_huge_pte(pte_t entry, unsigned int shift, vm_flags_t flags); #define arch_make_huge_pte arch_make_huge_pte diff --git a/arch/riscv/include/asm/perf_event.h b/arch/riscv/include/asm/perf_event.h index d42c901f9a9770..665bbc9b2f840a 100644 --- a/arch/riscv/include/asm/perf_event.h +++ b/arch/riscv/include/asm/perf_event.h @@ -10,4 +10,11 @@ #include #define perf_arch_bpf_user_pt_regs(regs) (struct user_regs_struct *)regs + +#define perf_arch_fetch_caller_regs(regs, __ip) { \ + (regs)->epc = (__ip); \ + (regs)->s0 = (unsigned long) __builtin_frame_address(0); \ + (regs)->sp = current_stack_pointer; \ + (regs)->status = SR_PP; \ +} #endif /* _ASM_RISCV_PERF_EVENT_H */ diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index fbdccc21418a5b..153864e4f3996d 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -23,6 +23,10 @@ ifdef CONFIG_FTRACE CFLAGS_REMOVE_alternative.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_cpufeature.o = $(CC_FLAGS_FTRACE) endif +ifdef CONFIG_RELOCATABLE +CFLAGS_alternative.o += -fno-pie +CFLAGS_cpufeature.o += -fno-pie +endif ifdef CONFIG_KASAN KASAN_SANITIZE_alternative.o := n KASAN_SANITIZE_cpufeature.o := n diff --git a/arch/riscv/kernel/probes/Makefile b/arch/riscv/kernel/probes/Makefile index c40139e9ca4781..8265ff497977cf 100644 --- a/arch/riscv/kernel/probes/Makefile +++ b/arch/riscv/kernel/probes/Makefile @@ -4,3 +4,5 @@ obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o obj-$(CONFIG_KPROBES_ON_FTRACE) += ftrace.o obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o simulate-insn.o CFLAGS_REMOVE_simulate-insn.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_rethook_trampoline.o = $(CC_FLAGS_FTRACE) diff --git a/arch/riscv/mm/hugetlbpage.c b/arch/riscv/mm/hugetlbpage.c index a163a3e0f0d46b..e0ef56dc57b90a 100644 --- a/arch/riscv/mm/hugetlbpage.c +++ b/arch/riscv/mm/hugetlbpage.c @@ -3,6 +3,30 @@ #include #ifdef CONFIG_RISCV_ISA_SVNAPOT +pte_t huge_ptep_get(pte_t *ptep) +{ + unsigned long pte_num; + int i; + pte_t orig_pte = ptep_get(ptep); + + if (!pte_present(orig_pte) || !pte_napot(orig_pte)) + return orig_pte; + + pte_num = napot_pte_num(napot_cont_order(orig_pte)); + + for (i = 0; i < pte_num; i++, ptep++) { + pte_t pte = ptep_get(ptep); + + if (pte_dirty(pte)) + orig_pte = pte_mkdirty(orig_pte); + + if (pte_young(pte)) + orig_pte = pte_mkyoung(orig_pte); + } + + return orig_pte; +} + pte_t *huge_pte_alloc(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long addr, @@ -218,6 +242,7 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, { pte_t pte = ptep_get(ptep); unsigned long order; + pte_t orig_pte; int i, pte_num; if (!pte_napot(pte)) { @@ -228,9 +253,12 @@ void huge_ptep_set_wrprotect(struct mm_struct *mm, order = napot_cont_order(pte); pte_num = napot_pte_num(order); ptep = huge_pte_offset(mm, addr, napot_cont_size(order)); + orig_pte = get_clear_contig_flush(mm, addr, ptep, pte_num); + + orig_pte = pte_wrprotect(orig_pte); for (i = 0; i < pte_num; i++, addr += PAGE_SIZE, ptep++) - ptep_set_wrprotect(mm, addr, ptep); + set_pte_at(mm, addr, ptep, orig_pte); } pte_t huge_ptep_clear_flush(struct vm_area_struct *vma, diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index 747e5b1ef02d35..c6bb966e412372 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -922,9 +922,9 @@ static void __init create_kernel_page_table(pgd_t *pgdir, bool early) static void __init create_fdt_early_page_table(uintptr_t fix_fdt_va, uintptr_t dtb_pa) { +#ifndef CONFIG_BUILTIN_DTB uintptr_t pa = dtb_pa & ~(PMD_SIZE - 1); -#ifndef CONFIG_BUILTIN_DTB /* Make sure the fdt fixmap address is always aligned on PMD size */ BUILD_BUG_ON(FIX_FDT % (PMD_SIZE / PAGE_SIZE)); diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index db20c1589a98f3..6dab9c1be508b9 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -469,19 +469,11 @@ config SCHED_SMT config SCHED_MC def_bool n -config SCHED_BOOK - def_bool n - -config SCHED_DRAWER - def_bool n - config SCHED_TOPOLOGY def_bool y prompt "Topology scheduler support" select SCHED_SMT select SCHED_MC - select SCHED_BOOK - select SCHED_DRAWER help Topology scheduler support improves the CPU scheduler's decision making when dealing with machines that have multi-threading, @@ -716,7 +708,6 @@ config EADM_SCH config VFIO_CCW def_tristate n prompt "Support for VFIO-CCW subchannels" - depends on S390_CCW_IOMMU depends on VFIO select VFIO_MDEV help @@ -728,7 +719,7 @@ config VFIO_CCW config VFIO_AP def_tristate n prompt "VFIO support for AP devices" - depends on S390_AP_IOMMU && KVM + depends on KVM depends on VFIO depends on ZCRYPT select VFIO_MDEV diff --git a/arch/s390/configs/debug_defconfig b/arch/s390/configs/debug_defconfig index 4ccf66d29fc24b..be3bf03bf36185 100644 --- a/arch/s390/configs/debug_defconfig +++ b/arch/s390/configs/debug_defconfig @@ -591,8 +591,6 @@ CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_INPUT=y CONFIG_VHOST_NET=m CONFIG_VHOST_VSOCK=m -CONFIG_S390_CCW_IOMMU=y -CONFIG_S390_AP_IOMMU=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y @@ -703,6 +701,7 @@ CONFIG_IMA_DEFAULT_HASH_SHA256=y CONFIG_IMA_WRITE_POLICY=y CONFIG_IMA_APPRAISE=y CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" +CONFIG_INIT_STACK_NONE=y CONFIG_CRYPTO_USER=m # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set CONFIG_CRYPTO_PCRYPT=m diff --git a/arch/s390/configs/defconfig b/arch/s390/configs/defconfig index 693297a2e89733..769c7eed8b6ac6 100644 --- a/arch/s390/configs/defconfig +++ b/arch/s390/configs/defconfig @@ -580,8 +580,6 @@ CONFIG_VIRTIO_BALLOON=m CONFIG_VIRTIO_INPUT=y CONFIG_VHOST_NET=m CONFIG_VHOST_VSOCK=m -CONFIG_S390_CCW_IOMMU=y -CONFIG_S390_AP_IOMMU=y CONFIG_EXT4_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_EXT4_FS_SECURITY=y @@ -686,6 +684,7 @@ CONFIG_IMA_DEFAULT_HASH_SHA256=y CONFIG_IMA_WRITE_POLICY=y CONFIG_IMA_APPRAISE=y CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" +CONFIG_INIT_STACK_NONE=y CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_USER=m # CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set diff --git a/arch/s390/configs/zfcpdump_defconfig b/arch/s390/configs/zfcpdump_defconfig index 33a232bb68af95..6f68b39817effc 100644 --- a/arch/s390/configs/zfcpdump_defconfig +++ b/arch/s390/configs/zfcpdump_defconfig @@ -67,6 +67,7 @@ CONFIG_ZFCP=y # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_NETWORK_FILESYSTEMS is not set CONFIG_LSM="yama,loadpin,safesetid,integrity" +CONFIG_INIT_STACK_NONE=y # CONFIG_ZLIB_DFLTCC is not set CONFIG_XZ_DEC_MICROLZMA=y CONFIG_PRINTK_TIME=y diff --git a/arch/s390/crypto/chacha-glue.c b/arch/s390/crypto/chacha-glue.c index 7752bd314558e5..5fae187f947a08 100644 --- a/arch/s390/crypto/chacha-glue.c +++ b/arch/s390/crypto/chacha-glue.c @@ -82,7 +82,7 @@ void chacha_crypt_arch(u32 *state, u8 *dst, const u8 *src, * it cannot handle a block of data or less, but otherwise * it can handle data of arbitrary size */ - if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20) + if (bytes <= CHACHA_BLOCK_SIZE || nrounds != 20 || !MACHINE_HAS_VX) chacha_crypt_generic(state, dst, src, bytes, nrounds); else chacha20_crypt_s390(state, dst, src, bytes, diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index a386070f1d5653..3cb9d813f022b9 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -112,7 +112,7 @@ struct compat_statfs64 { u32 f_namelen; u32 f_frsize; u32 f_flags; - u32 f_spare[4]; + u32 f_spare[5]; }; /* diff --git a/arch/s390/include/uapi/asm/statfs.h b/arch/s390/include/uapi/asm/statfs.h index 72604f7792c336..f85b50723dd355 100644 --- a/arch/s390/include/uapi/asm/statfs.h +++ b/arch/s390/include/uapi/asm/statfs.h @@ -30,7 +30,7 @@ struct statfs { unsigned int f_namelen; unsigned int f_frsize; unsigned int f_flags; - unsigned int f_spare[4]; + unsigned int f_spare[5]; }; struct statfs64 { @@ -45,7 +45,7 @@ struct statfs64 { unsigned int f_namelen; unsigned int f_frsize; unsigned int f_flags; - unsigned int f_spare[4]; + unsigned int f_spare[5]; }; #endif diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 8983837b356591..6b2a051e1f8a2a 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -10,6 +10,7 @@ CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) # Do not trace early setup code CFLAGS_REMOVE_early.o = $(CC_FLAGS_FTRACE) +CFLAGS_REMOVE_rethook.o = $(CC_FLAGS_FTRACE) endif diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 43de939b7af199..f44f70de966115 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c @@ -1935,14 +1935,13 @@ static struct shutdown_action __refdata dump_action = { static void dump_reipl_run(struct shutdown_trigger *trigger) { - unsigned long ipib = (unsigned long) reipl_block_actual; struct lowcore *abs_lc; unsigned int csum; csum = (__force unsigned int) csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0); abs_lc = get_abs_lowcore(); - abs_lc->ipib = ipib; + abs_lc->ipib = __pa(reipl_block_actual); abs_lc->ipib_checksum = csum; put_abs_lowcore(abs_lc); dump_run(trigger); diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 9fd19530c9a562..68adf1de8888b2 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c @@ -95,7 +95,7 @@ static void cpu_group_map(cpumask_t *dst, struct mask_info *info, unsigned int c static void cpu_thread_map(cpumask_t *dst, unsigned int cpu) { static cpumask_t mask; - int i; + unsigned int max_cpu; cpumask_clear(&mask); if (!cpumask_test_cpu(cpu, &cpu_setup_mask)) @@ -104,9 +104,10 @@ static void cpu_thread_map(cpumask_t *dst, unsigned int cpu) if (topology_mode != TOPOLOGY_MODE_HW) goto out; cpu -= cpu % (smp_cpu_mtid + 1); - for (i = 0; i <= smp_cpu_mtid; i++) { - if (cpumask_test_cpu(cpu + i, &cpu_setup_mask)) - cpumask_set_cpu(cpu + i, &mask); + max_cpu = min(cpu + smp_cpu_mtid, nr_cpu_ids - 1); + for (; cpu <= max_cpu; cpu++) { + if (cpumask_test_cpu(cpu, &cpu_setup_mask)) + cpumask_set_cpu(cpu, &mask); } out: cpumask_copy(dst, &mask); @@ -123,25 +124,26 @@ static void add_cpus_to_mask(struct topology_core *tl_core, unsigned int core; for_each_set_bit(core, &tl_core->mask, TOPOLOGY_CORE_BITS) { - unsigned int rcore; - int lcpu, i; + unsigned int max_cpu, rcore; + int cpu; rcore = TOPOLOGY_CORE_BITS - 1 - core + tl_core->origin; - lcpu = smp_find_processor_id(rcore << smp_cpu_mt_shift); - if (lcpu < 0) + cpu = smp_find_processor_id(rcore << smp_cpu_mt_shift); + if (cpu < 0) continue; - for (i = 0; i <= smp_cpu_mtid; i++) { - topo = &cpu_topology[lcpu + i]; + max_cpu = min(cpu + smp_cpu_mtid, nr_cpu_ids - 1); + for (; cpu <= max_cpu; cpu++) { + topo = &cpu_topology[cpu]; topo->drawer_id = drawer->id; topo->book_id = book->id; topo->socket_id = socket->id; topo->core_id = rcore; - topo->thread_id = lcpu + i; + topo->thread_id = cpu; topo->dedicated = tl_core->d; - cpumask_set_cpu(lcpu + i, &drawer->mask); - cpumask_set_cpu(lcpu + i, &book->mask); - cpumask_set_cpu(lcpu + i, &socket->mask); - smp_cpu_set_polarization(lcpu + i, tl_core->pp); + cpumask_set_cpu(cpu, &drawer->mask); + cpumask_set_cpu(cpu, &book->mask); + cpumask_set_cpu(cpu, &socket->mask); + smp_cpu_set_polarization(cpu, tl_core->pp); } } } diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h index 2fda57a3ea86e6..682da3714686c9 100644 --- a/arch/sparc/include/uapi/asm/socket.h +++ b/arch/sparc/include/uapi/asm/socket.h @@ -130,6 +130,9 @@ #define SO_RCVMARK 0x0054 +#define SO_PASSPIDFD 0x0055 +#define SO_PEERPIDFD 0x0056 + #if !defined(__KERNEL__) diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile index dee6f66353b334..a461a950f0518d 100644 --- a/arch/um/drivers/Makefile +++ b/arch/um/drivers/Makefile @@ -16,7 +16,8 @@ mconsole-objs := mconsole_kern.o mconsole_user.o hostaudio-objs := hostaudio_kern.o ubd-objs := ubd_kern.o ubd_user.o port-objs := port_kern.o port_user.o -harddog-objs := harddog_kern.o harddog_user.o +harddog-objs := harddog_kern.o +harddog-builtin-$(CONFIG_UML_WATCHDOG) := harddog_user.o harddog_user_exp.o rtc-objs := rtc_kern.o rtc_user.o LDFLAGS_pcap.o = $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libpcap.a) @@ -60,6 +61,7 @@ obj-$(CONFIG_PTY_CHAN) += pty.o obj-$(CONFIG_TTY_CHAN) += tty.o obj-$(CONFIG_XTERM_CHAN) += xterm.o xterm_kern.o obj-$(CONFIG_UML_WATCHDOG) += harddog.o +obj-y += $(harddog-builtin-y) $(harddog-builtin-m) obj-$(CONFIG_BLK_DEV_COW_COMMON) += cow_user.o obj-$(CONFIG_UML_RANDOM) += random.o obj-$(CONFIG_VIRTIO_UML) += virtio_uml.o diff --git a/arch/um/drivers/harddog.h b/arch/um/drivers/harddog.h new file mode 100644 index 00000000000000..6d9ea60e7133e8 --- /dev/null +++ b/arch/um/drivers/harddog.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef UM_WATCHDOG_H +#define UM_WATCHDOG_H + +int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); +void stop_watchdog(int in_fd, int out_fd); +int ping_watchdog(int fd); + +#endif /* UM_WATCHDOG_H */ diff --git a/arch/um/drivers/harddog_kern.c b/arch/um/drivers/harddog_kern.c index e6d4f43deba82a..60d1c6cab8a951 100644 --- a/arch/um/drivers/harddog_kern.c +++ b/arch/um/drivers/harddog_kern.c @@ -47,6 +47,7 @@ #include #include #include "mconsole.h" +#include "harddog.h" MODULE_LICENSE("GPL"); @@ -60,8 +61,6 @@ static int harddog_out_fd = -1; * Allow only one person to hold it open */ -extern int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock); - static int harddog_open(struct inode *inode, struct file *file) { int err = -EBUSY; @@ -92,8 +91,6 @@ static int harddog_open(struct inode *inode, struct file *file) return err; } -extern void stop_watchdog(int in_fd, int out_fd); - static int harddog_release(struct inode *inode, struct file *file) { /* @@ -112,8 +109,6 @@ static int harddog_release(struct inode *inode, struct file *file) return 0; } -extern int ping_watchdog(int fd); - static ssize_t harddog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c index 070468d22e3943..9ed89304975ed3 100644 --- a/arch/um/drivers/harddog_user.c +++ b/arch/um/drivers/harddog_user.c @@ -7,6 +7,7 @@ #include #include #include +#include "harddog.h" struct dog_data { int stdin_fd; diff --git a/arch/um/drivers/harddog_user_exp.c b/arch/um/drivers/harddog_user_exp.c new file mode 100644 index 00000000000000..c74d4b815d143d --- /dev/null +++ b/arch/um/drivers/harddog_user_exp.c @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include "harddog.h" + +#if IS_MODULE(CONFIG_UML_WATCHDOG) +EXPORT_SYMBOL(start_watchdog); +EXPORT_SYMBOL(stop_watchdog); +EXPORT_SYMBOL(ping_watchdog); +#endif diff --git a/arch/x86/crypto/aria-aesni-avx-asm_64.S b/arch/x86/crypto/aria-aesni-avx-asm_64.S index 7c1abc513f3462..9556dacd984154 100644 --- a/arch/x86/crypto/aria-aesni-avx-asm_64.S +++ b/arch/x86/crypto/aria-aesni-avx-asm_64.S @@ -773,8 +773,6 @@ .octa 0x3F893781E95FE1576CDA64D2BA0CB204 #ifdef CONFIG_AS_GFNI -.section .rodata.cst8, "aM", @progbits, 8 -.align 8 /* AES affine: */ #define tf_aff_const BV8(1, 1, 0, 0, 0, 1, 1, 0) .Ltf_aff_bitmatrix: diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index 070cc4ef267210..89b9c1cebb613a 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4074,7 +4074,7 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data) if (x86_pmu.intel_cap.pebs_baseline) { arr[(*nr)++] = (struct perf_guest_switch_msr){ .msr = MSR_PEBS_DATA_CFG, - .host = cpuc->pebs_data_cfg, + .host = cpuc->active_pebs_data_cfg, .guest = kvm_pmu->pebs_data_cfg, }; } diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c index fa9b209a11fabc..d49e90dc04a4cc 100644 --- a/arch/x86/events/intel/uncore_snbep.c +++ b/arch/x86/events/intel/uncore_snbep.c @@ -6150,6 +6150,7 @@ static struct intel_uncore_type spr_uncore_mdf = { }; #define UNCORE_SPR_NUM_UNCORE_TYPES 12 +#define UNCORE_SPR_CHA 0 #define UNCORE_SPR_IIO 1 #define UNCORE_SPR_IMC 6 #define UNCORE_SPR_UPI 8 @@ -6460,12 +6461,22 @@ static int uncore_type_max_boxes(struct intel_uncore_type **types, return max + 1; } +#define SPR_MSR_UNC_CBO_CONFIG 0x2FFE + void spr_uncore_cpu_init(void) { + struct intel_uncore_type *type; + u64 num_cbo; + uncore_msr_uncores = uncore_get_uncores(UNCORE_ACCESS_MSR, UNCORE_SPR_MSR_EXTRA_UNCORES, spr_msr_uncores); + type = uncore_find_type_by_id(uncore_msr_uncores, UNCORE_SPR_CHA); + if (type) { + rdmsrl(SPR_MSR_UNC_CBO_CONFIG, num_cbo); + type->num_boxes = num_cbo; + } spr_uncore_iio_free_running.num_boxes = uncore_type_max_boxes(uncore_msr_uncores, UNCORE_SPR_IIO); } diff --git a/arch/x86/include/asm/fpu/sched.h b/arch/x86/include/asm/fpu/sched.h index c2d6cd78ed0c29..78fcde7b1f0700 100644 --- a/arch/x86/include/asm/fpu/sched.h +++ b/arch/x86/include/asm/fpu/sched.h @@ -39,7 +39,7 @@ extern void fpu_flush_thread(void); static inline void switch_fpu_prepare(struct fpu *old_fpu, int cpu) { if (cpu_feature_enabled(X86_FEATURE_FPU) && - !(current->flags & (PF_KTHREAD | PF_IO_WORKER))) { + !(current->flags & (PF_KTHREAD | PF_USER_WORKER))) { save_fpregs_to_fpstate(old_fpu); /* * The save operation preserved register state, so the diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 498dc600bd5c8e..0d02c4aafa6f49 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h @@ -13,7 +13,9 @@ #include +#include #include + #include #include diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index dd61752f4c966b..4070a01c11b72a 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -17,6 +17,7 @@ CFLAGS_REMOVE_ftrace.o = -pg CFLAGS_REMOVE_early_printk.o = -pg CFLAGS_REMOVE_head64.o = -pg CFLAGS_REMOVE_sev.o = -pg +CFLAGS_REMOVE_rethook.o = -pg endif KASAN_SANITIZE_head$(BITS).o := n diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index 5e868b62a7c4e4..0270925fe013bc 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -79,7 +79,7 @@ int detect_extended_topology_early(struct cpuinfo_x86 *c) * initial apic id, which also represents 32-bit extended x2apic id. */ c->initial_apicid = edx; - smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); + smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx)); #endif return 0; } @@ -109,7 +109,8 @@ int detect_extended_topology(struct cpuinfo_x86 *c) */ cpuid_count(leaf, SMT_LEVEL, &eax, &ebx, &ecx, &edx); c->initial_apicid = edx; - core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); + core_level_siblings = LEVEL_MAX_SIBLINGS(ebx); + smp_num_siblings = max_t(int, smp_num_siblings, LEVEL_MAX_SIBLINGS(ebx)); core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); die_level_siblings = LEVEL_MAX_SIBLINGS(ebx); pkg_mask_width = die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 0bf6779187dda1..f18ca44c904b74 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -195,7 +195,6 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, printk("%sCall Trace:\n", log_lvl); unwind_start(&state, task, regs, stack); - stack = stack ? : get_stack_pointer(task, regs); regs = unwind_get_entry_regs(&state, &partial); /* @@ -214,9 +213,13 @@ static void show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, * - hardirq stack * - entry stack */ - for ( ; stack; stack = PTR_ALIGN(stack_info.next_sp, sizeof(long))) { + for (stack = stack ?: get_stack_pointer(task, regs); + stack; + stack = stack_info.next_sp) { const char *stack_name; + stack = PTR_ALIGN(stack, sizeof(long)); + if (get_stack_info(stack, task, &stack_info, &visit_mask)) { /* * We weren't on a valid stack. It's possible that diff --git a/arch/x86/kernel/fpu/context.h b/arch/x86/kernel/fpu/context.h index 9fcfa5c4dad799..af5cbdd9bd29a2 100644 --- a/arch/x86/kernel/fpu/context.h +++ b/arch/x86/kernel/fpu/context.h @@ -57,7 +57,7 @@ static inline void fpregs_restore_userregs(void) struct fpu *fpu = ¤t->thread.fpu; int cpu = smp_processor_id(); - if (WARN_ON_ONCE(current->flags & (PF_KTHREAD | PF_IO_WORKER))) + if (WARN_ON_ONCE(current->flags & (PF_KTHREAD | PF_USER_WORKER))) return; if (!fpregs_state_valid(fpu, cpu)) { diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c index caf33486dc5ee5..1015af1ae562bf 100644 --- a/arch/x86/kernel/fpu/core.c +++ b/arch/x86/kernel/fpu/core.c @@ -426,7 +426,7 @@ void kernel_fpu_begin_mask(unsigned int kfpu_mask) this_cpu_write(in_kernel_fpu, true); - if (!(current->flags & (PF_KTHREAD | PF_IO_WORKER)) && + if (!(current->flags & (PF_KTHREAD | PF_USER_WORKER)) && !test_thread_flag(TIF_NEED_FPU_LOAD)) { set_thread_flag(TIF_NEED_FPU_LOAD); save_fpregs_to_fpstate(¤t->thread.fpu); diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 123bf8b97a4b21..0c9660a07b233f 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -253,7 +253,6 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e int nent) { struct kvm_cpuid_entry2 *best; - u64 guest_supported_xcr0 = cpuid_get_supported_xcr0(entries, nent); best = cpuid_entry2_find(entries, nent, 1, KVM_CPUID_INDEX_NOT_SIGNIFICANT); if (best) { @@ -292,21 +291,6 @@ static void __kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu, struct kvm_cpuid_e vcpu->arch.ia32_misc_enable_msr & MSR_IA32_MISC_ENABLE_MWAIT); } - - /* - * Bits 127:0 of the allowed SECS.ATTRIBUTES (CPUID.0x12.0x1) enumerate - * the supported XSAVE Feature Request Mask (XFRM), i.e. the enclave's - * requested XCR0 value. The enclave's XFRM must be a subset of XCRO - * at the time of EENTER, thus adjust the allowed XFRM by the guest's - * supported XCR0. Similar to XCR0 handling, FP and SSE are forced to - * '1' even on CPUs that don't support XSAVE. - */ - best = cpuid_entry2_find(entries, nent, 0x12, 0x1); - if (best) { - best->ecx &= guest_supported_xcr0 & 0xffffffff; - best->edx &= guest_supported_xcr0 >> 32; - best->ecx |= XFEATURE_MASK_FPSSE; - } } void kvm_update_cpuid_runtime(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index e542cf285b5184..3c300a196bdf94 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -228,6 +228,23 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, u32 xapic_id = kvm_xapic_id(apic); u32 physical_id; + /* + * For simplicity, KVM always allocates enough space for all possible + * xAPIC IDs. Yell, but don't kill the VM, as KVM can continue on + * without the optimized map. + */ + if (WARN_ON_ONCE(xapic_id > new->max_apic_id)) + return -EINVAL; + + /* + * Bail if a vCPU was added and/or enabled its APIC between allocating + * the map and doing the actual calculations for the map. Note, KVM + * hardcodes the x2APIC ID to vcpu_id, i.e. there's no TOCTOU bug if + * the compiler decides to reload x2apic_id after this check. + */ + if (x2apic_id > new->max_apic_id) + return -E2BIG; + /* * Deliberately truncate the vCPU ID when detecting a mismatched APIC * ID to avoid false positives if the vCPU ID, i.e. x2APIC ID, is a @@ -253,8 +270,7 @@ static int kvm_recalculate_phys_map(struct kvm_apic_map *new, */ if (vcpu->kvm->arch.x2apic_format) { /* See also kvm_apic_match_physical_addr(). */ - if ((apic_x2apic_mode(apic) || x2apic_id > 0xff) && - x2apic_id <= new->max_apic_id) + if (apic_x2apic_mode(apic) || x2apic_id > 0xff) new->phys_map[x2apic_id] = apic; if (!apic_x2apic_mode(apic) && !new->phys_map[xapic_id]) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index c8961f45e3b1c1..6eaa3d6994aebe 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -7091,7 +7091,10 @@ static void kvm_recover_nx_huge_pages(struct kvm *kvm) */ slot = NULL; if (atomic_read(&kvm->nr_memslots_dirty_logging)) { - slot = gfn_to_memslot(kvm, sp->gfn); + struct kvm_memslots *slots; + + slots = kvm_memslots_for_spte_role(kvm, sp->role); + slot = __gfn_to_memslot(slots, sp->gfn); WARN_ON_ONCE(!slot); } diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index ca32389f3c36ba..54089f990c8f83 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -3510,7 +3510,7 @@ static bool svm_is_vnmi_pending(struct kvm_vcpu *vcpu) if (!is_vnmi_enabled(svm)) return false; - return !!(svm->vmcb->control.int_ctl & V_NMI_BLOCKING_MASK); + return !!(svm->vmcb->control.int_ctl & V_NMI_PENDING_MASK); } static bool svm_set_vnmi_pending(struct kvm_vcpu *vcpu) diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c index 0574030b071fbf..2261b684a7d447 100644 --- a/arch/x86/kvm/vmx/sgx.c +++ b/arch/x86/kvm/vmx/sgx.c @@ -170,12 +170,19 @@ static int __handle_encls_ecreate(struct kvm_vcpu *vcpu, return 1; } - /* Enforce CPUID restrictions on MISCSELECT, ATTRIBUTES and XFRM. */ + /* + * Enforce CPUID restrictions on MISCSELECT, ATTRIBUTES and XFRM. Note + * that the allowed XFRM (XFeature Request Mask) isn't strictly bound + * by the supported XCR0. FP+SSE *must* be set in XFRM, even if XSAVE + * is unsupported, i.e. even if XCR0 itself is completely unsupported. + */ if ((u32)miscselect & ~sgx_12_0->ebx || (u32)attributes & ~sgx_12_1->eax || (u32)(attributes >> 32) & ~sgx_12_1->ebx || (u32)xfrm & ~sgx_12_1->ecx || - (u32)(xfrm >> 32) & ~sgx_12_1->edx) { + (u32)(xfrm >> 32) & ~sgx_12_1->edx || + xfrm & ~(vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FPSSE) || + (xfrm & XFEATURE_MASK_FPSSE) != XFEATURE_MASK_FPSSE) { kvm_inject_gp(vcpu, 0); return 1; } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ceb7c5e9cf9e92..04b57a336b34e5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1446,7 +1446,7 @@ static const u32 msrs_to_save_base[] = { #endif MSR_IA32_TSC, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA, MSR_IA32_FEAT_CTL, MSR_IA32_BNDCFGS, MSR_TSC_AUX, - MSR_IA32_SPEC_CTRL, + MSR_IA32_SPEC_CTRL, MSR_IA32_TSX_CTRL, MSR_IA32_RTIT_CTL, MSR_IA32_RTIT_STATUS, MSR_IA32_RTIT_CR3_MATCH, MSR_IA32_RTIT_OUTPUT_BASE, MSR_IA32_RTIT_OUTPUT_MASK, MSR_IA32_RTIT_ADDR0_A, MSR_IA32_RTIT_ADDR0_B, @@ -7155,6 +7155,10 @@ static void kvm_probe_msr_to_save(u32 msr_index) if (!kvm_cpu_cap_has(X86_FEATURE_XFD)) return; break; + case MSR_IA32_TSX_CTRL: + if (!(kvm_get_arch_capabilities() & ARCH_CAP_TSX_CTRL_MSR)) + return; + break; default: break; } @@ -10754,6 +10758,9 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) exit_fastpath = EXIT_FASTPATH_EXIT_HANDLED; break; } + + /* Note, VM-Exits that go down the "slow" path are accounted below. */ + ++vcpu->stat.exits; } /* diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S index 4fc5c2de2de467..01c5de4c279b8f 100644 --- a/arch/x86/lib/copy_user_64.S +++ b/arch/x86/lib/copy_user_64.S @@ -7,6 +7,8 @@ */ #include +#include +#include #include #include @@ -29,7 +31,7 @@ */ SYM_FUNC_START(rep_movs_alternative) cmpq $64,%rcx - jae .Lunrolled + jae .Llarge cmp $8,%ecx jae .Lword @@ -65,6 +67,12 @@ SYM_FUNC_START(rep_movs_alternative) _ASM_EXTABLE_UA( 2b, .Lcopy_user_tail) _ASM_EXTABLE_UA( 3b, .Lcopy_user_tail) +.Llarge: +0: ALTERNATIVE "jmp .Lunrolled", "rep movsb", X86_FEATURE_ERMS +1: RET + + _ASM_EXTABLE_UA( 0b, 1b) + .p2align 4 .Lunrolled: 10: movq (%rsi),%r8 diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 3cdac0f0055dee..8192452d1d2d35 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -261,6 +262,24 @@ static void __init probe_page_size_mask(void) } } +#define INTEL_MATCH(_model) { .vendor = X86_VENDOR_INTEL, \ + .family = 6, \ + .model = _model, \ + } +/* + * INVLPG may not properly flush Global entries + * on these CPUs when PCIDs are enabled. + */ +static const struct x86_cpu_id invlpg_miss_ids[] = { + INTEL_MATCH(INTEL_FAM6_ALDERLAKE ), + INTEL_MATCH(INTEL_FAM6_ALDERLAKE_L ), + INTEL_MATCH(INTEL_FAM6_ALDERLAKE_N ), + INTEL_MATCH(INTEL_FAM6_RAPTORLAKE ), + INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_P), + INTEL_MATCH(INTEL_FAM6_RAPTORLAKE_S), + {} +}; + static void setup_pcid(void) { if (!IS_ENABLED(CONFIG_X86_64)) @@ -269,6 +288,12 @@ static void setup_pcid(void) if (!boot_cpu_has(X86_FEATURE_PCID)) return; + if (x86_match_cpu(invlpg_miss_ids)) { + pr_info("Incomplete global flushes, disabling PCID"); + setup_clear_cpu_cap(X86_FEATURE_PCID); + return; + } + if (boot_cpu_has(X86_FEATURE_PGE)) { /* * This can't be cr4_set_bits_and_update_boot() -- the diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 8babce71915fe5..014c508e914d98 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -198,7 +198,7 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) i++; } kfree(v); - return 0; + return msi_device_populate_sysfs(&dev->dev); error: if (ret == -ENOSYS) @@ -254,7 +254,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) dev_dbg(&dev->dev, "xen: msi --> pirq=%d --> irq=%d\n", pirq, irq); } - return 0; + return msi_device_populate_sysfs(&dev->dev); error: dev_err(&dev->dev, "Failed to create MSI%s! ret=%d!\n", @@ -346,7 +346,7 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) if (ret < 0) goto out; } - ret = 0; + ret = msi_device_populate_sysfs(&dev->dev); out: return ret; } @@ -394,6 +394,8 @@ static void xen_teardown_msi_irqs(struct pci_dev *dev) xen_destroy_irq(msidesc->irq + i); msidesc->irq = 0; } + + msi_device_destroy_sysfs(&dev->dev); } static void xen_pv_teardown_msi_irqs(struct pci_dev *dev) diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 876d5df157ed98..5c01d7e70d90da 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -343,7 +343,19 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, struct rt_sigframe *frame; int err = 0, sig = ksig->sig; unsigned long sp, ra, tp, ps; + unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler; + unsigned long handler_fdpic_GOT = 0; unsigned int base; + bool fdpic = IS_ENABLED(CONFIG_BINFMT_ELF_FDPIC) && + (current->personality & FDPIC_FUNCPTRS); + + if (fdpic) { + unsigned long __user *fdpic_func_desc = + (unsigned long __user *)handler; + if (__get_user(handler, &fdpic_func_desc[0]) || + __get_user(handler_fdpic_GOT, &fdpic_func_desc[1])) + return -EFAULT; + } sp = regs->areg[1]; @@ -373,20 +385,26 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); if (ksig->ka.sa.sa_flags & SA_RESTORER) { - ra = (unsigned long)ksig->ka.sa.sa_restorer; + if (fdpic) { + unsigned long __user *fdpic_func_desc = + (unsigned long __user *)ksig->ka.sa.sa_restorer; + + err |= __get_user(ra, fdpic_func_desc); + } else { + ra = (unsigned long)ksig->ka.sa.sa_restorer; + } } else { /* Create sys_rt_sigreturn syscall in stack frame */ err |= gen_return_code(frame->retcode); - - if (err) { - return -EFAULT; - } ra = (unsigned long) frame->retcode; } - /* + if (err) + return -EFAULT; + + /* * Create signal handler execution context. * Return context not modified until this point. */ @@ -394,8 +412,7 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, /* Set up registers for signal handler; preserve the threadptr */ tp = regs->threadptr; ps = regs->ps; - start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler, - (unsigned long) frame); + start_thread(regs, handler, (unsigned long)frame); /* Set up a stack frame for a call4 if userspace uses windowed ABI */ if (ps & PS_WOE_MASK) { @@ -413,6 +430,8 @@ static int setup_frame(struct ksignal *ksig, sigset_t *set, regs->areg[base + 4] = (unsigned long) &frame->uc; regs->threadptr = tp; regs->ps = ps; + if (fdpic) + regs->areg[base + 11] = handler_fdpic_GOT; pr_debug("SIG rt deliver (%s:%d): signal=%d sp=%p pc=%08lx\n", current->comm, current->pid, sig, frame, regs->pc); diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 2a31b1ab0c9f20..17a7ef86fd0dd0 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -56,6 +56,8 @@ EXPORT_SYMBOL(empty_zero_page); */ extern long long __ashrdi3(long long, int); extern long long __ashldi3(long long, int); +extern long long __bswapdi2(long long); +extern int __bswapsi2(int); extern long long __lshrdi3(long long, int); extern int __divsi3(int, int); extern int __modsi3(int, int); @@ -66,6 +68,8 @@ extern unsigned long long __umulsidi3(unsigned int, unsigned int); EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__ashrdi3); +EXPORT_SYMBOL(__bswapdi2); +EXPORT_SYMBOL(__bswapsi2); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(__divsi3); EXPORT_SYMBOL(__modsi3); diff --git a/arch/xtensa/lib/Makefile b/arch/xtensa/lib/Makefile index 7ecef0519a27ca..c9c2614188f74c 100644 --- a/arch/xtensa/lib/Makefile +++ b/arch/xtensa/lib/Makefile @@ -4,7 +4,7 @@ # lib-y += memcopy.o memset.o checksum.o \ - ashldi3.o ashrdi3.o lshrdi3.o \ + ashldi3.o ashrdi3.o bswapdi2.o bswapsi2.o lshrdi3.o \ divsi3.o udivsi3.o modsi3.o umodsi3.o mulsi3.o umulsidi3.o \ usercopy.o strncpy_user.o strnlen_user.o lib-$(CONFIG_PCI) += pci-auto.o diff --git a/arch/xtensa/lib/bswapdi2.S b/arch/xtensa/lib/bswapdi2.S new file mode 100644 index 00000000000000..d8e52e05eba664 --- /dev/null +++ b/arch/xtensa/lib/bswapdi2.S @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ +#include +#include +#include + +ENTRY(__bswapdi2) + + abi_entry_default + ssai 8 + srli a4, a2, 16 + src a4, a4, a2 + src a4, a4, a4 + src a4, a2, a4 + srli a2, a3, 16 + src a2, a2, a3 + src a2, a2, a2 + src a2, a3, a2 + mov a3, a4 + abi_ret_default + +ENDPROC(__bswapdi2) diff --git a/arch/xtensa/lib/bswapsi2.S b/arch/xtensa/lib/bswapsi2.S new file mode 100644 index 00000000000000..9c1de1344f79ad --- /dev/null +++ b/arch/xtensa/lib/bswapsi2.S @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ +#include +#include +#include + +ENTRY(__bswapsi2) + + abi_entry_default + ssai 8 + srli a3, a2, 16 + src a3, a3, a2 + src a3, a3, a3 + src a2, a2, a3 + abi_ret_default + +ENDPROC(__bswapsi2) diff --git a/block/blk-core.c b/block/blk-core.c index 00c74330fa92c2..1da77e7d628946 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -520,7 +520,7 @@ static inline int bio_check_eod(struct bio *bio) sector_t maxsector = bdev_nr_sectors(bio->bi_bdev); unsigned int nr_sectors = bio_sectors(bio); - if (nr_sectors && maxsector && + if (nr_sectors && (nr_sectors > maxsector || bio->bi_iter.bi_sector > maxsector - nr_sectors)) { pr_info_ratelimited("%s: attempt to access beyond end of device\n" diff --git a/block/blk-map.c b/block/blk-map.c index 04c55f1c492eb1..46eed2e627c363 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -248,7 +248,7 @@ static struct bio *blk_rq_map_bio_alloc(struct request *rq, { struct bio *bio; - if (rq->cmd_flags & REQ_ALLOC_CACHE) { + if (rq->cmd_flags & REQ_ALLOC_CACHE && (nr_vecs <= BIO_INLINE_VECS)) { bio = bio_alloc_bioset(NULL, nr_vecs, rq->cmd_flags, gfp_mask, &fs_bio_set); if (!bio) diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index d6af9d431dc631..dfd81cab57888b 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -39,16 +39,20 @@ void __blk_mq_tag_busy(struct blk_mq_hw_ctx *hctx) { unsigned int users; + /* + * calling test_bit() prior to test_and_set_bit() is intentional, + * it avoids dirtying the cacheline if the queue is already active. + */ if (blk_mq_is_shared_tags(hctx->flags)) { struct request_queue *q = hctx->queue; - if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags)) + if (test_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags) || + test_and_set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags)) return; - set_bit(QUEUE_FLAG_HCTX_ACTIVE, &q->queue_flags); } else { - if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) + if (test_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state) || + test_and_set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state)) return; - set_bit(BLK_MQ_S_TAG_ACTIVE, &hctx->state); } users = atomic_inc_return(&hctx->tags->active_queues); diff --git a/block/blk-settings.c b/block/blk-settings.c index 896b4654ab00fa..4dd59059b788eb 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -915,6 +915,7 @@ static bool disk_has_partitions(struct gendisk *disk) void disk_set_zoned(struct gendisk *disk, enum blk_zoned_model model) { struct request_queue *q = disk->queue; + unsigned int old_model = q->limits.zoned; switch (model) { case BLK_ZONED_HM: @@ -952,7 +953,7 @@ void disk_set_zoned(struct gendisk *disk, enum blk_zoned_model model) */ blk_queue_zone_write_granularity(q, queue_logical_block_size(q)); - } else { + } else if (old_model != BLK_ZONED_NONE) { disk_clear_zone_settings(disk); } } diff --git a/block/blk-wbt.c b/block/blk-wbt.c index e49a4868453276..9ec2a2f1eda388 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -730,14 +730,16 @@ void wbt_enable_default(struct gendisk *disk) { struct request_queue *q = disk->queue; struct rq_qos *rqos; - bool disable_flag = q->elevator && - test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags); + bool enable = IS_ENABLED(CONFIG_BLK_WBT_MQ); + + if (q->elevator && + test_bit(ELEVATOR_FLAG_DISABLE_WBT, &q->elevator->flags)) + enable = false; /* Throttling already enabled? */ rqos = wbt_rq_qos(q); if (rqos) { - if (!disable_flag && - RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT) + if (enable && RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT) RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT; return; } @@ -746,7 +748,7 @@ void wbt_enable_default(struct gendisk *disk) if (!blk_queue_registered(q)) return; - if (queue_is_mq(q) && !disable_flag) + if (queue_is_mq(q) && enable) wbt_init(disk); } EXPORT_SYMBOL_GPL(wbt_enable_default); diff --git a/block/fops.c b/block/fops.c index d2e6be4e3d1c7d..58d0aebc7313a8 100644 --- a/block/fops.c +++ b/block/fops.c @@ -678,6 +678,16 @@ static long blkdev_fallocate(struct file *file, int mode, loff_t start, return error; } +static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) +{ + struct inode *bd_inode = bdev_file_inode(file); + + if (bdev_read_only(I_BDEV(bd_inode))) + return generic_file_readonly_mmap(file, vma); + + return generic_file_mmap(file, vma); +} + const struct file_operations def_blk_fops = { .open = blkdev_open, .release = blkdev_close, @@ -685,7 +695,7 @@ const struct file_operations def_blk_fops = { .read_iter = blkdev_read_iter, .write_iter = blkdev_write_iter, .iopoll = iocb_bio_iopoll, - .mmap = generic_file_mmap, + .mmap = blkdev_mmap, .fsync = blkdev_fsync, .unlocked_ioctl = blkdev_ioctl, #ifdef CONFIG_COMPAT diff --git a/crypto/af_alg.c b/crypto/af_alg.c index 5f7252a5b7b44a..7d4b6016b83d1c 100644 --- a/crypto/af_alg.c +++ b/crypto/af_alg.c @@ -531,50 +531,25 @@ static const struct net_proto_family alg_family = { .owner = THIS_MODULE, }; -int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len) -{ - size_t off; - ssize_t n; - int npages, i; - - n = iov_iter_get_pages2(iter, sgl->pages, len, ALG_MAX_PAGES, &off); - if (n < 0) - return n; - - npages = DIV_ROUND_UP(off + n, PAGE_SIZE); - if (WARN_ON(npages == 0)) - return -EINVAL; - /* Add one extra for linking */ - sg_init_table(sgl->sg, npages + 1); - - for (i = 0, len = n; i < npages; i++) { - int plen = min_t(int, len, PAGE_SIZE - off); - - sg_set_page(sgl->sg + i, sgl->pages[i], plen, off); - - off = 0; - len -= plen; - } - sg_mark_end(sgl->sg + npages - 1); - sgl->npages = npages; - - return n; -} -EXPORT_SYMBOL_GPL(af_alg_make_sg); - static void af_alg_link_sg(struct af_alg_sgl *sgl_prev, struct af_alg_sgl *sgl_new) { - sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); - sg_chain(sgl_prev->sg, sgl_prev->npages + 1, sgl_new->sg); + sg_unmark_end(sgl_prev->sgt.sgl + sgl_prev->sgt.nents - 1); + sg_chain(sgl_prev->sgt.sgl, sgl_prev->sgt.nents + 1, sgl_new->sgt.sgl); } void af_alg_free_sg(struct af_alg_sgl *sgl) { int i; - for (i = 0; i < sgl->npages; i++) - put_page(sgl->pages[i]); + if (sgl->sgt.sgl) { + if (sgl->need_unpin) + for (i = 0; i < sgl->sgt.nents; i++) + unpin_user_page(sg_page(&sgl->sgt.sgl[i])); + if (sgl->sgt.sgl != sgl->sgl) + kvfree(sgl->sgt.sgl); + sgl->sgt.sgl = NULL; + } } EXPORT_SYMBOL_GPL(af_alg_free_sg); @@ -1015,7 +990,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, while (size) { struct scatterlist *sg; size_t len = size; - size_t plen; + ssize_t plen; /* use the existing memory in an allocated page */ if (ctx->merge) { @@ -1060,35 +1035,58 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size, if (sgl->cur) sg_unmark_end(sg + sgl->cur - 1); - do { - struct page *pg; - unsigned int i = sgl->cur; - - plen = min_t(size_t, len, PAGE_SIZE); - - pg = alloc_page(GFP_KERNEL); - if (!pg) { - err = -ENOMEM; + if (msg->msg_flags & MSG_SPLICE_PAGES) { + struct sg_table sgtable = { + .sgl = sg, + .nents = sgl->cur, + .orig_nents = sgl->cur, + }; + + plen = extract_iter_to_sg(&msg->msg_iter, len, &sgtable, + MAX_SGL_ENTS, 0); + if (plen < 0) { + err = plen; goto unlock; } - sg_assign_page(sg + i, pg); - - err = memcpy_from_msg(page_address(sg_page(sg + i)), - msg, plen); - if (err) { - __free_page(sg_page(sg + i)); - sg_assign_page(sg + i, NULL); - goto unlock; - } - - sg[i].length = plen; + for (; sgl->cur < sgtable.nents; sgl->cur++) + get_page(sg_page(&sg[sgl->cur])); len -= plen; ctx->used += plen; copied += plen; size -= plen; - sgl->cur++; - } while (len && sgl->cur < MAX_SGL_ENTS); + } else { + do { + struct page *pg; + unsigned int i = sgl->cur; + + plen = min_t(size_t, len, PAGE_SIZE); + + pg = alloc_page(GFP_KERNEL); + if (!pg) { + err = -ENOMEM; + goto unlock; + } + + sg_assign_page(sg + i, pg); + + err = memcpy_from_msg( + page_address(sg_page(sg + i)), + msg, plen); + if (err) { + __free_page(sg_page(sg + i)); + sg_assign_page(sg + i, NULL); + goto unlock; + } + + sg[i].length = plen; + len -= plen; + ctx->used += plen; + copied += plen; + size -= plen; + sgl->cur++; + } while (len && sgl->cur < MAX_SGL_ENTS); + } if (!size) sg_mark_end(sg + sgl->cur - 1); @@ -1121,53 +1119,17 @@ EXPORT_SYMBOL_GPL(af_alg_sendmsg); ssize_t af_alg_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { - struct sock *sk = sock->sk; - struct alg_sock *ask = alg_sk(sk); - struct af_alg_ctx *ctx = ask->private; - struct af_alg_tsgl *sgl; - int err = -EINVAL; + struct bio_vec bvec; + struct msghdr msg = { + .msg_flags = flags | MSG_SPLICE_PAGES, + }; if (flags & MSG_SENDPAGE_NOTLAST) - flags |= MSG_MORE; - - lock_sock(sk); - if (!ctx->more && ctx->used) - goto unlock; - - if (!size) - goto done; - - if (!af_alg_writable(sk)) { - err = af_alg_wait_for_wmem(sk, flags); - if (err) - goto unlock; - } - - err = af_alg_alloc_tsgl(sk); - if (err) - goto unlock; - - ctx->merge = 0; - sgl = list_entry(ctx->tsgl_list.prev, struct af_alg_tsgl, list); - - if (sgl->cur) - sg_unmark_end(sgl->sg + sgl->cur - 1); - - sg_mark_end(sgl->sg + sgl->cur); - - get_page(page); - sg_set_page(sgl->sg + sgl->cur, page, size, offset); - sgl->cur++; - ctx->used += size; + msg.msg_flags |= MSG_MORE; -done: - ctx->more = flags & MSG_MORE; - -unlock: - af_alg_data_wakeup(sk); - release_sock(sk); - - return err ?: size; + bvec_set_page(&bvec, page, size, offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size); + return sock_sendmsg(sock, &msg); } EXPORT_SYMBOL_GPL(af_alg_sendpage); @@ -1288,8 +1250,8 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, while (maxsize > len && msg_data_left(msg)) { struct af_alg_rsgl *rsgl; + ssize_t err; size_t seglen; - int err; /* limit the amount of readable buffers */ if (!af_alg_readable(sk)) @@ -1306,16 +1268,23 @@ int af_alg_get_rsgl(struct sock *sk, struct msghdr *msg, int flags, return -ENOMEM; } - rsgl->sgl.npages = 0; + rsgl->sgl.sgt.sgl = rsgl->sgl.sgl; + rsgl->sgl.sgt.nents = 0; + rsgl->sgl.sgt.orig_nents = 0; list_add_tail(&rsgl->list, &areq->rsgl_list); - /* make one iovec available as scatterlist */ - err = af_alg_make_sg(&rsgl->sgl, &msg->msg_iter, seglen); + sg_init_table(rsgl->sgl.sgt.sgl, ALG_MAX_PAGES); + err = extract_iter_to_sg(&msg->msg_iter, seglen, &rsgl->sgl.sgt, + ALG_MAX_PAGES, 0); if (err < 0) { rsgl->sg_num_bytes = 0; return err; } + sg_mark_end(rsgl->sgl.sgt.sgl + rsgl->sgl.sgt.nents - 1); + rsgl->sgl.need_unpin = + iov_iter_extract_will_pin(&msg->msg_iter); + /* chain the new scatterlist with previous one */ if (areq->last_rsgl) af_alg_link_sg(&areq->last_rsgl->sgl, &rsgl->sgl); diff --git a/crypto/algif_aead.c b/crypto/algif_aead.c index 42493b4d8ce462..35bfa283748d95 100644 --- a/crypto/algif_aead.c +++ b/crypto/algif_aead.c @@ -9,8 +9,8 @@ * The following concept of the memory management is used: * * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is - * filled by user space with the data submitted via sendpage/sendmsg. Filling - * up the TX SGL does not cause a crypto operation -- the data will only be + * filled by user space with the data submitted via sendpage. Filling up + * the TX SGL does not cause a crypto operation -- the data will only be * tracked by the kernel. Upon receipt of one recvmsg call, the caller must * provide a buffer which is tracked with the RX SGL. * @@ -113,19 +113,19 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, } /* - * Data length provided by caller via sendmsg/sendpage that has not - * yet been processed. + * Data length provided by caller via sendmsg that has not yet been + * processed. */ used = ctx->used; /* - * Make sure sufficient data is present -- note, the same check is - * also present in sendmsg/sendpage. The checks in sendpage/sendmsg - * shall provide an information to the data sender that something is - * wrong, but they are irrelevant to maintain the kernel integrity. - * We need this check here too in case user space decides to not honor - * the error message in sendmsg/sendpage and still call recvmsg. This - * check here protects the kernel integrity. + * Make sure sufficient data is present -- note, the same check is also + * present in sendmsg. The checks in sendmsg shall provide an + * information to the data sender that something is wrong, but they are + * irrelevant to maintain the kernel integrity. We need this check + * here too in case user space decides to not honor the error message + * in sendmsg and still call recvmsg. This check here protects the + * kernel integrity. */ if (!aead_sufficient_data(sk)) return -EINVAL; @@ -210,7 +210,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, */ /* Use the RX SGL as source (and destination) for crypto op. */ - rsgl_src = areq->first_rsgl.sgl.sg; + rsgl_src = areq->first_rsgl.sgl.sgt.sgl; if (ctx->enc) { /* @@ -224,7 +224,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, * RX SGL: AAD || PT || Tag */ err = crypto_aead_copy_sgl(null_tfm, tsgl_src, - areq->first_rsgl.sgl.sg, processed); + areq->first_rsgl.sgl.sgt.sgl, + processed); if (err) goto free; af_alg_pull_tsgl(sk, processed, NULL, 0); @@ -242,7 +243,8 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* Copy AAD || CT to RX SGL buffer for in-place operation. */ err = crypto_aead_copy_sgl(null_tfm, tsgl_src, - areq->first_rsgl.sgl.sg, outlen); + areq->first_rsgl.sgl.sgt.sgl, + outlen); if (err) goto free; @@ -267,10 +269,10 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, if (usedpages) { /* RX SGL present */ struct af_alg_sgl *sgl_prev = &areq->last_rsgl->sgl; + struct scatterlist *sg = sgl_prev->sgt.sgl; - sg_unmark_end(sgl_prev->sg + sgl_prev->npages - 1); - sg_chain(sgl_prev->sg, sgl_prev->npages + 1, - areq->tsgl); + sg_unmark_end(sg + sgl_prev->sgt.nents - 1); + sg_chain(sg, sgl_prev->sgt.nents + 1, areq->tsgl); } else /* no RX SGL present (e.g. authentication only) */ rsgl_src = areq->tsgl; @@ -278,7 +280,7 @@ static int _aead_recvmsg(struct socket *sock, struct msghdr *msg, /* Initialize the crypto operation */ aead_request_set_crypt(&areq->cra_u.aead_req, rsgl_src, - areq->first_rsgl.sgl.sg, used, ctx->iv); + areq->first_rsgl.sgl.sgt.sgl, used, ctx->iv); aead_request_set_ad(&areq->cra_u.aead_req, ctx->aead_assoclen); aead_request_set_tfm(&areq->cra_u.aead_req, tfm); diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 63af72e19fa8c9..dfb048cefb6073 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -63,122 +63,102 @@ static void hash_free_result(struct sock *sk, struct hash_ctx *ctx) static int hash_sendmsg(struct socket *sock, struct msghdr *msg, size_t ignored) { - int limit = ALG_MAX_PAGES * PAGE_SIZE; struct sock *sk = sock->sk; struct alg_sock *ask = alg_sk(sk); struct hash_ctx *ctx = ask->private; - long copied = 0; + ssize_t copied = 0; + size_t len, max_pages, npages; + bool continuing = ctx->more, need_init = false; int err; - if (limit > sk->sk_sndbuf) - limit = sk->sk_sndbuf; + max_pages = min_t(size_t, ALG_MAX_PAGES, + DIV_ROUND_UP(sk->sk_sndbuf, PAGE_SIZE)); lock_sock(sk); - if (!ctx->more) { + if (!continuing) { if ((msg->msg_flags & MSG_MORE)) hash_free_result(sk, ctx); - - err = crypto_wait_req(crypto_ahash_init(&ctx->req), &ctx->wait); - if (err) - goto unlock; + need_init = true; } ctx->more = false; while (msg_data_left(msg)) { - int len = msg_data_left(msg); - - if (len > limit) - len = limit; - - len = af_alg_make_sg(&ctx->sgl, &msg->msg_iter, len); - if (len < 0) { - err = copied ? 0 : len; - goto unlock; - } - - ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, NULL, len); - - err = crypto_wait_req(crypto_ahash_update(&ctx->req), - &ctx->wait); - af_alg_free_sg(&ctx->sgl); - if (err) { - iov_iter_revert(&msg->msg_iter, len); - goto unlock; + ctx->sgl.sgt.sgl = ctx->sgl.sgl; + ctx->sgl.sgt.nents = 0; + ctx->sgl.sgt.orig_nents = 0; + + err = -EIO; + npages = iov_iter_npages(&msg->msg_iter, max_pages); + if (npages == 0) + goto unlock_free; + + if (npages > ARRAY_SIZE(ctx->sgl.sgl)) { + err = -ENOMEM; + ctx->sgl.sgt.sgl = + kvmalloc(array_size(npages, + sizeof(*ctx->sgl.sgt.sgl)), + GFP_KERNEL); + if (!ctx->sgl.sgt.sgl) + goto unlock_free; } + sg_init_table(ctx->sgl.sgl, npages); - copied += len; - } + ctx->sgl.need_unpin = iov_iter_extract_will_pin(&msg->msg_iter); - err = 0; + err = extract_iter_to_sg(&msg->msg_iter, LONG_MAX, + &ctx->sgl.sgt, npages, 0); + if (err < 0) + goto unlock_free; + len = err; + sg_mark_end(ctx->sgl.sgt.sgl + ctx->sgl.sgt.nents - 1); - ctx->more = msg->msg_flags & MSG_MORE; - if (!ctx->more) { - err = hash_alloc_result(sk, ctx); - if (err) - goto unlock; - - ahash_request_set_crypt(&ctx->req, NULL, ctx->result, 0); - err = crypto_wait_req(crypto_ahash_final(&ctx->req), - &ctx->wait); - } - -unlock: - release_sock(sk); - - return err ?: copied; -} - -static ssize_t hash_sendpage(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - struct sock *sk = sock->sk; - struct alg_sock *ask = alg_sk(sk); - struct hash_ctx *ctx = ask->private; - int err; - - if (flags & MSG_SENDPAGE_NOTLAST) - flags |= MSG_MORE; - - lock_sock(sk); - sg_init_table(ctx->sgl.sg, 1); - sg_set_page(ctx->sgl.sg, page, size, offset); - - if (!(flags & MSG_MORE)) { - err = hash_alloc_result(sk, ctx); - if (err) - goto unlock; - } else if (!ctx->more) - hash_free_result(sk, ctx); + if (!msg_data_left(msg)) { + err = hash_alloc_result(sk, ctx); + if (err) + goto unlock_free; + } - ahash_request_set_crypt(&ctx->req, ctx->sgl.sg, ctx->result, size); + ahash_request_set_crypt(&ctx->req, ctx->sgl.sgt.sgl, + ctx->result, len); - if (!(flags & MSG_MORE)) { - if (ctx->more) - err = crypto_ahash_finup(&ctx->req); - else + if (!msg_data_left(msg) && !continuing && + !(msg->msg_flags & MSG_MORE)) { err = crypto_ahash_digest(&ctx->req); - } else { - if (!ctx->more) { - err = crypto_ahash_init(&ctx->req); - err = crypto_wait_req(err, &ctx->wait); - if (err) - goto unlock; + } else { + if (need_init) { + err = crypto_wait_req( + crypto_ahash_init(&ctx->req), + &ctx->wait); + if (err) + goto unlock_free; + need_init = false; + } + + if (msg_data_left(msg) || (msg->msg_flags & MSG_MORE)) + err = crypto_ahash_update(&ctx->req); + else + err = crypto_ahash_finup(&ctx->req); + continuing = true; } - err = crypto_ahash_update(&ctx->req); - } - - err = crypto_wait_req(err, &ctx->wait); - if (err) - goto unlock; + err = crypto_wait_req(err, &ctx->wait); + if (err) + goto unlock_free; - ctx->more = flags & MSG_MORE; + copied += len; + af_alg_free_sg(&ctx->sgl); + } + ctx->more = msg->msg_flags & MSG_MORE; + err = 0; unlock: release_sock(sk); + return copied ?: err; - return err ?: size; +unlock_free: + af_alg_free_sg(&ctx->sgl); + goto unlock; } static int hash_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, @@ -296,7 +276,6 @@ static struct proto_ops algif_hash_ops = { .release = af_alg_release, .sendmsg = hash_sendmsg, - .sendpage = hash_sendpage, .recvmsg = hash_recvmsg, .accept = hash_accept, }; @@ -348,18 +327,6 @@ static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg, return hash_sendmsg(sock, msg, size); } -static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page, - int offset, size_t size, int flags) -{ - int err; - - err = hash_check_key(sock); - if (err) - return err; - - return hash_sendpage(sock, page, offset, size, flags); -} - static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg, size_t ignored, int flags) { @@ -398,7 +365,6 @@ static struct proto_ops algif_hash_ops_nokey = { .release = af_alg_release, .sendmsg = hash_sendmsg_nokey, - .sendpage = hash_sendpage_nokey, .recvmsg = hash_recvmsg_nokey, .accept = hash_accept_nokey, }; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index ee8890ee8f3329..b1f321b9f846af 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -9,10 +9,10 @@ * The following concept of the memory management is used: * * The kernel maintains two SGLs, the TX SGL and the RX SGL. The TX SGL is - * filled by user space with the data submitted via sendpage/sendmsg. Filling - * up the TX SGL does not cause a crypto operation -- the data will only be - * tracked by the kernel. Upon receipt of one recvmsg call, the caller must - * provide a buffer which is tracked with the RX SGL. + * filled by user space with the data submitted via sendmsg. Filling up the TX + * SGL does not cause a crypto operation -- the data will only be tracked by + * the kernel. Upon receipt of one recvmsg call, the caller must provide a + * buffer which is tracked with the RX SGL. * * During the processing of the recvmsg operation, the cipher request is * allocated and prepared. As part of the recvmsg operation, the processed @@ -105,7 +105,7 @@ static int _skcipher_recvmsg(struct socket *sock, struct msghdr *msg, /* Initialize the crypto operation */ skcipher_request_set_tfm(&areq->cra_u.skcipher_req, tfm); skcipher_request_set_crypt(&areq->cra_u.skcipher_req, areq->tsgl, - areq->first_rsgl.sgl.sg, len, ctx->iv); + areq->first_rsgl.sgl.sgt.sgl, len, ctx->iv); if (msg->msg_iocb && !is_sync_kiocb(msg->msg_iocb)) { /* AIO operation */ diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index eca5671ad3f228..50c933f86b218c 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -380,9 +380,10 @@ int public_key_verify_signature(const struct public_key *pkey, struct crypto_wait cwait; struct crypto_akcipher *tfm; struct akcipher_request *req; - struct scatterlist src_sg[2]; + struct scatterlist src_sg; char alg_name[CRYPTO_MAX_ALG_NAME]; - char *key, *ptr; + char *buf, *ptr; + size_t buf_len; int ret; pr_devel("==>%s()\n", __func__); @@ -420,34 +421,37 @@ int public_key_verify_signature(const struct public_key *pkey, if (!req) goto error_free_tfm; - key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, - GFP_KERNEL); - if (!key) + buf_len = max_t(size_t, pkey->keylen + sizeof(u32) * 2 + pkey->paramlen, + sig->s_size + sig->digest_size); + + buf = kmalloc(buf_len, GFP_KERNEL); + if (!buf) goto error_free_req; - memcpy(key, pkey->key, pkey->keylen); - ptr = key + pkey->keylen; + memcpy(buf, pkey->key, pkey->keylen); + ptr = buf + pkey->keylen; ptr = pkey_pack_u32(ptr, pkey->algo); ptr = pkey_pack_u32(ptr, pkey->paramlen); memcpy(ptr, pkey->params, pkey->paramlen); if (pkey->key_is_private) - ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen); + ret = crypto_akcipher_set_priv_key(tfm, buf, pkey->keylen); else - ret = crypto_akcipher_set_pub_key(tfm, key, pkey->keylen); + ret = crypto_akcipher_set_pub_key(tfm, buf, pkey->keylen); if (ret) - goto error_free_key; + goto error_free_buf; if (strcmp(pkey->pkey_algo, "sm2") == 0 && sig->data_size) { ret = cert_sig_digest_update(sig, tfm); if (ret) - goto error_free_key; + goto error_free_buf; } - sg_init_table(src_sg, 2); - sg_set_buf(&src_sg[0], sig->s, sig->s_size); - sg_set_buf(&src_sg[1], sig->digest, sig->digest_size); - akcipher_request_set_crypt(req, src_sg, NULL, sig->s_size, + memcpy(buf, sig->s, sig->s_size); + memcpy(buf + sig->s_size, sig->digest, sig->digest_size); + + sg_init_one(&src_sg, buf, sig->s_size + sig->digest_size); + akcipher_request_set_crypt(req, &src_sg, NULL, sig->s_size, sig->digest_size); crypto_init_wait(&cwait); akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | @@ -455,8 +459,8 @@ int public_key_verify_signature(const struct public_key *pkey, crypto_req_done, &cwait); ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); -error_free_key: - kfree(key); +error_free_buf: + kfree(buf); error_free_req: akcipher_request_free(req); error_free_tfm: diff --git a/drivers/accel/qaic/qaic_control.c b/drivers/accel/qaic/qaic_control.c index 9f216eb6f76ed8..5c57f7b4494e48 100644 --- a/drivers/accel/qaic/qaic_control.c +++ b/drivers/accel/qaic/qaic_control.c @@ -997,14 +997,34 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u struct xfer_queue_elem elem; struct wire_msg *out_buf; struct wrapper_msg *w; + long ret = -EAGAIN; + int xfer_count = 0; int retry_count; - long ret; if (qdev->in_reset) { mutex_unlock(&qdev->cntl_mutex); return ERR_PTR(-ENODEV); } + /* Attempt to avoid a partial commit of a message */ + list_for_each_entry(w, &wrappers->list, list) + xfer_count++; + + for (retry_count = 0; retry_count < QAIC_MHI_RETRY_MAX; retry_count++) { + if (xfer_count <= mhi_get_free_desc_count(qdev->cntl_ch, DMA_TO_DEVICE)) { + ret = 0; + break; + } + msleep_interruptible(QAIC_MHI_RETRY_WAIT_MS); + if (signal_pending(current)) + break; + } + + if (ret) { + mutex_unlock(&qdev->cntl_mutex); + return ERR_PTR(ret); + } + elem.seq_num = seq_num; elem.buf = NULL; init_completion(&elem.xfer_done); @@ -1038,16 +1058,9 @@ static void *msg_xfer(struct qaic_device *qdev, struct wrapper_list *wrappers, u list_for_each_entry(w, &wrappers->list, list) { kref_get(&w->ref_count); retry_count = 0; -retry: ret = mhi_queue_buf(qdev->cntl_ch, DMA_TO_DEVICE, &w->msg, w->len, list_is_last(&w->list, &wrappers->list) ? MHI_EOT : MHI_CHAIN); if (ret) { - if (ret == -EAGAIN && retry_count++ < QAIC_MHI_RETRY_MAX) { - msleep_interruptible(QAIC_MHI_RETRY_WAIT_MS); - if (!signal_pending(current)) - goto retry; - } - qdev->cntl_lost_buf = true; kref_put(&w->ref_count, free_wrapper); mutex_unlock(&qdev->cntl_mutex); @@ -1249,7 +1262,7 @@ static int qaic_manage(struct qaic_device *qdev, struct qaic_user *usr, struct m int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct qaic_manage_msg *user_msg; + struct qaic_manage_msg *user_msg = data; struct qaic_device *qdev; struct manage_msg *msg; struct qaic_user *usr; @@ -1258,6 +1271,9 @@ int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ int usr_rcu_id; int ret; + if (user_msg->len > QAIC_MANAGE_MAX_MSG_LENGTH) + return -EINVAL; + usr = file_priv->driver_priv; usr_rcu_id = srcu_read_lock(&usr->qddev_lock); @@ -1275,13 +1291,6 @@ int qaic_manage_ioctl(struct drm_device *dev, void *data, struct drm_file *file_ return -ENODEV; } - user_msg = data; - - if (user_msg->len > QAIC_MANAGE_MAX_MSG_LENGTH) { - ret = -EINVAL; - goto out; - } - msg = kzalloc(QAIC_MANAGE_MAX_MSG_LENGTH + sizeof(*msg), GFP_KERNEL); if (!msg) { ret = -ENOMEM; diff --git a/drivers/accel/qaic/qaic_data.c b/drivers/accel/qaic/qaic_data.c index c0a574cd1b35c6..e42c1f9ffff85e 100644 --- a/drivers/accel/qaic/qaic_data.c +++ b/drivers/accel/qaic/qaic_data.c @@ -591,7 +591,7 @@ static int qaic_gem_object_mmap(struct drm_gem_object *obj, struct vm_area_struc struct qaic_bo *bo = to_qaic_bo(obj); unsigned long offset = 0; struct scatterlist *sg; - int ret; + int ret = 0; if (obj->import_attach) return -EINVAL; @@ -663,6 +663,10 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi if (args->pad) return -EINVAL; + size = PAGE_ALIGN(args->size); + if (size == 0) + return -EINVAL; + usr = file_priv->driver_priv; usr_rcu_id = srcu_read_lock(&usr->qddev_lock); if (!usr->qddev) { @@ -677,12 +681,6 @@ int qaic_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *fi goto unlock_dev_srcu; } - size = PAGE_ALIGN(args->size); - if (size == 0) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - bo = qaic_alloc_init_bo(); if (IS_ERR(bo)) { ret = PTR_ERR(bo); @@ -926,8 +924,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi { struct qaic_attach_slice_entry *slice_ent; struct qaic_attach_slice *args = data; + int rcu_id, usr_rcu_id, qdev_rcu_id; struct dma_bridge_chan *dbc; - int usr_rcu_id, qdev_rcu_id; struct drm_gem_object *obj; struct qaic_device *qdev; unsigned long arg_size; @@ -936,6 +934,22 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi struct qaic_bo *bo; int ret; + if (args->hdr.count == 0) + return -EINVAL; + + arg_size = args->hdr.count * sizeof(*slice_ent); + if (arg_size / args->hdr.count != sizeof(*slice_ent)) + return -EINVAL; + + if (args->hdr.size == 0) + return -EINVAL; + + if (!(args->hdr.dir == DMA_TO_DEVICE || args->hdr.dir == DMA_FROM_DEVICE)) + return -EINVAL; + + if (args->data == 0) + return -EINVAL; + usr = file_priv->driver_priv; usr_rcu_id = srcu_read_lock(&usr->qddev_lock); if (!usr->qddev) { @@ -950,43 +964,11 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi goto unlock_dev_srcu; } - if (args->hdr.count == 0) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - - arg_size = args->hdr.count * sizeof(*slice_ent); - if (arg_size / args->hdr.count != sizeof(*slice_ent)) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - if (args->hdr.dbc_id >= qdev->num_dbc) { ret = -EINVAL; goto unlock_dev_srcu; } - if (args->hdr.size == 0) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - - if (!(args->hdr.dir == DMA_TO_DEVICE || args->hdr.dir == DMA_FROM_DEVICE)) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - - dbc = &qdev->dbc[args->hdr.dbc_id]; - if (dbc->usr != usr) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - - if (args->data == 0) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - user_data = u64_to_user_ptr(args->data); slice_ent = kzalloc(arg_size, GFP_KERNEL); @@ -1013,9 +995,21 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi bo = to_qaic_bo(obj); + if (bo->sliced) { + ret = -EINVAL; + goto put_bo; + } + + dbc = &qdev->dbc[args->hdr.dbc_id]; + rcu_id = srcu_read_lock(&dbc->ch_lock); + if (dbc->usr != usr) { + ret = -EINVAL; + goto unlock_ch_srcu; + } + ret = qaic_prepare_bo(qdev, bo, &args->hdr); if (ret) - goto put_bo; + goto unlock_ch_srcu; ret = qaic_attach_slicing_bo(qdev, bo, &args->hdr, slice_ent); if (ret) @@ -1025,6 +1019,7 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi dma_sync_sgtable_for_cpu(&qdev->pdev->dev, bo->sgt, args->hdr.dir); bo->dbc = dbc; + srcu_read_unlock(&dbc->ch_lock, rcu_id); drm_gem_object_put(obj); srcu_read_unlock(&qdev->dev_lock, qdev_rcu_id); srcu_read_unlock(&usr->qddev_lock, usr_rcu_id); @@ -1033,6 +1028,8 @@ int qaic_attach_slice_bo_ioctl(struct drm_device *dev, void *data, struct drm_fi unprepare_bo: qaic_unprepare_bo(qdev, bo); +unlock_ch_srcu: + srcu_read_unlock(&dbc->ch_lock, rcu_id); put_bo: drm_gem_object_put(obj); free_slice_ent: @@ -1316,7 +1313,6 @@ static int __qaic_execute_bo_ioctl(struct drm_device *dev, void *data, struct dr received_ts = ktime_get_ns(); size = is_partial ? sizeof(*pexec) : sizeof(*exec); - n = (unsigned long)size * args->hdr.count; if (args->hdr.count == 0 || n / args->hdr.count != size) return -EINVAL; @@ -1665,6 +1661,9 @@ int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file int rcu_id; int ret; + if (args->pad != 0) + return -EINVAL; + usr = file_priv->driver_priv; usr_rcu_id = srcu_read_lock(&usr->qddev_lock); if (!usr->qddev) { @@ -1679,11 +1678,6 @@ int qaic_wait_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file goto unlock_dev_srcu; } - if (args->pad != 0) { - ret = -EINVAL; - goto unlock_dev_srcu; - } - if (args->dbc_id >= qdev->num_dbc) { ret = -EINVAL; goto unlock_dev_srcu; @@ -1855,6 +1849,11 @@ void wakeup_dbc(struct qaic_device *qdev, u32 dbc_id) dbc->usr = NULL; empty_xfer_list(qdev, dbc); synchronize_srcu(&dbc->ch_lock); + /* + * Threads holding channel lock, may add more elements in the xfer_list. + * Flush out these elements from xfer_list. + */ + empty_xfer_list(qdev, dbc); } void release_dbc(struct qaic_device *qdev, u32 dbc_id) diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c index ff80eb5717290c..2d0828db28d8e9 100644 --- a/drivers/accel/qaic/qaic_drv.c +++ b/drivers/accel/qaic/qaic_drv.c @@ -262,8 +262,8 @@ static void qaic_destroy_drm_device(struct qaic_device *qdev, s32 partition_id) static int qaic_mhi_probe(struct mhi_device *mhi_dev, const struct mhi_device_id *id) { + u16 major = -1, minor = -1; struct qaic_device *qdev; - u16 major, minor; int ret; /* diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index 1d6ef96547252d..67c2c3b959e153 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -7,7 +7,6 @@ #ifndef APEI_INTERNAL_H #define APEI_INTERNAL_H -#include #include struct apei_exec_context; @@ -130,10 +129,5 @@ static inline u32 cper_estatus_len(struct acpi_hest_generic_status *estatus) return sizeof(*estatus) + estatus->data_length; } -void cper_estatus_print(const char *pfx, - const struct acpi_hest_generic_status *estatus); -int cper_estatus_check_header(const struct acpi_hest_generic_status *estatus); -int cper_estatus_check(const struct acpi_hest_generic_status *estatus); - int apei_osc_setup(void); #endif diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c index c23eb75866d021..7514e38d5640ee 100644 --- a/drivers/acpi/apei/bert.c +++ b/drivers/acpi/apei/bert.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "apei-internal.h" diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index e8492b3a393ab6..0800a9d7755806 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -516,6 +516,17 @@ static const struct dmi_system_id maingear_laptop[] = { { } }; +static const struct dmi_system_id lg_laptop[] = { + { + .ident = "LG Electronics 17U70P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), + DMI_MATCH(DMI_BOARD_NAME, "17U70P"), + }, + }, + { } +}; + struct irq_override_cmp { const struct dmi_system_id *system; unsigned char irq; @@ -532,6 +543,7 @@ static const struct irq_override_cmp override_table[] = { { lenovo_laptop, 10, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, true }, { tongfang_gm_rg, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, { maingear_laptop, 1, ACPI_EDGE_SENSITIVE, ACPI_ACTIVE_LOW, 1, true }, + { lg_laptop, 1, ACPI_LEVEL_SENSITIVE, ACPI_ACTIVE_LOW, 0, false }, }; static bool acpi_dev_irq_override(u32 gsi, u8 triggering, u8 polarity, diff --git a/drivers/android/binder.c b/drivers/android/binder.c index fb56bfc45096d4..8fb7672021ee2d 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -1934,24 +1934,23 @@ static void binder_deferred_fd_close(int fd) static void binder_transaction_buffer_release(struct binder_proc *proc, struct binder_thread *thread, struct binder_buffer *buffer, - binder_size_t failed_at, + binder_size_t off_end_offset, bool is_failure) { int debug_id = buffer->debug_id; - binder_size_t off_start_offset, buffer_offset, off_end_offset; + binder_size_t off_start_offset, buffer_offset; binder_debug(BINDER_DEBUG_TRANSACTION, "%d buffer release %d, size %zd-%zd, failed at %llx\n", proc->pid, buffer->debug_id, buffer->data_size, buffer->offsets_size, - (unsigned long long)failed_at); + (unsigned long long)off_end_offset); if (buffer->target_node) binder_dec_node(buffer->target_node, 1, 0); off_start_offset = ALIGN(buffer->data_size, sizeof(void *)); - off_end_offset = is_failure && failed_at ? failed_at : - off_start_offset + buffer->offsets_size; + for (buffer_offset = off_start_offset; buffer_offset < off_end_offset; buffer_offset += sizeof(binder_size_t)) { struct binder_object_header *hdr; @@ -2111,6 +2110,21 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, } } +/* Clean up all the objects in the buffer */ +static inline void binder_release_entire_buffer(struct binder_proc *proc, + struct binder_thread *thread, + struct binder_buffer *buffer, + bool is_failure) +{ + binder_size_t off_end_offset; + + off_end_offset = ALIGN(buffer->data_size, sizeof(void *)); + off_end_offset += buffer->offsets_size; + + binder_transaction_buffer_release(proc, thread, buffer, + off_end_offset, is_failure); +} + static int binder_translate_binder(struct flat_binder_object *fp, struct binder_transaction *t, struct binder_thread *thread) @@ -2806,7 +2820,7 @@ static int binder_proc_transaction(struct binder_transaction *t, t_outdated->buffer = NULL; buffer->transaction = NULL; trace_binder_transaction_update_buffer_release(buffer); - binder_transaction_buffer_release(proc, NULL, buffer, 0, 0); + binder_release_entire_buffer(proc, NULL, buffer, false); binder_alloc_free_buf(&proc->alloc, buffer); kfree(t_outdated); binder_stats_deleted(BINDER_STAT_TRANSACTION); @@ -3775,7 +3789,7 @@ binder_free_buf(struct binder_proc *proc, binder_node_inner_unlock(buf_node); } trace_binder_transaction_buffer_release(buffer); - binder_transaction_buffer_release(proc, thread, buffer, 0, is_failure); + binder_release_entire_buffer(proc, thread, buffer, is_failure); binder_alloc_free_buf(&proc->alloc, buffer); } diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 55a3c3c2409f01..662a2a2e2e84a7 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -212,8 +212,8 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, mm = alloc->mm; if (mm) { - mmap_read_lock(mm); - vma = vma_lookup(mm, alloc->vma_addr); + mmap_write_lock(mm); + vma = alloc->vma; } if (!vma && need_mm) { @@ -270,7 +270,7 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, trace_binder_alloc_page_end(alloc, index); } if (mm) { - mmap_read_unlock(mm); + mmap_write_unlock(mm); mmput(mm); } return 0; @@ -303,21 +303,24 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, } err_no_vma: if (mm) { - mmap_read_unlock(mm); + mmap_write_unlock(mm); mmput(mm); } return vma ? -ENOMEM : -ESRCH; } +static inline void binder_alloc_set_vma(struct binder_alloc *alloc, + struct vm_area_struct *vma) +{ + /* pairs with smp_load_acquire in binder_alloc_get_vma() */ + smp_store_release(&alloc->vma, vma); +} + static inline struct vm_area_struct *binder_alloc_get_vma( struct binder_alloc *alloc) { - struct vm_area_struct *vma = NULL; - - if (alloc->vma_addr) - vma = vma_lookup(alloc->mm, alloc->vma_addr); - - return vma; + /* pairs with smp_store_release in binder_alloc_set_vma() */ + return smp_load_acquire(&alloc->vma); } static bool debug_low_async_space_locked(struct binder_alloc *alloc, int pid) @@ -380,15 +383,13 @@ static struct binder_buffer *binder_alloc_new_buf_locked( size_t size, data_offsets_size; int ret; - mmap_read_lock(alloc->mm); + /* Check binder_alloc is fully initialized */ if (!binder_alloc_get_vma(alloc)) { - mmap_read_unlock(alloc->mm); binder_alloc_debug(BINDER_DEBUG_USER_ERROR, "%d: binder_alloc_buf, no vma\n", alloc->pid); return ERR_PTR(-ESRCH); } - mmap_read_unlock(alloc->mm); data_offsets_size = ALIGN(data_size, sizeof(void *)) + ALIGN(offsets_size, sizeof(void *)); @@ -778,7 +779,9 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, buffer->free = 1; binder_insert_free_buffer(alloc, buffer); alloc->free_async_space = alloc->buffer_size / 2; - alloc->vma_addr = vma->vm_start; + + /* Signal binder_alloc is fully initialized */ + binder_alloc_set_vma(alloc, vma); return 0; @@ -808,8 +811,7 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) buffers = 0; mutex_lock(&alloc->mutex); - BUG_ON(alloc->vma_addr && - vma_lookup(alloc->mm, alloc->vma_addr)); + BUG_ON(alloc->vma); while ((n = rb_first(&alloc->allocated_buffers))) { buffer = rb_entry(n, struct binder_buffer, rb_node); @@ -916,25 +918,17 @@ void binder_alloc_print_pages(struct seq_file *m, * Make sure the binder_alloc is fully initialized, otherwise we might * read inconsistent state. */ - - mmap_read_lock(alloc->mm); - if (binder_alloc_get_vma(alloc) == NULL) { - mmap_read_unlock(alloc->mm); - goto uninitialized; - } - - mmap_read_unlock(alloc->mm); - for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { - page = &alloc->pages[i]; - if (!page->page_ptr) - free++; - else if (list_empty(&page->lru)) - active++; - else - lru++; + if (binder_alloc_get_vma(alloc) != NULL) { + for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) { + page = &alloc->pages[i]; + if (!page->page_ptr) + free++; + else if (list_empty(&page->lru)) + active++; + else + lru++; + } } - -uninitialized: mutex_unlock(&alloc->mutex); seq_printf(m, " pages: %d:%d:%d\n", active, lru, free); seq_printf(m, " pages high watermark: %zu\n", alloc->pages_high); @@ -969,7 +963,7 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc) */ void binder_alloc_vma_close(struct binder_alloc *alloc) { - alloc->vma_addr = 0; + binder_alloc_set_vma(alloc, NULL); } /** diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 0f811ac4bcffd1..138d1d5af9ce36 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -75,7 +75,7 @@ struct binder_lru_page { /** * struct binder_alloc - per-binder proc state for binder allocator * @mutex: protects binder_alloc fields - * @vma_addr: vm_area_struct->vm_start passed to mmap_handler + * @vma: vm_area_struct passed to mmap_handler * (invariant after mmap) * @mm: copy of task->mm (invariant after open) * @buffer: base of per-proc address space mapped via mmap @@ -99,7 +99,7 @@ struct binder_lru_page { */ struct binder_alloc { struct mutex mutex; - unsigned long vma_addr; + struct vm_area_struct *vma; struct mm_struct *mm; void __user *buffer; struct list_head buffers; diff --git a/drivers/android/binder_alloc_selftest.c b/drivers/android/binder_alloc_selftest.c index 43a881073a4283..c2b323bc3b3a53 100644 --- a/drivers/android/binder_alloc_selftest.c +++ b/drivers/android/binder_alloc_selftest.c @@ -287,7 +287,7 @@ void binder_selftest_alloc(struct binder_alloc *alloc) if (!binder_selftest_run) return; mutex_lock(&binder_selftest_lock); - if (!binder_selftest_run || !alloc->vma_addr) + if (!binder_selftest_run || !alloc->vma) goto done; pr_info("STARTED\n"); binder_selftest_alloc_offset(alloc, end_offset, 0); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 7bb12deab70c46..8ce90284eb344b 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -2694,18 +2694,36 @@ static unsigned int atapi_xlat(struct ata_queued_cmd *qc) return 0; } -static struct ata_device *ata_find_dev(struct ata_port *ap, int devno) +static struct ata_device *ata_find_dev(struct ata_port *ap, unsigned int devno) { - if (!sata_pmp_attached(ap)) { - if (likely(devno >= 0 && - devno < ata_link_max_devices(&ap->link))) + /* + * For the non-PMP case, ata_link_max_devices() returns 1 (SATA case), + * or 2 (IDE master + slave case). However, the former case includes + * libsas hosted devices which are numbered per scsi host, leading + * to devno potentially being larger than 0 but with each struct + * ata_device having its own struct ata_port and struct ata_link. + * To accommodate these, ignore devno and always use device number 0. + */ + if (likely(!sata_pmp_attached(ap))) { + int link_max_devices = ata_link_max_devices(&ap->link); + + if (link_max_devices == 1) + return &ap->link.device[0]; + + if (devno < link_max_devices) return &ap->link.device[devno]; - } else { - if (likely(devno >= 0 && - devno < ap->nr_pmp_links)) - return &ap->pmp_link[devno].device[0]; + + return NULL; } + /* + * For PMP-attached devices, the device number corresponds to C + * (channel) of SCSI [H:C:I:L], indicating the port pmp link + * for the device. + */ + if (devno < ap->nr_pmp_links) + return &ap->pmp_link[devno].device[0]; + return NULL; } diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index bba3482ddeb82e..cbae8be1fe5200 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -388,6 +388,16 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) continue;/* skip if itself or no cacheinfo */ for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) { sib_leaf = per_cpu_cacheinfo_idx(i, sib_index); + + /* + * Comparing cache IDs only makes sense if the leaves + * belong to the same cache level of same type. Skip + * the check if level and type do not match. + */ + if (sib_leaf->level != this_leaf->level || + sib_leaf->type != this_leaf->type) + continue; + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { cpumask_set_cpu(cpu, &sib_leaf->shared_cpu_map); cpumask_set_cpu(i, &this_leaf->shared_cpu_map); @@ -400,11 +410,14 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) coherency_max_size = this_leaf->coherency_line_size; } + /* shared_cpu_map is now populated for the cpu */ + this_cpu_ci->cpu_map_populated = true; return 0; } static void cache_shared_cpu_map_remove(unsigned int cpu) { + struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); struct cacheinfo *this_leaf, *sib_leaf; unsigned int sibling, index, sib_index; @@ -419,6 +432,16 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) { sib_leaf = per_cpu_cacheinfo_idx(sibling, sib_index); + + /* + * Comparing cache IDs only makes sense if the leaves + * belong to the same cache level of same type. Skip + * the check if level and type do not match. + */ + if (sib_leaf->level != this_leaf->level || + sib_leaf->type != this_leaf->type) + continue; + if (cache_leaves_are_shared(this_leaf, sib_leaf)) { cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); @@ -427,6 +450,9 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) } } } + + /* cpu is no longer populated in the shared map */ + this_cpu_ci->cpu_map_populated = false; } static void free_cache_attributes(unsigned int cpu) diff --git a/drivers/base/class.c b/drivers/base/class.c index ac1808d1a2e8f0..05d9df90f621be 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -320,6 +320,7 @@ void class_dev_iter_init(struct class_dev_iter *iter, const struct class *class, start_knode = &start->p->knode_class; klist_iter_init_node(&sp->klist_devices, &iter->ki, start_knode); iter->type = type; + iter->sp = sp; } EXPORT_SYMBOL_GPL(class_dev_iter_init); @@ -361,6 +362,7 @@ EXPORT_SYMBOL_GPL(class_dev_iter_next); void class_dev_iter_exit(struct class_dev_iter *iter) { klist_iter_exit(&iter->ki); + subsys_put(iter->sp); } EXPORT_SYMBOL_GPL(class_dev_iter_exit); diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index 9d79d5ad910241..b58c42f1b1ce65 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -812,7 +812,7 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st char *outbuf; alg = crypto_alloc_shash("sha256", 0, 0); - if (!alg) + if (IS_ERR(alg)) return; sha256buf = kmalloc(SHA256_DIGEST_SIZE, GFP_KERNEL); diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 33a8366e22a584..0db2021f7477f2 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig @@ -4,16 +4,23 @@ # subsystems should select the appropriate symbols. config REGMAP + bool "Register Map support" if KUNIT_ALL_TESTS default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_W1 || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ || REGMAP_SOUNDWIRE || REGMAP_SOUNDWIRE_MBQ || REGMAP_SCCB || REGMAP_I3C || REGMAP_SPI_AVMM || REGMAP_MDIO || REGMAP_FSI) select IRQ_DOMAIN if REGMAP_IRQ select MDIO_BUS if REGMAP_MDIO - bool + help + Enable support for the Register Map (regmap) access API. + + Usually, this option is automatically selected when needed. + However, you may want to enable it manually for running the regmap + KUnit tests. + + If unsure, say N. config REGMAP_KUNIT tristate "KUnit tests for regmap" - depends on KUNIT + depends on KUNIT && REGMAP default KUNIT_ALL_TESTS - select REGMAP select REGMAP_RAM config REGMAP_AC97 diff --git a/drivers/base/regmap/regcache-maple.c b/drivers/base/regmap/regcache-maple.c index 9b1b559107ef4d..c2e3a0f6c2183b 100644 --- a/drivers/base/regmap/regcache-maple.c +++ b/drivers/base/regmap/regcache-maple.c @@ -203,15 +203,18 @@ static int regcache_maple_sync(struct regmap *map, unsigned int min, mas_for_each(&mas, entry, max) { for (r = max(mas.index, lmin); r <= min(mas.last, lmax); r++) { + mas_pause(&mas); + rcu_read_unlock(); ret = regcache_sync_val(map, r, entry[r - mas.index]); if (ret != 0) goto out; + rcu_read_lock(); } } -out: rcu_read_unlock(); +out: map->cache_bypass = false; return ret; diff --git a/drivers/base/regmap/regmap-sdw.c b/drivers/base/regmap/regmap-sdw.c index 09899ae99fc199..159c0b740b001c 100644 --- a/drivers/base/regmap/regmap-sdw.c +++ b/drivers/base/regmap/regmap-sdw.c @@ -59,6 +59,10 @@ static int regmap_sdw_config_check(const struct regmap_config *config) if (config->pad_bits != 0) return -ENOTSUPP; + /* Only bulk writes are supported not multi-register writes */ + if (config->can_multi_write) + return -ENOTSUPP; + return 0; } diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index db7851f0e3b8cd..fa2d3fba6ac9d1 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -2082,6 +2082,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, size_t val_count = val_len / val_bytes; size_t chunk_count, chunk_bytes; size_t chunk_regs = val_count; + size_t max_data = map->max_raw_write - map->format.reg_bytes - + map->format.pad_bytes; int ret, i; if (!val_count) @@ -2089,8 +2091,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg, if (map->use_single_write) chunk_regs = 1; - else if (map->max_raw_write && val_len > map->max_raw_write) - chunk_regs = map->max_raw_write / val_bytes; + else if (map->max_raw_write && val_len > max_data) + chunk_regs = max_data / val_bytes; chunk_count = val_count / chunk_regs; chunk_bytes = chunk_regs * val_bytes; diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c index c7ed5d69e9eee2..33d3298a0da16f 100644 --- a/drivers/block/ublk_drv.c +++ b/drivers/block/ublk_drv.c @@ -1120,6 +1120,11 @@ static inline bool ublk_queue_ready(struct ublk_queue *ubq) return ubq->nr_io_ready == ubq->q_depth; } +static void ublk_cmd_cancel_cb(struct io_uring_cmd *cmd, unsigned issue_flags) +{ + io_uring_cmd_done(cmd, UBLK_IO_RES_ABORT, 0, issue_flags); +} + static void ublk_cancel_queue(struct ublk_queue *ubq) { int i; @@ -1131,8 +1136,8 @@ static void ublk_cancel_queue(struct ublk_queue *ubq) struct ublk_io *io = &ubq->ios[i]; if (io->flags & UBLK_IO_FLAG_ACTIVE) - io_uring_cmd_done(io->cmd, UBLK_IO_RES_ABORT, 0, - IO_URING_F_UNLOCKED); + io_uring_cmd_complete_in_task(io->cmd, + ublk_cmd_cancel_cb); } /* all io commands are canceled */ diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 23ed258b57f0e5..c1890c8a9f6e76 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -780,7 +780,8 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri ring_req->u.rw.handle = info->handle; ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; - if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) { + if (req_op(req) == REQ_OP_FLUSH || + (req_op(req) == REQ_OP_WRITE && (req->cmd_flags & REQ_FUA))) { /* * Ideally we can do an unordered flush-to-disk. * In case the backend onlysupports barriers, use that. diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c index 3a34d7c1475bce..52ef44688d38a3 100644 --- a/drivers/bluetooth/btnxpuart.c +++ b/drivers/bluetooth/btnxpuart.c @@ -1319,17 +1319,17 @@ static void nxp_serdev_remove(struct serdev_device *serdev) hci_free_dev(hdev); } -static struct btnxpuart_data w8987_data = { +static struct btnxpuart_data w8987_data __maybe_unused = { .helper_fw_name = NULL, .fw_name = FIRMWARE_W8987, }; -static struct btnxpuart_data w8997_data = { +static struct btnxpuart_data w8997_data __maybe_unused = { .helper_fw_name = FIRMWARE_HELPER, .fw_name = FIRMWARE_W8997, }; -static const struct of_device_id nxpuart_of_match_table[] = { +static const struct of_device_id nxpuart_of_match_table[] __maybe_unused = { { .compatible = "nxp,88w8987-bt", .data = &w8987_data }, { .compatible = "nxp,88w8997-bt", .data = &w8997_data }, { } diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index 1b064504b38875..e30c979535b1da 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -78,7 +78,8 @@ enum qca_flags { QCA_HW_ERROR_EVENT, QCA_SSR_TRIGGERED, QCA_BT_OFF, - QCA_ROM_FW + QCA_ROM_FW, + QCA_DEBUGFS_CREATED, }; enum qca_capabilities { @@ -635,6 +636,9 @@ static void qca_debugfs_init(struct hci_dev *hdev) if (!hdev->debugfs) return; + if (test_and_set_bit(QCA_DEBUGFS_CREATED, &qca->flags)) + return; + ibs_dir = debugfs_create_dir("ibs", hdev->debugfs); /* read only */ diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index d68d05d5d38388..514f9f287a781d 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -90,6 +90,9 @@ parisc_agp_tlbflush(struct agp_memory *mem) { struct _parisc_agp_info *info = &parisc_agp_info; + /* force fdc ops to be visible to IOMMU */ + asm_io_sync(); + writeq(info->gart_base | ilog2(info->gart_size), info->ioc_regs+IOC_PCOM); readq(info->ioc_regs+IOC_PCOM); /* flush */ } @@ -158,6 +161,7 @@ parisc_agp_insert_memory(struct agp_memory *mem, off_t pg_start, int type) info->gatt[j] = parisc_agp_mask_memory(agp_bridge, paddr, type); + asm_io_fdc(&info->gatt[j]); } } @@ -191,7 +195,16 @@ static unsigned long parisc_agp_mask_memory(struct agp_bridge_data *bridge, dma_addr_t addr, int type) { - return SBA_PDIR_VALID_BIT | addr; + unsigned ci; /* coherent index */ + dma_addr_t pa; + + pa = addr & IOVP_MASK; + asm("lci 0(%1), %0" : "=r" (ci) : "r" (phys_to_virt(pa))); + + pa |= (ci >> PAGE_SHIFT) & 0xff;/* move CI (8 bits) into lowest byte */ + pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */ + + return cpu_to_le64(pa); } static void diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 709b4e13bd6ec9..7db3593941eaa0 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -138,6 +138,13 @@ static const struct dmi_system_id tpm_tis_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad L490"), }, }, + { + .callback = tpm_tis_disable_irq, + .ident = "UPX-TGL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AAEON"), + }, + }, {} }; diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index e978f457fd4d4c..610bfadb6acf1c 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -84,10 +84,10 @@ enum tis_defaults { #define ILB_REMAP_SIZE 0x100 enum tpm_tis_flags { - TPM_TIS_ITPM_WORKAROUND = BIT(0), - TPM_TIS_INVALID_STATUS = BIT(1), - TPM_TIS_DEFAULT_CANCELLATION = BIT(2), - TPM_TIS_IRQ_TESTED = BIT(3), + TPM_TIS_ITPM_WORKAROUND = 0, + TPM_TIS_INVALID_STATUS = 1, + TPM_TIS_DEFAULT_CANCELLATION = 2, + TPM_TIS_IRQ_TESTED = 3, }; struct tpm_tis_data { diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 29904395e95f9c..b2f05d27167e39 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -975,7 +975,7 @@ static int __init acpi_cpufreq_probe(struct platform_device *pdev) /* don't keep reloading if cpufreq_driver exists */ if (cpufreq_get_current_driver()) - return -EEXIST; + return -ENODEV; pr_debug("%s\n", __func__); diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c index 5a3d4aa0f45a6a..ddd346a239e0b5 100644 --- a/drivers/cpufreq/amd-pstate.c +++ b/drivers/cpufreq/amd-pstate.c @@ -444,9 +444,8 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy) return 0; } -static int amd_pstate_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation) +static int amd_pstate_update_freq(struct cpufreq_policy *policy, + unsigned int target_freq, bool fast_switch) { struct cpufreq_freqs freqs; struct amd_cpudata *cpudata = policy->driver_data; @@ -465,26 +464,51 @@ static int amd_pstate_target(struct cpufreq_policy *policy, des_perf = DIV_ROUND_CLOSEST(target_freq * cap_perf, cpudata->max_freq); - cpufreq_freq_transition_begin(policy, &freqs); + WARN_ON(fast_switch && !policy->fast_switch_enabled); + /* + * If fast_switch is desired, then there aren't any registered + * transition notifiers. See comment for + * cpufreq_enable_fast_switch(). + */ + if (!fast_switch) + cpufreq_freq_transition_begin(policy, &freqs); + amd_pstate_update(cpudata, min_perf, des_perf, - max_perf, false, policy->governor->flags); - cpufreq_freq_transition_end(policy, &freqs, false); + max_perf, fast_switch, policy->governor->flags); + + if (!fast_switch) + cpufreq_freq_transition_end(policy, &freqs, false); return 0; } +static int amd_pstate_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation) +{ + return amd_pstate_update_freq(policy, target_freq, false); +} + +static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy, + unsigned int target_freq) +{ + return amd_pstate_update_freq(policy, target_freq, true); +} + static void amd_pstate_adjust_perf(unsigned int cpu, unsigned long _min_perf, unsigned long target_perf, unsigned long capacity) { unsigned long max_perf, min_perf, des_perf, - cap_perf, lowest_nonlinear_perf; + cap_perf, lowest_nonlinear_perf, max_freq; struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); struct amd_cpudata *cpudata = policy->driver_data; + unsigned int target_freq; cap_perf = READ_ONCE(cpudata->highest_perf); lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); + max_freq = READ_ONCE(cpudata->max_freq); des_perf = cap_perf; if (target_perf < capacity) @@ -501,6 +525,10 @@ static void amd_pstate_adjust_perf(unsigned int cpu, if (max_perf < min_perf) max_perf = min_perf; + des_perf = clamp_t(unsigned long, des_perf, min_perf, max_perf); + target_freq = div_u64(des_perf * max_freq, max_perf); + policy->cur = target_freq; + amd_pstate_update(cpudata, min_perf, des_perf, max_perf, true, policy->governor->flags); cpufreq_cpu_put(policy); @@ -715,6 +743,7 @@ static int amd_pstate_cpu_exit(struct cpufreq_policy *policy) freq_qos_remove_request(&cpudata->req[1]); freq_qos_remove_request(&cpudata->req[0]); + policy->fast_switch_possible = false; kfree(cpudata); return 0; @@ -1079,7 +1108,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) policy->policy = CPUFREQ_POLICY_POWERSAVE; if (boot_cpu_has(X86_FEATURE_CPPC)) { - policy->fast_switch_possible = true; ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &value); if (ret) return ret; @@ -1102,7 +1130,6 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) static int amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy) { pr_debug("CPU %d exiting\n", policy->cpu); - policy->fast_switch_possible = false; return 0; } @@ -1309,6 +1336,7 @@ static struct cpufreq_driver amd_pstate_driver = { .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS, .verify = amd_pstate_verify, .target = amd_pstate_target, + .fast_switch = amd_pstate_fast_switch, .init = amd_pstate_cpu_init, .exit = amd_pstate_cpu_exit, .suspend = amd_pstate_cpu_suspend, diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 1d2cfea9858afc..73efbcf5513b2c 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -583,7 +583,7 @@ static int __init pcc_cpufreq_probe(struct platform_device *pdev) /* Skip initialization if another cpufreq driver is there. */ if (cpufreq_get_current_driver()) - return -EEXIST; + return -ENODEV; if (acpi_disabled) return -ENODEV; diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c index 23b9ff920d7e85..bea9cf31a12df9 100644 --- a/drivers/cxl/core/mbox.c +++ b/drivers/cxl/core/mbox.c @@ -1028,7 +1028,7 @@ static int cxl_mem_get_partition_info(struct cxl_dev_state *cxlds) * cxl_dev_state_identify() - Send the IDENTIFY command to the device. * @cxlds: The device data for the operation * - * Return: 0 if identify was executed successfully. + * Return: 0 if identify was executed successfully or media not ready. * * This will dispatch the identify command to the device and on success populate * structures to be exported to sysfs. @@ -1041,6 +1041,9 @@ int cxl_dev_state_identify(struct cxl_dev_state *cxlds) u32 val; int rc; + if (!cxlds->media_ready) + return 0; + mbox_cmd = (struct cxl_mbox_cmd) { .opcode = CXL_MBOX_OP_IDENTIFY, .size_out = sizeof(id), @@ -1102,6 +1105,13 @@ int cxl_mem_create_range_info(struct cxl_dev_state *cxlds) struct device *dev = cxlds->dev; int rc; + if (!cxlds->media_ready) { + cxlds->dpa_res = DEFINE_RES_MEM(0, 0); + cxlds->ram_res = DEFINE_RES_MEM(0, 0); + cxlds->pmem_res = DEFINE_RES_MEM(0, 0); + return 0; + } + cxlds->dpa_res = (struct resource)DEFINE_RES_MEM(0, cxlds->total_bytes); diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c index f332fe7af92ba3..67f4ab6daa34f0 100644 --- a/drivers/cxl/core/pci.c +++ b/drivers/cxl/core/pci.c @@ -101,23 +101,57 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port) } EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, CXL); -/* - * Wait up to @media_ready_timeout for the device to report memory - * active. - */ -int cxl_await_media_ready(struct cxl_dev_state *cxlds) +static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id) +{ + struct pci_dev *pdev = to_pci_dev(cxlds->dev); + int d = cxlds->cxl_dvsec; + bool valid = false; + int rc, i; + u32 temp; + + if (id > CXL_DVSEC_RANGE_MAX) + return -EINVAL; + + /* Check MEM INFO VALID bit first, give up after 1s */ + i = 1; + do { + rc = pci_read_config_dword(pdev, + d + CXL_DVSEC_RANGE_SIZE_LOW(id), + &temp); + if (rc) + return rc; + + valid = FIELD_GET(CXL_DVSEC_MEM_INFO_VALID, temp); + if (valid) + break; + msleep(1000); + } while (i--); + + if (!valid) { + dev_err(&pdev->dev, + "Timeout awaiting memory range %d valid after 1s.\n", + id); + return -ETIMEDOUT; + } + + return 0; +} + +static int cxl_dvsec_mem_range_active(struct cxl_dev_state *cxlds, int id) { struct pci_dev *pdev = to_pci_dev(cxlds->dev); int d = cxlds->cxl_dvsec; bool active = false; - u64 md_status; int rc, i; + u32 temp; - for (i = media_ready_timeout; i; i--) { - u32 temp; + if (id > CXL_DVSEC_RANGE_MAX) + return -EINVAL; + /* Check MEM ACTIVE bit, up to 60s timeout by default */ + for (i = media_ready_timeout; i; i--) { rc = pci_read_config_dword( - pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(0), &temp); + pdev, d + CXL_DVSEC_RANGE_SIZE_LOW(id), &temp); if (rc) return rc; @@ -134,6 +168,39 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds) return -ETIMEDOUT; } + return 0; +} + +/* + * Wait up to @media_ready_timeout for the device to report memory + * active. + */ +int cxl_await_media_ready(struct cxl_dev_state *cxlds) +{ + struct pci_dev *pdev = to_pci_dev(cxlds->dev); + int d = cxlds->cxl_dvsec; + int rc, i, hdm_count; + u64 md_status; + u16 cap; + + rc = pci_read_config_word(pdev, + d + CXL_DVSEC_CAP_OFFSET, &cap); + if (rc) + return rc; + + hdm_count = FIELD_GET(CXL_DVSEC_HDM_COUNT_MASK, cap); + for (i = 0; i < hdm_count; i++) { + rc = cxl_dvsec_mem_range_valid(cxlds, i); + if (rc) + return rc; + } + + for (i = 0; i < hdm_count; i++) { + rc = cxl_dvsec_mem_range_active(cxlds, i); + if (rc) + return rc; + } + md_status = readq(cxlds->regs.memdev + CXLMDEV_STATUS_OFFSET); if (!CXLMDEV_READY(md_status)) return -EIO; @@ -241,17 +308,36 @@ static void disable_hdm(void *_cxlhdm) hdm + CXL_HDM_DECODER_CTRL_OFFSET); } -static int devm_cxl_enable_hdm(struct device *host, struct cxl_hdm *cxlhdm) +int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm) { - void __iomem *hdm = cxlhdm->regs.hdm_decoder; + void __iomem *hdm; u32 global_ctrl; + /* + * If the hdm capability was not mapped there is nothing to enable and + * the caller is responsible for what happens next. For example, + * emulate a passthrough decoder. + */ + if (IS_ERR(cxlhdm)) + return 0; + + hdm = cxlhdm->regs.hdm_decoder; global_ctrl = readl(hdm + CXL_HDM_DECODER_CTRL_OFFSET); + + /* + * If the HDM decoder capability was enabled on entry, skip + * registering disable_hdm() since this decode capability may be + * owned by platform firmware. + */ + if (global_ctrl & CXL_HDM_DECODER_ENABLE) + return 0; + writel(global_ctrl | CXL_HDM_DECODER_ENABLE, hdm + CXL_HDM_DECODER_CTRL_OFFSET); - return devm_add_action_or_reset(host, disable_hdm, cxlhdm); + return devm_add_action_or_reset(&port->dev, disable_hdm, cxlhdm); } +EXPORT_SYMBOL_NS_GPL(devm_cxl_enable_hdm, CXL); int cxl_dvsec_rr_decode(struct device *dev, int d, struct cxl_endpoint_dvsec_info *info) @@ -425,7 +511,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm, if (info->mem_enabled) return 0; - rc = devm_cxl_enable_hdm(&port->dev, cxlhdm); + rc = devm_cxl_enable_hdm(port, cxlhdm); if (rc) return rc; diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c index da2068475fa26c..e7c284c890bc11 100644 --- a/drivers/cxl/core/port.c +++ b/drivers/cxl/core/port.c @@ -750,11 +750,10 @@ struct cxl_port *devm_cxl_add_port(struct device *host, struct device *uport, parent_port = parent_dport ? parent_dport->port : NULL; if (IS_ERR(port)) { - dev_dbg(uport, "Failed to add %s%s%s%s: %ld\n", - dev_name(&port->dev), - parent_port ? " to " : "", + dev_dbg(uport, "Failed to add%s%s%s: %ld\n", + parent_port ? " port to " : "", parent_port ? dev_name(&parent_port->dev) : "", - parent_port ? "" : " (root port)", + parent_port ? "" : " root port", PTR_ERR(port)); } else { dev_dbg(uport, "%s added%s%s%s\n", diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h index 044a92d9813e23..f93a285389621c 100644 --- a/drivers/cxl/cxl.h +++ b/drivers/cxl/cxl.h @@ -710,6 +710,7 @@ struct cxl_endpoint_dvsec_info { struct cxl_hdm; struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port, struct cxl_endpoint_dvsec_info *info); +int devm_cxl_enable_hdm(struct cxl_port *port, struct cxl_hdm *cxlhdm); int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm, struct cxl_endpoint_dvsec_info *info); int devm_cxl_add_passthrough_decoder(struct cxl_port *port); diff --git a/drivers/cxl/cxlmem.h b/drivers/cxl/cxlmem.h index db12b6313afbf7..a2845a7a69d820 100644 --- a/drivers/cxl/cxlmem.h +++ b/drivers/cxl/cxlmem.h @@ -266,6 +266,7 @@ struct cxl_poison_state { * @regs: Parsed register blocks * @cxl_dvsec: Offset to the PCIe device DVSEC * @rcd: operating in RCD mode (CXL 3.0 9.11.8 CXL Devices Attached to an RCH) + * @media_ready: Indicate whether the device media is usable * @payload_size: Size of space for payload * (CXL 2.0 8.2.8.4.3 Mailbox Capabilities Register) * @lsa_size: Size of Label Storage Area @@ -303,6 +304,7 @@ struct cxl_dev_state { int cxl_dvsec; bool rcd; + bool media_ready; size_t payload_size; size_t lsa_size; struct mutex mbox_mutex; /* Protects device mailbox and firmware */ diff --git a/drivers/cxl/cxlpci.h b/drivers/cxl/cxlpci.h index 0465ef963cd6a0..7c02e55b80429a 100644 --- a/drivers/cxl/cxlpci.h +++ b/drivers/cxl/cxlpci.h @@ -31,6 +31,8 @@ #define CXL_DVSEC_RANGE_BASE_LOW(i) (0x24 + (i * 0x10)) #define CXL_DVSEC_MEM_BASE_LOW_MASK GENMASK(31, 28) +#define CXL_DVSEC_RANGE_MAX 2 + /* CXL 2.0 8.1.4: Non-CXL Function Map DVSEC */ #define CXL_DVSEC_FUNCTION_MAP 2 diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 10caf180b3fa0b..519edd0eb1967d 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -124,6 +124,9 @@ static int cxl_mem_probe(struct device *dev) struct dentry *dentry; int rc; + if (!cxlds->media_ready) + return -EBUSY; + /* * Someone is trying to reattach this device after it lost its port * connection (an endpoint port previously registered by this memdev was diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c index f7a5b8e9c10241..0872f2233ed0c8 100644 --- a/drivers/cxl/pci.c +++ b/drivers/cxl/pci.c @@ -708,6 +708,12 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (rc) dev_dbg(&pdev->dev, "Failed to map RAS capability.\n"); + rc = cxl_await_media_ready(cxlds); + if (rc == 0) + cxlds->media_ready = true; + else + dev_warn(&pdev->dev, "Media not active (%d)\n", rc); + rc = cxl_pci_setup_mailbox(cxlds); if (rc) return rc; diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c index eb57324c4ad4a0..c23b6164e1c0fa 100644 --- a/drivers/cxl/port.c +++ b/drivers/cxl/port.c @@ -60,13 +60,17 @@ static int discover_region(struct device *dev, void *root) static int cxl_switch_port_probe(struct cxl_port *port) { struct cxl_hdm *cxlhdm; - int rc; + int rc, nr_dports; - rc = devm_cxl_port_enumerate_dports(port); - if (rc < 0) - return rc; + nr_dports = devm_cxl_port_enumerate_dports(port); + if (nr_dports < 0) + return nr_dports; cxlhdm = devm_cxl_setup_hdm(port, NULL); + rc = devm_cxl_enable_hdm(port, cxlhdm); + if (rc) + return rc; + if (!IS_ERR(cxlhdm)) return devm_cxl_enumerate_decoders(cxlhdm, NULL); @@ -75,7 +79,7 @@ static int cxl_switch_port_probe(struct cxl_port *port) return PTR_ERR(cxlhdm); } - if (rc == 1) { + if (nr_dports == 1) { dev_dbg(&port->dev, "Fallback to passthrough decoder\n"); return devm_cxl_add_passthrough_decoder(port); } @@ -113,12 +117,6 @@ static int cxl_endpoint_port_probe(struct cxl_port *port) if (rc) return rc; - rc = cxl_await_media_ready(cxlds); - if (rc) { - dev_err(&port->dev, "Media not active (%d)\n", rc); - return rc; - } - rc = devm_cxl_enumerate_decoders(cxlhdm, &info); if (rc) return rc; diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 8858470246e155..ee3a219e3a897c 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -132,7 +132,7 @@ #define ATC_DST_PIP BIT(12) /* Destination Picture-in-Picture enabled */ #define ATC_SRC_DSCR_DIS BIT(16) /* Src Descriptor fetch disable */ #define ATC_DST_DSCR_DIS BIT(20) /* Dst Descriptor fetch disable */ -#define ATC_FC GENMASK(22, 21) /* Choose Flow Controller */ +#define ATC_FC GENMASK(23, 21) /* Choose Flow Controller */ #define ATC_FC_MEM2MEM 0x0 /* Mem-to-Mem (DMA) */ #define ATC_FC_MEM2PER 0x1 /* Mem-to-Periph (DMA) */ #define ATC_FC_PER2MEM 0x2 /* Periph-to-Mem (DMA) */ @@ -153,8 +153,6 @@ #define ATC_AUTO BIT(31) /* Auto multiple buffer tx enable */ /* Bitfields in CFG */ -#define ATC_PER_MSB(h) ((0x30U & (h)) >> 4) /* Extract most significant bits of a handshaking identifier */ - #define ATC_SRC_PER GENMASK(3, 0) /* Channel src rq associated with periph handshaking ifc h */ #define ATC_DST_PER GENMASK(7, 4) /* Channel dst rq associated with periph handshaking ifc h */ #define ATC_SRC_REP BIT(8) /* Source Replay Mod */ @@ -181,10 +179,15 @@ #define ATC_DPIP_HOLE GENMASK(15, 0) #define ATC_DPIP_BOUNDARY GENMASK(25, 16) -#define ATC_SRC_PER_ID(id) (FIELD_PREP(ATC_SRC_PER_MSB, (id)) | \ - FIELD_PREP(ATC_SRC_PER, (id))) -#define ATC_DST_PER_ID(id) (FIELD_PREP(ATC_DST_PER_MSB, (id)) | \ - FIELD_PREP(ATC_DST_PER, (id))) +#define ATC_PER_MSB GENMASK(5, 4) /* Extract MSBs of a handshaking identifier */ +#define ATC_SRC_PER_ID(id) \ + ({ typeof(id) _id = (id); \ + FIELD_PREP(ATC_SRC_PER_MSB, FIELD_GET(ATC_PER_MSB, _id)) | \ + FIELD_PREP(ATC_SRC_PER, _id); }) +#define ATC_DST_PER_ID(id) \ + ({ typeof(id) _id = (id); \ + FIELD_PREP(ATC_DST_PER_MSB, FIELD_GET(ATC_PER_MSB, _id)) | \ + FIELD_PREP(ATC_DST_PER, _id); }) diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 7da6d9b6098e71..c3b37168b21f16 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1102,6 +1102,8 @@ at_xdmac_prep_interleaved(struct dma_chan *chan, NULL, src_addr, dst_addr, xt, xt->sgl); + if (!first) + return NULL; /* Length of the block is (BLEN+1) microblocks. */ for (i = 0; i < xt->numf - 1; i++) @@ -1132,8 +1134,9 @@ at_xdmac_prep_interleaved(struct dma_chan *chan, src_addr, dst_addr, xt, chunk); if (!desc) { - list_splice_tail_init(&first->descs_list, - &atchan->free_descs_list); + if (first) + list_splice_tail_init(&first->descs_list, + &atchan->free_descs_list); return NULL; } diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c index ecbf67c2ad2b07..d32deb9b4e3dee 100644 --- a/drivers/dma/idxd/cdev.c +++ b/drivers/dma/idxd/cdev.c @@ -277,7 +277,6 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) if (wq_dedicated(wq)) { rc = idxd_wq_set_pasid(wq, pasid); if (rc < 0) { - iommu_sva_unbind_device(sva); dev_err(dev, "wq set pasid failed: %d\n", rc); goto failed_set_pasid; } diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 0d9257fbdfb0d9..b4731fe6bbc14f 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1050,7 +1050,7 @@ static bool _trigger(struct pl330_thread *thrd) return true; } -static bool _start(struct pl330_thread *thrd) +static bool pl330_start_thread(struct pl330_thread *thrd) { switch (_state(thrd)) { case PL330_STATE_FAULT_COMPLETING: @@ -1702,7 +1702,7 @@ static int pl330_update(struct pl330_dmac *pl330) thrd->req_running = -1; /* Get going again ASAP */ - _start(thrd); + pl330_start_thread(thrd); /* For now, just make a list of callbacks to be done */ list_add_tail(&descdone->rqd, &pl330->req_done); @@ -2089,7 +2089,7 @@ static void pl330_tasklet(struct tasklet_struct *t) } else { /* Make sure the PL330 Channel thread is active */ spin_lock(&pch->thread->dmac->lock); - _start(pch->thread); + pl330_start_thread(pch->thread); spin_unlock(&pch->thread->dmac->lock); } @@ -2107,7 +2107,7 @@ static void pl330_tasklet(struct tasklet_struct *t) if (power_down) { pch->active = true; spin_lock(&pch->thread->dmac->lock); - _start(pch->thread); + pl330_start_thread(pch->thread); spin_unlock(&pch->thread->dmac->lock); power_down = false; } diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index fc3a2a05ab7b70..b8329a23728d73 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -5527,7 +5527,7 @@ static int udma_probe(struct platform_device *pdev) return ret; } -static int udma_pm_suspend(struct device *dev) +static int __maybe_unused udma_pm_suspend(struct device *dev) { struct udma_dev *ud = dev_get_drvdata(dev); struct dma_device *dma_dev = &ud->ddev; @@ -5549,7 +5549,7 @@ static int udma_pm_suspend(struct device *dev) return 0; } -static int udma_pm_resume(struct device *dev) +static int __maybe_unused udma_pm_resume(struct device *dev) { struct udma_dev *ud = dev_get_drvdata(dev); struct dma_device *dma_dev = &ud->ddev; diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c index f29d77ecf72db6..2b8bfcd010f5fd 100644 --- a/drivers/firmware/arm_ffa/bus.c +++ b/drivers/firmware/arm_ffa/bus.c @@ -15,6 +15,8 @@ #include "common.h" +static DEFINE_IDA(ffa_bus_id); + static int ffa_device_match(struct device *dev, struct device_driver *drv) { const struct ffa_device_id *id_table; @@ -53,7 +55,8 @@ static void ffa_device_remove(struct device *dev) { struct ffa_driver *ffa_drv = to_ffa_driver(dev->driver); - ffa_drv->remove(to_ffa_dev(dev)); + if (ffa_drv->remove) + ffa_drv->remove(to_ffa_dev(dev)); } static int ffa_device_uevent(const struct device *dev, struct kobj_uevent_env *env) @@ -130,6 +133,7 @@ static void ffa_release_device(struct device *dev) { struct ffa_device *ffa_dev = to_ffa_dev(dev); + ida_free(&ffa_bus_id, ffa_dev->id); kfree(ffa_dev); } @@ -170,18 +174,24 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev) struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id, const struct ffa_ops *ops) { - int ret; + int id, ret; struct device *dev; struct ffa_device *ffa_dev; + id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL); + if (id < 0) + return NULL; + ffa_dev = kzalloc(sizeof(*ffa_dev), GFP_KERNEL); - if (!ffa_dev) + if (!ffa_dev) { + ida_free(&ffa_bus_id, id); return NULL; + } dev = &ffa_dev->dev; dev->bus = &ffa_bus_type; dev->release = ffa_release_device; - dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id); + dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id); ffa_dev->vm_id = vm_id; ffa_dev->ops = ops; @@ -217,4 +227,5 @@ void arm_ffa_bus_exit(void) { ffa_devices_unregister(); bus_unregister(&ffa_bus_type); + ida_destroy(&ffa_bus_id); } diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c index fa85c64d3dede7..e234091386671f 100644 --- a/drivers/firmware/arm_ffa/driver.c +++ b/drivers/firmware/arm_ffa/driver.c @@ -193,7 +193,8 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3, int idx, count, flags = 0, sz, buf_sz; ffa_value_t partition_info; - if (!buffer || !num_partitions) /* Just get the count for now */ + if (drv_info->version > FFA_VERSION_1_0 && + (!buffer || !num_partitions)) /* Just get the count for now */ flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY; mutex_lock(&drv_info->rx_lock); @@ -420,12 +421,17 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, ep_mem_access->receiver = args->attrs[idx].receiver; ep_mem_access->attrs = args->attrs[idx].attrs; ep_mem_access->composite_off = COMPOSITE_OFFSET(args->nattrs); + ep_mem_access->flag = 0; + ep_mem_access->reserved = 0; } + mem_region->reserved_0 = 0; + mem_region->reserved_1 = 0; mem_region->ep_count = args->nattrs; composite = buffer + COMPOSITE_OFFSET(args->nattrs); composite->total_pg_cnt = ffa_get_num_pages_sg(args->sg); composite->addr_range_cnt = num_entries; + composite->reserved = 0; length = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, num_entries); frag_len = COMPOSITE_CONSTITUENTS_OFFSET(args->nattrs, 0); @@ -460,6 +466,7 @@ ffa_setup_and_transmit(u32 func_id, void *buffer, u32 max_fragsize, constituents->address = sg_phys(args->sg); constituents->pg_cnt = args->sg->length / FFA_PAGE_SIZE; + constituents->reserved = 0; constituents++; frag_len += sizeof(struct ffa_mem_region_addr_range); } while ((args->sg = sg_next(args->sg))); diff --git a/drivers/firmware/arm_scmi/raw_mode.c b/drivers/firmware/arm_scmi/raw_mode.c index d40df099fd5152..6971dcf72fb998 100644 --- a/drivers/firmware/arm_scmi/raw_mode.c +++ b/drivers/firmware/arm_scmi/raw_mode.c @@ -1066,7 +1066,7 @@ static int scmi_xfer_raw_worker_init(struct scmi_raw_mode_info *raw) raw->wait_wq = alloc_workqueue("scmi-raw-wait-wq-%d", WQ_UNBOUND | WQ_FREEZABLE | - WQ_HIGHPRI, WQ_SYSFS, raw->id); + WQ_HIGHPRI | WQ_SYSFS, 0, raw->id); if (!raw->wait_wq) return -ENOMEM; diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot index 89ef820f3b3448..2c489627a80789 100644 --- a/drivers/firmware/efi/libstub/Makefile.zboot +++ b/drivers/firmware/efi/libstub/Makefile.zboot @@ -32,7 +32,8 @@ zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0 $(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE $(call if_changed,$(zboot-method-y)) -OBJCOPYFLAGS_vmlinuz.o := -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \ +# avoid eager evaluation to prevent references to non-existent build artifacts +OBJCOPYFLAGS_vmlinuz.o = -I binary -O $(EFI_ZBOOT_BFD_TARGET) $(EFI_ZBOOT_OBJCOPY_FLAGS) \ --rename-section .data=.gzdata,load,alloc,readonly,contents $(obj)/vmlinuz.o: $(obj)/vmlinuz FORCE $(call if_changed,objcopy) diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h index 67d5a20802e0b7..54a2822cae7714 100644 --- a/drivers/firmware/efi/libstub/efistub.h +++ b/drivers/firmware/efi/libstub/efistub.h @@ -1133,4 +1133,7 @@ const u8 *__efi_get_smbios_string(const struct efi_smbios_record *record, void efi_remap_image(unsigned long image_base, unsigned alloc_size, unsigned long code_size); +asmlinkage efi_status_t __efiapi +efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab); + #endif diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 5521f060d58e9d..f45c6a36551c75 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -897,7 +897,7 @@ config GPIO_F7188X help This option enables support for GPIOs found on Fintek Super-I/O chips F71869, F71869A, F71882FG, F71889F and F81866. - As well as Nuvoton Super-I/O chip NCT6116D. + As well as Nuvoton Super-I/O chip NCT6126D. To compile this driver as a module, choose M here: the module will be called f7188x-gpio. diff --git a/drivers/gpio/gpio-f7188x.c b/drivers/gpio/gpio-f7188x.c index 9effa7769bef5b..f54ca5a1775ea2 100644 --- a/drivers/gpio/gpio-f7188x.c +++ b/drivers/gpio/gpio-f7188x.c @@ -48,7 +48,7 @@ /* * Nuvoton devices. */ -#define SIO_NCT6116D_ID 0xD283 /* NCT6116D chipset ID */ +#define SIO_NCT6126D_ID 0xD283 /* NCT6126D chipset ID */ #define SIO_LD_GPIO_NUVOTON 0x07 /* GPIO logical device */ @@ -62,7 +62,7 @@ enum chips { f81866, f81804, f81865, - nct6116d, + nct6126d, }; static const char * const f7188x_names[] = { @@ -74,7 +74,7 @@ static const char * const f7188x_names[] = { "f81866", "f81804", "f81865", - "nct6116d", + "nct6126d", }; struct f7188x_sio { @@ -187,8 +187,8 @@ static int f7188x_gpio_set_config(struct gpio_chip *chip, unsigned offset, /* Output mode register (0:open drain 1:push-pull). */ #define f7188x_gpio_out_mode(base) ((base) + 3) -#define f7188x_gpio_dir_invert(type) ((type) == nct6116d) -#define f7188x_gpio_data_single(type) ((type) == nct6116d) +#define f7188x_gpio_dir_invert(type) ((type) == nct6126d) +#define f7188x_gpio_data_single(type) ((type) == nct6126d) static struct f7188x_gpio_bank f71869_gpio_bank[] = { F7188X_GPIO_BANK(0, 6, 0xF0, DRVNAME "-0"), @@ -274,7 +274,7 @@ static struct f7188x_gpio_bank f81865_gpio_bank[] = { F7188X_GPIO_BANK(60, 5, 0x90, DRVNAME "-6"), }; -static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { +static struct f7188x_gpio_bank nct6126d_gpio_bank[] = { F7188X_GPIO_BANK(0, 8, 0xE0, DRVNAME "-0"), F7188X_GPIO_BANK(10, 8, 0xE4, DRVNAME "-1"), F7188X_GPIO_BANK(20, 8, 0xE8, DRVNAME "-2"), @@ -282,7 +282,7 @@ static struct f7188x_gpio_bank nct6116d_gpio_bank[] = { F7188X_GPIO_BANK(40, 8, 0xF0, DRVNAME "-4"), F7188X_GPIO_BANK(50, 8, 0xF4, DRVNAME "-5"), F7188X_GPIO_BANK(60, 8, 0xF8, DRVNAME "-6"), - F7188X_GPIO_BANK(70, 1, 0xFC, DRVNAME "-7"), + F7188X_GPIO_BANK(70, 8, 0xFC, DRVNAME "-7"), }; static int f7188x_gpio_get_direction(struct gpio_chip *chip, unsigned offset) @@ -490,9 +490,9 @@ static int f7188x_gpio_probe(struct platform_device *pdev) data->nr_bank = ARRAY_SIZE(f81865_gpio_bank); data->bank = f81865_gpio_bank; break; - case nct6116d: - data->nr_bank = ARRAY_SIZE(nct6116d_gpio_bank); - data->bank = nct6116d_gpio_bank; + case nct6126d: + data->nr_bank = ARRAY_SIZE(nct6126d_gpio_bank); + data->bank = nct6126d_gpio_bank; break; default: return -ENODEV; @@ -559,9 +559,9 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) case SIO_F81865_ID: sio->type = f81865; break; - case SIO_NCT6116D_ID: + case SIO_NCT6126D_ID: sio->device = SIO_LD_GPIO_NUVOTON; - sio->type = nct6116d; + sio->type = nct6126d; break; default: pr_info("Unsupported Fintek device 0x%04x\n", devid); @@ -569,7 +569,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) } /* double check manufacturer where possible */ - if (sio->type != nct6116d) { + if (sio->type != nct6126d) { manid = superio_inw(addr, SIO_FINTEK_MANID); if (manid != SIO_FINTEK_ID) { pr_debug("Not a Fintek device at 0x%08x\n", addr); @@ -581,7 +581,7 @@ static int __init f7188x_find(int addr, struct f7188x_sio *sio) err = 0; pr_info("Found %s at %#x\n", f7188x_names[sio->type], (unsigned int)addr); - if (sio->type != nct6116d) + if (sio->type != nct6126d) pr_info(" revision %d\n", superio_inb(addr, SIO_FINTEK_DEVREV)); err: diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index e6a7049bef6417..b32063ac845a50 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -369,7 +369,7 @@ static void gpio_mockup_debugfs_setup(struct device *dev, priv->offset = i; priv->desc = gpiochip_get_desc(gc, i); - debugfs_create_file(name, 0200, chip->dbg_dir, priv, + debugfs_create_file(name, 0600, chip->dbg_dir, priv, &gpio_mockup_debugfs_ops); } } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 04fb05df805b01..a7220e04a93e56 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -209,6 +209,8 @@ static int gpiochip_find_base(int ngpio) break; /* nope, check the space right after the chip */ base = gdev->base + gdev->ngpio; + if (base < GPIO_DYNAMIC_BASE) + base = GPIO_DYNAMIC_BASE; } if (gpio_is_valid(base)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index f52d0ba91a770a..a7d250809da99e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -582,7 +582,8 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev) if (r) amdgpu_fence_driver_force_completion(ring); - if (ring->fence_drv.irq_src) + if (!drm_dev_is_unplugged(adev_to_drm(adev)) && + ring->fence_drv.irq_src) amdgpu_irq_put(adev, ring->fence_drv.irq_src, ring->fence_drv.irq_type); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 4e2531758866c6..95b0f984acbfd8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -593,6 +593,8 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case IP_VERSION(9, 3, 0): /* GC 10.3.7 */ case IP_VERSION(10, 3, 7): + /* GC 11.0.1 */ + case IP_VERSION(11, 0, 1): if (amdgpu_tmz == 0) { adev->gmc.tmz_enabled = false; dev_info(adev->dev, @@ -616,7 +618,6 @@ void amdgpu_gmc_tmz_set(struct amdgpu_device *adev) case IP_VERSION(10, 3, 1): /* YELLOW_CARP*/ case IP_VERSION(10, 3, 3): - case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 4): /* Don't enable it by default yet. */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c index b07c000fc8ba39..4fa019c8aefc4d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c @@ -241,6 +241,31 @@ int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev, return 0; } +int amdgpu_jpeg_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block) +{ + int r, i; + + r = amdgpu_ras_block_late_init(adev, ras_block); + if (r) + return r; + + if (amdgpu_ras_is_supported(adev, ras_block->block)) { + for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) { + if (adev->jpeg.harvest_config & (1 << i)) + continue; + + r = amdgpu_irq_get(adev, &adev->jpeg.inst[i].ras_poison_irq, 0); + if (r) + goto late_fini; + } + } + return 0; + +late_fini: + amdgpu_ras_block_late_fini(adev, ras_block); + return r; +} + int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev) { int err; @@ -262,7 +287,7 @@ int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev) adev->jpeg.ras_if = &ras->ras_block.ras_comm; if (!ras->ras_block.ras_late_init) - ras->ras_block.ras_late_init = amdgpu_ras_block_late_init; + ras->ras_block.ras_late_init = amdgpu_jpeg_ras_late_init; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h index 0ca76f0f23e9c8..1471a1ebb03449 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h @@ -38,6 +38,7 @@ struct amdgpu_jpeg_reg{ struct amdgpu_jpeg_inst { struct amdgpu_ring ring_dec; struct amdgpu_irq_src irq; + struct amdgpu_irq_src ras_poison_irq; struct amdgpu_jpeg_reg external; }; @@ -72,6 +73,8 @@ int amdgpu_jpeg_dec_ring_test_ib(struct amdgpu_ring *ring, long timeout); int amdgpu_jpeg_process_poison_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry); +int amdgpu_jpeg_ras_late_init(struct amdgpu_device *adev, + struct ras_common_if *ras_block); int amdgpu_jpeg_ras_sw_init(struct amdgpu_device *adev); #endif /*__AMDGPU_JPEG_H__*/ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c index e63fcc58e8e062..2d94f1b63bd6c4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c @@ -1181,6 +1181,31 @@ int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev, return 0; } +int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block) +{ + int r, i; + + r = amdgpu_ras_block_late_init(adev, ras_block); + if (r) + return r; + + if (amdgpu_ras_is_supported(adev, ras_block->block)) { + for (i = 0; i < adev->vcn.num_vcn_inst; i++) { + if (adev->vcn.harvest_config & (1 << i)) + continue; + + r = amdgpu_irq_get(adev, &adev->vcn.inst[i].ras_poison_irq, 0); + if (r) + goto late_fini; + } + } + return 0; + +late_fini: + amdgpu_ras_block_late_fini(adev, ras_block); + return r; +} + int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev) { int err; @@ -1202,7 +1227,7 @@ int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev) adev->vcn.ras_if = &ras->ras_block.ras_comm; if (!ras->ras_block.ras_late_init) - ras->ras_block.ras_late_init = amdgpu_ras_block_late_init; + ras->ras_block.ras_late_init = amdgpu_vcn_ras_late_init; return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index c730949ece7d9b..f1397ef66fd77e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -234,6 +234,7 @@ struct amdgpu_vcn_inst { struct amdgpu_ring ring_enc[AMDGPU_VCN_MAX_ENC_RINGS]; atomic_t sched_score; struct amdgpu_irq_src irq; + struct amdgpu_irq_src ras_poison_irq; struct amdgpu_vcn_reg external; struct amdgpu_bo *dpg_sram_bo; struct dpg_pause_state pause_state; @@ -400,6 +401,8 @@ void amdgpu_debugfs_vcn_fwlog_init(struct amdgpu_device *adev, int amdgpu_vcn_process_poison_irq(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry); +int amdgpu_vcn_ras_late_init(struct amdgpu_device *adev, + struct ras_common_if *ras_block); int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index f5b5ce1051a286..ab44c1391d5265 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6892,8 +6892,10 @@ static int gfx_v10_0_kiq_resume(struct amdgpu_device *adev) return r; r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) + if (unlikely(r != 0)) { + amdgpu_bo_unreserve(ring->mqd_obj); return r; + } gfx_v10_0_kiq_init_queue(ring); amdgpu_bo_kunmap(ring->mqd_obj); @@ -8152,8 +8154,14 @@ static int gfx_v10_0_set_powergating_state(void *handle, case IP_VERSION(10, 3, 3): case IP_VERSION(10, 3, 6): case IP_VERSION(10, 3, 7): + if (!enable) + amdgpu_gfx_off_ctrl(adev, false); + gfx_v10_cntl_pg(adev, enable); - amdgpu_gfx_off_ctrl(adev, enable); + + if (enable) + amdgpu_gfx_off_ctrl(adev, true); + break; default: break; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index f5c3762769843a..c4940b6ea1c4cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -4667,24 +4667,27 @@ static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev) uint64_t clock; uint64_t clock_counter_lo, clock_counter_hi_pre, clock_counter_hi_after; - amdgpu_gfx_off_ctrl(adev, false); - mutex_lock(&adev->gfx.gpu_clock_mutex); if (amdgpu_sriov_vf(adev)) { + amdgpu_gfx_off_ctrl(adev, false); + mutex_lock(&adev->gfx.gpu_clock_mutex); clock_counter_hi_pre = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_HI); clock_counter_lo = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_LO); clock_counter_hi_after = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_HI); if (clock_counter_hi_pre != clock_counter_hi_after) clock_counter_lo = (uint64_t)RREG32_SOC15(GC, 0, regCP_MES_MTIME_LO); + mutex_unlock(&adev->gfx.gpu_clock_mutex); + amdgpu_gfx_off_ctrl(adev, true); } else { + preempt_disable(); clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER); clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER); clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER); if (clock_counter_hi_pre != clock_counter_hi_after) clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER); + preempt_enable(); } clock = clock_counter_lo | (clock_counter_hi_after << 32ULL); - mutex_unlock(&adev->gfx.gpu_clock_mutex); - amdgpu_gfx_off_ctrl(adev, true); + return clock; } @@ -5150,8 +5153,14 @@ static int gfx_v11_0_set_powergating_state(void *handle, break; case IP_VERSION(11, 0, 1): case IP_VERSION(11, 0, 4): + if (!enable) + amdgpu_gfx_off_ctrl(adev, false); + gfx_v11_cntl_pg(adev, enable); - amdgpu_gfx_off_ctrl(adev, enable); + + if (enable) + amdgpu_gfx_off_ctrl(adev, true); + break; default: break; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index f46d4b18a3fa35..ce22f7b3041603 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3617,8 +3617,10 @@ static int gfx_v9_0_kiq_resume(struct amdgpu_device *adev) return r; r = amdgpu_bo_kmap(ring->mqd_obj, (void **)&ring->mqd_ptr); - if (unlikely(r != 0)) + if (unlikely(r != 0)) { + amdgpu_bo_unreserve(ring->mqd_obj); return r; + } gfx_v9_0_kiq_init_queue(ring); amdgpu_bo_kunmap(ring->mqd_obj); @@ -4003,30 +4005,25 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev) clock = clock_lo | (clock_hi << 32ULL); break; case IP_VERSION(9, 1, 0): + case IP_VERSION(9, 2, 2): preempt_disable(); - clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven); - clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven); - hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven); - /* The PWR TSC clock frequency is 100MHz, which sets 32-bit carry over - * roughly every 42 seconds. - */ - if (hi_check != clock_hi) { + if (adev->rev_id >= 0x8) { + clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2); + clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2); + hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2); + } else { + clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven); clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven); - clock_hi = hi_check; + hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven); } - preempt_enable(); - clock = clock_lo | (clock_hi << 32ULL); - break; - case IP_VERSION(9, 2, 2): - preempt_disable(); - clock_hi = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2); - clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2); - hi_check = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_UPPER_Raven2); /* The PWR TSC clock frequency is 100MHz, which sets 32-bit carry over - * roughly every 42 seconds. - */ + * roughly every 42 seconds. + */ if (hi_check != clock_hi) { - clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2); + if (adev->rev_id >= 0x8) + clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven2); + else + clock_lo = RREG32_SOC15_NO_KIQ(PWR, 0, mmGOLDEN_TSC_COUNT_LOWER_Raven); clock_hi = hi_check; } preempt_enable(); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c index d95f9fe8f1c54e..4116c112e8a01d 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v11_0.c @@ -31,6 +31,8 @@ #include "umc_v8_10.h" #include "athub/athub_3_0_0_sh_mask.h" #include "athub/athub_3_0_0_offset.h" +#include "dcn/dcn_3_2_0_offset.h" +#include "dcn/dcn_3_2_0_sh_mask.h" #include "oss/osssys_6_0_0_offset.h" #include "ivsrcid/vmc/irqsrcs_vmc_1_0.h" #include "navi10_enum.h" @@ -546,7 +548,24 @@ static void gmc_v11_0_get_vm_pte(struct amdgpu_device *adev, static unsigned gmc_v11_0_get_vbios_fb_size(struct amdgpu_device *adev) { - return 0; + u32 d1vga_control = RREG32_SOC15(DCE, 0, regD1VGA_CONTROL); + unsigned size; + + if (REG_GET_FIELD(d1vga_control, D1VGA_CONTROL, D1VGA_MODE_ENABLE)) { + size = AMDGPU_VBIOS_VGA_ALLOCATION; + } else { + u32 viewport; + u32 pitch; + + viewport = RREG32_SOC15(DCE, 0, regHUBP0_DCSURF_PRI_VIEWPORT_DIMENSION); + pitch = RREG32_SOC15(DCE, 0, regHUBPREQ0_DCSURF_SURFACE_PITCH); + size = (REG_GET_FIELD(viewport, + HUBP0_DCSURF_PRI_VIEWPORT_DIMENSION, PRI_VIEWPORT_HEIGHT) * + REG_GET_FIELD(pitch, HUBPREQ0_DCSURF_SURFACE_PITCH, PITCH) * + 4); + } + + return size; } static const struct amdgpu_gmc_funcs gmc_v11_0_gmc_funcs = { diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c index b040f51d9aa9d2..73e0dc5a10cd4a 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c @@ -102,13 +102,13 @@ static int jpeg_v2_5_sw_init(void *handle) /* JPEG DJPEG POISON EVENT */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i], - VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].irq); + VCN_2_6__SRCID_DJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq); if (r) return r; /* JPEG EJPEG POISON EVENT */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_jpeg[i], - VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].irq); + VCN_2_6__SRCID_EJPEG0_POISON, &adev->jpeg.inst[i].ras_poison_irq); if (r) return r; } @@ -221,6 +221,9 @@ static int jpeg_v2_5_hw_fini(void *handle) if (adev->jpeg.cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS)) jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE); + + if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG)) + amdgpu_irq_put(adev, &adev->jpeg.inst[i].ras_poison_irq, 0); } return 0; @@ -569,6 +572,14 @@ static int jpeg_v2_5_set_interrupt_state(struct amdgpu_device *adev, return 0; } +static int jpeg_v2_6_set_ras_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned int type, + enum amdgpu_interrupt_state state) +{ + return 0; +} + static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) @@ -593,10 +604,6 @@ static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev, case VCN_2_0__SRCID__JPEG_DECODE: amdgpu_fence_process(&adev->jpeg.inst[ip_instance].ring_dec); break; - case VCN_2_6__SRCID_DJPEG0_POISON: - case VCN_2_6__SRCID_EJPEG0_POISON: - amdgpu_jpeg_process_poison_irq(adev, source, entry); - break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data[0]); @@ -725,6 +732,11 @@ static const struct amdgpu_irq_src_funcs jpeg_v2_5_irq_funcs = { .process = jpeg_v2_5_process_interrupt, }; +static const struct amdgpu_irq_src_funcs jpeg_v2_6_ras_irq_funcs = { + .set = jpeg_v2_6_set_ras_interrupt_state, + .process = amdgpu_jpeg_process_poison_irq, +}; + static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev) { int i; @@ -735,6 +747,9 @@ static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev) adev->jpeg.inst[i].irq.num_types = 1; adev->jpeg.inst[i].irq.funcs = &jpeg_v2_5_irq_funcs; + + adev->jpeg.inst[i].ras_poison_irq.num_types = 1; + adev->jpeg.inst[i].ras_poison_irq.funcs = &jpeg_v2_6_ras_irq_funcs; } } @@ -800,6 +815,7 @@ const struct amdgpu_ras_block_hw_ops jpeg_v2_6_ras_hw_ops = { static struct amdgpu_jpeg_ras jpeg_v2_6_ras = { .ras_block = { .hw_ops = &jpeg_v2_6_ras_hw_ops, + .ras_late_init = amdgpu_jpeg_ras_late_init, }, }; diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c index 77e1e64aa1d1c7..a3d83c9f2c9a3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c @@ -87,13 +87,13 @@ static int jpeg_v4_0_sw_init(void *handle) /* JPEG DJPEG POISON EVENT */ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, - VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->irq); + VCN_4_0__SRCID_DJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq); if (r) return r; /* JPEG EJPEG POISON EVENT */ r = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_VCN, - VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->irq); + VCN_4_0__SRCID_EJPEG0_POISON, &adev->jpeg.inst->ras_poison_irq); if (r) return r; @@ -202,7 +202,8 @@ static int jpeg_v4_0_hw_fini(void *handle) RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS)) jpeg_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE); } - amdgpu_irq_put(adev, &adev->jpeg.inst->irq, 0); + if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__JPEG)) + amdgpu_irq_put(adev, &adev->jpeg.inst->ras_poison_irq, 0); return 0; } @@ -670,6 +671,14 @@ static int jpeg_v4_0_set_interrupt_state(struct amdgpu_device *adev, return 0; } +static int jpeg_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned int type, + enum amdgpu_interrupt_state state) +{ + return 0; +} + static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) @@ -680,10 +689,6 @@ static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev, case VCN_4_0__SRCID__JPEG_DECODE: amdgpu_fence_process(&adev->jpeg.inst->ring_dec); break; - case VCN_4_0__SRCID_DJPEG0_POISON: - case VCN_4_0__SRCID_EJPEG0_POISON: - amdgpu_jpeg_process_poison_irq(adev, source, entry); - break; default: DRM_DEV_ERROR(adev->dev, "Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data[0]); @@ -753,10 +758,18 @@ static const struct amdgpu_irq_src_funcs jpeg_v4_0_irq_funcs = { .process = jpeg_v4_0_process_interrupt, }; +static const struct amdgpu_irq_src_funcs jpeg_v4_0_ras_irq_funcs = { + .set = jpeg_v4_0_set_ras_interrupt_state, + .process = amdgpu_jpeg_process_poison_irq, +}; + static void jpeg_v4_0_set_irq_funcs(struct amdgpu_device *adev) { adev->jpeg.inst->irq.num_types = 1; adev->jpeg.inst->irq.funcs = &jpeg_v4_0_irq_funcs; + + adev->jpeg.inst->ras_poison_irq.num_types = 1; + adev->jpeg.inst->ras_poison_irq.funcs = &jpeg_v4_0_ras_irq_funcs; } const struct amdgpu_ip_block_version jpeg_v4_0_ip_block = { @@ -811,6 +824,7 @@ const struct amdgpu_ras_block_hw_ops jpeg_v4_0_ras_hw_ops = { static struct amdgpu_jpeg_ras jpeg_v4_0_ras = { .ras_block = { .hw_ops = &jpeg_v4_0_ras_hw_ops, + .ras_late_init = amdgpu_jpeg_ras_late_init, }, }; diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c index e1b7fca096660a..5f10883da6a238 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c @@ -57,7 +57,13 @@ static int psp_v10_0_init_microcode(struct psp_context *psp) if (err) return err; - return psp_init_ta_microcode(psp, ucode_prefix); + err = psp_init_ta_microcode(psp, ucode_prefix); + if ((adev->ip_versions[GC_HWIP][0] == IP_VERSION(9, 1, 0)) && + (adev->pdev->revision == 0xa1) && + (psp->securedisplay_context.context.bin_desc.fw_version >= 0x27000008)) { + adev->psp.securedisplay_context.context.bin_desc.size_bytes = 0; + } + return err; } static int psp_v10_0_ring_create(struct psp_context *psp, diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index ab0b45d0ead18a..515681c88dcbca 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -143,7 +143,7 @@ static int vcn_v2_5_sw_init(void *handle) /* VCN POISON TRAP */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[j], - VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].irq); + VCN_2_6__SRCID_UVD_POISON, &adev->vcn.inst[j].ras_poison_irq); if (r) return r; } @@ -354,6 +354,9 @@ static int vcn_v2_5_hw_fini(void *handle) (adev->vcn.cur_state != AMD_PG_STATE_GATE && RREG32_SOC15(VCN, i, mmUVD_STATUS))) vcn_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE); + + if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) + amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0); } return 0; @@ -1807,6 +1810,14 @@ static int vcn_v2_5_set_interrupt_state(struct amdgpu_device *adev, return 0; } +static int vcn_v2_6_set_ras_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned int type, + enum amdgpu_interrupt_state state) +{ + return 0; +} + static int vcn_v2_5_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) @@ -1837,9 +1848,6 @@ static int vcn_v2_5_process_interrupt(struct amdgpu_device *adev, case VCN_2_0__SRCID__UVD_ENC_LOW_LATENCY: amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[1]); break; - case VCN_2_6__SRCID_UVD_POISON: - amdgpu_vcn_process_poison_irq(adev, source, entry); - break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data[0]); @@ -1854,6 +1862,11 @@ static const struct amdgpu_irq_src_funcs vcn_v2_5_irq_funcs = { .process = vcn_v2_5_process_interrupt, }; +static const struct amdgpu_irq_src_funcs vcn_v2_6_ras_irq_funcs = { + .set = vcn_v2_6_set_ras_interrupt_state, + .process = amdgpu_vcn_process_poison_irq, +}; + static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev) { int i; @@ -1863,6 +1876,9 @@ static void vcn_v2_5_set_irq_funcs(struct amdgpu_device *adev) continue; adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v2_5_irq_funcs; + + adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v2_6_ras_irq_funcs; } } @@ -1965,6 +1981,7 @@ const struct amdgpu_ras_block_hw_ops vcn_v2_6_ras_hw_ops = { static struct amdgpu_vcn_ras vcn_v2_6_ras = { .ras_block = { .hw_ops = &vcn_v2_6_ras_hw_ops, + .ras_late_init = amdgpu_vcn_ras_late_init, }, }; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index bf0674039598d3..e5fd1e00914d0e 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -139,7 +139,7 @@ static int vcn_v4_0_sw_init(void *handle) /* VCN POISON TRAP */ r = amdgpu_irq_add_id(adev, amdgpu_ih_clientid_vcns[i], - VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].irq); + VCN_4_0__SRCID_UVD_POISON, &adev->vcn.inst[i].ras_poison_irq); if (r) return r; @@ -305,8 +305,8 @@ static int vcn_v4_0_hw_fini(void *handle) vcn_v4_0_set_powergating_state(adev, AMD_PG_STATE_GATE); } } - - amdgpu_irq_put(adev, &adev->vcn.inst[i].irq, 0); + if (amdgpu_ras_is_supported(adev, AMDGPU_RAS_BLOCK__VCN)) + amdgpu_irq_put(adev, &adev->vcn.inst[i].ras_poison_irq, 0); } return 0; @@ -1975,6 +1975,24 @@ static int vcn_v4_0_set_interrupt_state(struct amdgpu_device *adev, struct amdgp return 0; } +/** + * vcn_v4_0_set_ras_interrupt_state - set VCN block RAS interrupt state + * + * @adev: amdgpu_device pointer + * @source: interrupt sources + * @type: interrupt types + * @state: interrupt states + * + * Set VCN block RAS interrupt state + */ +static int vcn_v4_0_set_ras_interrupt_state(struct amdgpu_device *adev, + struct amdgpu_irq_src *source, + unsigned int type, + enum amdgpu_interrupt_state state) +{ + return 0; +} + /** * vcn_v4_0_process_interrupt - process VCN block interrupt * @@ -2007,9 +2025,6 @@ static int vcn_v4_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_ case VCN_4_0__SRCID__UVD_ENC_GENERAL_PURPOSE: amdgpu_fence_process(&adev->vcn.inst[ip_instance].ring_enc[0]); break; - case VCN_4_0__SRCID_UVD_POISON: - amdgpu_vcn_process_poison_irq(adev, source, entry); - break; default: DRM_ERROR("Unhandled interrupt: %d %d\n", entry->src_id, entry->src_data[0]); @@ -2024,6 +2039,11 @@ static const struct amdgpu_irq_src_funcs vcn_v4_0_irq_funcs = { .process = vcn_v4_0_process_interrupt, }; +static const struct amdgpu_irq_src_funcs vcn_v4_0_ras_irq_funcs = { + .set = vcn_v4_0_set_ras_interrupt_state, + .process = amdgpu_vcn_process_poison_irq, +}; + /** * vcn_v4_0_set_irq_funcs - set VCN block interrupt irq functions * @@ -2041,6 +2061,9 @@ static void vcn_v4_0_set_irq_funcs(struct amdgpu_device *adev) adev->vcn.inst[i].irq.num_types = adev->vcn.num_enc_rings + 1; adev->vcn.inst[i].irq.funcs = &vcn_v4_0_irq_funcs; + + adev->vcn.inst[i].ras_poison_irq.num_types = adev->vcn.num_enc_rings + 1; + adev->vcn.inst[i].ras_poison_irq.funcs = &vcn_v4_0_ras_irq_funcs; } } @@ -2114,6 +2137,7 @@ const struct amdgpu_ras_block_hw_ops vcn_v4_0_ras_hw_ops = { static struct amdgpu_vcn_ras vcn_v4_0_ras = { .ras_block = { .hw_ops = &vcn_v4_0_ras_hw_ops, + .ras_late_init = amdgpu_vcn_ras_late_init, }, }; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 8b4b186c57f515..d5cec03eaa8d3b 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2479,20 +2479,25 @@ static void dm_gpureset_toggle_interrupts(struct amdgpu_device *adev, if (acrtc && state->stream_status[i].plane_count != 0) { irq_source = IRQ_TYPE_PFLIP + acrtc->otg_inst; rc = dc_interrupt_set(adev->dm.dc, irq_source, enable) ? 0 : -EBUSY; - DRM_DEBUG_VBL("crtc %d - vupdate irq %sabling: r=%d\n", - acrtc->crtc_id, enable ? "en" : "dis", rc); if (rc) DRM_WARN("Failed to %s pflip interrupts\n", enable ? "enable" : "disable"); if (enable) { - rc = amdgpu_dm_crtc_enable_vblank(&acrtc->base); - if (rc) - DRM_WARN("Failed to enable vblank interrupts\n"); - } else { - amdgpu_dm_crtc_disable_vblank(&acrtc->base); - } + if (amdgpu_dm_crtc_vrr_active(to_dm_crtc_state(acrtc->base.state))) + rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, true); + } else + rc = amdgpu_dm_crtc_set_vupdate_irq(&acrtc->base, false); + if (rc) + DRM_WARN("Failed to %sable vupdate interrupt\n", enable ? "en" : "dis"); + + irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; + /* During gpu-reset we disable and then enable vblank irq, so + * don't use amdgpu_irq_get/put() to avoid refcount change. + */ + if (!dc_interrupt_set(adev->dm.dc, irq_source, enable)) + DRM_WARN("Failed to %sable vblank interrupt\n", enable ? "en" : "dis"); } } @@ -2852,7 +2857,7 @@ static int dm_resume(void *handle) * this is the case when traversing through already created * MST connectors, should be skipped */ - if (aconnector->dc_link->type == dc_connection_mst_branch) + if (aconnector && aconnector->mst_root) continue; mutex_lock(&aconnector->hpd_lock); @@ -6737,7 +6742,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder, int clock, bpp = 0; bool is_y420 = false; - if (!aconnector->mst_output_port || !aconnector->dc_sink) + if (!aconnector->mst_output_port) return 0; mst_port = aconnector->mst_output_port; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c index e3762e806617c1..440fc0869a34ba 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c @@ -146,7 +146,6 @@ static void vblank_control_worker(struct work_struct *work) static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) { - enum dc_irq_source irq_source; struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc); struct amdgpu_device *adev = drm_to_adev(crtc->dev); struct dm_crtc_state *acrtc_state = to_dm_crtc_state(crtc->state); @@ -169,18 +168,9 @@ static inline int dm_set_vblank(struct drm_crtc *crtc, bool enable) if (rc) return rc; - if (amdgpu_in_reset(adev)) { - irq_source = IRQ_TYPE_VBLANK + acrtc->otg_inst; - /* During gpu-reset we disable and then enable vblank irq, so - * don't use amdgpu_irq_get/put() to avoid refcount change. - */ - if (!dc_interrupt_set(adev->dm.dc, irq_source, enable)) - rc = -EBUSY; - } else { - rc = (enable) - ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id) - : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id); - } + rc = (enable) + ? amdgpu_irq_get(adev, &adev->crtc_irq, acrtc->crtc_id) + : amdgpu_irq_put(adev, &adev->crtc_irq, acrtc->crtc_id); if (rc) return rc; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index 422fbf79da64fb..5403e9399a465c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -2113,15 +2113,6 @@ void dcn20_optimize_bandwidth( if (hubbub->funcs->program_compbuf_size) hubbub->funcs->program_compbuf_size(hubbub, context->bw_ctx.bw.dcn.compbuf_size_kb, true); - if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) { - dc_dmub_srv_p_state_delegate(dc, - true, context); - context->bw_ctx.bw.dcn.clk.p_state_change_support = true; - dc->clk_mgr->clks.fw_based_mclk_switching = true; - } else { - dc->clk_mgr->clks.fw_based_mclk_switching = false; - } - dc->clk_mgr->funcs->update_clocks( dc->clk_mgr, context, diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c index 8263a07f265f21..32121db2851e66 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hwseq.c @@ -983,36 +983,13 @@ void dcn30_set_disp_pattern_generator(const struct dc *dc, } void dcn30_prepare_bandwidth(struct dc *dc, - struct dc_state *context) + struct dc_state *context) { - bool p_state_change_support = context->bw_ctx.bw.dcn.clk.p_state_change_support; - /* Any transition into an FPO config should disable MCLK switching first to avoid - * driver and FW P-State synchronization issues. - */ - if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) { - dc->optimized_required = true; - context->bw_ctx.bw.dcn.clk.p_state_change_support = false; - } - if (dc->clk_mgr->dc_mode_softmax_enabled) if (dc->clk_mgr->clks.dramclk_khz <= dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 && context->bw_ctx.bw.dcn.clk.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000) dc->clk_mgr->funcs->set_max_memclk(dc->clk_mgr, dc->clk_mgr->bw_params->clk_table.entries[dc->clk_mgr->bw_params->clk_table.num_entries - 1].memclk_mhz); dcn20_prepare_bandwidth(dc, context); - /* - * enabled -> enabled: do not disable - * enabled -> disabled: disable - * disabled -> enabled: don't care - * disabled -> disabled: don't care - */ - if (!context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching) - dc_dmub_srv_p_state_delegate(dc, false, context); - - if (context->bw_ctx.bw.dcn.clk.fw_based_mclk_switching || dc->clk_mgr->clks.fw_based_mclk_switching) { - /* After disabling P-State, restore the original value to ensure we get the correct P-State - * on the next optimize. */ - context->bw_ctx.bw.dcn.clk.p_state_change_support = p_state_change_support; - } } diff --git a/drivers/gpu/drm/amd/display/dc/link/link_validation.c b/drivers/gpu/drm/amd/display/dc/link/link_validation.c index d4b7da526f0a55..e8b2fc4002a52d 100644 --- a/drivers/gpu/drm/amd/display/dc/link/link_validation.c +++ b/drivers/gpu/drm/amd/display/dc/link/link_validation.c @@ -359,5 +359,8 @@ bool link_validate_dpia_bandwidth(const struct dc_stream_state *stream, const un link[i] = stream[i].link; bw_needed[i] = dc_bandwidth_in_kbps_from_timing(&stream[i].timing); } + + ret = dpia_validate_usb4_bw(link, bw_needed, num_streams); + return ret; } diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 58c2246918fdab..f4f40459f22b97 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -871,13 +871,11 @@ static ssize_t amdgpu_get_pp_od_clk_voltage(struct device *dev, } if (ret == -ENOENT) { size = amdgpu_dpm_print_clock_levels(adev, OD_SCLK, buf); - if (size > 0) { - size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size); - size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size); - size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size); - size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size); - } + size += amdgpu_dpm_print_clock_levels(adev, OD_MCLK, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDC_CURVE, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_VDDGFX_OFFSET, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_RANGE, buf + size); + size += amdgpu_dpm_print_clock_levels(adev, OD_CCLK, buf + size); } if (size == 0) diff --git a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c index d6d9e3b1b2c0e4..02e69ccff3bac4 100644 --- a/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c +++ b/drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c @@ -6925,23 +6925,6 @@ static int si_dpm_enable(struct amdgpu_device *adev) return 0; } -static int si_set_temperature_range(struct amdgpu_device *adev) -{ - int ret; - - ret = si_thermal_enable_alert(adev, false); - if (ret) - return ret; - ret = si_thermal_set_temperature_range(adev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); - if (ret) - return ret; - ret = si_thermal_enable_alert(adev, true); - if (ret) - return ret; - - return ret; -} - static void si_dpm_disable(struct amdgpu_device *adev) { struct rv7xx_power_info *pi = rv770_get_pi(adev); @@ -7626,18 +7609,6 @@ static int si_dpm_process_interrupt(struct amdgpu_device *adev, static int si_dpm_late_init(void *handle) { - int ret; - struct amdgpu_device *adev = (struct amdgpu_device *)handle; - - if (!adev->pm.dpm_enabled) - return 0; - - ret = si_set_temperature_range(adev); - if (ret) - return ret; -#if 0 //TODO ? - si_dpm_powergate_uvd(adev, true); -#endif return 0; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c index 5633c5797e85a4..2ddf5198e5c486 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c +++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c @@ -733,6 +733,24 @@ static int smu_late_init(void *handle) return ret; } + /* + * Explicitly notify PMFW the power mode the system in. Since + * the PMFW may boot the ASIC with a different mode. + * For those supporting ACDC switch via gpio, PMFW will + * handle the switch automatically. Driver involvement + * is unnecessary. + */ + if (!smu->dc_controlled_by_gpio) { + ret = smu_set_power_source(smu, + adev->pm.ac_power ? SMU_POWER_SOURCE_AC : + SMU_POWER_SOURCE_DC); + if (ret) { + dev_err(adev->dev, "Failed to switch to %s mode!\n", + adev->pm.ac_power ? "AC" : "DC"); + return ret; + } + } + if ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 1)) || (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(13, 0, 3))) return 0; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c index c4000518dc56d8..275f708db63626 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c @@ -3413,26 +3413,8 @@ static int navi10_post_smu_init(struct smu_context *smu) return 0; ret = navi10_run_umc_cdr_workaround(smu); - if (ret) { + if (ret) dev_err(adev->dev, "Failed to apply umc cdr workaround!\n"); - return ret; - } - - if (!smu->dc_controlled_by_gpio) { - /* - * For Navi1X, manually switch it to AC mode as PMFW - * may boot it with DC mode. - */ - ret = smu_v11_0_set_power_source(smu, - adev->pm.ac_power ? - SMU_POWER_SOURCE_AC : - SMU_POWER_SOURCE_DC); - if (ret) { - dev_err(adev->dev, "Failed to switch to %s mode!\n", - adev->pm.ac_power ? "AC" : "DC"); - return ret; - } - } return ret; } diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 7433dcaa16e046..067b4e0b026c0b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -582,7 +582,7 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, DpmClocks_t *clk_table = smu->smu_table.clocks_table; SmuMetrics_legacy_t metrics; struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - int i, size = 0, ret = 0; + int i, idx, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0; bool cur_value_match_level = false; @@ -656,7 +656,8 @@ static int vangogh_print_legacy_clk_levels(struct smu_context *smu, case SMU_MCLK: case SMU_FCLK: for (i = 0; i < count; i++) { - ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value); + idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = vangogh_get_dpm_clk_limited(smu, clk_type, idx, &value); if (ret) return ret; if (!value) @@ -683,7 +684,7 @@ static int vangogh_print_clk_levels(struct smu_context *smu, DpmClocks_t *clk_table = smu->smu_table.clocks_table; SmuMetrics_t metrics; struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); - int i, size = 0, ret = 0; + int i, idx, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0; bool cur_value_match_level = false; uint32_t min, max; @@ -765,7 +766,8 @@ static int vangogh_print_clk_levels(struct smu_context *smu, case SMU_MCLK: case SMU_FCLK: for (i = 0; i < count; i++) { - ret = vangogh_get_dpm_clk_limited(smu, clk_type, i, &value); + idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = vangogh_get_dpm_clk_limited(smu, clk_type, idx, &value); if (ret) return ret; if (!value) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c index 5cdc07165480b5..8a8ba25c9ad7cc 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c @@ -494,7 +494,7 @@ static int renoir_set_fine_grain_gfx_freq_parameters(struct smu_context *smu) static int renoir_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { - int i, size = 0, ret = 0; + int i, idx, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0, min = 0, max = 0; SmuMetrics_t metrics; struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm); @@ -594,7 +594,8 @@ static int renoir_print_clk_levels(struct smu_context *smu, case SMU_VCLK: case SMU_DCLK: for (i = 0; i < count; i++) { - ret = renoir_get_dpm_clk_limited(smu, clk_type, i, &value); + idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = renoir_get_dpm_clk_limited(smu, clk_type, idx, &value); if (ret) return ret; if (!value) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c index 8fa9a36c38b64e..6d9760eac16d8d 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_4_ppt.c @@ -478,7 +478,7 @@ static int smu_v13_0_4_get_dpm_level_count(struct smu_context *smu, static int smu_v13_0_4_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { - int i, size = 0, ret = 0; + int i, idx, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0; uint32_t min, max; @@ -512,7 +512,8 @@ static int smu_v13_0_4_print_clk_levels(struct smu_context *smu, break; for (i = 0; i < count; i++) { - ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, i, &value); + idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = smu_v13_0_4_get_dpm_freq_by_index(smu, clk_type, idx, &value); if (ret) break; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c index 66445964efbd1e..0081fa607e02e4 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_5_ppt.c @@ -866,7 +866,7 @@ static int smu_v13_0_5_set_soft_freq_limited_range(struct smu_context *smu, static int smu_v13_0_5_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { - int i, size = 0, ret = 0; + int i, idx, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0; uint32_t min = 0, max = 0; @@ -898,7 +898,8 @@ static int smu_v13_0_5_print_clk_levels(struct smu_context *smu, goto print_clk_out; for (i = 0; i < count; i++) { - ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, i, &value); + idx = (clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = smu_v13_0_5_get_dpm_freq_by_index(smu, clk_type, idx, &value); if (ret) goto print_clk_out; diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c index 3d9ff46706fb70..bba621615abf09 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c @@ -125,6 +125,7 @@ static struct cmn2asic_msg_mapping smu_v13_0_7_message_map[SMU_MSG_MAX_COUNT] = MSG_MAP(ArmD3, PPSMC_MSG_ArmD3, 0), MSG_MAP(AllowGpo, PPSMC_MSG_SetGpoAllow, 0), MSG_MAP(GetPptLimit, PPSMC_MSG_GetPptLimit, 0), + MSG_MAP(NotifyPowerSource, PPSMC_MSG_NotifyPowerSource, 0), }; static struct cmn2asic_mapping smu_v13_0_7_clk_map[SMU_CLK_COUNT] = { @@ -1770,6 +1771,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = { .enable_mgpu_fan_boost = smu_v13_0_7_enable_mgpu_fan_boost, .get_power_limit = smu_v13_0_7_get_power_limit, .set_power_limit = smu_v13_0_set_power_limit, + .set_power_source = smu_v13_0_set_power_source, .get_power_profile_mode = smu_v13_0_7_get_power_profile_mode, .set_power_profile_mode = smu_v13_0_7_set_power_profile_mode, .set_tool_table_location = smu_v13_0_set_tool_table_location, diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c index 04e56b0b3033ea..798f36cfcebd38 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/yellow_carp_ppt.c @@ -1000,7 +1000,7 @@ static int yellow_carp_set_soft_freq_limited_range(struct smu_context *smu, static int yellow_carp_print_clk_levels(struct smu_context *smu, enum smu_clk_type clk_type, char *buf) { - int i, size = 0, ret = 0; + int i, idx, size = 0, ret = 0; uint32_t cur_value = 0, value = 0, count = 0; uint32_t min, max; @@ -1033,7 +1033,8 @@ static int yellow_carp_print_clk_levels(struct smu_context *smu, goto print_clk_out; for (i = 0; i < count; i++) { - ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, i, &value); + idx = (clk_type == SMU_FCLK || clk_type == SMU_MCLK) ? (count - i - 1) : i; + ret = yellow_carp_get_dpm_freq_by_index(smu, clk_type, idx, &value); if (ret) goto print_clk_out; diff --git a/drivers/gpu/drm/drm_managed.c b/drivers/gpu/drm/drm_managed.c index 4cf214de50c403..c21c3f6230335f 100644 --- a/drivers/gpu/drm/drm_managed.c +++ b/drivers/gpu/drm/drm_managed.c @@ -264,28 +264,10 @@ void drmm_kfree(struct drm_device *dev, void *data) } EXPORT_SYMBOL(drmm_kfree); -static void drmm_mutex_release(struct drm_device *dev, void *res) +void __drmm_mutex_release(struct drm_device *dev, void *res) { struct mutex *lock = res; mutex_destroy(lock); } - -/** - * drmm_mutex_init - &drm_device-managed mutex_init() - * @dev: DRM device - * @lock: lock to be initialized - * - * Returns: - * 0 on success, or a negative errno code otherwise. - * - * This is a &drm_device-managed version of mutex_init(). The initialized - * lock is automatically destroyed on the final drm_dev_put(). - */ -int drmm_mutex_init(struct drm_device *dev, struct mutex *lock) -{ - mutex_init(lock); - - return drmm_add_action_or_reset(dev, drmm_mutex_release, lock); -} -EXPORT_SYMBOL(drmm_mutex_init); +EXPORT_SYMBOL(__drmm_mutex_release); diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index b1a38e6ce2f8fa..0cb646cb04ee1a 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -179,7 +179,7 @@ static const struct dmi_system_id orientation_data[] = { }, { /* AYA NEO AIR */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AYANEO"), - DMI_MATCH(DMI_BOARD_NAME, "AIR"), + DMI_MATCH(DMI_PRODUCT_NAME, "AIR"), }, .driver_data = (void *)&lcd1080x1920_leftside_up, }, { /* AYA NEO NEXT */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.h b/drivers/gpu/drm/exynos/exynos_drm_g2d.h index 74ea3c26deadce..1a5ae781b56c60 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.h +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.h @@ -34,11 +34,11 @@ static inline int exynos_g2d_exec_ioctl(struct drm_device *dev, void *data, return -ENODEV; } -int g2d_open(struct drm_device *drm_dev, struct drm_file *file) +static inline int g2d_open(struct drm_device *drm_dev, struct drm_file *file) { return 0; } -void g2d_close(struct drm_device *drm_dev, struct drm_file *file) +static inline void g2d_close(struct drm_device *drm_dev, struct drm_file *file) { } #endif diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3c29792137a56d..0aae9a1eb3d584 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1851,9 +1851,17 @@ static void hsw_crtc_disable(struct intel_atomic_state *state, intel_disable_shared_dpll(old_crtc_state); - intel_encoders_post_pll_disable(state, crtc); + if (!intel_crtc_is_bigjoiner_slave(old_crtc_state)) { + struct intel_crtc *slave_crtc; + + intel_encoders_post_pll_disable(state, crtc); - intel_dmc_disable_pipe(i915, crtc->pipe); + intel_dmc_disable_pipe(i915, crtc->pipe); + + for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, + intel_crtc_bigjoiner_slave_pipes(old_crtc_state)) + intel_dmc_disable_pipe(i915, slave_crtc->pipe); + } } static void i9xx_pfit_enable(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index 650232c4892b18..b183efab04a1d4 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -204,8 +204,6 @@ bool intel_hdcp2_capable(struct intel_connector *connector) struct intel_digital_port *dig_port = intel_attached_dig_port(connector); struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_hdcp *hdcp = &connector->hdcp; - struct intel_gt *gt = dev_priv->media_gt; - struct intel_gsc_uc *gsc = >->uc.gsc; bool capable = false; /* I915 support for HDCP2.2 */ @@ -213,9 +211,13 @@ bool intel_hdcp2_capable(struct intel_connector *connector) return false; /* If MTL+ make sure gsc is loaded and proxy is setup */ - if (intel_hdcp_gsc_cs_required(dev_priv)) - if (!intel_uc_fw_is_running(&gsc->fw)) + if (intel_hdcp_gsc_cs_required(dev_priv)) { + struct intel_gt *gt = dev_priv->media_gt; + struct intel_gsc_uc *gsc = gt ? >->uc.gsc : NULL; + + if (!gsc || !intel_uc_fw_is_running(&gsc->fw)) return false; + } /* MEI/GSC interface is solid depending on which is used */ mutex_lock(&dev_priv->display.hdcp.comp_mutex); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 050b8ae7b8e70b..3035cba2c6a29e 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -877,12 +877,17 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, stream->oa_buffer.last_ctx_id = ctx_id; } - /* - * Clear out the report id and timestamp as a means to detect unlanded - * reports. - */ - oa_report_id_clear(stream, report32); - oa_timestamp_clear(stream, report32); + if (is_power_of_2(report_size)) { + /* + * Clear out the report id and timestamp as a means + * to detect unlanded reports. + */ + oa_report_id_clear(stream, report32); + oa_timestamp_clear(stream, report32); + } else { + /* Zero out the entire report */ + memset(report32, 0, report_size); + } } if (start_offset != *offset) { diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 0f2dd26755df98..af3ce5a6a636ac 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -642,6 +642,11 @@ void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_ if (funcs->pixpllc_atomic_update) funcs->pixpllc_atomic_update(crtc, old_state); + if (crtc_state->gamma_lut) + mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data); + else + mgag200_crtc_set_gamma_linear(mdev, format); + mgag200_enable_display(mdev); if (funcs->enable_vidrst) diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h index 2b3ae84057dfe0..bdcd554fc8a80d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_3_0_msm8998.h @@ -98,17 +98,17 @@ static const struct dpu_sspp_cfg msm8998_sspp[] = { static const struct dpu_lm_cfg msm8998_lm[] = { LM_BLK("lm_0", LM_0, 0x44000, MIXER_MSM8998_MASK, - &msm8998_lm_sblk, PINGPONG_0, LM_2, DSPP_0), + &msm8998_lm_sblk, PINGPONG_0, LM_1, DSPP_0), LM_BLK("lm_1", LM_1, 0x45000, MIXER_MSM8998_MASK, - &msm8998_lm_sblk, PINGPONG_1, LM_5, DSPP_1), + &msm8998_lm_sblk, PINGPONG_1, LM_0, DSPP_1), LM_BLK("lm_2", LM_2, 0x46000, MIXER_MSM8998_MASK, - &msm8998_lm_sblk, PINGPONG_2, LM_0, 0), + &msm8998_lm_sblk, PINGPONG_2, LM_5, 0), LM_BLK("lm_3", LM_3, 0x47000, MIXER_MSM8998_MASK, &msm8998_lm_sblk, PINGPONG_MAX, 0, 0), LM_BLK("lm_4", LM_4, 0x48000, MIXER_MSM8998_MASK, &msm8998_lm_sblk, PINGPONG_MAX, 0, 0), LM_BLK("lm_5", LM_5, 0x49000, MIXER_MSM8998_MASK, - &msm8998_lm_sblk, PINGPONG_3, LM_1, 0), + &msm8998_lm_sblk, PINGPONG_3, LM_2, 0), }; static const struct dpu_pingpong_cfg msm8998_pp[] = { @@ -134,10 +134,10 @@ static const struct dpu_dspp_cfg msm8998_dspp[] = { }; static const struct dpu_intf_cfg msm8998_intf[] = { - INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25), - INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27), - INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29), - INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 25, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31), + INTF_BLK("intf_0", INTF_0, 0x6a000, 0x280, INTF_DP, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 24, 25), + INTF_BLK("intf_1", INTF_1, 0x6a800, 0x280, INTF_DSI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 26, 27), + INTF_BLK("intf_2", INTF_2, 0x6b000, 0x280, INTF_DSI, 1, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 28, 29), + INTF_BLK("intf_3", INTF_3, 0x6b800, 0x280, INTF_HDMI, 0, 21, INTF_SDM845_MASK, MDP_SSPP_TOP0_INTR, 30, 31), }; static const struct dpu_perf_cfg msm8998_perf_data = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h index 282d410269ff62..42b0e58624d008 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_0_sm8150.h @@ -128,10 +128,10 @@ static const struct dpu_dspp_cfg sm8150_dspp[] = { }; static const struct dpu_pingpong_cfg sm8150_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h index c57400265f2884..e3bdfe7b30f1f1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_5_1_sc8180x.h @@ -116,10 +116,10 @@ static const struct dpu_lm_cfg sc8180x_lm[] = { }; static const struct dpu_pingpong_cfg sc8180x_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h index 2c40229ea51594..ed130582873c70 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_0_sm8250.h @@ -129,10 +129,10 @@ static const struct dpu_dspp_cfg sm8250_dspp[] = { }; static const struct dpu_pingpong_cfg sm8250_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, MERGE_3D_0, sdm845_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, MERGE_3D_0, sdm845_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), PP_BLK("pingpong_2", PINGPONG_2, 0x71000, MERGE_3D_1, sdm845_pp_sblk, diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h index 8799ed7571190f..a46b11730a4d4a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_2_sc7180.h @@ -80,8 +80,8 @@ static const struct dpu_dspp_cfg sc7180_dspp[] = { }; static const struct dpu_pingpong_cfg sc7180_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk_te, -1, -1), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk_te, -1, -1), + PP_BLK("pingpong_0", PINGPONG_0, 0x70000, 0, sdm845_pp_sblk, -1, -1), + PP_BLK("pingpong_1", PINGPONG_1, 0x70800, 0, sdm845_pp_sblk, -1, -1), }; static const struct dpu_intf_cfg sc7180_intf[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h index 6f04d8f85c9250..988d820f7ef2e5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_3_sm6115.h @@ -122,7 +122,6 @@ const struct dpu_mdss_cfg dpu_sm6115_cfg = { .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ BIT(MDP_SSPP_TOP0_INTR2) | \ BIT(MDP_SSPP_TOP0_HIST_INTR) | \ - BIT(MDP_INTF0_INTR) | \ BIT(MDP_INTF1_INTR), }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h index 303492d62a5caa..c9003dcc1a59b6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_6_5_qcm2290.h @@ -112,7 +112,6 @@ const struct dpu_mdss_cfg dpu_qcm2290_cfg = { .mdss_irqs = BIT(MDP_SSPP_TOP0_INTR) | \ BIT(MDP_SSPP_TOP0_INTR2) | \ BIT(MDP_SSPP_TOP0_HIST_INTR) | \ - BIT(MDP_INTF0_INTR) | \ BIT(MDP_INTF1_INTR), }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h index ca107ca8de4624..4f6a965bcd90b1 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h @@ -127,22 +127,22 @@ static const struct dpu_dspp_cfg sm8350_dspp[] = { }; static const struct dpu_pingpong_cfg sm8350_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), - PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), - PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), - PP_BLK("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), - PP_BLK("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h index 5957de1859844f..6b2c7eae71d998 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h @@ -87,10 +87,10 @@ static const struct dpu_dspp_cfg sc7280_dspp[] = { }; static const struct dpu_pingpong_cfg sc7280_pp[] = { - PP_BLK("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1), - PP_BLK("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1), - PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1), - PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1), + PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, 0, sc7280_pp_sblk, -1, -1), + PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, 0, sc7280_pp_sblk, -1, -1), + PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1), + PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1), }; static const struct dpu_intf_cfg sc7280_intf[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h index 9aab110b8c44d6..706d0f13b598e5 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h @@ -121,18 +121,18 @@ static const struct dpu_dspp_cfg sc8280xp_dspp[] = { }; static const struct dpu_pingpong_cfg sc8280xp_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), -1), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), -1), - PP_BLK_TE("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk_te, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), -1), - PP_BLK_TE("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk_te, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), -1), - PP_BLK_TE("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk_te, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), - PP_BLK_TE("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk_te, - DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), + PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), -1), + PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), -1), + PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), -1), + PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), -1), + PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), + PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk, + DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), }; static const struct dpu_merge_3d_cfg sc8280xp_merge_3d[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h index 02a259b6b4268e..4ecb3df5cbc022 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h @@ -128,28 +128,28 @@ static const struct dpu_dspp_cfg sm8450_dspp[] = { }; /* FIXME: interrupts */ static const struct dpu_pingpong_cfg sm8450_pp[] = { - PP_BLK_TE("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 12)), - PP_BLK_TE("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sdm845_pp_sblk_te, + PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 13)), - PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 14)), - PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 15)), - PP_BLK("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), - PP_BLK("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), - PP_BLK("pingpong_6", PINGPONG_6, 0x65800, MERGE_3D_3, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_6", PINGPONG_6, 0x65800, MERGE_3D_3, sc7280_pp_sblk, -1, -1), - PP_BLK("pingpong_7", PINGPONG_7, 0x65c00, MERGE_3D_3, sdm845_pp_sblk, + PP_BLK_DITHER("pingpong_7", PINGPONG_7, 0x65c00, MERGE_3D_3, sc7280_pp_sblk, -1, -1), }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h index 9e403034093fdc..d0ab351b6a8b93 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h +++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h @@ -132,28 +132,28 @@ static const struct dpu_dspp_cfg sm8550_dspp[] = { &sm8150_dspp_sblk), }; static const struct dpu_pingpong_cfg sm8550_pp[] = { - PP_BLK_DIPHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_0", PINGPONG_0, 0x69000, MERGE_3D_0, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 8), -1), - PP_BLK_DIPHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_1", PINGPONG_1, 0x6a000, MERGE_3D_0, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 9), -1), - PP_BLK_DIPHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_2", PINGPONG_2, 0x6b000, MERGE_3D_1, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 10), -1), - PP_BLK_DIPHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_3", PINGPONG_3, 0x6c000, MERGE_3D_1, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR, 11), -1), - PP_BLK_DIPHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_4", PINGPONG_4, 0x6d000, MERGE_3D_2, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 30), -1), - PP_BLK_DIPHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_5", PINGPONG_5, 0x6e000, MERGE_3D_2, sc7280_pp_sblk, DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31), -1), - PP_BLK_DIPHER("pingpong_6", PINGPONG_6, 0x66000, MERGE_3D_3, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_6", PINGPONG_6, 0x66000, MERGE_3D_3, sc7280_pp_sblk, -1, -1), - PP_BLK_DIPHER("pingpong_7", PINGPONG_7, 0x66400, MERGE_3D_3, sc7280_pp_sblk, + PP_BLK_DITHER("pingpong_7", PINGPONG_7, 0x66400, MERGE_3D_3, sc7280_pp_sblk, -1, -1), }; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c index 03f162af1a50bc..5d994bce696f9e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c @@ -491,7 +491,7 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = { .len = 0x20, .version = 0x20000}, }; -#define PP_BLK_DIPHER(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \ +#define PP_BLK_DITHER(_name, _id, _base, _merge_3d, _sblk, _done, _rdptr) \ {\ .name = _name, .id = _id, \ .base = _base, .len = 0, \ @@ -587,12 +587,12 @@ static const u32 sdm845_nrt_pri_lvl[] = {3, 3, 3, 3, 3, 3, 3, 3}; static const struct dpu_vbif_dynamic_ot_cfg msm8998_ot_rdwr_cfg[] = { { - .pps = 1088 * 1920 * 30, + .pps = 1920 * 1080 * 30, .ot_limit = 2, }, { - .pps = 1088 * 1920 * 60, - .ot_limit = 6, + .pps = 1920 * 1080 * 60, + .ot_limit = 4, }, { .pps = 3840 * 2160 * 30, @@ -705,10 +705,7 @@ static const struct dpu_qos_lut_entry msm8998_qos_linear[] = { {.fl = 10, .lut = 0x1555b}, {.fl = 11, .lut = 0x5555b}, {.fl = 12, .lut = 0x15555b}, - {.fl = 13, .lut = 0x55555b}, - {.fl = 14, .lut = 0}, - {.fl = 1, .lut = 0x1b}, - {.fl = 0, .lut = 0} + {.fl = 0, .lut = 0x55555b} }; static const struct dpu_qos_lut_entry sdm845_qos_linear[] = { @@ -730,9 +727,7 @@ static const struct dpu_qos_lut_entry msm8998_qos_macrotile[] = { {.fl = 10, .lut = 0x1aaff}, {.fl = 11, .lut = 0x5aaff}, {.fl = 12, .lut = 0x15aaff}, - {.fl = 13, .lut = 0x55aaff}, - {.fl = 1, .lut = 0x1aaff}, - {.fl = 0, .lut = 0}, + {.fl = 0, .lut = 0x55aaff}, }; static const struct dpu_qos_lut_entry sc7180_qos_linear[] = { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c index 53326f25e40ef1..17f3e7e4f19410 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c @@ -15,7 +15,7 @@ /* * Register offsets in MDSS register file for the interrupt registers - * w.r.t. to the MDP base + * w.r.t. the MDP base */ #define MDP_SSPP_TOP0_OFF 0x0 #define MDP_INTF_0_OFF 0x6A000 @@ -24,20 +24,23 @@ #define MDP_INTF_3_OFF 0x6B800 #define MDP_INTF_4_OFF 0x6C000 #define MDP_INTF_5_OFF 0x6C800 +#define INTF_INTR_EN 0x1c0 +#define INTF_INTR_STATUS 0x1c4 +#define INTF_INTR_CLEAR 0x1c8 #define MDP_AD4_0_OFF 0x7C000 #define MDP_AD4_1_OFF 0x7D000 #define MDP_AD4_INTR_EN_OFF 0x41c #define MDP_AD4_INTR_CLEAR_OFF 0x424 #define MDP_AD4_INTR_STATUS_OFF 0x420 -#define MDP_INTF_0_OFF_REV_7xxx 0x34000 -#define MDP_INTF_1_OFF_REV_7xxx 0x35000 -#define MDP_INTF_2_OFF_REV_7xxx 0x36000 -#define MDP_INTF_3_OFF_REV_7xxx 0x37000 -#define MDP_INTF_4_OFF_REV_7xxx 0x38000 -#define MDP_INTF_5_OFF_REV_7xxx 0x39000 -#define MDP_INTF_6_OFF_REV_7xxx 0x3a000 -#define MDP_INTF_7_OFF_REV_7xxx 0x3b000 -#define MDP_INTF_8_OFF_REV_7xxx 0x3c000 +#define MDP_INTF_0_OFF_REV_7xxx 0x34000 +#define MDP_INTF_1_OFF_REV_7xxx 0x35000 +#define MDP_INTF_2_OFF_REV_7xxx 0x36000 +#define MDP_INTF_3_OFF_REV_7xxx 0x37000 +#define MDP_INTF_4_OFF_REV_7xxx 0x38000 +#define MDP_INTF_5_OFF_REV_7xxx 0x39000 +#define MDP_INTF_6_OFF_REV_7xxx 0x3a000 +#define MDP_INTF_7_OFF_REV_7xxx 0x3b000 +#define MDP_INTF_8_OFF_REV_7xxx 0x3c000 /** * struct dpu_intr_reg - array of DPU register sets diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c index 84ee2efa9c664e..b9dddf576c029f 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c @@ -56,11 +56,6 @@ #define INTF_TPG_RGB_MAPPING 0x11C #define INTF_PROG_FETCH_START 0x170 #define INTF_PROG_ROT_START 0x174 - -#define INTF_FRAME_LINE_COUNT_EN 0x0A8 -#define INTF_FRAME_COUNT 0x0AC -#define INTF_LINE_COUNT 0x0B0 - #define INTF_MUX 0x25C #define INTF_STATUS 0x26C diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c index 2d28afdf860efc..a3e413d277175e 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c @@ -61,6 +61,7 @@ static const struct dpu_wb_cfg *_wb_offset(enum dpu_wb wb, for (i = 0; i < m->wb_count; i++) { if (wb == m->wb[i].id) { b->blk_addr = addr + m->wb[i].base; + b->log_mask = DPU_DBG_MASK_WB; return &m->wb[i]; } } diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h index feb9a729844a3c..5acd5683d25a40 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hwio.h @@ -21,9 +21,6 @@ #define HIST_INTR_EN 0x01c #define HIST_INTR_STATUS 0x020 #define HIST_INTR_CLEAR 0x024 -#define INTF_INTR_EN 0x1C0 -#define INTF_INTR_STATUS 0x1C4 -#define INTF_INTR_CLEAR 0x1C8 #define SPLIT_DISPLAY_EN 0x2F4 #define SPLIT_DISPLAY_UPPER_PIPE_CTRL 0x2F8 #define DSPP_IGC_COLOR0_RAM_LUTN 0x300 diff --git a/drivers/gpu/drm/msm/dp/dp_audio.c b/drivers/gpu/drm/msm/dp/dp_audio.c index 6666783e1468e3..1245c7aa49df84 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.c +++ b/drivers/gpu/drm/msm/dp/dp_audio.c @@ -593,6 +593,18 @@ static struct hdmi_codec_pdata codec_data = { .i2s = 1, }; +void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio) +{ + struct dp_audio_private *audio_priv; + + audio_priv = container_of(dp_audio, struct dp_audio_private, dp_audio); + + if (audio_priv->audio_pdev) { + platform_device_unregister(audio_priv->audio_pdev); + audio_priv->audio_pdev = NULL; + } +} + int dp_register_audio_driver(struct device *dev, struct dp_audio *dp_audio) { diff --git a/drivers/gpu/drm/msm/dp/dp_audio.h b/drivers/gpu/drm/msm/dp/dp_audio.h index 84e5f4a5d26bad..4ab78880af8296 100644 --- a/drivers/gpu/drm/msm/dp/dp_audio.h +++ b/drivers/gpu/drm/msm/dp/dp_audio.h @@ -53,6 +53,8 @@ struct dp_audio *dp_audio_get(struct platform_device *pdev, int dp_register_audio_driver(struct device *dev, struct dp_audio *dp_audio); +void dp_unregister_audio_driver(struct device *dev, struct dp_audio *dp_audio); + /** * dp_audio_put() * diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c index 3e13acdfa7e533..99a38dbe51c0ff 100644 --- a/drivers/gpu/drm/msm/dp/dp_display.c +++ b/drivers/gpu/drm/msm/dp/dp_display.c @@ -326,6 +326,7 @@ static void dp_display_unbind(struct device *dev, struct device *master, kthread_stop(dp->ev_tsk); dp_power_client_deinit(dp->power); + dp_unregister_audio_driver(dev, dp->audio); dp_aux_unregister(dp->aux); dp->drm_dev = NULL; dp->aux->drm_dev = NULL; diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index d77fa9793c54dc..9c45d641b5212c 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -155,6 +155,8 @@ static bool can_do_async(struct drm_atomic_state *state, for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (drm_atomic_crtc_needs_modeset(crtc_state)) return false; + if (!crtc_state->active) + return false; if (++num_crtcs > 1) return false; *async_crtc = crtc; diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index db6c4e281d75d0..cd39b9d8abdbeb 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -219,7 +219,8 @@ static void put_pages(struct drm_gem_object *obj) } } -static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj) +static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj, + unsigned madv) { struct msm_drm_private *priv = obj->dev->dev_private; struct msm_gem_object *msm_obj = to_msm_bo(obj); @@ -227,7 +228,9 @@ static struct page **msm_gem_pin_pages_locked(struct drm_gem_object *obj) msm_gem_assert_locked(obj); - if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) { + if (GEM_WARN_ON(msm_obj->madv > madv)) { + DRM_DEV_ERROR(obj->dev->dev, "Invalid madv state: %u vs %u\n", + msm_obj->madv, madv); return ERR_PTR(-EBUSY); } @@ -248,7 +251,7 @@ struct page **msm_gem_pin_pages(struct drm_gem_object *obj) struct page **p; msm_gem_lock(obj); - p = msm_gem_pin_pages_locked(obj); + p = msm_gem_pin_pages_locked(obj, MSM_MADV_WILLNEED); msm_gem_unlock(obj); return p; @@ -473,10 +476,7 @@ int msm_gem_pin_vma_locked(struct drm_gem_object *obj, struct msm_gem_vma *vma) msm_gem_assert_locked(obj); - if (GEM_WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) - return -EBUSY; - - pages = msm_gem_pin_pages_locked(obj); + pages = msm_gem_pin_pages_locked(obj, MSM_MADV_WILLNEED); if (IS_ERR(pages)) return PTR_ERR(pages); @@ -699,13 +699,7 @@ static void *get_vaddr(struct drm_gem_object *obj, unsigned madv) if (obj->import_attach) return ERR_PTR(-ENODEV); - if (GEM_WARN_ON(msm_obj->madv > madv)) { - DRM_DEV_ERROR(obj->dev->dev, "Invalid madv state: %u vs %u\n", - msm_obj->madv, madv); - return ERR_PTR(-EBUSY); - } - - pages = msm_gem_pin_pages_locked(obj); + pages = msm_gem_pin_pages_locked(obj, madv); if (IS_ERR(pages)) return ERR_CAST(pages); diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index aff18c2f600ab2..9f5933c75e3df9 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -722,7 +722,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct msm_drm_private *priv = dev->dev_private; struct drm_msm_gem_submit *args = data; struct msm_file_private *ctx = file->driver_priv; - struct msm_gem_submit *submit; + struct msm_gem_submit *submit = NULL; struct msm_gpu *gpu = priv->gpu; struct msm_gpu_submitqueue *queue; struct msm_ringbuffer *ring; @@ -769,13 +769,15 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, out_fence_fd = get_unused_fd_flags(O_CLOEXEC); if (out_fence_fd < 0) { ret = out_fence_fd; - return ret; + goto out_post_unlock; } } submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds); - if (IS_ERR(submit)) - return PTR_ERR(submit); + if (IS_ERR(submit)) { + ret = PTR_ERR(submit); + goto out_post_unlock; + } trace_msm_gpu_submit(pid_nr(submit->pid), ring->id, submit->ident, args->nr_bos, args->nr_cmds); @@ -962,11 +964,20 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (has_ww_ticket) ww_acquire_fini(&submit->ticket); out_unlock: - if (ret && (out_fence_fd >= 0)) - put_unused_fd(out_fence_fd); mutex_unlock(&queue->lock); out_post_unlock: - msm_gem_submit_put(submit); + if (ret && (out_fence_fd >= 0)) + put_unused_fd(out_fence_fd); + + if (!IS_ERR_OR_NULL(submit)) { + msm_gem_submit_put(submit); + } else { + /* + * If the submit hasn't yet taken ownership of the queue + * then we need to drop the reference ourself: + */ + msm_submitqueue_put(queue); + } if (!IS_ERR_OR_NULL(post_deps)) { for (i = 0; i < args->nr_out_syncobjs; ++i) { kfree(post_deps[i].chain); diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 418e1e06cddefd..5cc8d358cc9759 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -234,7 +234,12 @@ struct msm_mmu *msm_iommu_pagetable_create(struct msm_mmu *parent) /* Get the pagetable configuration from the domain */ if (adreno_smmu->cookie) ttbr1_cfg = adreno_smmu->get_ttbr1_cfg(adreno_smmu->cookie); - if (!ttbr1_cfg) + + /* + * If you hit this WARN_ONCE() you are probably missing an entry in + * qcom_smmu_impl_of_match[] in arm-smmu-qcom.c + */ + if (WARN_ONCE(!ttbr1_cfg, "No per-process page tables")) return ERR_PTR(-ENODEV); pagetable = kzalloc(sizeof(*pagetable), GFP_KERNEL); @@ -410,7 +415,7 @@ struct msm_mmu *msm_iommu_gpu_new(struct device *dev, struct msm_gpu *gpu, unsig struct msm_mmu *mmu; mmu = msm_iommu_new(dev, quirks); - if (IS_ERR(mmu)) + if (IS_ERR_OR_NULL(mmu)) return mmu; iommu = to_msm_iommu(mmu); diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 6afdf260a4e226..b9fe926a49e8bb 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -53,7 +53,7 @@ pl111_mode_valid(struct drm_simple_display_pipe *pipe, { struct drm_device *drm = pipe->crtc.dev; struct pl111_drm_dev_private *priv = drm->dev_private; - u32 cpp = priv->variant->fb_bpp / 8; + u32 cpp = DIV_ROUND_UP(priv->variant->fb_depth, 8); u64 bw; /* diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index 2a46b5bd857649..d1fe756444ee52 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -114,7 +114,7 @@ struct drm_minor; * extensions to the control register * @formats: array of supported pixel formats on this variant * @nformats: the length of the array of supported pixel formats - * @fb_bpp: desired bits per pixel on the default framebuffer + * @fb_depth: desired depth per pixel on the default framebuffer */ struct pl111_variant_data { const char *name; @@ -126,7 +126,7 @@ struct pl111_variant_data { bool st_bitmux_control; const u32 *formats; unsigned int nformats; - unsigned int fb_bpp; + unsigned int fb_depth; }; struct pl111_drm_dev_private { diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 4b2a9e9753f6da..43049c8028b216 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -308,7 +308,7 @@ static int pl111_amba_probe(struct amba_device *amba_dev, if (ret < 0) goto dev_put; - drm_fbdev_dma_setup(drm, priv->variant->fb_bpp); + drm_fbdev_dma_setup(drm, priv->variant->fb_depth); return 0; @@ -351,7 +351,7 @@ static const struct pl111_variant_data pl110_variant = { .is_pl110 = true, .formats = pl110_pixel_formats, .nformats = ARRAY_SIZE(pl110_pixel_formats), - .fb_bpp = 16, + .fb_depth = 16, }; /* RealView, Versatile Express etc use this modern variant */ @@ -376,7 +376,7 @@ static const struct pl111_variant_data pl111_variant = { .name = "PL111", .formats = pl111_pixel_formats, .nformats = ARRAY_SIZE(pl111_pixel_formats), - .fb_bpp = 32, + .fb_depth = 32, }; static const u32 pl110_nomadik_pixel_formats[] = { @@ -405,7 +405,7 @@ static const struct pl111_variant_data pl110_nomadik_variant = { .is_lcdc = true, .st_bitmux_control = true, .broken_vblank = true, - .fb_bpp = 16, + .fb_depth = 16, }; static const struct amba_id pl111_id_table[] = { diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c index 1b436b75fd396f..00c3ebd32359b9 100644 --- a/drivers/gpu/drm/pl111/pl111_versatile.c +++ b/drivers/gpu/drm/pl111/pl111_versatile.c @@ -316,7 +316,7 @@ static const struct pl111_variant_data pl110_integrator = { .broken_vblank = true, .formats = pl110_integrator_pixel_formats, .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), - .fb_bpp = 16, + .fb_depth = 16, }; /* @@ -330,7 +330,7 @@ static const struct pl111_variant_data pl110_impd1 = { .broken_vblank = true, .formats = pl110_integrator_pixel_formats, .nformats = ARRAY_SIZE(pl110_integrator_pixel_formats), - .fb_bpp = 16, + .fb_depth = 15, }; /* @@ -343,7 +343,7 @@ static const struct pl111_variant_data pl110_versatile = { .external_bgr = true, .formats = pl110_versatile_pixel_formats, .nformats = ARRAY_SIZE(pl110_versatile_pixel_formats), - .fb_bpp = 16, + .fb_depth = 16, }; /* @@ -355,7 +355,7 @@ static const struct pl111_variant_data pl111_realview = { .name = "PL111 RealView", .formats = pl111_realview_pixel_formats, .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), - .fb_bpp = 16, + .fb_depth = 16, }; /* @@ -367,7 +367,7 @@ static const struct pl111_variant_data pl111_vexpress = { .name = "PL111 Versatile Express", .formats = pl111_realview_pixel_formats, .nformats = ARRAY_SIZE(pl111_realview_pixel_formats), - .fb_bpp = 16, + .fb_depth = 16, .broken_clockdivider = true, }; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 3377fbc71f6547..c4dda908666cfc 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -99,6 +99,16 @@ static void radeon_hotplug_work_func(struct work_struct *work) static void radeon_dp_work_func(struct work_struct *work) { + struct radeon_device *rdev = container_of(work, struct radeon_device, + dp_work); + struct drm_device *dev = rdev->ddev; + struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector *connector; + + mutex_lock(&mode_config->mutex); + list_for_each_entry(connector, &mode_config->connector_list, head) + radeon_connector_hotplug(connector); + mutex_unlock(&mode_config->mutex); } /** diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 8c183639603ec4..aea5a90ff98b98 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -1141,9 +1141,6 @@ void drm_sched_fini(struct drm_gpu_scheduler *sched) for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { struct drm_sched_rq *rq = &sched->sched_rq[i]; - if (!rq) - continue; - spin_lock(&rq->lock); list_for_each_entry(s_entity, &rq->entities, list) /* diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index 7ae5f27df54dd6..c6bdb9c4ef3e00 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -586,6 +586,8 @@ static const struct hid_device_id hammer_devices[] = { USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_EEL) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_JEWEL) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_MAGNEMITE) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index d79e946acdcbed..5d29abac2300e4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -529,6 +529,7 @@ #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 #define USB_DEVICE_ID_GOOGLE_DON 0x5050 #define USB_DEVICE_ID_GOOGLE_EEL 0x5057 +#define USB_DEVICE_ID_GOOGLE_JEWEL 0x5061 #define USB_VENDOR_ID_GOTOP 0x08f2 #define USB_DEVICE_ID_SUPER_Q2 0x007f diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 0fcfd85fea0fef..5e1a412fd28fa1 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -286,7 +286,7 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, struct hidpp_report *message, struct hidpp_report *response) { - int ret; + int ret = -1; int max_retries = 3; mutex_lock(&hidpp->send_mutex); @@ -300,13 +300,13 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, */ *response = *message; - for (; max_retries != 0; max_retries--) { + for (; max_retries != 0 && ret; max_retries--) { ret = __hidpp_send_report(hidpp->hid_dev, message); if (ret) { dbg_hid("__hidpp_send_report returned err: %d\n", ret); memset(response, 0, sizeof(struct hidpp_report)); - goto exit; + break; } if (!wait_event_timeout(hidpp->wait, hidpp->answer_available, @@ -314,13 +314,14 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, dbg_hid("%s:timeout waiting for response\n", __func__); memset(response, 0, sizeof(struct hidpp_report)); ret = -ETIMEDOUT; + break; } if (response->report_id == REPORT_ID_HIDPP_SHORT && response->rap.sub_id == HIDPP_ERROR) { ret = response->rap.params[1]; dbg_hid("%s:got hidpp error %02X\n", __func__, ret); - goto exit; + break; } if ((response->report_id == REPORT_ID_HIDPP_LONG || @@ -329,13 +330,12 @@ static int hidpp_send_message_sync(struct hidpp_device *hidpp, ret = response->fap.params[1]; if (ret != HIDPP20_ERROR_BUSY) { dbg_hid("%s:got hidpp 2.0 error %02X\n", __func__, ret); - goto exit; + break; } dbg_hid("%s:got busy hidpp 2.0 error %02X, retrying\n", __func__, ret); } } -exit: mutex_unlock(&hidpp->send_mutex); return ret; diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 8214896adadadd..76e5353aca0c74 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -2224,7 +2224,9 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) } else if (strstr(product_name, "Wacom") || strstr(product_name, "wacom") || strstr(product_name, "WACOM")) { - strscpy(name, product_name, sizeof(name)); + if (strscpy(name, product_name, sizeof(name)) < 0) { + hid_warn(wacom->hdev, "String overflow while assembling device name"); + } } else { snprintf(name, sizeof(name), "Wacom %s", product_name); } @@ -2242,7 +2244,9 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) if (name[strlen(name)-1] == ' ') name[strlen(name)-1] = '\0'; } else { - strscpy(name, features->name, sizeof(name)); + if (strscpy(name, features->name, sizeof(name)) < 0) { + hid_warn(wacom->hdev, "String overflow while assembling device name"); + } } snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s%s", @@ -2410,8 +2414,13 @@ static int wacom_parse_and_register(struct wacom *wacom, bool wireless) goto fail_quirks; } - if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) + if (features->device_type & WACOM_DEVICETYPE_WL_MONITOR) { error = hid_hw_open(hdev); + if (error) { + hid_err(hdev, "hw open failed\n"); + goto fail_quirks; + } + } wacom_set_shared_values(wacom_wac); devres_close_group(&hdev->dev, wacom); @@ -2500,8 +2509,10 @@ static void wacom_wireless_work(struct work_struct *work) goto fail; } - strscpy(wacom_wac->name, wacom_wac1->name, - sizeof(wacom_wac->name)); + if (strscpy(wacom_wac->name, wacom_wac1->name, + sizeof(wacom_wac->name)) < 0) { + hid_warn(wacom->hdev, "String overflow while assembling device name"); + } } return; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index dc0f7d9a992c10..2ccf838371343d 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -831,7 +831,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) /* Enter report */ if ((data[1] & 0xfc) == 0xc0) { /* serial number of the tool */ - wacom->serial[idx] = ((data[3] & 0x0f) << 28) + + wacom->serial[idx] = ((__u64)(data[3] & 0x0f) << 28) + (data[4] << 20) + (data[5] << 12) + (data[6] << 4) + (data[7] >> 4); diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c index 711f451b694694..89e8ed214ea496 100644 --- a/drivers/hwtracing/coresight/coresight-etm-perf.c +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c @@ -402,6 +402,7 @@ static void *etm_setup_aux(struct perf_event *event, void **pages, trace_id = coresight_trace_id_get_cpu_id(cpu); if (!IS_VALID_CS_TRACE_ID(trace_id)) { cpumask_clear_cpu(cpu, mask); + coresight_release_path(path); continue; } diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 918d461fcf4a68..eaa296ced16789 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -942,7 +942,7 @@ tmc_etr_buf_insert_barrier_packet(struct etr_buf *etr_buf, u64 offset) len = tmc_etr_buf_get_data(etr_buf, offset, CORESIGHT_BARRIER_PKT_SIZE, &bufp); - if (WARN_ON(len < CORESIGHT_BARRIER_PKT_SIZE)) + if (WARN_ON(len < 0 || len < CORESIGHT_BARRIER_PKT_SIZE)) return -EINVAL; coresight_insert_barrier_packet(bufp); return offset + CORESIGHT_BARRIER_PKT_SIZE; diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c index f98393d746668f..b8636fa8eaeb68 100644 --- a/drivers/iio/accel/kionix-kx022a.c +++ b/drivers/iio/accel/kionix-kx022a.c @@ -1048,7 +1048,7 @@ int kx022a_probe_internal(struct device *dev) data->ien_reg = KX022A_REG_INC4; } else { irq = fwnode_irq_get_byname(fwnode, "INT2"); - if (irq <= 0) + if (irq < 0) return dev_err_probe(dev, irq, "No suitable IRQ\n"); data->inc_reg = KX022A_REG_INC5; diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c index 5f7d81b44b1d28..282e539157f87c 100644 --- a/drivers/iio/accel/st_accel_core.c +++ b/drivers/iio/accel/st_accel_core.c @@ -1291,12 +1291,12 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev) adev = ACPI_COMPANION(indio_dev->dev.parent); if (!adev) - return 0; + return -ENXIO; /* Read _ONT data, which should be a package of 6 integers. */ status = acpi_evaluate_object(adev->handle, "_ONT", NULL, &buffer); if (status == AE_NOT_FOUND) { - return 0; + return -ENXIO; } else if (ACPI_FAILURE(status)) { dev_warn(&indio_dev->dev, "failed to execute _ONT: %d\n", status); diff --git a/drivers/iio/adc/ad4130.c b/drivers/iio/adc/ad4130.c index 38394341fd6e74..5a5dd5e87ffc44 100644 --- a/drivers/iio/adc/ad4130.c +++ b/drivers/iio/adc/ad4130.c @@ -1817,6 +1817,11 @@ static const struct clk_ops ad4130_int_clk_ops = { .unprepare = ad4130_int_clk_unprepare, }; +static void ad4130_clk_del_provider(void *of_node) +{ + of_clk_del_provider(of_node); +} + static int ad4130_setup_int_clk(struct ad4130_state *st) { struct device *dev = &st->spi->dev; @@ -1824,6 +1829,7 @@ static int ad4130_setup_int_clk(struct ad4130_state *st) struct clk_init_data init; const char *clk_name; struct clk *clk; + int ret; if (st->int_pin_sel == AD4130_INT_PIN_CLK || st->mclk_sel != AD4130_MCLK_76_8KHZ) @@ -1843,7 +1849,11 @@ static int ad4130_setup_int_clk(struct ad4130_state *st) if (IS_ERR(clk)) return PTR_ERR(clk); - return of_clk_add_provider(of_node, of_clk_src_simple_get, clk); + ret = of_clk_add_provider(of_node, of_clk_src_simple_get, clk); + if (ret) + return ret; + + return devm_add_action_or_reset(dev, ad4130_clk_del_provider, of_node); } static int ad4130_setup(struct iio_dev *indio_dev) diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c index 55a6ab59101607..99bb604b78c8cf 100644 --- a/drivers/iio/adc/ad7192.c +++ b/drivers/iio/adc/ad7192.c @@ -897,10 +897,6 @@ static const struct iio_info ad7195_info = { __AD719x_CHANNEL(_si, _channel1, -1, _address, NULL, IIO_VOLTAGE, \ BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info) -#define AD719x_SHORTED_CHANNEL(_si, _channel1, _address) \ - __AD719x_CHANNEL(_si, _channel1, -1, _address, "shorted", IIO_VOLTAGE, \ - BIT(IIO_CHAN_INFO_SCALE), ad7192_calibsys_ext_info) - #define AD719x_TEMP_CHANNEL(_si, _address) \ __AD719x_CHANNEL(_si, 0, -1, _address, NULL, IIO_TEMP, 0, NULL) @@ -908,7 +904,7 @@ static const struct iio_chan_spec ad7192_channels[] = { AD719x_DIFF_CHANNEL(0, 1, 2, AD7192_CH_AIN1P_AIN2M), AD719x_DIFF_CHANNEL(1, 3, 4, AD7192_CH_AIN3P_AIN4M), AD719x_TEMP_CHANNEL(2, AD7192_CH_TEMP), - AD719x_SHORTED_CHANNEL(3, 2, AD7192_CH_AIN2P_AIN2M), + AD719x_DIFF_CHANNEL(3, 2, 2, AD7192_CH_AIN2P_AIN2M), AD719x_CHANNEL(4, 1, AD7192_CH_AIN1), AD719x_CHANNEL(5, 2, AD7192_CH_AIN2), AD719x_CHANNEL(6, 3, AD7192_CH_AIN3), @@ -922,7 +918,7 @@ static const struct iio_chan_spec ad7193_channels[] = { AD719x_DIFF_CHANNEL(2, 5, 6, AD7193_CH_AIN5P_AIN6M), AD719x_DIFF_CHANNEL(3, 7, 8, AD7193_CH_AIN7P_AIN8M), AD719x_TEMP_CHANNEL(4, AD7193_CH_TEMP), - AD719x_SHORTED_CHANNEL(5, 2, AD7193_CH_AIN2P_AIN2M), + AD719x_DIFF_CHANNEL(5, 2, 2, AD7193_CH_AIN2P_AIN2M), AD719x_CHANNEL(6, 1, AD7193_CH_AIN1), AD719x_CHANNEL(7, 2, AD7193_CH_AIN2), AD719x_CHANNEL(8, 3, AD7193_CH_AIN3), diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index d8570f620785af..7e21928707437b 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -584,6 +584,10 @@ static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_de init_completion(&sigma_delta->completion); sigma_delta->irq_dis = true; + + /* the IRQ core clears IRQ_DISABLE_UNLAZY flag when freeing an IRQ */ + irq_set_status_flags(sigma_delta->spi->irq, IRQ_DISABLE_UNLAZY); + ret = devm_request_irq(dev, sigma_delta->spi->irq, ad_sd_data_rdy_trig_poll, sigma_delta->info->irq_flags | IRQF_NO_AUTOEN, diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c index a775d2e4056718..dce9ec91e4a778 100644 --- a/drivers/iio/adc/imx93_adc.c +++ b/drivers/iio/adc/imx93_adc.c @@ -236,8 +236,7 @@ static int imx93_adc_read_raw(struct iio_dev *indio_dev, { struct imx93_adc *adc = iio_priv(indio_dev); struct device *dev = adc->dev; - long ret; - u32 vref_uv; + int ret; switch (mask) { case IIO_CHAN_INFO_RAW: @@ -253,10 +252,10 @@ static int imx93_adc_read_raw(struct iio_dev *indio_dev, return IIO_VAL_INT; case IIO_CHAN_INFO_SCALE: - ret = vref_uv = regulator_get_voltage(adc->vref); + ret = regulator_get_voltage(adc->vref); if (ret < 0) return ret; - *val = vref_uv / 1000; + *val = ret / 1000; *val2 = 12; return IIO_VAL_FRACTIONAL_LOG2; diff --git a/drivers/iio/adc/mt6370-adc.c b/drivers/iio/adc/mt6370-adc.c index bc62e5a9d50d11..0bc112135bca1e 100644 --- a/drivers/iio/adc/mt6370-adc.c +++ b/drivers/iio/adc/mt6370-adc.c @@ -19,6 +19,7 @@ #include +#define MT6370_REG_DEV_INFO 0x100 #define MT6370_REG_CHG_CTRL3 0x113 #define MT6370_REG_CHG_CTRL7 0x117 #define MT6370_REG_CHG_ADC 0x121 @@ -27,6 +28,7 @@ #define MT6370_ADC_START_MASK BIT(0) #define MT6370_ADC_IN_SEL_MASK GENMASK(7, 4) #define MT6370_AICR_ICHG_MASK GENMASK(7, 2) +#define MT6370_VENID_MASK GENMASK(7, 4) #define MT6370_AICR_100_mA 0x0 #define MT6370_AICR_150_mA 0x1 @@ -47,6 +49,10 @@ #define ADC_CONV_TIME_MS 35 #define ADC_CONV_POLLING_TIME_US 1000 +#define MT6370_VID_RT5081 0x8 +#define MT6370_VID_RT5081A 0xA +#define MT6370_VID_MT6370 0xE + struct mt6370_adc_data { struct device *dev; struct regmap *regmap; @@ -55,6 +61,7 @@ struct mt6370_adc_data { * from being read at the same time. */ struct mutex adc_lock; + unsigned int vid; }; static int mt6370_adc_read_channel(struct mt6370_adc_data *priv, int chan, @@ -98,6 +105,30 @@ static int mt6370_adc_read_channel(struct mt6370_adc_data *priv, int chan, return ret; } +static int mt6370_adc_get_ibus_scale(struct mt6370_adc_data *priv) +{ + switch (priv->vid) { + case MT6370_VID_RT5081: + case MT6370_VID_RT5081A: + case MT6370_VID_MT6370: + return 3350; + default: + return 3875; + } +} + +static int mt6370_adc_get_ibat_scale(struct mt6370_adc_data *priv) +{ + switch (priv->vid) { + case MT6370_VID_RT5081: + case MT6370_VID_RT5081A: + case MT6370_VID_MT6370: + return 2680; + default: + return 3870; + } +} + static int mt6370_adc_read_scale(struct mt6370_adc_data *priv, int chan, int *val1, int *val2) { @@ -123,7 +154,7 @@ static int mt6370_adc_read_scale(struct mt6370_adc_data *priv, case MT6370_AICR_250_mA: case MT6370_AICR_300_mA: case MT6370_AICR_350_mA: - *val1 = 3350; + *val1 = mt6370_adc_get_ibus_scale(priv); break; default: *val1 = 5000; @@ -150,7 +181,7 @@ static int mt6370_adc_read_scale(struct mt6370_adc_data *priv, case MT6370_ICHG_600_mA: case MT6370_ICHG_700_mA: case MT6370_ICHG_800_mA: - *val1 = 2680; + *val1 = mt6370_adc_get_ibat_scale(priv); break; default: *val1 = 5000; @@ -251,6 +282,20 @@ static const struct iio_chan_spec mt6370_adc_channels[] = { MT6370_ADC_CHAN(TEMP_JC, IIO_TEMP, 12, BIT(IIO_CHAN_INFO_OFFSET)), }; +static int mt6370_get_vendor_info(struct mt6370_adc_data *priv) +{ + unsigned int dev_info; + int ret; + + ret = regmap_read(priv->regmap, MT6370_REG_DEV_INFO, &dev_info); + if (ret) + return ret; + + priv->vid = FIELD_GET(MT6370_VENID_MASK, dev_info); + + return 0; +} + static int mt6370_adc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -272,6 +317,10 @@ static int mt6370_adc_probe(struct platform_device *pdev) priv->regmap = regmap; mutex_init(&priv->adc_lock); + ret = mt6370_get_vendor_info(priv); + if (ret) + return dev_err_probe(dev, ret, "Failed to get vid\n"); + ret = regmap_write(priv->regmap, MT6370_REG_CHG_ADC, 0); if (ret) return dev_err_probe(dev, ret, "Failed to reset ADC\n"); diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index bca79a93cbe431..a50f39143d3ea3 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -757,13 +757,13 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev) ret = mxs_lradc_adc_trigger_init(iio); if (ret) - goto err_trig; + return ret; ret = iio_triggered_buffer_setup(iio, &iio_pollfunc_store_time, &mxs_lradc_adc_trigger_handler, &mxs_lradc_adc_buffer_ops); if (ret) - return ret; + goto err_trig; adc->vref_mv = mxs_lradc_adc_vref_mv[lradc->soc]; @@ -801,9 +801,9 @@ static int mxs_lradc_adc_probe(struct platform_device *pdev) err_dev: mxs_lradc_adc_hw_stop(adc); - mxs_lradc_adc_trigger_remove(iio); -err_trig: iio_triggered_buffer_cleanup(iio); +err_trig: + mxs_lradc_adc_trigger_remove(iio); return ret; } @@ -814,8 +814,8 @@ static int mxs_lradc_adc_remove(struct platform_device *pdev) iio_device_unregister(iio); mxs_lradc_adc_hw_stop(adc); - mxs_lradc_adc_trigger_remove(iio); iio_triggered_buffer_cleanup(iio); + mxs_lradc_adc_trigger_remove(iio); return 0; } diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c index c1c439215aeb5f..7dfc9c927a23f1 100644 --- a/drivers/iio/adc/palmas_gpadc.c +++ b/drivers/iio/adc/palmas_gpadc.c @@ -547,7 +547,7 @@ static int palmas_gpadc_read_raw(struct iio_dev *indio_dev, int adc_chan = chan->channel; int ret = 0; - if (adc_chan > PALMAS_ADC_CH_MAX) + if (adc_chan >= PALMAS_ADC_CH_MAX) return -EINVAL; mutex_lock(&adc->lock); @@ -595,7 +595,7 @@ static int palmas_gpadc_read_event_config(struct iio_dev *indio_dev, int adc_chan = chan->channel; int ret = 0; - if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) + if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) return -EINVAL; mutex_lock(&adc->lock); @@ -684,7 +684,7 @@ static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev, int adc_chan = chan->channel; int ret; - if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) + if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) return -EINVAL; mutex_lock(&adc->lock); @@ -710,7 +710,7 @@ static int palmas_gpadc_read_event_value(struct iio_dev *indio_dev, int adc_chan = chan->channel; int ret; - if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) + if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) return -EINVAL; mutex_lock(&adc->lock); @@ -744,7 +744,7 @@ static int palmas_gpadc_write_event_value(struct iio_dev *indio_dev, int old; int ret; - if (adc_chan > PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) + if (adc_chan >= PALMAS_ADC_CH_MAX || type != IIO_EV_TYPE_THRESH) return -EINVAL; mutex_lock(&adc->lock); diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index 1aadb2ad2cabdf..bd7e2408bf281d 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -2006,16 +2006,15 @@ static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm * to get the *real* number of channels. */ ret = device_property_count_u32(dev, "st,adc-diff-channels"); - if (ret < 0) - return ret; - - ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32)); - if (ret > adc_info->max_channels) { - dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n"); - return -EINVAL; - } else if (ret > 0) { - adc->num_diff = ret; - num_channels += ret; + if (ret > 0) { + ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32)); + if (ret > adc_info->max_channels) { + dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n"); + return -EINVAL; + } else if (ret > 0) { + adc->num_diff = ret; + num_channels += ret; + } } /* Optional sample time is provided either for each, or all channels */ @@ -2037,6 +2036,7 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX]; struct device *dev = &indio_dev->dev; u32 num_diff = adc->num_diff; + int num_se = nchans - num_diff; int size = num_diff * sizeof(*diff) / sizeof(u32); int scan_index = 0, ret, i, c; u32 smp = 0, smps[STM32_ADC_CH_MAX], chans[STM32_ADC_CH_MAX]; @@ -2063,29 +2063,32 @@ static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev, scan_index++; } } - - ret = device_property_read_u32_array(dev, "st,adc-channels", chans, - nchans); - if (ret) - return ret; - - for (c = 0; c < nchans; c++) { - if (chans[c] >= adc_info->max_channels) { - dev_err(&indio_dev->dev, "Invalid channel %d\n", - chans[c]); - return -EINVAL; + if (num_se > 0) { + ret = device_property_read_u32_array(dev, "st,adc-channels", chans, num_se); + if (ret) { + dev_err(&indio_dev->dev, "Failed to get st,adc-channels %d\n", ret); + return ret; } - /* Channel can't be configured both as single-ended & diff */ - for (i = 0; i < num_diff; i++) { - if (chans[c] == diff[i].vinp) { - dev_err(&indio_dev->dev, "channel %d misconfigured\n", chans[c]); + for (c = 0; c < num_se; c++) { + if (chans[c] >= adc_info->max_channels) { + dev_err(&indio_dev->dev, "Invalid channel %d\n", + chans[c]); return -EINVAL; } + + /* Channel can't be configured both as single-ended & diff */ + for (i = 0; i < num_diff; i++) { + if (chans[c] == diff[i].vinp) { + dev_err(&indio_dev->dev, "channel %d misconfigured\n", + chans[c]); + return -EINVAL; + } + } + stm32_adc_chan_init_one(indio_dev, &channels[scan_index], + chans[c], 0, scan_index, false); + scan_index++; } - stm32_adc_chan_init_one(indio_dev, &channels[scan_index], - chans[c], 0, scan_index, false); - scan_index++; } if (adc->nsmps > 0) { @@ -2306,7 +2309,7 @@ static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping) if (legacy) ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels, - num_channels); + timestamping ? num_channels - 1 : num_channels); else ret = stm32_adc_generic_chan_init(indio_dev, adc, channels); if (ret < 0) diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c index 07e9f6ae16a83d..e3366cf5eb3194 100644 --- a/drivers/iio/addac/ad74413r.c +++ b/drivers/iio/addac/ad74413r.c @@ -1007,7 +1007,7 @@ static int ad74413r_read_raw(struct iio_dev *indio_dev, ret = ad74413r_get_single_adc_result(indio_dev, chan->channel, val); - if (ret) + if (ret < 0) return ret; ad74413r_adc_to_resistance_result(*val, val); diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile index 6c74fea21736a4..addd97a788389c 100644 --- a/drivers/iio/dac/Makefile +++ b/drivers/iio/dac/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_AD5592R_BASE) += ad5592r-base.o obj-$(CONFIG_AD5592R) += ad5592r.o obj-$(CONFIG_AD5593R) += ad5593r.o obj-$(CONFIG_AD5755) += ad5755.o -obj-$(CONFIG_AD5755) += ad5758.o +obj-$(CONFIG_AD5758) += ad5758.o obj-$(CONFIG_AD5761) += ad5761.o obj-$(CONFIG_AD5764) += ad5764.o obj-$(CONFIG_AD5766) += ad5766.o diff --git a/drivers/iio/dac/mcp4725.c b/drivers/iio/dac/mcp4725.c index 46bf758760f85b..3f5661a3718fe8 100644 --- a/drivers/iio/dac/mcp4725.c +++ b/drivers/iio/dac/mcp4725.c @@ -47,12 +47,18 @@ static int mcp4725_suspend(struct device *dev) struct mcp4725_data *data = iio_priv(i2c_get_clientdata( to_i2c_client(dev))); u8 outbuf[2]; + int ret; outbuf[0] = (data->powerdown_mode + 1) << 4; outbuf[1] = 0; data->powerdown = true; - return i2c_master_send(data->client, outbuf, 2); + ret = i2c_master_send(data->client, outbuf, 2); + if (ret < 0) + return ret; + else if (ret != 2) + return -EIO; + return 0; } static int mcp4725_resume(struct device *dev) @@ -60,13 +66,19 @@ static int mcp4725_resume(struct device *dev) struct mcp4725_data *data = iio_priv(i2c_get_clientdata( to_i2c_client(dev))); u8 outbuf[2]; + int ret; /* restore previous DAC value */ outbuf[0] = (data->dac_value >> 8) & 0xf; outbuf[1] = data->dac_value & 0xff; data->powerdown = false; - return i2c_master_send(data->client, outbuf, 2); + ret = i2c_master_send(data->client, outbuf, 2); + if (ret < 0) + return ret; + else if (ret != 2) + return -EIO; + return 0; } static DEFINE_SIMPLE_DEV_PM_OPS(mcp4725_pm_ops, mcp4725_suspend, mcp4725_resume); diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c index 99576b2c171f4d..32d7f836423036 100644 --- a/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c +++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_buffer.c @@ -275,9 +275,14 @@ static int inv_icm42600_buffer_preenable(struct iio_dev *indio_dev) { struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev); struct device *dev = regmap_get_device(st->map); + struct inv_icm42600_timestamp *ts = iio_priv(indio_dev); pm_runtime_get_sync(dev); + mutex_lock(&st->lock); + inv_icm42600_timestamp_reset(ts); + mutex_unlock(&st->lock); + return 0; } @@ -375,7 +380,6 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) struct device *dev = regmap_get_device(st->map); unsigned int sensor; unsigned int *watermark; - struct inv_icm42600_timestamp *ts; struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT; unsigned int sleep_temp = 0; unsigned int sleep_sensor = 0; @@ -385,11 +389,9 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) if (indio_dev == st->indio_gyro) { sensor = INV_ICM42600_SENSOR_GYRO; watermark = &st->fifo.watermark.gyro; - ts = iio_priv(st->indio_gyro); } else if (indio_dev == st->indio_accel) { sensor = INV_ICM42600_SENSOR_ACCEL; watermark = &st->fifo.watermark.accel; - ts = iio_priv(st->indio_accel); } else { return -EINVAL; } @@ -417,8 +419,6 @@ static int inv_icm42600_buffer_postdisable(struct iio_dev *indio_dev) if (!st->fifo.on) ret = inv_icm42600_set_temp_conf(st, false, &sleep_temp); - inv_icm42600_timestamp_reset(ts); - out_unlock: mutex_unlock(&st->lock); diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c index 8bb68975b2598a..7653261d2dc2bf 100644 --- a/drivers/iio/industrialio-gts-helper.c +++ b/drivers/iio/industrialio-gts-helper.c @@ -337,6 +337,17 @@ static int iio_gts_build_avail_scale_table(struct iio_gts *gts) return ret; } +static void iio_gts_us_to_int_micro(int *time_us, int *int_micro_times, + int num_times) +{ + int i; + + for (i = 0; i < num_times; i++) { + int_micro_times[i * 2] = time_us[i] / 1000000; + int_micro_times[i * 2 + 1] = time_us[i] % 1000000; + } +} + /** * iio_gts_build_avail_time_table - build table of available integration times * @gts: Gain time scale descriptor @@ -351,7 +362,7 @@ static int iio_gts_build_avail_scale_table(struct iio_gts *gts) */ static int iio_gts_build_avail_time_table(struct iio_gts *gts) { - int *times, i, j, idx = 0; + int *times, i, j, idx = 0, *int_micro_times; if (!gts->num_itime) return 0; @@ -378,13 +389,24 @@ static int iio_gts_build_avail_time_table(struct iio_gts *gts) } } } - gts->avail_time_tables = times; - /* - * This is just to survive a unlikely corner-case where times in the - * given time table were not unique. Else we could just trust the - * gts->num_itime. - */ - gts->num_avail_time_tables = idx; + + /* create a list of times formatted as list of IIO_VAL_INT_PLUS_MICRO */ + int_micro_times = kcalloc(idx, sizeof(int) * 2, GFP_KERNEL); + if (int_micro_times) { + /* + * This is just to survive a unlikely corner-case where times in + * the given time table were not unique. Else we could just + * trust the gts->num_itime. + */ + gts->num_avail_time_tables = idx; + iio_gts_us_to_int_micro(times, int_micro_times, idx); + } + + gts->avail_time_tables = int_micro_times; + kfree(times); + + if (!int_micro_times) + return -ENOMEM; return 0; } @@ -683,8 +705,8 @@ int iio_gts_avail_times(struct iio_gts *gts, const int **vals, int *type, return -EINVAL; *vals = gts->avail_time_tables; - *type = IIO_VAL_INT; - *length = gts->num_avail_time_tables; + *type = IIO_VAL_INT_PLUS_MICRO; + *length = gts->num_avail_time_tables * 2; return IIO_AVAIL_LIST; } diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c index e486dcf35eba7d..f85194fda6b093 100644 --- a/drivers/iio/light/rohm-bu27034.c +++ b/drivers/iio/light/rohm-bu27034.c @@ -231,6 +231,9 @@ struct bu27034_result { static const struct regmap_range bu27034_volatile_ranges[] = { { + .range_min = BU27034_REG_SYSTEM_CONTROL, + .range_max = BU27034_REG_SYSTEM_CONTROL, + }, { .range_min = BU27034_REG_MODE_CONTROL4, .range_max = BU27034_REG_MODE_CONTROL4, }, { @@ -1167,11 +1170,12 @@ static int bu27034_read_raw(struct iio_dev *idev, switch (mask) { case IIO_CHAN_INFO_INT_TIME: - *val = bu27034_get_int_time(data); - if (*val < 0) - return *val; + *val = 0; + *val2 = bu27034_get_int_time(data); + if (*val2 < 0) + return *val2; - return IIO_VAL_INT; + return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_SCALE: return bu27034_get_scale(data, chan->channel, val, val2); @@ -1229,7 +1233,10 @@ static int bu27034_write_raw(struct iio_dev *idev, ret = bu27034_set_scale(data, chan->channel, val, val2); break; case IIO_CHAN_INFO_INT_TIME: - ret = bu27034_try_set_int_time(data, val); + if (!val) + ret = bu27034_try_set_int_time(data, val2); + else + ret = -EINVAL; break; default: ret = -EINVAL; @@ -1268,12 +1275,19 @@ static int bu27034_chip_init(struct bu27034_data *data) int ret, sel; /* Reset */ - ret = regmap_update_bits(data->regmap, BU27034_REG_SYSTEM_CONTROL, + ret = regmap_write_bits(data->regmap, BU27034_REG_SYSTEM_CONTROL, BU27034_MASK_SW_RESET, BU27034_MASK_SW_RESET); if (ret) return dev_err_probe(data->dev, ret, "Sensor reset failed\n"); msleep(1); + + ret = regmap_reinit_cache(data->regmap, &bu27034_regmap); + if (ret) { + dev_err(data->dev, "Failed to reinit reg cache\n"); + return ret; + } + /* * Read integration time here to ensure it is in regmap cache. We do * this to speed-up the int-time acquisition in the start of the buffer diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 14e29330e972eb..94f5d611e98c3c 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -8,6 +8,7 @@ * TODO: Proximity */ #include +#include #include #include #include @@ -42,6 +43,7 @@ #define VCNL4035_ALS_PERS_MASK GENMASK(3, 2) #define VCNL4035_INT_ALS_IF_H_MASK BIT(12) #define VCNL4035_INT_ALS_IF_L_MASK BIT(13) +#define VCNL4035_DEV_ID_MASK GENMASK(7, 0) /* Default values */ #define VCNL4035_MODE_ALS_ENABLE BIT(0) @@ -413,6 +415,7 @@ static int vcnl4035_init(struct vcnl4035_data *data) return ret; } + id = FIELD_GET(VCNL4035_DEV_ID_MASK, id); if (id != VCNL4035_DEV_ID_VAL) { dev_err(&data->client->dev, "Wrong id, got %x, expected %x\n", id, VCNL4035_DEV_ID_VAL); diff --git a/drivers/iio/magnetometer/tmag5273.c b/drivers/iio/magnetometer/tmag5273.c index 28bb7efe8df8c0..e155a75b3cd29d 100644 --- a/drivers/iio/magnetometer/tmag5273.c +++ b/drivers/iio/magnetometer/tmag5273.c @@ -296,12 +296,13 @@ static int tmag5273_read_raw(struct iio_dev *indio_dev, return ret; ret = tmag5273_get_measure(data, &t, &x, &y, &z, &angle, &magnitude); - if (ret) - return ret; pm_runtime_mark_last_busy(data->dev); pm_runtime_put_autosuspend(data->dev); + if (ret) + return ret; + switch (chan->address) { case TEMPERATURE: *val = t; diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index e86afecfbe46e6..b1c36412025f31 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -3341,9 +3341,7 @@ static int bnxt_re_process_raw_qp_pkt_rx(struct bnxt_re_qp *gsi_qp, udwr.remote_qkey = gsi_sqp->qplib_qp.qkey; /* post data received in the send queue */ - rc = bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr); - - return 0; + return bnxt_re_post_send_shadow_qp(rdev, gsi_sqp, swr); } static void bnxt_re_process_res_rawqp1_wc(struct ib_wc *wc, diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c index b9e2f89337e85e..e34eccd178d0f3 100644 --- a/drivers/infiniband/hw/bnxt_re/main.c +++ b/drivers/infiniband/hw/bnxt_re/main.c @@ -1336,6 +1336,10 @@ static void bnxt_re_setup_cc(struct bnxt_re_dev *rdev, bool enable) { struct bnxt_qplib_cc_param cc_param = {}; + /* Do not enable congestion control on VFs */ + if (rdev->is_virtfn) + return; + /* Currently enabling only for GenP5 adapters */ if (!bnxt_qplib_is_chip_gen_p5(rdev->chip_ctx)) return; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c index f139d4cd17128a..8974f6235cfaa8 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c @@ -2056,6 +2056,12 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) u32 pg_sz_lvl; int rc; + if (!cq->dpi) { + dev_err(&rcfw->pdev->dev, + "FP: CREATE_CQ failed due to NULL DPI\n"); + return -EINVAL; + } + hwq_attr.res = res; hwq_attr.depth = cq->max_wqe; hwq_attr.stride = sizeof(struct cq_base); @@ -2069,11 +2075,6 @@ int bnxt_qplib_create_cq(struct bnxt_qplib_res *res, struct bnxt_qplib_cq *cq) CMDQ_BASE_OPCODE_CREATE_CQ, sizeof(req)); - if (!cq->dpi) { - dev_err(&rcfw->pdev->dev, - "FP: CREATE_CQ failed due to NULL DPI\n"); - return -EINVAL; - } req.dpi = cpu_to_le32(cq->dpi->dpi); req.cq_handle = cpu_to_le64(cq->cq_handle); req.cq_size = cpu_to_le32(cq->hwq.max_elements); diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index 126d4f26f75ad7..81b0c5e879f9e8 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -215,17 +215,9 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, return -EINVAL; hwq_attr->sginfo->npages = npages; } else { - unsigned long sginfo_num_pages = ib_umem_num_dma_blocks( - hwq_attr->sginfo->umem, hwq_attr->sginfo->pgsize); - + npages = ib_umem_num_dma_blocks(hwq_attr->sginfo->umem, + hwq_attr->sginfo->pgsize); hwq->is_user = true; - npages = sginfo_num_pages; - npages = (npages * PAGE_SIZE) / - BIT_ULL(hwq_attr->sginfo->pgshft); - if ((sginfo_num_pages * PAGE_SIZE) % - BIT_ULL(hwq_attr->sginfo->pgshft)) - if (!npages) - npages++; } if (npages == MAX_PBL_LVL_0_PGS && !hwq_attr->sginfo->nopte) { diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c index 1714a1e231132f..b967a17a44bebc 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c @@ -617,16 +617,15 @@ int bnxt_qplib_reg_mr(struct bnxt_qplib_res *res, struct bnxt_qplib_mrw *mr, /* Free the hwq if it already exist, must be a rereg */ if (mr->hwq.max_elements) bnxt_qplib_free_hwq(res, &mr->hwq); - /* Use system PAGE_SIZE */ hwq_attr.res = res; hwq_attr.depth = pages; - hwq_attr.stride = buf_pg_size; + hwq_attr.stride = sizeof(dma_addr_t); hwq_attr.type = HWQ_TYPE_MR; hwq_attr.sginfo = &sginfo; hwq_attr.sginfo->umem = umem; hwq_attr.sginfo->npages = pages; - hwq_attr.sginfo->pgsize = PAGE_SIZE; - hwq_attr.sginfo->pgshft = PAGE_SHIFT; + hwq_attr.sginfo->pgsize = buf_pg_size; + hwq_attr.sginfo->pgshft = ilog2(buf_pg_size); rc = bnxt_qplib_alloc_init_hwq(&mr->hwq, &hwq_attr); if (rc) { dev_err(&res->pdev->dev, diff --git a/drivers/infiniband/hw/efa/efa_verbs.c b/drivers/infiniband/hw/efa/efa_verbs.c index 8eca6c14d0cfca..2a195c4b0f17de 100644 --- a/drivers/infiniband/hw/efa/efa_verbs.c +++ b/drivers/infiniband/hw/efa/efa_verbs.c @@ -1403,7 +1403,7 @@ static int pbl_continuous_initialize(struct efa_dev *dev, */ static int pbl_indirect_initialize(struct efa_dev *dev, struct pbl_context *pbl) { - u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, PAGE_SIZE); + u32 size_in_pages = DIV_ROUND_UP(pbl->pbl_buf_size_in_bytes, EFA_CHUNK_PAYLOAD_SIZE); struct scatterlist *sgl; int sg_dma_cnt, err; diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 84f1167de1d9e7..d4c6b9bc0a4ea2 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -4583,11 +4583,9 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, mtu = ib_mtu_enum_to_int(ib_mtu); if (WARN_ON(mtu <= 0)) return -EINVAL; -#define MAX_LP_MSG_LEN 16384 - /* MTU * (2 ^ LP_PKTN_INI) shouldn't be bigger than 16KB */ - lp_pktn_ini = ilog2(MAX_LP_MSG_LEN / mtu); - if (WARN_ON(lp_pktn_ini >= 0xF)) - return -EINVAL; +#define MIN_LP_MSG_LEN 1024 + /* mtu * (2 ^ lp_pktn_ini) should be in the range of 1024 to mtu */ + lp_pktn_ini = ilog2(max(mtu, MIN_LP_MSG_LEN) / mtu); if (attr_mask & IB_QP_PATH_MTU) { hr_reg_write(context, QPC_MTU, ib_mtu); @@ -5012,7 +5010,6 @@ static int hns_roce_v2_set_abs_fields(struct ib_qp *ibqp, static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout) { #define QP_ACK_TIMEOUT_MAX_HIP08 20 -#define QP_ACK_TIMEOUT_OFFSET 10 #define QP_ACK_TIMEOUT_MAX 31 if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) { @@ -5021,7 +5018,7 @@ static bool check_qp_timeout_cfg_range(struct hns_roce_dev *hr_dev, u8 *timeout) "local ACK timeout shall be 0 to 20.\n"); return false; } - *timeout += QP_ACK_TIMEOUT_OFFSET; + *timeout += HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08; } else if (hr_dev->pci_dev->revision > PCI_REVISION_ID_HIP08) { if (*timeout > QP_ACK_TIMEOUT_MAX) { ibdev_warn(&hr_dev->ib_dev, @@ -5307,6 +5304,18 @@ static int hns_roce_v2_query_qpc(struct hns_roce_dev *hr_dev, u32 qpn, return ret; } +static u8 get_qp_timeout_attr(struct hns_roce_dev *hr_dev, + struct hns_roce_v2_qp_context *context) +{ + u8 timeout; + + timeout = (u8)hr_reg_read(context, QPC_AT); + if (hr_dev->pci_dev->revision == PCI_REVISION_ID_HIP08) + timeout -= HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08; + + return timeout; +} + static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr) @@ -5384,7 +5393,7 @@ static int hns_roce_v2_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *qp_attr, qp_attr->max_dest_rd_atomic = 1 << hr_reg_read(&context, QPC_RR_MAX); qp_attr->min_rnr_timer = (u8)hr_reg_read(&context, QPC_MIN_RNR_TIME); - qp_attr->timeout = (u8)hr_reg_read(&context, QPC_AT); + qp_attr->timeout = get_qp_timeout_attr(hr_dev, &context); qp_attr->retry_cnt = hr_reg_read(&context, QPC_RETRY_NUM_INIT); qp_attr->rnr_retry = hr_reg_read(&context, QPC_RNR_NUM_INIT); diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index 1b44d2434ab415..7033eae2407c54 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -44,6 +44,8 @@ #define HNS_ROCE_V2_MAX_XRCD_NUM 0x1000000 #define HNS_ROCE_V2_RSV_XRCD_NUM 0 +#define HNS_ROCE_V2_QP_ACK_TIMEOUT_OFS_HIP08 10 + #define HNS_ROCE_V3_SCCC_SZ 64 #define HNS_ROCE_V3_GMV_ENTRY_SZ 32 diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index 37a5cf62f88b48..14376490ac226a 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -33,6 +33,7 @@ #include #include +#include #include "hns_roce_device.h" #include "hns_roce_cmd.h" #include "hns_roce_hem.h" @@ -909,6 +910,44 @@ static int mtr_init_buf_cfg(struct hns_roce_dev *hr_dev, return page_cnt; } +static u64 cal_pages_per_l1ba(unsigned int ba_per_bt, unsigned int hopnum) +{ + return int_pow(ba_per_bt, hopnum - 1); +} + +static unsigned int cal_best_bt_pg_sz(struct hns_roce_dev *hr_dev, + struct hns_roce_mtr *mtr, + unsigned int pg_shift) +{ + unsigned long cap = hr_dev->caps.page_size_cap; + struct hns_roce_buf_region *re; + unsigned int pgs_per_l1ba; + unsigned int ba_per_bt; + unsigned int ba_num; + int i; + + for_each_set_bit_from(pg_shift, &cap, sizeof(cap) * BITS_PER_BYTE) { + if (!(BIT(pg_shift) & cap)) + continue; + + ba_per_bt = BIT(pg_shift) / BA_BYTE_LEN; + ba_num = 0; + for (i = 0; i < mtr->hem_cfg.region_count; i++) { + re = &mtr->hem_cfg.region[i]; + if (re->hopnum == 0) + continue; + + pgs_per_l1ba = cal_pages_per_l1ba(ba_per_bt, re->hopnum); + ba_num += DIV_ROUND_UP(re->count, pgs_per_l1ba); + } + + if (ba_num <= ba_per_bt) + return pg_shift; + } + + return 0; +} + static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, unsigned int ba_page_shift) { @@ -917,6 +956,10 @@ static int mtr_alloc_mtt(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr, hns_roce_hem_list_init(&mtr->hem_list); if (!cfg->is_direct) { + ba_page_shift = cal_best_bt_pg_sz(hr_dev, mtr, ba_page_shift); + if (!ba_page_shift) + return -ERANGE; + ret = hns_roce_hem_list_request(hr_dev, &mtr->hem_list, cfg->region, cfg->region_count, ba_page_shift); diff --git a/drivers/infiniband/hw/irdma/verbs.c b/drivers/infiniband/hw/irdma/verbs.c index ab5cdf78278521..eaa12c12459828 100644 --- a/drivers/infiniband/hw/irdma/verbs.c +++ b/drivers/infiniband/hw/irdma/verbs.c @@ -522,11 +522,6 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) if (!iwqp->user_mode) cancel_delayed_work_sync(&iwqp->dwork_flush); - irdma_qp_rem_ref(&iwqp->ibqp); - wait_for_completion(&iwqp->free_qp); - irdma_free_lsmm_rsrc(iwqp); - irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp); - if (!iwqp->user_mode) { if (iwqp->iwscq) { irdma_clean_cqes(iwqp, iwqp->iwscq); @@ -534,6 +529,12 @@ static int irdma_destroy_qp(struct ib_qp *ibqp, struct ib_udata *udata) irdma_clean_cqes(iwqp, iwqp->iwrcq); } } + + irdma_qp_rem_ref(&iwqp->ibqp); + wait_for_completion(&iwqp->free_qp); + irdma_free_lsmm_rsrc(iwqp); + irdma_cqp_qp_destroy_cmd(&iwdev->rf->sc_dev, &iwqp->sc_qp); + irdma_remove_push_mmap_entries(iwqp); irdma_free_qp_rsrc(iwqp); @@ -3291,6 +3292,7 @@ static int irdma_post_send(struct ib_qp *ibqp, break; case IB_WR_LOCAL_INV: info.op_type = IRDMA_OP_TYPE_INV_STAG; + info.local_fence = info.read_fence; info.op.inv_local_stag.target_stag = ib_wr->ex.invalidate_rkey; err = irdma_uk_stag_local_invalidate(ukqp, &info, true); break; diff --git a/drivers/infiniband/hw/mlx5/ib_rep.c b/drivers/infiniband/hw/mlx5/ib_rep.c index ddcfc116b19a52..c7a4ee89612145 100644 --- a/drivers/infiniband/hw/mlx5/ib_rep.c +++ b/drivers/infiniband/hw/mlx5/ib_rep.c @@ -30,45 +30,65 @@ mlx5_ib_set_vport_rep(struct mlx5_core_dev *dev, static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev); +static void mlx5_ib_num_ports_update(struct mlx5_core_dev *dev, u32 *num_ports) +{ + struct mlx5_core_dev *peer_dev; + int i; + + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { + u32 peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev); + + if (mlx5_lag_is_mpesw(peer_dev)) + *num_ports += peer_num_ports; + else + /* Only 1 ib port is the representor for all uplinks */ + *num_ports += peer_num_ports - 1; + } +} + static int mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) { u32 num_ports = mlx5_eswitch_get_total_vports(dev); + struct mlx5_core_dev *lag_master = dev; const struct mlx5_ib_profile *profile; struct mlx5_core_dev *peer_dev; struct mlx5_ib_dev *ibdev; - int second_uplink = false; - u32 peer_num_ports; + int new_uplink = false; int vport_index; int ret; + int i; vport_index = rep->vport_index; if (mlx5_lag_is_shared_fdb(dev)) { - peer_dev = mlx5_lag_get_peer_mdev(dev); - peer_num_ports = mlx5_eswitch_get_total_vports(peer_dev); if (mlx5_lag_is_master(dev)) { - if (mlx5_lag_is_mpesw(dev)) - num_ports += peer_num_ports; - else - num_ports += peer_num_ports - 1; - + mlx5_ib_num_ports_update(dev, &num_ports); } else { if (rep->vport == MLX5_VPORT_UPLINK) { if (!mlx5_lag_is_mpesw(dev)) return 0; - second_uplink = true; + new_uplink = true; } + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { + u32 peer_n_ports = mlx5_eswitch_get_total_vports(peer_dev); + + if (mlx5_lag_is_master(peer_dev)) + lag_master = peer_dev; + else if (!mlx5_lag_is_mpesw(dev)) + /* Only 1 ib port is the representor for all uplinks */ + peer_n_ports--; - vport_index += peer_num_ports; - dev = peer_dev; + if (mlx5_get_dev_index(peer_dev) < mlx5_get_dev_index(dev)) + vport_index += peer_n_ports; + } } } - if (rep->vport == MLX5_VPORT_UPLINK && !second_uplink) + if (rep->vport == MLX5_VPORT_UPLINK && !new_uplink) profile = &raw_eth_profile; else - return mlx5_ib_set_vport_rep(dev, rep, vport_index); + return mlx5_ib_set_vport_rep(lag_master, rep, vport_index); ibdev = ib_alloc_device(mlx5_ib_dev, ib_dev); if (!ibdev) @@ -85,8 +105,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) vport_index = rep->vport_index; ibdev->port[vport_index].rep = rep; ibdev->port[vport_index].roce.netdev = - mlx5_ib_get_rep_netdev(dev->priv.eswitch, rep->vport); - ibdev->mdev = dev; + mlx5_ib_get_rep_netdev(lag_master->priv.eswitch, rep->vport); + ibdev->mdev = lag_master; ibdev->num_ports = num_ports; ret = __mlx5_ib_add(ibdev, profile); @@ -94,8 +114,8 @@ mlx5_ib_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep) goto fail_add; rep->rep_data[REP_IB].priv = ibdev; - if (mlx5_lag_is_shared_fdb(dev)) - mlx5_ib_register_peer_vport_reps(dev); + if (mlx5_lag_is_shared_fdb(lag_master)) + mlx5_ib_register_peer_vport_reps(lag_master); return 0; @@ -118,23 +138,27 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) struct mlx5_ib_dev *dev = mlx5_ib_rep_to_dev(rep); int vport_index = rep->vport_index; struct mlx5_ib_port *port; + int i; if (WARN_ON(!mdev)) return; + if (!dev) + return; + if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev)) { - struct mlx5_core_dev *peer_mdev; - - if (rep->vport == MLX5_VPORT_UPLINK) + if (rep->vport == MLX5_VPORT_UPLINK && !mlx5_lag_is_mpesw(mdev)) return; - peer_mdev = mlx5_lag_get_peer_mdev(mdev); - vport_index += mlx5_eswitch_get_total_vports(peer_mdev); + for (i = 0; i < dev->num_ports; i++) { + if (dev->port[i].rep == rep) + break; + } + if (WARN_ON(i == dev->num_ports)) + return; + vport_index = i; } - if (!dev) - return; - port = &dev->port[vport_index]; write_lock(&port->roce.netdev_lock); port->roce.netdev = NULL; @@ -143,13 +167,18 @@ mlx5_ib_vport_rep_unload(struct mlx5_eswitch_rep *rep) port->rep = NULL; if (rep->vport == MLX5_VPORT_UPLINK) { - struct mlx5_core_dev *peer_mdev; - struct mlx5_eswitch *esw; + + if (mlx5_lag_is_shared_fdb(mdev) && !mlx5_lag_is_master(mdev)) + return; if (mlx5_lag_is_shared_fdb(mdev)) { - peer_mdev = mlx5_lag_get_peer_mdev(mdev); - esw = peer_mdev->priv.eswitch; - mlx5_eswitch_unregister_vport_reps(esw, REP_IB); + struct mlx5_core_dev *peer_mdev; + struct mlx5_eswitch *esw; + + mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) { + esw = peer_mdev->priv.eswitch; + mlx5_eswitch_unregister_vport_reps(esw, REP_IB); + } } __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX); } @@ -163,14 +192,14 @@ static const struct mlx5_eswitch_rep_ops rep_ops = { static void mlx5_ib_register_peer_vport_reps(struct mlx5_core_dev *mdev) { - struct mlx5_core_dev *peer_mdev = mlx5_lag_get_peer_mdev(mdev); + struct mlx5_core_dev *peer_mdev; struct mlx5_eswitch *esw; + int i; - if (!peer_mdev) - return; - - esw = peer_mdev->priv.eswitch; - mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB); + mlx5_lag_for_each_peer_mdev(mdev, peer_mdev, i) { + esw = peer_mdev->priv.eswitch; + mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_IB); + } } struct net_device *mlx5_ib_get_rep_netdev(struct mlx5_eswitch *esw, diff --git a/drivers/infiniband/sw/rxe/rxe_comp.c b/drivers/infiniband/sw/rxe/rxe_comp.c index db18ace74d2b53..f46c5a5fd0aea4 100644 --- a/drivers/infiniband/sw/rxe/rxe_comp.c +++ b/drivers/infiniband/sw/rxe/rxe_comp.c @@ -115,15 +115,16 @@ static enum ib_wc_opcode wr_to_wc_opcode(enum ib_wr_opcode opcode) void retransmit_timer(struct timer_list *t) { struct rxe_qp *qp = from_timer(qp, t, retrans_timer); + unsigned long flags; rxe_dbg_qp(qp, "retransmit timer fired\n"); - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp->valid) { qp->comp.timeout = 1; rxe_sched_task(&qp->comp.task); } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } void rxe_comp_queue_pkt(struct rxe_qp *qp, struct sk_buff *skb) @@ -481,11 +482,13 @@ static void do_complete(struct rxe_qp *qp, struct rxe_send_wqe *wqe) static void comp_check_sq_drain_done(struct rxe_qp *qp) { - spin_lock_bh(&qp->state_lock); + unsigned long flags; + + spin_lock_irqsave(&qp->state_lock, flags); if (unlikely(qp_state(qp) == IB_QPS_SQD)) { if (qp->attr.sq_draining && qp->comp.psn == qp->req.psn) { qp->attr.sq_draining = 0; - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (qp->ibqp.event_handler) { struct ib_event ev; @@ -499,7 +502,7 @@ static void comp_check_sq_drain_done(struct rxe_qp *qp) return; } } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } static inline enum comp_state complete_ack(struct rxe_qp *qp, @@ -625,13 +628,15 @@ static void free_pkt(struct rxe_pkt_info *pkt) */ static void reset_retry_timer(struct rxe_qp *qp) { + unsigned long flags; + if (qp_type(qp) == IB_QPT_RC && qp->qp_timeout_jiffies) { - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp_state(qp) >= IB_QPS_RTS && psn_compare(qp->req.psn, qp->comp.psn) > 0) mod_timer(&qp->retrans_timer, jiffies + qp->qp_timeout_jiffies); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } } @@ -643,18 +648,19 @@ int rxe_completer(struct rxe_qp *qp) struct rxe_pkt_info *pkt = NULL; enum comp_state state; int ret; + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (!qp->valid || qp_state(qp) == IB_QPS_ERR || qp_state(qp) == IB_QPS_RESET) { bool notify = qp->valid && (qp_state(qp) == IB_QPS_ERR); drain_resp_pkts(qp); flush_send_queue(qp, notify); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); goto exit; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (qp->comp.timeout) { qp->comp.timeout_retry = 1; diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index 2bc7361152ea70..a38fab19bed19c 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -412,15 +412,16 @@ int rxe_xmit_packet(struct rxe_qp *qp, struct rxe_pkt_info *pkt, int err; int is_request = pkt->mask & RXE_REQ_MASK; struct rxe_dev *rxe = to_rdev(qp->ibqp.device); + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if ((is_request && (qp_state(qp) < IB_QPS_RTS)) || (!is_request && (qp_state(qp) < IB_QPS_RTR))) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); rxe_dbg_qp(qp, "Packet dropped. QP is not in ready state\n"); goto drop; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); rxe_icrc_generate(skb, pkt); diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index c5451a4488ca35..61a2eb77d9999e 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -300,6 +300,7 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd, struct rxe_cq *rcq = to_rcq(init->recv_cq); struct rxe_cq *scq = to_rcq(init->send_cq); struct rxe_srq *srq = init->srq ? to_rsrq(init->srq) : NULL; + unsigned long flags; rxe_get(pd); rxe_get(rcq); @@ -325,10 +326,10 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd, if (err) goto err2; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); qp->attr.qp_state = IB_QPS_RESET; qp->valid = 1; - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return 0; @@ -492,24 +493,28 @@ static void rxe_qp_reset(struct rxe_qp *qp) /* move the qp to the error state */ void rxe_qp_error(struct rxe_qp *qp) { - spin_lock_bh(&qp->state_lock); + unsigned long flags; + + spin_lock_irqsave(&qp->state_lock, flags); qp->attr.qp_state = IB_QPS_ERR; /* drain work and packet queues */ rxe_sched_task(&qp->resp.task); rxe_sched_task(&qp->comp.task); rxe_sched_task(&qp->req.task); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } static void rxe_qp_sqd(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask) { - spin_lock_bh(&qp->state_lock); + unsigned long flags; + + spin_lock_irqsave(&qp->state_lock, flags); qp->attr.sq_draining = 1; rxe_sched_task(&qp->comp.task); rxe_sched_task(&qp->req.task); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } /* caller should hold qp->state_lock */ @@ -555,14 +560,16 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask, qp->attr.cur_qp_state = attr->qp_state; if (mask & IB_QP_STATE) { - spin_lock_bh(&qp->state_lock); + unsigned long flags; + + spin_lock_irqsave(&qp->state_lock, flags); err = __qp_chk_state(qp, attr, mask); if (!err) { qp->attr.qp_state = attr->qp_state; rxe_dbg_qp(qp, "state -> %s\n", qps2str[attr->qp_state]); } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (err) return err; @@ -688,6 +695,8 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask, /* called by the query qp verb */ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask) { + unsigned long flags; + *attr = qp->attr; attr->rq_psn = qp->resp.psn; @@ -708,12 +717,13 @@ int rxe_qp_to_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask) /* Applications that get this state typically spin on it. * Yield the processor */ - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp->attr.sq_draining) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); cond_resched(); + } else { + spin_unlock_irqrestore(&qp->state_lock, flags); } - spin_unlock_bh(&qp->state_lock); return 0; } @@ -736,10 +746,11 @@ int rxe_qp_chk_destroy(struct rxe_qp *qp) static void rxe_qp_do_cleanup(struct work_struct *work) { struct rxe_qp *qp = container_of(work, typeof(*qp), cleanup_work.work); + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); qp->valid = 0; - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); qp->qp_timeout_jiffies = 0; if (qp_type(qp) == IB_QPT_RC) { diff --git a/drivers/infiniband/sw/rxe/rxe_recv.c b/drivers/infiniband/sw/rxe/rxe_recv.c index 2f953cc74256d9..5861e42440490d 100644 --- a/drivers/infiniband/sw/rxe/rxe_recv.c +++ b/drivers/infiniband/sw/rxe/rxe_recv.c @@ -14,6 +14,7 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, struct rxe_qp *qp) { unsigned int pkt_type; + unsigned long flags; if (unlikely(!qp->valid)) return -EINVAL; @@ -38,19 +39,19 @@ static int check_type_state(struct rxe_dev *rxe, struct rxe_pkt_info *pkt, return -EINVAL; } - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (pkt->mask & RXE_REQ_MASK) { if (unlikely(qp_state(qp) < IB_QPS_RTR)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return -EINVAL; } } else { if (unlikely(qp_state(qp) < IB_QPS_RTS)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return -EINVAL; } } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return 0; } diff --git a/drivers/infiniband/sw/rxe/rxe_req.c b/drivers/infiniband/sw/rxe/rxe_req.c index 65134a9aefe7bf..5fe7cbae30313c 100644 --- a/drivers/infiniband/sw/rxe/rxe_req.c +++ b/drivers/infiniband/sw/rxe/rxe_req.c @@ -99,17 +99,18 @@ static void req_retry(struct rxe_qp *qp) void rnr_nak_timer(struct timer_list *t) { struct rxe_qp *qp = from_timer(qp, t, rnr_nak_timer); + unsigned long flags; rxe_dbg_qp(qp, "nak timer fired\n"); - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp->valid) { /* request a send queue retry */ qp->req.need_retry = 1; qp->req.wait_for_rnr_timer = 0; rxe_sched_task(&qp->req.task); } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } static void req_check_sq_drain_done(struct rxe_qp *qp) @@ -118,8 +119,9 @@ static void req_check_sq_drain_done(struct rxe_qp *qp) unsigned int index; unsigned int cons; struct rxe_send_wqe *wqe; + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp_state(qp) == IB_QPS_SQD) { q = qp->sq.queue; index = qp->req.wqe_index; @@ -140,7 +142,7 @@ static void req_check_sq_drain_done(struct rxe_qp *qp) break; qp->attr.sq_draining = 0; - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (qp->ibqp.event_handler) { struct ib_event ev; @@ -154,7 +156,7 @@ static void req_check_sq_drain_done(struct rxe_qp *qp) return; } while (0); } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); } static struct rxe_send_wqe *__req_next_wqe(struct rxe_qp *qp) @@ -173,6 +175,7 @@ static struct rxe_send_wqe *__req_next_wqe(struct rxe_qp *qp) static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp) { struct rxe_send_wqe *wqe; + unsigned long flags; req_check_sq_drain_done(qp); @@ -180,13 +183,13 @@ static struct rxe_send_wqe *req_next_wqe(struct rxe_qp *qp) if (wqe == NULL) return NULL; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (unlikely((qp_state(qp) == IB_QPS_SQD) && (wqe->state != wqe_state_processing))) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return NULL; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); wqe->mask = wr_opcode_mask(wqe->wr.opcode, qp); return wqe; @@ -676,16 +679,17 @@ int rxe_requester(struct rxe_qp *qp) struct rxe_queue *q = qp->sq.queue; struct rxe_ah *ah; struct rxe_av *av; + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (unlikely(!qp->valid)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); goto exit; } if (unlikely(qp_state(qp) == IB_QPS_ERR)) { wqe = __req_next_wqe(qp); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (wqe) goto err; else @@ -700,10 +704,10 @@ int rxe_requester(struct rxe_qp *qp) qp->req.wait_psn = 0; qp->req.need_retry = 0; qp->req.wait_for_rnr_timer = 0; - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); goto exit; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); /* we come here if the retransmit timer has fired * or if the rnr timer has fired. If the retransmit diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index 68f6cd188d8ed2..1da044f6b7d494 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -1047,6 +1047,7 @@ static enum resp_states do_complete(struct rxe_qp *qp, struct ib_uverbs_wc *uwc = &cqe.uibwc; struct rxe_recv_wqe *wqe = qp->resp.wqe; struct rxe_dev *rxe = to_rdev(qp->ibqp.device); + unsigned long flags; if (!wqe) goto finish; @@ -1137,12 +1138,12 @@ static enum resp_states do_complete(struct rxe_qp *qp, return RESPST_ERR_CQ_OVERFLOW; finish: - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (unlikely(qp_state(qp) == IB_QPS_ERR)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return RESPST_CHK_RESOURCE; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (unlikely(!pkt)) return RESPST_DONE; @@ -1468,18 +1469,19 @@ int rxe_responder(struct rxe_qp *qp) enum resp_states state; struct rxe_pkt_info *pkt = NULL; int ret; + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (!qp->valid || qp_state(qp) == IB_QPS_ERR || qp_state(qp) == IB_QPS_RESET) { bool notify = qp->valid && (qp_state(qp) == IB_QPS_ERR); drain_req_pkts(qp); flush_recv_queue(qp, notify); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); goto exit; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); qp->resp.aeth_syndrome = AETH_ACK_UNLIMITED; diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c index dea605b7f68335..4d8f6b8051ff7d 100644 --- a/drivers/infiniband/sw/rxe/rxe_verbs.c +++ b/drivers/infiniband/sw/rxe/rxe_verbs.c @@ -904,10 +904,10 @@ static int rxe_post_send_kernel(struct rxe_qp *qp, if (!err) rxe_sched_task(&qp->req.task); - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp_state(qp) == IB_QPS_ERR) rxe_sched_task(&qp->comp.task); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return err; } @@ -917,22 +917,23 @@ static int rxe_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr, { struct rxe_qp *qp = to_rqp(ibqp); int err; + unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); /* caller has already called destroy_qp */ if (WARN_ON_ONCE(!qp->valid)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); rxe_err_qp(qp, "qp has been destroyed"); return -EINVAL; } if (unlikely(qp_state(qp) < IB_QPS_RTS)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); *bad_wr = wr; rxe_err_qp(qp, "qp not ready to send"); return -EINVAL; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (qp->is_user) { /* Utilize process context to do protocol processing */ @@ -1008,22 +1009,22 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr, struct rxe_rq *rq = &qp->rq; unsigned long flags; - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); /* caller has already called destroy_qp */ if (WARN_ON_ONCE(!qp->valid)) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); rxe_err_qp(qp, "qp has been destroyed"); return -EINVAL; } /* see C10-97.2.1 */ if (unlikely((qp_state(qp) < IB_QPS_INIT))) { - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); *bad_wr = wr; rxe_dbg_qp(qp, "qp not ready to post recv"); return -EINVAL; } - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); if (unlikely(qp->srq)) { *bad_wr = wr; @@ -1044,10 +1045,10 @@ static int rxe_post_recv(struct ib_qp *ibqp, const struct ib_recv_wr *wr, spin_unlock_irqrestore(&rq->producer_lock, flags); - spin_lock_bh(&qp->state_lock); + spin_lock_irqsave(&qp->state_lock, flags); if (qp_state(qp) == IB_QPS_ERR) rxe_sched_task(&qp->resp.task); - spin_unlock_bh(&qp->state_lock); + spin_unlock_irqrestore(&qp->state_lock, flags); return err; } diff --git a/drivers/infiniband/sw/siw/siw_qp_tx.c b/drivers/infiniband/sw/siw/siw_qp_tx.c index 4b292e0504f1a1..ffb16beb6c3055 100644 --- a/drivers/infiniband/sw/siw/siw_qp_tx.c +++ b/drivers/infiniband/sw/siw/siw_qp_tx.c @@ -312,7 +312,7 @@ static int siw_tx_ctrl(struct siw_iwarp_tx *c_tx, struct socket *s, } /* - * 0copy TCP transmit interface: Use do_tcp_sendpages. + * 0copy TCP transmit interface: Use MSG_SPLICE_PAGES. * * Using sendpage to push page by page appears to be less efficient * than using sendmsg, even if data are copied. @@ -323,20 +323,27 @@ static int siw_tx_ctrl(struct siw_iwarp_tx *c_tx, struct socket *s, static int siw_tcp_sendpages(struct socket *s, struct page **page, int offset, size_t size) { + struct bio_vec bvec; + struct msghdr msg = { + .msg_flags = (MSG_MORE | MSG_DONTWAIT | MSG_SENDPAGE_NOTLAST | + MSG_SPLICE_PAGES), + }; struct sock *sk = s->sk; - int i = 0, rv = 0, sent = 0, - flags = MSG_MORE | MSG_DONTWAIT | MSG_SENDPAGE_NOTLAST; + int i = 0, rv = 0, sent = 0; while (size) { size_t bytes = min_t(size_t, PAGE_SIZE - offset, size); if (size + offset <= PAGE_SIZE) - flags = MSG_MORE | MSG_DONTWAIT; + msg.msg_flags &= ~MSG_SENDPAGE_NOTLAST; tcp_rate_check_app_limited(sk); + bvec_set_page(&bvec, page[i], bytes, offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size); + try_page_again: lock_sock(sk); - rv = do_tcp_sendpages(sk, page[i], offset, bytes, flags); + rv = tcp_sendmsg_locked(sk, &msg, size); release_sock(sk); if (rv > 0) { diff --git a/drivers/input/input.c b/drivers/input/input.c index 37e876d45eb9c2..641eb86f276e6d 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -703,7 +703,7 @@ void input_close_device(struct input_handle *handle) __input_release_device(handle); - if (!dev->inhibited && !--dev->users) { + if (!--dev->users && !dev->inhibited) { if (dev->poller) input_dev_poller_stop(dev->poller); if (dev->close) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 28be88e0e96abe..f33622fe946f65 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -281,7 +281,6 @@ static const struct xpad_device { { 0x1430, 0xf801, "RedOctane Controller", 0, XTYPE_XBOX360 }, { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, { 0x146b, 0x0604, "Bigben Interactive DAIJA Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, - { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE }, { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 }, diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c index 09489380afda7a..e79f5497948b8c 100644 --- a/drivers/input/misc/soc_button_array.c +++ b/drivers/input/misc/soc_button_array.c @@ -108,6 +108,27 @@ static const struct dmi_system_id dmi_use_low_level_irq[] = { {} /* Terminating entry */ }; +/* + * Some devices have a wrong entry which points to a GPIO which is + * required in another driver, so this driver must not claim it. + */ +static const struct dmi_system_id dmi_invalid_acpi_index[] = { + { + /* + * Lenovo Yoga Book X90F / X90L, the PNP0C40 home button entry + * points to a GPIO which is not a home button and which is + * required by the lenovo-yogabook driver. + */ + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "CHERRYVIEW D1 PLATFORM"), + DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "YETI-11"), + }, + .driver_data = (void *)1l, + }, + {} /* Terminating entry */ +}; + /* * Get the Nth GPIO number from the ACPI object. */ @@ -137,6 +158,8 @@ soc_button_device_create(struct platform_device *pdev, struct platform_device *pd; struct gpio_keys_button *gpio_keys; struct gpio_keys_platform_data *gpio_keys_pdata; + const struct dmi_system_id *dmi_id; + int invalid_acpi_index = -1; int error, gpio, irq; int n_buttons = 0; @@ -154,10 +177,17 @@ soc_button_device_create(struct platform_device *pdev, gpio_keys = (void *)(gpio_keys_pdata + 1); n_buttons = 0; + dmi_id = dmi_first_match(dmi_invalid_acpi_index); + if (dmi_id) + invalid_acpi_index = (long)dmi_id->driver_data; + for (info = button_info; info->name; info++) { if (info->autorepeat != autorepeat) continue; + if (info->acpi_index == invalid_acpi_index) + continue; + error = soc_button_lookup_gpio(&pdev->dev, info->acpi_index, &gpio, &irq); if (error || irq < 0) { /* diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index ece97f8c6a3e39..2118b2075f437c 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -674,10 +674,11 @@ static void process_packet_head_v4(struct psmouse *psmouse) struct input_dev *dev = psmouse->dev; struct elantech_data *etd = psmouse->private; unsigned char *packet = psmouse->packet; - int id = ((packet[3] & 0xe0) >> 5) - 1; + int id; int pres, traces; - if (id < 0) + id = ((packet[3] & 0xe0) >> 5) - 1; + if (id < 0 || id >= ETP_MAX_FINGERS) return; etd->mt[id].x = ((packet[1] & 0x0f) << 8) | packet[2]; @@ -707,7 +708,7 @@ static void process_packet_motion_v4(struct psmouse *psmouse) int id, sid; id = ((packet[0] & 0xe0) >> 5) - 1; - if (id < 0) + if (id < 0 || id >= ETP_MAX_FINGERS) return; sid = ((packet[3] & 0xe0) >> 5) - 1; @@ -728,7 +729,7 @@ static void process_packet_motion_v4(struct psmouse *psmouse) input_report_abs(dev, ABS_MT_POSITION_X, etd->mt[id].x); input_report_abs(dev, ABS_MT_POSITION_Y, etd->mt[id].y); - if (sid >= 0) { + if (sid >= 0 && sid < ETP_MAX_FINGERS) { etd->mt[sid].x += delta_x2 * weight; etd->mt[sid].y -= delta_y2 * weight; input_mt_slot(dev, sid); diff --git a/drivers/input/touchscreen/cyttsp5.c b/drivers/input/touchscreen/cyttsp5.c index 30102cb80fac82..3c9d07218f48df 100644 --- a/drivers/input/touchscreen/cyttsp5.c +++ b/drivers/input/touchscreen/cyttsp5.c @@ -560,7 +560,7 @@ static int cyttsp5_hid_output_get_sysinfo(struct cyttsp5 *ts) static int cyttsp5_hid_output_bl_launch_app(struct cyttsp5 *ts) { int rc; - u8 cmd[HID_OUTPUT_BL_LAUNCH_APP]; + u8 cmd[HID_OUTPUT_BL_LAUNCH_APP_SIZE]; u16 crc; put_unaligned_le16(HID_OUTPUT_BL_LAUNCH_APP_SIZE, cmd); diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index db98c3f86e8c8b..4d800601e8ecd6 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -282,6 +282,7 @@ config EXYNOS_IOMMU_DEBUG config IPMMU_VMSA bool "Renesas VMSA-compatible IPMMU" depends on ARCH_RENESAS || COMPILE_TEST + depends on ARM || ARM64 || COMPILE_TEST depends on !GENERIC_ATOMIC64 # for IOMMU_IO_PGTABLE_LPAE select IOMMU_API select IOMMU_IO_PGTABLE_LPAE @@ -417,22 +418,6 @@ config S390_IOMMU help Support for the IOMMU API for s390 PCI devices. -config S390_CCW_IOMMU - bool "S390 CCW IOMMU Support" - depends on S390 && CCW || COMPILE_TEST - select IOMMU_API - help - Enables bits of IOMMU API required by VFIO. The iommu_ops - is not implemented as it is not necessary for VFIO. - -config S390_AP_IOMMU - bool "S390 AP IOMMU Support" - depends on S390 && ZCRYPT || COMPILE_TEST - select IOMMU_API - help - Enables bits of IOMMU API required by VFIO. The iommu_ops - is not implemented as it is not necessary for VFIO. - config MTK_IOMMU tristate "MediaTek IOMMU Support" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/iommu/amd/amd_iommu.h b/drivers/iommu/amd/amd_iommu.h index e98f20a9bdd82e..9beeceb9d825df 100644 --- a/drivers/iommu/amd/amd_iommu.h +++ b/drivers/iommu/amd/amd_iommu.h @@ -15,9 +15,7 @@ extern irqreturn_t amd_iommu_int_thread(int irq, void *data); extern irqreturn_t amd_iommu_int_handler(int irq, void *data); extern void amd_iommu_apply_erratum_63(struct amd_iommu *iommu, u16 devid); extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu); -extern int amd_iommu_init_devices(void); -extern void amd_iommu_uninit_devices(void); -extern void amd_iommu_init_notifier(void); +extern void amd_iommu_restart_ga_log(struct amd_iommu *iommu); extern void amd_iommu_set_rlookup_table(struct amd_iommu *iommu, u16 devid); #ifdef CONFIG_AMD_IOMMU_DEBUGFS diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 329a406cc37de8..c2d80a4e5fb066 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -758,6 +758,30 @@ void amd_iommu_restart_event_logging(struct amd_iommu *iommu) iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN); } +/* + * This function restarts event logging in case the IOMMU experienced + * an GA log overflow. + */ +void amd_iommu_restart_ga_log(struct amd_iommu *iommu) +{ + u32 status; + + status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); + if (status & MMIO_STATUS_GALOG_RUN_MASK) + return; + + pr_info_ratelimited("IOMMU GA Log restarting\n"); + + iommu_feature_disable(iommu, CONTROL_GALOG_EN); + iommu_feature_disable(iommu, CONTROL_GAINT_EN); + + writel(MMIO_STATUS_GALOG_OVERFLOW_MASK, + iommu->mmio_base + MMIO_STATUS_OFFSET); + + iommu_feature_enable(iommu, CONTROL_GAINT_EN); + iommu_feature_enable(iommu, CONTROL_GALOG_EN); +} + /* * This function resets the command buffer if the IOMMU stopped fetching * commands from it. diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index 4a314647d1f792..dc1ec684977542 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -845,6 +845,7 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { } (MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \ MMIO_STATUS_EVT_INT_MASK | \ MMIO_STATUS_PPR_INT_MASK | \ + MMIO_STATUS_GALOG_OVERFLOW_MASK | \ MMIO_STATUS_GALOG_INT_MASK) irqreturn_t amd_iommu_int_thread(int irq, void *data) @@ -868,10 +869,16 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data) } #ifdef CONFIG_IRQ_REMAP - if (status & MMIO_STATUS_GALOG_INT_MASK) { + if (status & (MMIO_STATUS_GALOG_INT_MASK | + MMIO_STATUS_GALOG_OVERFLOW_MASK)) { pr_devel("Processing IOMMU GA Log\n"); iommu_poll_ga_log(iommu); } + + if (status & MMIO_STATUS_GALOG_OVERFLOW_MASK) { + pr_info_ratelimited("IOMMU GA Log overflow\n"); + amd_iommu_restart_ga_log(iommu); + } #endif if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) { @@ -2067,7 +2074,7 @@ static struct protection_domain *protection_domain_alloc(unsigned int type) { struct io_pgtable_ops *pgtbl_ops; struct protection_domain *domain; - int pgtable = amd_iommu_pgtable; + int pgtable; int mode = DEFAULT_PGTABLE_LEVEL; int ret; @@ -2084,6 +2091,10 @@ static struct protection_domain *protection_domain_alloc(unsigned int type) mode = PAGE_MODE_NONE; } else if (type == IOMMU_DOMAIN_UNMANAGED) { pgtable = AMD_IOMMU_V1; + } else if (type == IOMMU_DOMAIN_DMA || type == IOMMU_DOMAIN_DMA_FQ) { + pgtable = amd_iommu_pgtable; + } else { + return NULL; } switch (pgtable) { @@ -2118,6 +2129,15 @@ static struct protection_domain *protection_domain_alloc(unsigned int type) return NULL; } +static inline u64 dma_max_address(void) +{ + if (amd_iommu_pgtable == AMD_IOMMU_V1) + return ~0ULL; + + /* V2 with 4/5 level page table */ + return ((1ULL << PM_LEVEL_SHIFT(amd_iommu_gpt_level)) - 1); +} + static struct iommu_domain *amd_iommu_domain_alloc(unsigned type) { struct protection_domain *domain; @@ -2134,7 +2154,7 @@ static struct iommu_domain *amd_iommu_domain_alloc(unsigned type) return NULL; domain->domain.geometry.aperture_start = 0; - domain->domain.geometry.aperture_end = ~0ULL; + domain->domain.geometry.aperture_end = dma_max_address(); domain->domain.geometry.force_aperture = true; return &domain->domain; @@ -2387,7 +2407,7 @@ static void amd_iommu_iotlb_sync(struct iommu_domain *domain, unsigned long flags; spin_lock_irqsave(&dom->lock, flags); - domain_flush_pages(dom, gather->start, gather->end - gather->start, 1); + domain_flush_pages(dom, gather->start, gather->end - gather->start + 1, 1); amd_iommu_domain_flush_complete(dom); spin_unlock_irqrestore(&dom->lock, flags); } @@ -3493,8 +3513,7 @@ int amd_iommu_activate_guest_mode(void *data) struct irte_ga *entry = (struct irte_ga *) ir_data->entry; u64 valid; - if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || - !entry || entry->lo.fields_vapic.guest_mode) + if (!AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) || !entry) return 0; valid = entry->lo.fields_vapic.valid; diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c index ae09c627bc8448..c71afda79d6442 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c @@ -517,6 +517,7 @@ static const struct of_device_id __maybe_unused qcom_smmu_impl_of_match[] = { { .compatible = "qcom,qcm2290-smmu-500", .data = &qcom_smmu_500_impl0_data }, { .compatible = "qcom,qdu1000-smmu-500", .data = &qcom_smmu_500_impl0_data }, { .compatible = "qcom,sc7180-smmu-500", .data = &qcom_smmu_500_impl0_data }, + { .compatible = "qcom,sc7180-smmu-v2", .data = &qcom_smmu_v2_data }, { .compatible = "qcom,sc7280-smmu-500", .data = &qcom_smmu_500_impl0_data }, { .compatible = "qcom,sc8180x-smmu-500", .data = &qcom_smmu_500_impl0_data }, { .compatible = "qcom,sc8280xp-smmu-500", .data = &qcom_smmu_500_impl0_data }, @@ -561,5 +562,14 @@ struct arm_smmu_device *qcom_smmu_impl_init(struct arm_smmu_device *smmu) if (match) return qcom_smmu_create(smmu, match->data); + /* + * If you hit this WARN_ON() you are missing an entry in the + * qcom_smmu_impl_of_match[] table, and GPU per-process page- + * tables will be broken. + */ + WARN(of_device_is_compatible(np, "qcom,adreno-smmu"), + "Missing qcom_smmu_impl_of_match entry for: %s", + dev_name(smmu->dev)); + return smmu; } diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index aecc7d154f28ee..e93906d6e112e8 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -781,7 +781,8 @@ static void mtk_iommu_flush_iotlb_all(struct iommu_domain *domain) { struct mtk_iommu_domain *dom = to_mtk_domain(domain); - mtk_iommu_tlb_flush_all(dom->bank->parent_data); + if (dom->bank) + mtk_iommu_tlb_flush_all(dom->bank->parent_data); } static void mtk_iommu_iotlb_sync(struct iommu_domain *domain, diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c index ea5a3088bb7e8a..4054030c323795 100644 --- a/drivers/iommu/rockchip-iommu.c +++ b/drivers/iommu/rockchip-iommu.c @@ -1335,20 +1335,22 @@ static int rk_iommu_probe(struct platform_device *pdev) for (i = 0; i < iommu->num_irq; i++) { int irq = platform_get_irq(pdev, i); - if (irq < 0) - return irq; + if (irq < 0) { + err = irq; + goto err_pm_disable; + } err = devm_request_irq(iommu->dev, irq, rk_iommu_irq, IRQF_SHARED, dev_name(dev), iommu); - if (err) { - pm_runtime_disable(dev); - goto err_remove_sysfs; - } + if (err) + goto err_pm_disable; } dma_set_mask_and_coherent(dev, rk_ops->dma_bit_mask); return 0; +err_pm_disable: + pm_runtime_disable(dev); err_remove_sysfs: iommu_device_sysfs_remove(&iommu->iommu); err_put_group: diff --git a/drivers/irqchip/irq-gic-common.c b/drivers/irqchip/irq-gic-common.c index a610821c8ff2af..afd6a1841715a1 100644 --- a/drivers/irqchip/irq-gic-common.c +++ b/drivers/irqchip/irq-gic-common.c @@ -16,7 +16,13 @@ void gic_enable_of_quirks(const struct device_node *np, const struct gic_quirk *quirks, void *data) { for (; quirks->desc; quirks++) { - if (!of_device_is_compatible(np, quirks->compatible)) + if (!quirks->compatible && !quirks->property) + continue; + if (quirks->compatible && + !of_device_is_compatible(np, quirks->compatible)) + continue; + if (quirks->property && + !of_property_read_bool(np, quirks->property)) continue; if (quirks->init(data)) pr_info("GIC: enabling workaround for %s\n", @@ -28,7 +34,7 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks, void *data) { for (; quirks->desc; quirks++) { - if (quirks->compatible) + if (quirks->compatible || quirks->property) continue; if (quirks->iidr != (quirks->mask & iidr)) continue; diff --git a/drivers/irqchip/irq-gic-common.h b/drivers/irqchip/irq-gic-common.h index 27e3d4ed4f3286..3db4592cda1c01 100644 --- a/drivers/irqchip/irq-gic-common.h +++ b/drivers/irqchip/irq-gic-common.h @@ -13,6 +13,7 @@ struct gic_quirk { const char *desc; const char *compatible; + const char *property; bool (*init)(void *data); u32 iidr; u32 mask; diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 6fcee221f20172..a605aa79435a4d 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -39,6 +39,7 @@ #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996 (1ULL << 0) #define FLAGS_WORKAROUND_CAVIUM_ERRATUM_38539 (1ULL << 1) +#define FLAGS_WORKAROUND_MTK_GICR_SAVE (1ULL << 2) #define GIC_IRQ_TYPE_PARTITION (GIC_IRQ_TYPE_LPI + 1) @@ -1720,6 +1721,15 @@ static bool gic_enable_quirk_msm8996(void *data) return true; } +static bool gic_enable_quirk_mtk_gicr(void *data) +{ + struct gic_chip_data *d = data; + + d->flags |= FLAGS_WORKAROUND_MTK_GICR_SAVE; + + return true; +} + static bool gic_enable_quirk_cavium_38539(void *data) { struct gic_chip_data *d = data; @@ -1792,6 +1802,11 @@ static const struct gic_quirk gic_quirks[] = { .compatible = "qcom,msm8996-gic-v3", .init = gic_enable_quirk_msm8996, }, + { + .desc = "GICv3: Mediatek Chromebook GICR save problem", + .property = "mediatek,broken-save-restore-fw", + .init = gic_enable_quirk_mtk_gicr, + }, { .desc = "GICv3: HIP06 erratum 161010803", .iidr = 0x0204043b, @@ -1834,6 +1849,11 @@ static void gic_enable_nmi_support(void) if (!gic_prio_masking_enabled()) return; + if (gic_data.flags & FLAGS_WORKAROUND_MTK_GICR_SAVE) { + pr_warn("Skipping NMI enable due to firmware issues\n"); + return; + } + ppi_nmi_refs = kcalloc(gic_data.ppi_nr, sizeof(*ppi_nmi_refs), GFP_KERNEL); if (!ppi_nmi_refs) return; diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c index eada5e0e3eb956..5101a3fb11df5b 100644 --- a/drivers/irqchip/irq-mbigen.c +++ b/drivers/irqchip/irq-mbigen.c @@ -240,26 +240,27 @@ static int mbigen_of_create_domain(struct platform_device *pdev, struct irq_domain *domain; struct device_node *np; u32 num_pins; + int ret = 0; + + parent = bus_get_dev_root(&platform_bus_type); + if (!parent) + return -ENODEV; for_each_child_of_node(pdev->dev.of_node, np) { if (!of_property_read_bool(np, "interrupt-controller")) continue; - parent = bus_get_dev_root(&platform_bus_type); - if (parent) { - child = of_platform_device_create(np, NULL, parent); - put_device(parent); - if (!child) { - of_node_put(np); - return -ENOMEM; - } + child = of_platform_device_create(np, NULL, parent); + if (!child) { + ret = -ENOMEM; + break; } if (of_property_read_u32(child->dev.of_node, "num-pins", &num_pins) < 0) { dev_err(&pdev->dev, "No num-pins property\n"); - of_node_put(np); - return -EINVAL; + ret = -EINVAL; + break; } domain = platform_msi_create_device_domain(&child->dev, num_pins, @@ -267,12 +268,16 @@ static int mbigen_of_create_domain(struct platform_device *pdev, &mbigen_domain_ops, mgn_chip); if (!domain) { - of_node_put(np); - return -ENOMEM; + ret = -ENOMEM; + break; } } - return 0; + put_device(parent); + if (ret) + of_node_put(np); + + return ret; } #ifdef CONFIG_ACPI diff --git a/drivers/irqchip/irq-meson-gpio.c b/drivers/irqchip/irq-meson-gpio.c index 2aaa9aad3e87ac..7da18ef9521198 100644 --- a/drivers/irqchip/irq-meson-gpio.c +++ b/drivers/irqchip/irq-meson-gpio.c @@ -150,7 +150,7 @@ static const struct meson_gpio_irq_params s4_params = { INIT_MESON_S4_COMMON_DATA(82) }; -static const struct of_device_id meson_irq_gpio_matches[] = { +static const struct of_device_id meson_irq_gpio_matches[] __maybe_unused = { { .compatible = "amlogic,meson8-gpio-intc", .data = &meson8_params }, { .compatible = "amlogic,meson8b-gpio-intc", .data = &meson8b_params }, { .compatible = "amlogic,meson-gxbb-gpio-intc", .data = &gxbb_params }, diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 046c355e120b64..6d5ecc10a87032 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -50,7 +50,7 @@ void __iomem *mips_gic_base; static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[GIC_MAX_LONGS], pcpu_masks); -static DEFINE_SPINLOCK(gic_lock); +static DEFINE_RAW_SPINLOCK(gic_lock); static struct irq_domain *gic_irq_domain; static int gic_shared_intrs; static unsigned int gic_cpu_pin; @@ -210,7 +210,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) irq = GIC_HWIRQ_TO_SHARED(d->hwirq); - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); switch (type & IRQ_TYPE_SENSE_MASK) { case IRQ_TYPE_EDGE_FALLING: pol = GIC_POL_FALLING_EDGE; @@ -250,7 +250,7 @@ static int gic_set_type(struct irq_data *d, unsigned int type) else irq_set_chip_handler_name_locked(d, &gic_level_irq_controller, handle_level_irq, NULL); - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); return 0; } @@ -268,7 +268,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, return -EINVAL; /* Assumption : cpumask refers to a single CPU */ - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); /* Re-route this IRQ */ write_gic_map_vp(irq, BIT(mips_cm_vp_id(cpu))); @@ -279,7 +279,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, set_bit(irq, per_cpu_ptr(pcpu_masks, cpu)); irq_data_update_effective_affinity(d, cpumask_of(cpu)); - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); return IRQ_SET_MASK_OK; } @@ -357,12 +357,12 @@ static void gic_mask_local_irq_all_vpes(struct irq_data *d) cd = irq_data_get_irq_chip_data(d); cd->mask = false; - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for_each_online_cpu(cpu) { write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vo_rmask(BIT(intr)); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); } static void gic_unmask_local_irq_all_vpes(struct irq_data *d) @@ -375,12 +375,12 @@ static void gic_unmask_local_irq_all_vpes(struct irq_data *d) cd = irq_data_get_irq_chip_data(d); cd->mask = true; - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for_each_online_cpu(cpu) { write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vo_smask(BIT(intr)); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); } static void gic_all_vpes_irq_cpu_online(void) @@ -393,19 +393,21 @@ static void gic_all_vpes_irq_cpu_online(void) unsigned long flags; int i; - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for (i = 0; i < ARRAY_SIZE(local_intrs); i++) { unsigned int intr = local_intrs[i]; struct gic_all_vpes_chip_data *cd; + if (!gic_local_irq_is_routable(intr)) + continue; cd = &gic_all_vpes_chip_data[intr]; write_gic_vl_map(mips_gic_vx_map_reg(intr), cd->map); if (cd->mask) write_gic_vl_smask(BIT(intr)); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); } static struct irq_chip gic_all_vpes_local_irq_controller = { @@ -435,11 +437,11 @@ static int gic_shared_irq_domain_map(struct irq_domain *d, unsigned int virq, data = irq_get_irq_data(virq); - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); write_gic_map_pin(intr, GIC_MAP_PIN_MAP_TO_PIN | gic_cpu_pin); write_gic_map_vp(intr, BIT(mips_cm_vp_id(cpu))); irq_data_update_effective_affinity(data, cpumask_of(cpu)); - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); return 0; } @@ -531,12 +533,12 @@ static int gic_irq_domain_map(struct irq_domain *d, unsigned int virq, if (!gic_local_irq_is_routable(intr)) return -EPERM; - spin_lock_irqsave(&gic_lock, flags); + raw_spin_lock_irqsave(&gic_lock, flags); for_each_online_cpu(cpu) { write_gic_vl_other(mips_cm_vp_id(cpu)); write_gic_vo_map(mips_gic_vx_map_reg(intr), map); } - spin_unlock_irqrestore(&gic_lock, flags); + raw_spin_unlock_irqrestore(&gic_lock, flags); return 0; } diff --git a/drivers/leds/rgb/leds-qcom-lpg.c b/drivers/leds/rgb/leds-qcom-lpg.c index 55a037234df1b0..1c849814a4917f 100644 --- a/drivers/leds/rgb/leds-qcom-lpg.c +++ b/drivers/leds/rgb/leds-qcom-lpg.c @@ -312,14 +312,14 @@ static int lpg_calc_freq(struct lpg_channel *chan, uint64_t period) max_res = LPG_RESOLUTION_9BIT; } - min_period = (u64)NSEC_PER_SEC * - div64_u64((1 << pwm_resolution_arr[0]), clk_rate_arr[clk_len - 1]); + min_period = div64_u64((u64)NSEC_PER_SEC * (1 << pwm_resolution_arr[0]), + clk_rate_arr[clk_len - 1]); if (period <= min_period) return -EINVAL; /* Limit period to largest possible value, to avoid overflows */ - max_period = (u64)NSEC_PER_SEC * max_res * LPG_MAX_PREDIV * - div64_u64((1 << LPG_MAX_M), 1024); + max_period = div64_u64((u64)NSEC_PER_SEC * max_res * LPG_MAX_PREDIV * (1 << LPG_MAX_M), + 1024); if (period > max_period) period = max_period; diff --git a/drivers/leds/trigger/ledtrig-netdev.c b/drivers/leds/trigger/ledtrig-netdev.c index d5e774d8302158..b0a6f274955200 100644 --- a/drivers/leds/trigger/ledtrig-netdev.c +++ b/drivers/leds/trigger/ledtrig-netdev.c @@ -20,10 +20,12 @@ #include #include #include -#include +#include #include #include "../leds.h" +#define NETDEV_LED_DEFAULT_INTERVAL 50 + /* * Configurable sysfs attributes: * @@ -37,7 +39,7 @@ */ struct led_netdev_data { - spinlock_t lock; + struct mutex lock; struct delayed_work work; struct notifier_block notifier; @@ -50,16 +52,8 @@ struct led_netdev_data { unsigned int last_activity; unsigned long mode; -#define NETDEV_LED_LINK 0 -#define NETDEV_LED_TX 1 -#define NETDEV_LED_RX 2 -#define NETDEV_LED_MODE_LINKUP 3 -}; - -enum netdev_led_attr { - NETDEV_ATTR_LINK, - NETDEV_ATTR_TX, - NETDEV_ATTR_RX + bool carrier_link_up; + bool hw_control; }; static void set_baseline_state(struct led_netdev_data *trigger_data) @@ -67,16 +61,23 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) int current_brightness; struct led_classdev *led_cdev = trigger_data->led_cdev; + /* Already validated, hw control is possible with the requested mode */ + if (trigger_data->hw_control) { + led_cdev->hw_control_set(led_cdev, trigger_data->mode); + + return; + } + current_brightness = led_cdev->brightness; if (current_brightness) led_cdev->blink_brightness = current_brightness; if (!led_cdev->blink_brightness) led_cdev->blink_brightness = led_cdev->max_brightness; - if (!test_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode)) + if (!trigger_data->carrier_link_up) { led_set_brightness(led_cdev, LED_OFF); - else { - if (test_bit(NETDEV_LED_LINK, &trigger_data->mode)) + } else { + if (test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode)) led_set_brightness(led_cdev, led_cdev->blink_brightness); else @@ -85,44 +86,107 @@ static void set_baseline_state(struct led_netdev_data *trigger_data) /* If we are looking for RX/TX start periodically * checking stats */ - if (test_bit(NETDEV_LED_TX, &trigger_data->mode) || - test_bit(NETDEV_LED_RX, &trigger_data->mode)) + if (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) || + test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) schedule_delayed_work(&trigger_data->work, 0); } } +static bool supports_hw_control(struct led_classdev *led_cdev) +{ + if (!led_cdev->hw_control_get || !led_cdev->hw_control_set || + !led_cdev->hw_control_is_supported) + return false; + + return !strcmp(led_cdev->hw_control_trigger, led_cdev->trigger->name); +} + +/* + * Validate the configured netdev is the same as the one associated with + * the LED driver in hw control. + */ +static bool validate_net_dev(struct led_classdev *led_cdev, + struct net_device *net_dev) +{ + struct device *dev = led_cdev->hw_control_get_device(led_cdev); + struct net_device *ndev; + + if (!dev) + return false; + + ndev = to_net_dev(dev); + + return ndev == net_dev; +} + +static bool can_hw_control(struct led_netdev_data *trigger_data) +{ + unsigned long default_interval = msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL); + unsigned int interval = atomic_read(&trigger_data->interval); + struct led_classdev *led_cdev = trigger_data->led_cdev; + int ret; + + if (!supports_hw_control(led_cdev)) + return false; + + /* + * Interval must be set to the default + * value. Any different value is rejected if in hw + * control. + */ + if (interval != default_interval) + return false; + + /* + * net_dev must be set with hw control, otherwise no + * blinking can be happening and there is nothing to + * offloaded. Additionally, for hw control to be + * valid, the configured netdev must be the same as + * netdev associated to the LED. + */ + if (!validate_net_dev(led_cdev, trigger_data->net_dev)) + return false; + + /* Check if the requested mode is supported */ + ret = led_cdev->hw_control_is_supported(led_cdev, trigger_data->mode); + /* Fall back to software blinking if not supported */ + if (ret == -EOPNOTSUPP) + return false; + if (ret) { + dev_warn(led_cdev->dev, + "Current mode check failed with error %d\n", ret); + return false; + } + + return true; +} + static ssize_t device_name_show(struct device *dev, struct device_attribute *attr, char *buf) { struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); ssize_t len; - spin_lock_bh(&trigger_data->lock); + mutex_lock(&trigger_data->lock); len = sprintf(buf, "%s\n", trigger_data->device_name); - spin_unlock_bh(&trigger_data->lock); + mutex_unlock(&trigger_data->lock); return len; } -static ssize_t device_name_store(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t size) +static int set_device_name(struct led_netdev_data *trigger_data, + const char *name, size_t size) { - struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); - - if (size >= IFNAMSIZ) - return -EINVAL; - cancel_delayed_work_sync(&trigger_data->work); - spin_lock_bh(&trigger_data->lock); + mutex_lock(&trigger_data->lock); if (trigger_data->net_dev) { dev_put(trigger_data->net_dev); trigger_data->net_dev = NULL; } - memcpy(trigger_data->device_name, buf, size); + memcpy(trigger_data->device_name, name, size); trigger_data->device_name[size] = 0; if (size > 0 && trigger_data->device_name[size - 1] == '\n') trigger_data->device_name[size - 1] = 0; @@ -131,36 +195,48 @@ static ssize_t device_name_store(struct device *dev, trigger_data->net_dev = dev_get_by_name(&init_net, trigger_data->device_name); - clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + trigger_data->carrier_link_up = false; if (trigger_data->net_dev != NULL) - if (netif_carrier_ok(trigger_data->net_dev)) - set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + trigger_data->carrier_link_up = netif_carrier_ok(trigger_data->net_dev); trigger_data->last_activity = 0; set_baseline_state(trigger_data); - spin_unlock_bh(&trigger_data->lock); + mutex_unlock(&trigger_data->lock); + return 0; +} + +static ssize_t device_name_store(struct device *dev, + struct device_attribute *attr, const char *buf, + size_t size) +{ + struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); + int ret; + + if (size >= IFNAMSIZ) + return -EINVAL; + + ret = set_device_name(trigger_data, buf, size); + + if (ret < 0) + return ret; return size; } static DEVICE_ATTR_RW(device_name); static ssize_t netdev_led_attr_show(struct device *dev, char *buf, - enum netdev_led_attr attr) + enum led_trigger_netdev_modes attr) { struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); int bit; switch (attr) { - case NETDEV_ATTR_LINK: - bit = NETDEV_LED_LINK; - break; - case NETDEV_ATTR_TX: - bit = NETDEV_LED_TX; - break; - case NETDEV_ATTR_RX: - bit = NETDEV_LED_RX; + case TRIGGER_NETDEV_LINK: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; break; default: return -EINVAL; @@ -170,7 +246,7 @@ static ssize_t netdev_led_attr_show(struct device *dev, char *buf, } static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, - size_t size, enum netdev_led_attr attr) + size_t size, enum led_trigger_netdev_modes attr) { struct led_netdev_data *trigger_data = led_trigger_get_drvdata(dev); unsigned long state; @@ -182,14 +258,10 @@ static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, return ret; switch (attr) { - case NETDEV_ATTR_LINK: - bit = NETDEV_LED_LINK; - break; - case NETDEV_ATTR_TX: - bit = NETDEV_LED_TX; - break; - case NETDEV_ATTR_RX: - bit = NETDEV_LED_RX; + case TRIGGER_NETDEV_LINK: + case TRIGGER_NETDEV_TX: + case TRIGGER_NETDEV_RX: + bit = attr; break; default: return -EINVAL; @@ -202,52 +274,29 @@ static ssize_t netdev_led_attr_store(struct device *dev, const char *buf, else clear_bit(bit, &trigger_data->mode); + trigger_data->hw_control = can_hw_control(trigger_data); + set_baseline_state(trigger_data); return size; } -static ssize_t link_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return netdev_led_attr_show(dev, buf, NETDEV_ATTR_LINK); -} - -static ssize_t link_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_LINK); -} - -static DEVICE_ATTR_RW(link); - -static ssize_t tx_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return netdev_led_attr_show(dev, buf, NETDEV_ATTR_TX); -} - -static ssize_t tx_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_TX); -} - -static DEVICE_ATTR_RW(tx); - -static ssize_t rx_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return netdev_led_attr_show(dev, buf, NETDEV_ATTR_RX); -} - -static ssize_t rx_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - return netdev_led_attr_store(dev, buf, size, NETDEV_ATTR_RX); -} - -static DEVICE_ATTR_RW(rx); +#define DEFINE_NETDEV_TRIGGER(trigger_name, trigger) \ + static ssize_t trigger_name##_show(struct device *dev, \ + struct device_attribute *attr, char *buf) \ + { \ + return netdev_led_attr_show(dev, buf, trigger); \ + } \ + static ssize_t trigger_name##_store(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t size) \ + { \ + return netdev_led_attr_store(dev, buf, size, trigger); \ + } \ + static DEVICE_ATTR_RW(trigger_name) + +DEFINE_NETDEV_TRIGGER(link, TRIGGER_NETDEV_LINK); +DEFINE_NETDEV_TRIGGER(tx, TRIGGER_NETDEV_TX); +DEFINE_NETDEV_TRIGGER(rx, TRIGGER_NETDEV_RX); static ssize_t interval_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -266,6 +315,9 @@ static ssize_t interval_store(struct device *dev, unsigned long value; int ret; + if (trigger_data->hw_control) + return -EINVAL; + ret = kstrtoul(buf, 0, &value); if (ret) return ret; @@ -313,11 +365,13 @@ static int netdev_trig_notify(struct notifier_block *nb, cancel_delayed_work_sync(&trigger_data->work); - spin_lock_bh(&trigger_data->lock); + mutex_lock(&trigger_data->lock); - clear_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + trigger_data->carrier_link_up = false; switch (evt) { case NETDEV_CHANGENAME: + trigger_data->carrier_link_up = netif_carrier_ok(dev); + fallthrough; case NETDEV_REGISTER: if (trigger_data->net_dev) dev_put(trigger_data->net_dev); @@ -330,14 +384,13 @@ static int netdev_trig_notify(struct notifier_block *nb, break; case NETDEV_UP: case NETDEV_CHANGE: - if (netif_carrier_ok(dev)) - set_bit(NETDEV_LED_MODE_LINKUP, &trigger_data->mode); + trigger_data->carrier_link_up = netif_carrier_ok(dev); break; } set_baseline_state(trigger_data); - spin_unlock_bh(&trigger_data->lock); + mutex_unlock(&trigger_data->lock); return NOTIFY_DONE; } @@ -360,21 +413,21 @@ static void netdev_trig_work(struct work_struct *work) } /* If we are not looking for RX/TX then return */ - if (!test_bit(NETDEV_LED_TX, &trigger_data->mode) && - !test_bit(NETDEV_LED_RX, &trigger_data->mode)) + if (!test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) && + !test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode)) return; dev_stats = dev_get_stats(trigger_data->net_dev, &temp); new_activity = - (test_bit(NETDEV_LED_TX, &trigger_data->mode) ? + (test_bit(TRIGGER_NETDEV_TX, &trigger_data->mode) ? dev_stats->tx_packets : 0) + - (test_bit(NETDEV_LED_RX, &trigger_data->mode) ? + (test_bit(TRIGGER_NETDEV_RX, &trigger_data->mode) ? dev_stats->rx_packets : 0); if (trigger_data->last_activity != new_activity) { led_stop_software_blink(trigger_data->led_cdev); - invert = test_bit(NETDEV_LED_LINK, &trigger_data->mode); + invert = test_bit(TRIGGER_NETDEV_LINK, &trigger_data->mode); interval = jiffies_to_msecs( atomic_read(&trigger_data->interval)); /* base state is ON (link present) */ @@ -392,13 +445,15 @@ static void netdev_trig_work(struct work_struct *work) static int netdev_trig_activate(struct led_classdev *led_cdev) { struct led_netdev_data *trigger_data; + unsigned long mode; + struct device *dev; int rc; trigger_data = kzalloc(sizeof(struct led_netdev_data), GFP_KERNEL); if (!trigger_data) return -ENOMEM; - spin_lock_init(&trigger_data->lock); + mutex_init(&trigger_data->lock); trigger_data->notifier.notifier_call = netdev_trig_notify; trigger_data->notifier.priority = 10; @@ -410,9 +465,24 @@ static int netdev_trig_activate(struct led_classdev *led_cdev) trigger_data->device_name[0] = 0; trigger_data->mode = 0; - atomic_set(&trigger_data->interval, msecs_to_jiffies(50)); + atomic_set(&trigger_data->interval, msecs_to_jiffies(NETDEV_LED_DEFAULT_INTERVAL)); trigger_data->last_activity = 0; + /* Check if hw control is active by default on the LED. + * Init already enabled mode in hw control. + */ + if (supports_hw_control(led_cdev) && + !led_cdev->hw_control_get(led_cdev, &mode)) { + dev = led_cdev->hw_control_get_device(led_cdev); + if (dev) { + const char *name = dev_name(dev); + + set_device_name(trigger_data, name, strlen(name)); + trigger_data->hw_control = true; + trigger_data->mode = mode; + } + } + led_set_trigger_data(led_cdev, trigger_data); rc = register_netdevice_notifier(&trigger_data->notifier); diff --git a/drivers/mailbox/mailbox-test.c b/drivers/mailbox/mailbox-test.c index c4a705c3033142..fc6a12a51b4038 100644 --- a/drivers/mailbox/mailbox-test.c +++ b/drivers/mailbox/mailbox-test.c @@ -98,6 +98,7 @@ static ssize_t mbox_test_message_write(struct file *filp, size_t count, loff_t *ppos) { struct mbox_test_device *tdev = filp->private_data; + char *message; void *data; int ret; @@ -113,12 +114,13 @@ static ssize_t mbox_test_message_write(struct file *filp, return -EINVAL; } - mutex_lock(&tdev->mutex); - - tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL); - if (!tdev->message) + message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL); + if (!message) return -ENOMEM; + mutex_lock(&tdev->mutex); + + tdev->message = message; ret = copy_from_user(tdev->message, userbuf, count); if (ret) { ret = -EFAULT; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 4739ed891e756e..9ea285fbc4a654 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5516,7 +5516,7 @@ static int raid5_read_one_chunk(struct mddev *mddev, struct bio *raid_bio) sector = raid5_compute_sector(conf, raid_bio->bi_iter.bi_sector, 0, &dd_idx, NULL); - end_sector = bio_end_sector(raid_bio); + end_sector = sector + bio_sectors(raid_bio); rcu_read_lock(); if (r5c_big_stripe_cached(conf, sector)) diff --git a/drivers/media/cec/core/cec-adap.c b/drivers/media/cec/core/cec-adap.c index 769ea6b2e1d0b6..241b1621b197c4 100644 --- a/drivers/media/cec/core/cec-adap.c +++ b/drivers/media/cec/core/cec-adap.c @@ -1091,7 +1091,8 @@ void cec_received_msg_ts(struct cec_adapter *adap, mutex_lock(&adap->lock); dprintk(2, "%s: %*ph\n", __func__, msg->len, msg->msg); - adap->last_initiator = 0xff; + if (!adap->transmit_in_progress) + adap->last_initiator = 0xff; /* Check if this message was for us (directed or broadcast). */ if (!cec_msg_is_broadcast(msg)) { @@ -1585,7 +1586,7 @@ static void cec_claim_log_addrs(struct cec_adapter *adap, bool block) * * This function is called with adap->lock held. */ -static int cec_adap_enable(struct cec_adapter *adap) +int cec_adap_enable(struct cec_adapter *adap) { bool enable; int ret = 0; @@ -1595,6 +1596,9 @@ static int cec_adap_enable(struct cec_adapter *adap) if (adap->needs_hpd) enable = enable && adap->phys_addr != CEC_PHYS_ADDR_INVALID; + if (adap->devnode.unregistered) + enable = false; + if (enable == adap->is_enabled) return 0; diff --git a/drivers/media/cec/core/cec-core.c b/drivers/media/cec/core/cec-core.c index af358e901b5f35..7e153c5cad04f5 100644 --- a/drivers/media/cec/core/cec-core.c +++ b/drivers/media/cec/core/cec-core.c @@ -191,6 +191,8 @@ static void cec_devnode_unregister(struct cec_adapter *adap) mutex_lock(&adap->lock); __cec_s_phys_addr(adap, CEC_PHYS_ADDR_INVALID, false); __cec_s_log_addrs(adap, NULL, false); + // Disable the adapter (since adap->devnode.unregistered is true) + cec_adap_enable(adap); mutex_unlock(&adap->lock); cdev_device_del(&devnode->cdev, &devnode->dev); diff --git a/drivers/media/cec/core/cec-priv.h b/drivers/media/cec/core/cec-priv.h index b78df931aa74b0..ed1f8c67626bf9 100644 --- a/drivers/media/cec/core/cec-priv.h +++ b/drivers/media/cec/core/cec-priv.h @@ -47,6 +47,7 @@ int cec_monitor_pin_cnt_inc(struct cec_adapter *adap); void cec_monitor_pin_cnt_dec(struct cec_adapter *adap); int cec_adap_status(struct seq_file *file, void *priv); int cec_thread_func(void *_adap); +int cec_adap_enable(struct cec_adapter *adap); void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block); int __cec_s_log_addrs(struct cec_adapter *adap, struct cec_log_addrs *log_addrs, bool block); diff --git a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c index 29991551cf6140..0fbd030026c729 100644 --- a/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c +++ b/drivers/media/platform/mediatek/vcodec/mtk_vcodec_dec_stateful.c @@ -584,6 +584,9 @@ static void mtk_init_vdec_params(struct mtk_vcodec_ctx *ctx) if (!(ctx->dev->dec_capability & VCODEC_CAPABILITY_4K_DISABLED)) { for (i = 0; i < num_supported_formats; i++) { + if (mtk_video_formats[i].type != MTK_FMT_DEC) + continue; + mtk_video_formats[i].frmsize.max_width = VCODEC_DEC_4K_CODED_WIDTH; mtk_video_formats[i].frmsize.max_height = diff --git a/drivers/media/platform/qcom/camss/camss-video.c b/drivers/media/platform/qcom/camss/camss-video.c index 898f32177b12a5..8640db30602680 100644 --- a/drivers/media/platform/qcom/camss/camss-video.c +++ b/drivers/media/platform/qcom/camss/camss-video.c @@ -353,7 +353,6 @@ static int video_get_subdev_format(struct camss_video *video, if (subdev == NULL) return -EPIPE; - memset(&fmt, 0, sizeof(fmt)); fmt.pad = pad; ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt); diff --git a/drivers/media/platform/verisilicon/hantro_v4l2.c b/drivers/media/platform/verisilicon/hantro_v4l2.c index 835518534e3b94..61cfaaf4e927b3 100644 --- a/drivers/media/platform/verisilicon/hantro_v4l2.c +++ b/drivers/media/platform/verisilicon/hantro_v4l2.c @@ -397,10 +397,12 @@ hantro_reset_raw_fmt(struct hantro_ctx *ctx, int bit_depth) if (!raw_vpu_fmt) return -EINVAL; - if (ctx->is_encoder) + if (ctx->is_encoder) { encoded_fmt = &ctx->dst_fmt; - else + ctx->vpu_src_fmt = raw_vpu_fmt; + } else { encoded_fmt = &ctx->src_fmt; + } hantro_reset_fmt(&raw_fmt, raw_vpu_fmt); raw_fmt.width = encoded_fmt->width; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 7aefa76a42b316..d631ce4f9f7bb2 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -251,14 +251,17 @@ static int uvc_parse_format(struct uvc_device *dev, /* Find the format descriptor from its GUID. */ fmtdesc = uvc_format_by_guid(&buffer[5]); - if (fmtdesc != NULL) { - format->fcc = fmtdesc->fcc; - } else { + if (!fmtdesc) { + /* + * Unknown video formats are not fatal errors, the + * caller will skip this descriptor. + */ dev_info(&streaming->intf->dev, "Unknown video format %pUl\n", &buffer[5]); - format->fcc = 0; + return 0; } + format->fcc = fmtdesc->fcc; format->bpp = buffer[21]; /* @@ -675,7 +678,7 @@ static int uvc_parse_streaming(struct uvc_device *dev, interval = (u32 *)&frame[nframes]; streaming->format = format; - streaming->nformats = nformats; + streaming->nformats = 0; /* Parse the format descriptors. */ while (buflen > 2 && buffer[1] == USB_DT_CS_INTERFACE) { @@ -689,7 +692,10 @@ static int uvc_parse_streaming(struct uvc_device *dev, &interval, buffer, buflen); if (ret < 0) goto error; + if (!ret) + break; + streaming->nformats++; frame += format->nframes; format++; diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index bf0c18100664f5..22fe08fce0a9ab 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -314,8 +314,7 @@ int v4l2_create_fwnode_links_to_pad(struct v4l2_subdev *src_sd, { struct fwnode_handle *endpoint; - if (!(sink->flags & MEDIA_PAD_FL_SINK) || - !is_media_entity_v4l2_subdev(sink->entity)) + if (!(sink->flags & MEDIA_PAD_FL_SINK)) return -EINVAL; fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) { diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index f48466960f1b9c..30d4d0476248ff 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -316,12 +316,14 @@ static void fastrpc_free_map(struct kref *ref) if (map->table) { if (map->attr & FASTRPC_ATTR_SECUREMAP) { struct qcom_scm_vmperm perm; + int vmid = map->fl->cctx->vmperms[0].vmid; + u64 src_perms = BIT(QCOM_SCM_VMID_HLOS) | BIT(vmid); int err = 0; perm.vmid = QCOM_SCM_VMID_HLOS; perm.perm = QCOM_SCM_PERM_RWX; err = qcom_scm_assign_mem(map->phys, map->size, - &map->fl->cctx->perms, &perm, 1); + &src_perms, &perm, 1); if (err) { dev_err(map->fl->sctx->dev, "Failed to assign memory phys 0x%llx size 0x%llx err %d", map->phys, map->size, err); @@ -787,8 +789,12 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd, goto map_err; } - map->phys = sg_dma_address(map->table->sgl); - map->phys += ((u64)fl->sctx->sid << 32); + if (attr & FASTRPC_ATTR_SECUREMAP) { + map->phys = sg_phys(map->table->sgl); + } else { + map->phys = sg_dma_address(map->table->sgl); + map->phys += ((u64)fl->sctx->sid << 32); + } map->size = len; map->va = sg_virt(map->table->sgl); map->len = len; @@ -798,9 +804,15 @@ static int fastrpc_map_create(struct fastrpc_user *fl, int fd, * If subsystem VMIDs are defined in DTSI, then do * hyp_assign from HLOS to those VM(s) */ + u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); + struct qcom_scm_vmperm dst_perms[2] = {0}; + + dst_perms[0].vmid = QCOM_SCM_VMID_HLOS; + dst_perms[0].perm = QCOM_SCM_PERM_RW; + dst_perms[1].vmid = fl->cctx->vmperms[0].vmid; + dst_perms[1].perm = QCOM_SCM_PERM_RWX; map->attr = attr; - err = qcom_scm_assign_mem(map->phys, (u64)map->size, &fl->cctx->perms, - fl->cctx->vmperms, fl->cctx->vmcount); + err = qcom_scm_assign_mem(map->phys, (u64)map->size, &src_perms, dst_perms, 2); if (err) { dev_err(sess->dev, "Failed to assign memory with phys 0x%llx size 0x%llx err %d", map->phys, map->size, err); @@ -1892,7 +1904,7 @@ static int fastrpc_req_mmap(struct fastrpc_user *fl, char __user *argp) req.vaddrout = rsp_msg.vaddr; /* Add memory to static PD pool, protection thru hypervisor */ - if (req.flags != ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) { + if (req.flags == ADSP_MMAP_REMOTE_HEAP_ADDR && fl->cctx->vmcount) { struct qcom_scm_vmperm perm; perm.vmid = QCOM_SCM_VMID_HLOS; @@ -2337,8 +2349,10 @@ static void fastrpc_notify_users(struct fastrpc_user *user) struct fastrpc_invoke_ctx *ctx; spin_lock(&user->lock); - list_for_each_entry(ctx, &user->pending, node) + list_for_each_entry(ctx, &user->pending, node) { + ctx->retval = -EPIPE; complete(&ctx->work); + } spin_unlock(&user->lock); } @@ -2349,7 +2363,9 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) struct fastrpc_user *user; unsigned long flags; + /* No invocations past this point */ spin_lock_irqsave(&cctx->lock, flags); + cctx->rpdev = NULL; list_for_each_entry(user, &cctx->users, user) fastrpc_notify_users(user); spin_unlock_irqrestore(&cctx->lock, flags); @@ -2368,7 +2384,6 @@ static void fastrpc_rpmsg_remove(struct rpmsg_device *rpdev) of_platform_depopulate(&rpdev->dev); - cctx->rpdev = NULL; fastrpc_channel_ctx_put(cctx); } diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 00c33edb9fb94e..d920c417838930 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -264,6 +264,7 @@ static ssize_t power_ro_lock_store(struct device *dev, goto out_put; } req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_BOOT_WP; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; blk_execute_rq(req, false); ret = req_to_mmc_queue_req(req)->drv_op_result; blk_mq_free_request(req); @@ -651,6 +652,7 @@ static int mmc_blk_ioctl_cmd(struct mmc_blk_data *md, idatas[0] = idata; req_to_mmc_queue_req(req)->drv_op = rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; req_to_mmc_queue_req(req)->drv_op_data = idatas; req_to_mmc_queue_req(req)->ioc_count = 1; blk_execute_rq(req, false); @@ -722,6 +724,7 @@ static int mmc_blk_ioctl_multi_cmd(struct mmc_blk_data *md, } req_to_mmc_queue_req(req)->drv_op = rpmb ? MMC_DRV_OP_IOCTL_RPMB : MMC_DRV_OP_IOCTL; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; req_to_mmc_queue_req(req)->drv_op_data = idata; req_to_mmc_queue_req(req)->ioc_count = n; blk_execute_rq(req, false); @@ -2806,6 +2809,7 @@ static int mmc_dbg_card_status_get(void *data, u64 *val) if (IS_ERR(req)) return PTR_ERR(req); req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_CARD_STATUS; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; blk_execute_rq(req, false); ret = req_to_mmc_queue_req(req)->drv_op_result; if (ret >= 0) { @@ -2844,6 +2848,7 @@ static int mmc_ext_csd_open(struct inode *inode, struct file *filp) goto out_free; } req_to_mmc_queue_req(req)->drv_op = MMC_DRV_OP_GET_EXT_CSD; + req_to_mmc_queue_req(req)->drv_op_result = -EIO; req_to_mmc_queue_req(req)->drv_op_data = &ext_csd; blk_execute_rq(req, false); err = req_to_mmc_queue_req(req)->drv_op_result; diff --git a/drivers/mmc/core/pwrseq_sd8787.c b/drivers/mmc/core/pwrseq_sd8787.c index 2e120ad83020f8..0c5f5e371e1f83 100644 --- a/drivers/mmc/core/pwrseq_sd8787.c +++ b/drivers/mmc/core/pwrseq_sd8787.c @@ -28,7 +28,6 @@ struct mmc_pwrseq_sd8787 { struct mmc_pwrseq pwrseq; struct gpio_desc *reset_gpio; struct gpio_desc *pwrdn_gpio; - u32 reset_pwrdwn_delay_ms; }; #define to_pwrseq_sd8787(p) container_of(p, struct mmc_pwrseq_sd8787, pwrseq) @@ -39,7 +38,7 @@ static void mmc_pwrseq_sd8787_pre_power_on(struct mmc_host *host) gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); - msleep(pwrseq->reset_pwrdwn_delay_ms); + msleep(300); gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1); } @@ -51,17 +50,37 @@ static void mmc_pwrseq_sd8787_power_off(struct mmc_host *host) gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); } +static void mmc_pwrseq_wilc1000_pre_power_on(struct mmc_host *host) +{ + struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq); + + /* The pwrdn_gpio is really CHIP_EN, reset_gpio is RESETN */ + gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 1); + msleep(5); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); +} + +static void mmc_pwrseq_wilc1000_power_off(struct mmc_host *host) +{ + struct mmc_pwrseq_sd8787 *pwrseq = to_pwrseq_sd8787(host->pwrseq); + + gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); + gpiod_set_value_cansleep(pwrseq->pwrdn_gpio, 0); +} + static const struct mmc_pwrseq_ops mmc_pwrseq_sd8787_ops = { .pre_power_on = mmc_pwrseq_sd8787_pre_power_on, .power_off = mmc_pwrseq_sd8787_power_off, }; -static const u32 sd8787_delay_ms = 300; -static const u32 wilc1000_delay_ms = 5; +static const struct mmc_pwrseq_ops mmc_pwrseq_wilc1000_ops = { + .pre_power_on = mmc_pwrseq_wilc1000_pre_power_on, + .power_off = mmc_pwrseq_wilc1000_power_off, +}; static const struct of_device_id mmc_pwrseq_sd8787_of_match[] = { - { .compatible = "mmc-pwrseq-sd8787", .data = &sd8787_delay_ms }, - { .compatible = "mmc-pwrseq-wilc1000", .data = &wilc1000_delay_ms }, + { .compatible = "mmc-pwrseq-sd8787", .data = &mmc_pwrseq_sd8787_ops }, + { .compatible = "mmc-pwrseq-wilc1000", .data = &mmc_pwrseq_wilc1000_ops }, {/* sentinel */}, }; MODULE_DEVICE_TABLE(of, mmc_pwrseq_sd8787_of_match); @@ -77,7 +96,6 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) return -ENOMEM; match = of_match_node(mmc_pwrseq_sd8787_of_match, pdev->dev.of_node); - pwrseq->reset_pwrdwn_delay_ms = *(u32 *)match->data; pwrseq->pwrdn_gpio = devm_gpiod_get(dev, "powerdown", GPIOD_OUT_LOW); if (IS_ERR(pwrseq->pwrdn_gpio)) @@ -88,7 +106,7 @@ static int mmc_pwrseq_sd8787_probe(struct platform_device *pdev) return PTR_ERR(pwrseq->reset_gpio); pwrseq->pwrseq.dev = dev; - pwrseq->pwrseq.ops = &mmc_pwrseq_sd8787_ops; + pwrseq->pwrseq.ops = match->data; pwrseq->pwrseq.owner = THIS_MODULE; platform_set_drvdata(pdev, pwrseq); diff --git a/drivers/mmc/host/sdhci-cadence.c b/drivers/mmc/host/sdhci-cadence.c index b24aa27da50c40..d2f62505468932 100644 --- a/drivers/mmc/host/sdhci-cadence.c +++ b/drivers/mmc/host/sdhci-cadence.c @@ -540,9 +540,11 @@ static int sdhci_cdns_probe(struct platform_device *pdev) if (host->mmc->caps & MMC_CAP_HW_RESET) { priv->rst_hw = devm_reset_control_get_optional_exclusive(dev, NULL); - if (IS_ERR(priv->rst_hw)) - return dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw), - "reset controller error\n"); + if (IS_ERR(priv->rst_hw)) { + ret = dev_err_probe(mmc_dev(host->mmc), PTR_ERR(priv->rst_hw), + "reset controller error\n"); + goto free; + } if (priv->rst_hw) host->mmc_host_ops.card_hw_reset = sdhci_cdns_mmc_hw_reset; } diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index d7c0c0b9e26c5e..eebf94604a7fdd 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -1634,6 +1634,10 @@ sdhci_esdhc_imx_probe_dt(struct platform_device *pdev, if (ret) return ret; + /* HS400/HS400ES require 8 bit bus */ + if (!(host->mmc->caps & MMC_CAP_8_BIT_DATA)) + host->mmc->caps2 &= ~(MMC_CAP2_HS400 | MMC_CAP2_HS400_ES); + if (mmc_gpio_get_cd(host->mmc) >= 0) host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; @@ -1724,10 +1728,6 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) host->mmc_host_ops.init_card = usdhc_init_card; } - err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); - if (err) - goto disable_ahb_clk; - if (imx_data->socdata->flags & ESDHC_FLAG_MAN_TUNING) sdhci_esdhc_ops.platform_execute_tuning = esdhc_executing_tuning; @@ -1735,15 +1735,13 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) if (imx_data->socdata->flags & ESDHC_FLAG_ERR004536) host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; - if (host->mmc->caps & MMC_CAP_8_BIT_DATA && - imx_data->socdata->flags & ESDHC_FLAG_HS400) + if (imx_data->socdata->flags & ESDHC_FLAG_HS400) host->mmc->caps2 |= MMC_CAP2_HS400; if (imx_data->socdata->flags & ESDHC_FLAG_BROKEN_AUTO_CMD23) host->quirks2 |= SDHCI_QUIRK2_ACMD23_BROKEN; - if (host->mmc->caps & MMC_CAP_8_BIT_DATA && - imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { + if (imx_data->socdata->flags & ESDHC_FLAG_HS400_ES) { host->mmc->caps2 |= MMC_CAP2_HS400_ES; host->mmc_host_ops.hs400_enhanced_strobe = esdhc_hs400_enhanced_strobe; @@ -1765,6 +1763,10 @@ static int sdhci_esdhc_imx_probe(struct platform_device *pdev) goto disable_ahb_clk; } + err = sdhci_esdhc_imx_probe_dt(pdev, host, imx_data); + if (err) + goto disable_ahb_clk; + sdhci_esdhc_imx_hwinit(host); err = sdhci_add_host(host); diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index e4c4bfac3763ba..9ec593d52f0fa9 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -1713,6 +1713,9 @@ static void construct_request_response(struct vub300_mmc_host *vub300, int bytes = 3 & less_cmd; int words = less_cmd >> 2; u8 *r = vub300->resp.response.command_response; + + if (!resp_len) + return; if (bytes == 3) { cmd->resp[words] = (r[1 + (words << 2)] << 24) | (r[2 + (words << 2)] << 16) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 01f1c6792df9c7..8dc4f5c493fcba 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -590,8 +590,8 @@ static void adjust_oob_length(struct mtd_info *mtd, uint64_t start, (end_page - start_page + 1) * oob_per_page); } -static int mtdchar_write_ioctl(struct mtd_info *mtd, - struct mtd_write_req __user *argp) +static noinline_for_stack int +mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp) { struct mtd_info *master = mtd_get_master(mtd); struct mtd_write_req req; @@ -688,8 +688,8 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd, return ret; } -static int mtdchar_read_ioctl(struct mtd_info *mtd, - struct mtd_read_req __user *argp) +static noinline_for_stack int +mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp) { struct mtd_info *master = mtd_get_master(mtd); struct mtd_read_req req; diff --git a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h index 2cda439b5e11bf..017868f59f2221 100644 --- a/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h +++ b/drivers/mtd/nand/raw/ingenic/ingenic_ecc.h @@ -36,25 +36,25 @@ int ingenic_ecc_correct(struct ingenic_ecc *ecc, void ingenic_ecc_release(struct ingenic_ecc *ecc); struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np); #else /* CONFIG_MTD_NAND_INGENIC_ECC */ -int ingenic_ecc_calculate(struct ingenic_ecc *ecc, +static inline int ingenic_ecc_calculate(struct ingenic_ecc *ecc, struct ingenic_ecc_params *params, const u8 *buf, u8 *ecc_code) { return -ENODEV; } -int ingenic_ecc_correct(struct ingenic_ecc *ecc, +static inline int ingenic_ecc_correct(struct ingenic_ecc *ecc, struct ingenic_ecc_params *params, u8 *buf, u8 *ecc_code) { return -ENODEV; } -void ingenic_ecc_release(struct ingenic_ecc *ecc) +static inline void ingenic_ecc_release(struct ingenic_ecc *ecc) { } -struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np) +static inline struct ingenic_ecc *of_ingenic_ecc_get(struct device_node *np) { return ERR_PTR(-ENODEV); } diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index afb424579f0b89..30c15e4e1cc0d2 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -2457,6 +2457,12 @@ static int marvell_nfc_setup_interface(struct nand_chip *chip, int chipnr, NDTR1_WAIT_MODE; } + /* + * Reset nfc->selected_chip so the next command will cause the timing + * registers to be updated in marvell_nfc_select_target(). + */ + nfc->selected_chip = NULL; + return 0; } @@ -2894,10 +2900,6 @@ static int marvell_nfc_init(struct marvell_nfc *nfc) regmap_update_bits(sysctrl_base, GENCONF_CLK_GATING_CTRL, GENCONF_CLK_GATING_CTRL_ND_GATE, GENCONF_CLK_GATING_CTRL_ND_GATE); - - regmap_update_bits(sysctrl_base, GENCONF_ND_CLK_CTRL, - GENCONF_ND_CLK_CTRL_EN, - GENCONF_ND_CLK_CTRL_EN); } /* Configure the DMA if appropriate */ diff --git a/drivers/mtd/spi-nor/core.c b/drivers/mtd/spi-nor/core.c index 0bb0ad14a2fc01..5f29fac8669a30 100644 --- a/drivers/mtd/spi-nor/core.c +++ b/drivers/mtd/spi-nor/core.c @@ -2018,6 +2018,7 @@ static const struct spi_nor_manufacturer *manufacturers[] = { static const struct flash_info spi_nor_generic_flash = { .name = "spi-nor-generic", + .n_banks = 1, /* * JESD216 rev A doesn't specify the page size, therefore we need a * sane default. @@ -2921,7 +2922,8 @@ static void spi_nor_late_init_params(struct spi_nor *nor) if (nor->flags & SNOR_F_HAS_LOCK && !nor->params->locking_ops) spi_nor_init_default_locking_ops(nor); - nor->params->bank_size = div64_u64(nor->params->size, nor->info->n_banks); + if (nor->info->n_banks > 1) + params->bank_size = div64_u64(params->size, nor->info->n_banks); } /** @@ -2987,6 +2989,7 @@ static void spi_nor_init_default_params(struct spi_nor *nor) /* Set SPI NOR sizes. */ params->writesize = 1; params->size = (u64)info->sector_size * info->n_sectors; + params->bank_size = params->size; params->page_size = info->page_size; if (!(info->flags & SPI_NOR_NO_FR)) { diff --git a/drivers/mtd/spi-nor/spansion.c b/drivers/mtd/spi-nor/spansion.c index 15f9a80c10b9bd..36876aa849ede7 100644 --- a/drivers/mtd/spi-nor/spansion.c +++ b/drivers/mtd/spi-nor/spansion.c @@ -361,7 +361,7 @@ static int cypress_nor_determine_addr_mode_by_sr1(struct spi_nor *nor, */ static int cypress_nor_set_addr_mode_nbytes(struct spi_nor *nor) { - struct spi_mem_op op; + struct spi_mem_op op = {}; u8 addr_mode; int ret; @@ -492,7 +492,7 @@ s25fs256t_post_bfpt_fixup(struct spi_nor *nor, const struct sfdp_parameter_header *bfpt_header, const struct sfdp_bfpt *bfpt) { - struct spi_mem_op op; + struct spi_mem_op op = {}; int ret; ret = cypress_nor_set_addr_mode_nbytes(nor); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index fce81fafbedd02..007cec23a92f86 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3950,7 +3950,11 @@ static int bond_slave_netdev_event(unsigned long event, unblock_netpoll_tx(); break; case NETDEV_FEAT_CHANGE: - bond_compute_features(bond); + if (!bond->notifier_ctx) { + bond->notifier_ctx = true; + bond_compute_features(bond); + bond->notifier_ctx = false; + } break; case NETDEV_RESEND_IGMP: /* Propagate to master device */ @@ -6345,6 +6349,8 @@ static int bond_init(struct net_device *bond_dev) if (!bond->wq) return -ENOMEM; + bond->notifier_ctx = false; + spin_lock_init(&bond->stats_lock); netdev_lockdep_set_classes(bond_dev); diff --git a/drivers/net/dsa/hirschmann/hellcreek.c b/drivers/net/dsa/hirschmann/hellcreek.c index 595a548bb0a803..af50001ccdd4e6 100644 --- a/drivers/net/dsa/hirschmann/hellcreek.c +++ b/drivers/net/dsa/hirschmann/hellcreek.c @@ -1885,13 +1885,17 @@ static int hellcreek_port_setup_tc(struct dsa_switch *ds, int port, case TC_SETUP_QDISC_TAPRIO: { struct tc_taprio_qopt_offload *taprio = type_data; - if (!hellcreek_validate_schedule(hellcreek, taprio)) - return -EOPNOTSUPP; + switch (taprio->cmd) { + case TAPRIO_CMD_REPLACE: + if (!hellcreek_validate_schedule(hellcreek, taprio)) + return -EOPNOTSUPP; - if (taprio->enable) return hellcreek_port_set_schedule(ds, port, taprio); - - return hellcreek_port_del_schedule(ds, port); + case TAPRIO_CMD_DESTROY: + return hellcreek_port_del_schedule(ds, port); + default: + return -EOPNOTSUPP; + } } default: return -EOPNOTSUPP; diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index cbe83187534717..ff76444057d242 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1188,8 +1188,6 @@ static int lan9303_port_fdb_add(struct dsa_switch *ds, int port, struct lan9303 *chip = ds->priv; dev_dbg(chip->dev, "%s(%d, %pM, %d)\n", __func__, port, addr, vid); - if (vid) - return -EOPNOTSUPP; return lan9303_alr_add_port(chip, addr, port, false); } @@ -1201,8 +1199,6 @@ static int lan9303_port_fdb_del(struct dsa_switch *ds, int port, struct lan9303 *chip = ds->priv; dev_dbg(chip->dev, "%s(%d, %pM, %d)\n", __func__, port, addr, vid); - if (vid) - return -EOPNOTSUPP; lan9303_alr_del_port(chip, addr, port); return 0; @@ -1462,7 +1458,6 @@ int lan9303_remove(struct lan9303 *chip) /* assert reset to the whole device to prevent it from doing anything */ gpiod_set_value_cansleep(chip->reset_gpio, 1); - gpiod_unexport(chip->reset_gpio); return 0; } diff --git a/drivers/net/dsa/lan9303_i2c.c b/drivers/net/dsa/lan9303_i2c.c index e8844820c3a93a..bbbec322bc4fbb 100644 --- a/drivers/net/dsa/lan9303_i2c.c +++ b/drivers/net/dsa/lan9303_i2c.c @@ -105,7 +105,7 @@ static struct i2c_driver lan9303_i2c_driver = { .name = "LAN9303_I2C", .of_match_table = lan9303_i2c_of_match, }, - .probe_new = lan9303_i2c_probe, + .probe = lan9303_i2c_probe, .remove = lan9303_i2c_remove, .shutdown = lan9303_i2c_shutdown, .id_table = lan9303_i2c_id, diff --git a/drivers/net/dsa/microchip/ksz8795.c b/drivers/net/dsa/microchip/ksz8795.c index f56fca1b1a222a..84d502589f8e33 100644 --- a/drivers/net/dsa/microchip/ksz8795.c +++ b/drivers/net/dsa/microchip/ksz8795.c @@ -28,13 +28,13 @@ static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); + regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0); } static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } @@ -941,7 +941,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) { u8 learn[DSA_MAX_PORTS]; int first, index, cnt; - struct ksz_port *p; const u16 *regs; regs = dev->info->regs; @@ -955,9 +954,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) cnt = dev->info->port_cnt; } for (index = first; index < cnt; index++) { - p = &dev->ports[index]; - if (!p->on) - continue; ksz_pread8(dev, index, regs[P_STP_CTRL], &learn[index]); if (!(learn[index] & PORT_LEARN_DISABLE)) ksz_pwrite8(dev, index, regs[P_STP_CTRL], @@ -965,9 +961,6 @@ void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port) } ksz_cfg(dev, S_FLUSH_TABLE_CTRL, SW_FLUSH_DYN_MAC_TABLE, true); for (index = first; index < cnt; index++) { - p = &dev->ports[index]; - if (!p->on) - continue; if (!(learn[index] & PORT_LEARN_DISABLE)) ksz_pwrite8(dev, index, regs[P_STP_CTRL], learn[index]); } @@ -1338,25 +1331,14 @@ void ksz8_config_cpu_port(struct dsa_switch *ds) ksz_cfg(dev, regs[S_TAIL_TAG_CTRL], masks[SW_TAIL_TAG_ENABLE], true); - p = &dev->ports[dev->cpu_port]; - p->on = 1; - ksz8_port_setup(dev, dev->cpu_port, true); for (i = 0; i < dev->phy_port_cnt; i++) { - p = &dev->ports[i]; - ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED); - - /* Last port may be disabled. */ - if (i == dev->phy_port_cnt) - break; - p->on = 1; } for (i = 0; i < dev->phy_port_cnt; i++) { p = &dev->ports[i]; - if (!p->on) - continue; + if (!ksz_is_ksz88x3(dev)) { ksz_pread8(dev, i, regs[P_REMOTE_STATUS], &remote); if (remote & KSZ8_PORT_FIBER_MODE) @@ -1425,14 +1407,14 @@ int ksz8_setup(struct dsa_switch *ds) ksz_cfg(dev, S_LINK_AGING_CTRL, SW_LINK_AUTO_AGING, true); /* Enable aggressive back off algorithm in half duplex mode. */ - regmap_update_bits(dev->regmap[0], REG_SW_CTRL_1, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_1, SW_AGGR_BACKOFF, SW_AGGR_BACKOFF); /* * Make sure unicast VLAN boundary is set as default and * enable no excessive collision drop. */ - regmap_update_bits(dev->regmap[0], REG_SW_CTRL_2, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_CTRL_2, UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP, UNICAST_VLAN_BOUNDARY | NO_EXC_COLLISION_DROP); diff --git a/drivers/net/dsa/microchip/ksz8863_smi.c b/drivers/net/dsa/microchip/ksz8863_smi.c index 3698112138b78b..fd6e2e69a42ae7 100644 --- a/drivers/net/dsa/microchip/ksz8863_smi.c +++ b/drivers/net/dsa/microchip/ksz8863_smi.c @@ -104,6 +104,7 @@ static const struct regmap_config ksz8863_regmap_config[] = { .cache_type = REGCACHE_NONE, .lock = ksz_regmap_lock, .unlock = ksz_regmap_unlock, + .max_register = U8_MAX, }, { .name = "#16", @@ -113,6 +114,7 @@ static const struct regmap_config ksz8863_regmap_config[] = { .cache_type = REGCACHE_NONE, .lock = ksz_regmap_lock, .unlock = ksz_regmap_unlock, + .max_register = U8_MAX, }, { .name = "#32", @@ -122,11 +124,14 @@ static const struct regmap_config ksz8863_regmap_config[] = { .cache_type = REGCACHE_NONE, .lock = ksz_regmap_lock, .unlock = ksz_regmap_unlock, + .max_register = U8_MAX, } }; static int ksz8863_smi_probe(struct mdio_device *mdiodev) { + struct device *ddev = &mdiodev->dev; + const struct ksz_chip_data *chip; struct regmap_config rc; struct ksz_device *dev; int ret; @@ -136,9 +141,15 @@ static int ksz8863_smi_probe(struct mdio_device *mdiodev) if (!dev) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(ksz8863_regmap_config); i++) { + chip = device_get_match_data(ddev); + if (!chip) + return -EINVAL; + + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = ksz8863_regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; + rc.wr_table = chip->wr_table; + rc.rd_table = chip->rd_table; dev->regmap[i] = devm_regmap_init(&mdiodev->dev, ®map_smi[i], dev, &rc); diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index bf13d47c26cf70..fc5157a10af5ad 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -21,25 +21,25 @@ static void ksz_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); + regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0); } static void ksz_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bool set) { - regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } static void ksz9477_cfg32(struct ksz_device *dev, u32 addr, u32 bits, bool set) { - regmap_update_bits(dev->regmap[2], addr, bits, set ? bits : 0); + regmap_update_bits(ksz_regmap_32(dev), addr, bits, set ? bits : 0); } static void ksz9477_port_cfg32(struct ksz_device *dev, int port, int offset, u32 bits, bool set) { - regmap_update_bits(dev->regmap[2], PORT_CTRL_ADDR(port, offset), + regmap_update_bits(ksz_regmap_32(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } @@ -52,7 +52,7 @@ int ksz9477_change_mtu(struct ksz_device *dev, int port, int mtu) frame_size = mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - return regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, + return regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK, frame_size); } @@ -60,7 +60,7 @@ static int ksz9477_wait_vlan_ctrl_ready(struct ksz_device *dev) { unsigned int val; - return regmap_read_poll_timeout(dev->regmap[0], REG_SW_VLAN_CTRL, + return regmap_read_poll_timeout(ksz_regmap_8(dev), REG_SW_VLAN_CTRL, val, !(val & VLAN_START), 10, 1000); } @@ -147,7 +147,7 @@ static int ksz9477_wait_alu_ready(struct ksz_device *dev) { unsigned int val; - return regmap_read_poll_timeout(dev->regmap[2], REG_SW_ALU_CTRL__4, + return regmap_read_poll_timeout(ksz_regmap_32(dev), REG_SW_ALU_CTRL__4, val, !(val & ALU_START), 10, 1000); } @@ -155,7 +155,7 @@ static int ksz9477_wait_alu_sta_ready(struct ksz_device *dev) { unsigned int val; - return regmap_read_poll_timeout(dev->regmap[2], + return regmap_read_poll_timeout(ksz_regmap_32(dev), REG_SW_ALU_STAT_CTRL__4, val, !(val & ALU_STAT_START), 10, 1000); @@ -170,7 +170,7 @@ int ksz9477_reset_switch(struct ksz_device *dev) ksz_cfg(dev, REG_SW_OPERATION, SW_RESET, true); /* turn off SPI DO Edge select */ - regmap_update_bits(dev->regmap[0], REG_SW_GLOBAL_SERIAL_CTRL_0, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_GLOBAL_SERIAL_CTRL_0, SPI_AUTO_EDGE_DETECTION, 0); /* default configuration */ @@ -213,7 +213,7 @@ void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt) data |= (addr << MIB_COUNTER_INDEX_S); ksz_pwrite32(dev, port, REG_PORT_MIB_CTRL_STAT__4, data); - ret = regmap_read_poll_timeout(dev->regmap[2], + ret = regmap_read_poll_timeout(ksz_regmap_32(dev), PORT_CTRL_ADDR(port, REG_PORT_MIB_CTRL_STAT__4), val, !(val & MIB_COUNTER_READ), 10, 1000); /* failed to read MIB. get out of loop */ @@ -346,7 +346,7 @@ void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port) const u16 *regs = dev->info->regs; u8 data; - regmap_update_bits(dev->regmap[0], REG_SW_LUE_CTRL_2, + regmap_update_bits(ksz_regmap_8(dev), REG_SW_LUE_CTRL_2, SW_FLUSH_OPTION_M << SW_FLUSH_OPTION_S, SW_FLUSH_OPTION_DYN_MAC << SW_FLUSH_OPTION_S); @@ -889,62 +889,6 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port) return interface; } -static void ksz9477_port_mmd_write(struct ksz_device *dev, int port, - u8 dev_addr, u16 reg_addr, u16 val) -{ - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, - MMD_SETUP(PORT_MMD_OP_INDEX, dev_addr)); - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, reg_addr); - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_SETUP, - MMD_SETUP(PORT_MMD_OP_DATA_NO_INCR, dev_addr)); - ksz_pwrite16(dev, port, REG_PORT_PHY_MMD_INDEX_DATA, val); -} - -static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port) -{ - /* Apply PHY settings to address errata listed in - * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565 - * Silicon Errata and Data Sheet Clarification documents: - * - * Register settings are needed to improve PHY receive performance - */ - ksz9477_port_mmd_write(dev, port, 0x01, 0x6f, 0xdd0b); - ksz9477_port_mmd_write(dev, port, 0x01, 0x8f, 0x6032); - ksz9477_port_mmd_write(dev, port, 0x01, 0x9d, 0x248c); - ksz9477_port_mmd_write(dev, port, 0x01, 0x75, 0x0060); - ksz9477_port_mmd_write(dev, port, 0x01, 0xd3, 0x7777); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x06, 0x3008); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x08, 0x2001); - - /* Transmit waveform amplitude can be improved - * (1000BASE-T, 100BASE-TX, 10BASE-Te) - */ - ksz9477_port_mmd_write(dev, port, 0x1c, 0x04, 0x00d0); - - /* Energy Efficient Ethernet (EEE) feature select must - * be manually disabled (except on KSZ8565 which is 100Mbit) - */ - if (dev->info->gbit_capable[port]) - ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000); - - /* Register settings are required to meet data sheet - * supply current specifications - */ - ksz9477_port_mmd_write(dev, port, 0x1c, 0x13, 0x6eff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x14, 0xe6ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x15, 0x6eff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x16, 0xe6ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x17, 0x00ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x18, 0x43ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x19, 0xc3ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1a, 0x6fff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1b, 0x07ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1c, 0x0fff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1d, 0xe7ff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x1e, 0xefff); - ksz9477_port_mmd_write(dev, port, 0x1c, 0x20, 0xeeee); -} - void ksz9477_get_caps(struct ksz_device *dev, int port, struct phylink_config *config) { @@ -1029,20 +973,10 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port) /* enable 802.1p priority */ ksz_port_cfg(dev, port, P_PRIO_CTRL, PORT_802_1P_PRIO_ENABLE, true); - if (dev->info->internal_phy[port]) { - /* do not force flow control */ - ksz_port_cfg(dev, port, REG_PORT_CTRL_0, - PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, - false); - - if (dev->info->phy_errata_9477) - ksz9477_phy_errata_setup(dev, port); - } else { - /* force flow control */ - ksz_port_cfg(dev, port, REG_PORT_CTRL_0, - PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, - true); - } + /* force flow control for non-PHY ports only */ + ksz_port_cfg(dev, port, REG_PORT_CTRL_0, + PORT_FORCE_TX_FLOW_CTRL | PORT_FORCE_RX_FLOW_CTRL, + !dev->info->internal_phy[port]); if (cpu_port) member = dsa_user_ports(ds); @@ -1165,7 +1099,7 @@ int ksz9477_setup(struct dsa_switch *ds) ksz_cfg(dev, REG_SW_MAC_CTRL_1, SW_JUMBO_PACKET, true); /* Now we can configure default MTU value */ - ret = regmap_update_bits(dev->regmap[1], REG_SW_MTU__2, REG_SW_MTU_MASK, + ret = regmap_update_bits(ksz_regmap_16(dev), REG_SW_MTU__2, REG_SW_MTU_MASK, VLAN_ETH_FRAME_LEN + ETH_FCS_LEN); if (ret) return ret; diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c index 97a317263a2f44..2710afad4f3aff 100644 --- a/drivers/net/dsa/microchip/ksz9477_i2c.c +++ b/drivers/net/dsa/microchip/ksz9477_i2c.c @@ -24,7 +24,7 @@ static int ksz9477_i2c_probe(struct i2c_client *i2c) if (!dev) return -ENOMEM; - for (i = 0; i < ARRAY_SIZE(ksz9477_regmap_config); i++) { + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = ksz9477_regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; dev->regmap[i] = devm_regmap_init_i2c(i2c, &rc); @@ -119,7 +119,7 @@ static struct i2c_driver ksz9477_i2c_driver = { .name = "ksz9477-switch", .of_match_table = ksz9477_dt_ids, }, - .probe_new = ksz9477_i2c_probe, + .probe = ksz9477_i2c_probe, .remove = ksz9477_i2c_remove, .shutdown = ksz9477_i2c_shutdown, .id_table = ksz9477_i2c_id, diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index a4428be5f483ca..813b91a816bbee 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1075,6 +1075,45 @@ static const struct regmap_access_table ksz9896_register_set = { .n_yes_ranges = ARRAY_SIZE(ksz9896_valid_regs), }; +static const struct regmap_range ksz8873_valid_regs[] = { + regmap_reg_range(0x00, 0x01), + /* global control register */ + regmap_reg_range(0x02, 0x0f), + + /* port registers */ + regmap_reg_range(0x10, 0x1d), + regmap_reg_range(0x1e, 0x1f), + regmap_reg_range(0x20, 0x2d), + regmap_reg_range(0x2e, 0x2f), + regmap_reg_range(0x30, 0x39), + regmap_reg_range(0x3f, 0x3f), + + /* advanced control registers */ + regmap_reg_range(0x60, 0x6f), + regmap_reg_range(0x70, 0x75), + regmap_reg_range(0x76, 0x78), + regmap_reg_range(0x79, 0x7a), + regmap_reg_range(0x7b, 0x83), + regmap_reg_range(0x8e, 0x99), + regmap_reg_range(0x9a, 0xa5), + regmap_reg_range(0xa6, 0xa6), + regmap_reg_range(0xa7, 0xaa), + regmap_reg_range(0xab, 0xae), + regmap_reg_range(0xaf, 0xba), + regmap_reg_range(0xbb, 0xbc), + regmap_reg_range(0xbd, 0xbd), + regmap_reg_range(0xc0, 0xc0), + regmap_reg_range(0xc2, 0xc2), + regmap_reg_range(0xc3, 0xc3), + regmap_reg_range(0xc4, 0xc4), + regmap_reg_range(0xc6, 0xc6), +}; + +static const struct regmap_access_table ksz8873_register_set = { + .yes_ranges = ksz8873_valid_regs, + .n_yes_ranges = ARRAY_SIZE(ksz8873_valid_regs), +}; + const struct ksz_chip_data ksz_switch_chips[] = { [KSZ8563] = { .chip_id = KSZ8563_CHIP_ID, @@ -1214,6 +1253,8 @@ const struct ksz_chip_data ksz_switch_chips[] = { .supports_mii = {false, false, true}, .supports_rmii = {false, false, true}, .internal_phy = {true, true, false}, + .wr_table = &ksz8873_register_set, + .rd_table = &ksz8873_register_set, }, [KSZ9477] = { @@ -1229,7 +1270,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .tc_ets_supported = true, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1262,7 +1302,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .port_nirqs = 2, .num_tx_queues = 4, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1295,7 +1334,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .port_nirqs = 2, .num_tx_queues = 4, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -1382,7 +1420,6 @@ const struct ksz_chip_data ksz_switch_chips[] = { .tc_cbs_supported = true, .tc_ets_supported = true, .ops = &ksz9477_dev_ops, - .phy_errata_9477 = true, .mib_names = ksz9477_mib_names, .mib_cnt = ARRAY_SIZE(ksz9477_mib_names), .reg_mib_cnt = MIB_COUNTER_NUM, @@ -2095,7 +2132,7 @@ static int ksz_setup(struct dsa_switch *ds) } /* set broadcast storm protection 10% rate */ - regmap_update_bits(dev->regmap[1], regs[S_BROADCAST_CTRL], + regmap_update_bits(ksz_regmap_16(dev), regs[S_BROADCAST_CTRL], BROADCAST_STORM_RATE, (BROADCAST_STORM_VALUE * BROADCAST_STORM_PROT_RATE) / 100); @@ -2106,7 +2143,7 @@ static int ksz_setup(struct dsa_switch *ds) ds->num_tx_queues = dev->info->num_tx_queues; - regmap_update_bits(dev->regmap[0], regs[S_MULTICAST_CTRL], + regmap_update_bits(ksz_regmap_8(dev), regs[S_MULTICAST_CTRL], MULTICAST_STORM_DISABLE, MULTICAST_STORM_DISABLE); ksz_init_mib_timer(dev); @@ -2156,7 +2193,7 @@ static int ksz_setup(struct dsa_switch *ds) } /* start switch */ - regmap_update_bits(dev->regmap[0], regs[S_START_CTRL], + regmap_update_bits(ksz_regmap_8(dev), regs[S_START_CTRL], SW_START, SW_START); return 0; diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index 8abecaf6089ef4..a66b56857ec6aa 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -22,6 +22,13 @@ struct ksz_device; struct ksz_port; +enum ksz_regmap_width { + KSZ_REGMAP_8, + KSZ_REGMAP_16, + KSZ_REGMAP_32, + __KSZ_NUM_REGMAPS, +}; + struct vlan_table { u32 table[3]; }; @@ -53,7 +60,6 @@ struct ksz_chip_data { bool tc_cbs_supported; bool tc_ets_supported; const struct ksz_dev_ops *ops; - bool phy_errata_9477; bool ksz87xx_eee_link_erratum; const struct ksz_mib_names *mib_names; int mib_cnt; @@ -101,7 +107,6 @@ struct ksz_port { int stp_state; struct phy_device phydev; - u32 on:1; /* port is not disabled by hardware */ u32 fiber:1; /* port is fiber */ u32 force:1; u32 read:1; /* read MIB counters in background */ @@ -137,7 +142,7 @@ struct ksz_device { const struct ksz_dev_ops *dev_ops; struct device *dev; - struct regmap *regmap[3]; + struct regmap *regmap[__KSZ_NUM_REGMAPS]; void *priv; int irq; @@ -377,11 +382,25 @@ phy_interface_t ksz_get_xmii(struct ksz_device *dev, int port, bool gbit); extern const struct ksz_chip_data ksz_switch_chips[]; /* Common register access functions */ +static inline struct regmap *ksz_regmap_8(struct ksz_device *dev) +{ + return dev->regmap[KSZ_REGMAP_8]; +} + +static inline struct regmap *ksz_regmap_16(struct ksz_device *dev) +{ + return dev->regmap[KSZ_REGMAP_16]; +} + +static inline struct regmap *ksz_regmap_32(struct ksz_device *dev) +{ + return dev->regmap[KSZ_REGMAP_32]; +} static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val) { unsigned int value; - int ret = regmap_read(dev->regmap[0], reg, &value); + int ret = regmap_read(ksz_regmap_8(dev), reg, &value); if (ret) dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg, @@ -394,7 +413,7 @@ static inline int ksz_read8(struct ksz_device *dev, u32 reg, u8 *val) static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val) { unsigned int value; - int ret = regmap_read(dev->regmap[1], reg, &value); + int ret = regmap_read(ksz_regmap_16(dev), reg, &value); if (ret) dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg, @@ -407,7 +426,7 @@ static inline int ksz_read16(struct ksz_device *dev, u32 reg, u16 *val) static inline int ksz_read32(struct ksz_device *dev, u32 reg, u32 *val) { unsigned int value; - int ret = regmap_read(dev->regmap[2], reg, &value); + int ret = regmap_read(ksz_regmap_32(dev), reg, &value); if (ret) dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg, @@ -422,7 +441,7 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val) u32 value[2]; int ret; - ret = regmap_bulk_read(dev->regmap[2], reg, value, 2); + ret = regmap_bulk_read(ksz_regmap_32(dev), reg, value, 2); if (ret) dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -436,7 +455,7 @@ static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value) { int ret; - ret = regmap_write(dev->regmap[0], reg, value); + ret = regmap_write(ksz_regmap_8(dev), reg, value); if (ret) dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -448,7 +467,7 @@ static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value) { int ret; - ret = regmap_write(dev->regmap[1], reg, value); + ret = regmap_write(ksz_regmap_16(dev), reg, value); if (ret) dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -460,7 +479,7 @@ static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value) { int ret; - ret = regmap_write(dev->regmap[2], reg, value); + ret = regmap_write(ksz_regmap_32(dev), reg, value); if (ret) dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg, ERR_PTR(ret)); @@ -473,7 +492,7 @@ static inline int ksz_rmw16(struct ksz_device *dev, u32 reg, u16 mask, { int ret; - ret = regmap_update_bits(dev->regmap[1], reg, mask, value); + ret = regmap_update_bits(ksz_regmap_16(dev), reg, mask, value); if (ret) dev_err(dev->dev, "can't rmw 16bit reg 0x%x: %pe\n", reg, ERR_PTR(ret)); @@ -486,7 +505,7 @@ static inline int ksz_rmw32(struct ksz_device *dev, u32 reg, u32 mask, { int ret; - ret = regmap_update_bits(dev->regmap[2], reg, mask, value); + ret = regmap_update_bits(ksz_regmap_32(dev), reg, mask, value); if (ret) dev_err(dev->dev, "can't rmw 32bit reg 0x%x: %pe\n", reg, ERR_PTR(ret)); @@ -503,12 +522,19 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value) val[0] = swab32(value & 0xffffffffULL); val[1] = swab32(value >> 32ULL); - return regmap_bulk_write(dev->regmap[2], reg, val, 2); + return regmap_bulk_write(ksz_regmap_32(dev), reg, val, 2); } static inline int ksz_rmw8(struct ksz_device *dev, int offset, u8 mask, u8 val) { - return regmap_update_bits(dev->regmap[0], offset, mask, val); + int ret; + + ret = regmap_update_bits(ksz_regmap_8(dev), offset, mask, val); + if (ret) + dev_err(dev->dev, "can't rmw 8bit reg 0x%x: %pe\n", offset, + ERR_PTR(ret)); + + return ret; } static inline int ksz_pread8(struct ksz_device *dev, int port, int offset, @@ -549,12 +575,20 @@ static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset, data); } -static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset, - u8 mask, u8 val) +static inline int ksz_prmw8(struct ksz_device *dev, int port, int offset, + u8 mask, u8 val) { - regmap_update_bits(dev->regmap[0], - dev->dev_ops->get_port_addr(port, offset), - mask, val); + int ret; + + ret = regmap_update_bits(ksz_regmap_8(dev), + dev->dev_ops->get_port_addr(port, offset), + mask, val); + if (ret) + dev_err(dev->dev, "can't rmw 8bit reg 0x%x: %pe\n", + dev->dev_ops->get_port_addr(port, offset), + ERR_PTR(ret)); + + return ret; } static inline void ksz_regmap_lock(void *__mtx) @@ -709,9 +743,9 @@ static inline int is_lan937x(struct ksz_device *dev) #define KSZ_REGMAP_TABLE(ksz, swp, regbits, regpad, regalign) \ static const struct regmap_config ksz##_regmap_config[] = { \ - KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \ - KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \ - KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \ + [KSZ_REGMAP_8] = KSZ_REGMAP_ENTRY(8, swp, (regbits), (regpad), (regalign)), \ + [KSZ_REGMAP_16] = KSZ_REGMAP_ENTRY(16, swp, (regbits), (regpad), (regalign)), \ + [KSZ_REGMAP_32] = KSZ_REGMAP_ENTRY(32, swp, (regbits), (regpad), (regalign)), \ } #endif diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c index 96c52e8fb51b6c..279338451621b1 100644 --- a/drivers/net/dsa/microchip/ksz_spi.c +++ b/drivers/net/dsa/microchip/ksz_spi.c @@ -63,7 +63,7 @@ static int ksz_spi_probe(struct spi_device *spi) else regmap_config = ksz9477_regmap_config; - for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) { + for (i = 0; i < __KSZ_NUM_REGMAPS; i++) { rc = regmap_config[i]; rc.lock_arg = &dev->regmap_mutex; rc.wr_table = chip->wr_table; diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c index 399a3905e6cad1..b479a628b1ae56 100644 --- a/drivers/net/dsa/microchip/lan937x_main.c +++ b/drivers/net/dsa/microchip/lan937x_main.c @@ -20,13 +20,13 @@ static int lan937x_cfg(struct ksz_device *dev, u32 addr, u8 bits, bool set) { - return regmap_update_bits(dev->regmap[0], addr, bits, set ? bits : 0); + return regmap_update_bits(ksz_regmap_8(dev), addr, bits, set ? bits : 0); } static int lan937x_port_cfg(struct ksz_device *dev, int port, int offset, u8 bits, bool set) { - return regmap_update_bits(dev->regmap[0], PORT_CTRL_ADDR(port, offset), + return regmap_update_bits(ksz_regmap_8(dev), PORT_CTRL_ADDR(port, offset), bits, set ? bits : 0); } @@ -86,7 +86,7 @@ static int lan937x_internal_phy_write(struct ksz_device *dev, int addr, int reg, if (ret < 0) return ret; - ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2, + ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2, value, !(value & VPHY_IND_BUSY), 10, 1000); if (ret < 0) { @@ -116,7 +116,7 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg, if (ret < 0) return ret; - ret = regmap_read_poll_timeout(dev->regmap[1], REG_VPHY_IND_CTRL__2, + ret = regmap_read_poll_timeout(ksz_regmap_16(dev), REG_VPHY_IND_CTRL__2, value, !(value & VPHY_IND_BUSY), 10, 1000); if (ret < 0) { diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 64a2f2f83735d0..8b51756bd80544 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -463,11 +463,11 @@ static int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, return err; } -static int mv88e6xxx_phy_is_internal(struct dsa_switch *ds, int port) +static int mv88e6xxx_phy_is_internal(struct mv88e6xxx_chip *chip, int port) { - struct mv88e6xxx_chip *chip = ds->priv; - - return port < chip->info->num_internal_phys; + return port >= chip->info->internal_phys_offset && + port < chip->info->num_internal_phys + + chip->info->internal_phys_offset; } static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) @@ -479,7 +479,7 @@ static int mv88e6xxx_port_ppu_updates(struct mv88e6xxx_chip *chip, int port) * report whether the port is internal. */ if (chip->info->family == MV88E6XXX_FAMILY_6250) - return port < chip->info->num_internal_phys; + return mv88e6xxx_phy_is_internal(chip, port); err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_STS, ®); if (err) { @@ -584,7 +584,7 @@ static void mv88e6095_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100; - if (mv88e6xxx_phy_is_internal(chip->ds, port)) { + if (mv88e6xxx_phy_is_internal(chip, port)) { __set_bit(PHY_INTERFACE_MODE_MII, config->supported_interfaces); } else { if (cmode < ARRAY_SIZE(mv88e6185_phy_interface_modes) && @@ -790,6 +790,8 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, unsigned long *supported = config->supported_interfaces; bool is_6191x = chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6191X; + bool is_6361 = + chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361; mv88e6xxx_translate_cmode(chip->ports[port].cmode, supported); @@ -804,13 +806,16 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, /* 6191X supports >1G modes only on port 10 */ if (!is_6191x || port == 10) { __set_bit(PHY_INTERFACE_MODE_2500BASEX, supported); - __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); - __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); - /* FIXME: USXGMII is not supported yet */ - /* __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); */ - - config->mac_capabilities |= MAC_2500FD | MAC_5000FD | - MAC_10000FD; + config->mac_capabilities |= MAC_2500FD; + + /* 6361 only supports up to 2500BaseX */ + if (!is_6361) { + __set_bit(PHY_INTERFACE_MODE_5GBASER, supported); + __set_bit(PHY_INTERFACE_MODE_10GBASER, supported); + __set_bit(PHY_INTERFACE_MODE_USXGMII, supported); + config->mac_capabilities |= MAC_5000FD | + MAC_10000FD; + } } } @@ -832,7 +837,7 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, chip->info->ops->phylink_get_caps(chip, port, config); mv88e6xxx_reg_unlock(chip); - if (mv88e6xxx_phy_is_internal(ds, port)) { + if (mv88e6xxx_phy_is_internal(chip, port)) { __set_bit(PHY_INTERFACE_MODE_INTERNAL, config->supported_interfaces); /* Internal ports with no phy-mode need GMII for PHYLIB */ @@ -841,29 +846,38 @@ static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port, } } +static int mv88e6xxx_mac_prepare(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err = 0; + + /* In inband mode, the link may come up at any time while the link + * is not forced down. Force the link down while we reconfigure the + * interface mode. + */ + if (mode == MLO_AN_INBAND && + chip->ports[port].interface != interface && + chip->info->ops->port_set_link) { + mv88e6xxx_reg_lock(chip); + err = chip->info->ops->port_set_link(chip, port, + LINK_FORCED_DOWN); + mv88e6xxx_reg_unlock(chip); + } + + return err; +} + static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) { struct mv88e6xxx_chip *chip = ds->priv; - struct mv88e6xxx_port *p; int err = 0; - p = &chip->ports[port]; - mv88e6xxx_reg_lock(chip); - if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(ds, port)) { - /* In inband mode, the link may come up at any time while the - * link is not forced down. Force the link down while we - * reconfigure the interface mode. - */ - if (mode == MLO_AN_INBAND && - p->interface != state->interface && - chip->info->ops->port_set_link) - chip->info->ops->port_set_link(chip, port, - LINK_FORCED_DOWN); - + if (mode != MLO_AN_PHY || !mv88e6xxx_phy_is_internal(chip, port)) { err = mv88e6xxx_port_config_interface(chip, port, state->interface); if (err && err != -EOPNOTSUPP) @@ -880,24 +894,38 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, err = 0; } +err_unlock: + mv88e6xxx_reg_unlock(chip); + + if (err && err != -EOPNOTSUPP) + dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port); +} + +static int mv88e6xxx_mac_finish(struct dsa_switch *ds, int port, + unsigned int mode, phy_interface_t interface) +{ + struct mv88e6xxx_chip *chip = ds->priv; + int err = 0; + /* Undo the forced down state above after completing configuration * irrespective of its state on entry, which allows the link to come * up in the in-band case where there is no separate SERDES. Also * ensure that the link can come up if the PPU is in use and we are * in PHY mode (we treat the PPU as an effective in-band mechanism.) */ + mv88e6xxx_reg_lock(chip); + if (chip->info->ops->port_set_link && - ((mode == MLO_AN_INBAND && p->interface != state->interface) || + ((mode == MLO_AN_INBAND && + chip->ports[port].interface != interface) || (mode == MLO_AN_PHY && mv88e6xxx_port_ppu_updates(chip, port)))) - chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); - - p->interface = state->interface; + err = chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); -err_unlock: mv88e6xxx_reg_unlock(chip); - if (err && err != -EOPNOTSUPP) - dev_err(ds->dev, "p%d: failed to configure MAC/PCS\n", port); + chip->ports[port].interface = interface; + + return err; } static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, @@ -3311,7 +3339,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) caps = pl_config.mac_capabilities; if (chip->info->ops->port_max_speed_mode) - mode = chip->info->ops->port_max_speed_mode(port); + mode = chip->info->ops->port_max_speed_mode(chip, port); else mode = PHY_INTERFACE_MODE_NA; @@ -5043,6 +5071,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = { .avb_ops = &mv88e6352_avb_ops, .ptp_ops = &mv88e6250_ptp_ops, .phylink_get_caps = mv88e6250_phylink_get_caps, + .set_max_frame_size = mv88e6185_g1_set_max_frame_size, }; static const struct mv88e6xxx_ops mv88e6290_ops = { @@ -5642,6 +5671,46 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = { }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { + [MV88E6020] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6020, + .family = MV88E6XXX_FAMILY_6250, + .name = "Marvell 88E6020", + .num_databases = 64, + .num_ports = 4, + .num_internal_phys = 2, + .max_vid = 4095, + .port_base_addr = 0x8, + .phy_base_addr = 0x0, + .global1_addr = 0xf, + .global2_addr = 0x7, + .age_time_coeff = 15000, + .g1_irqs = 9, + .g2_irqs = 5, + .atu_move_port_mask = 0xf, + .dual_chip = true, + .ops = &mv88e6250_ops, + }, + + [MV88E6071] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6071, + .family = MV88E6XXX_FAMILY_6250, + .name = "Marvell 88E6071", + .num_databases = 64, + .num_ports = 7, + .num_internal_phys = 5, + .max_vid = 4095, + .port_base_addr = 0x08, + .phy_base_addr = 0x00, + .global1_addr = 0x0f, + .global2_addr = 0x07, + .age_time_coeff = 15000, + .g1_irqs = 9, + .g2_irqs = 5, + .atu_move_port_mask = 0xf, + .dual_chip = true, + .ops = &mv88e6250_ops, + }, + [MV88E6085] = { .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6085, .family = MV88E6XXX_FAMILY_6097, @@ -6024,7 +6093,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6191X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 9, + .num_internal_phys = 8, + .internal_phys_offset = 1, .max_vid = 8191, .max_sid = 63, .port_base_addr = 0x0, @@ -6047,7 +6117,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6193X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 9, + .num_internal_phys = 8, + .internal_phys_offset = 1, .max_vid = 8191, .max_sid = 63, .port_base_addr = 0x0, @@ -6309,6 +6380,32 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .ptp_support = true, .ops = &mv88e6352_ops, }, + [MV88E6361] = { + .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6361, + .family = MV88E6XXX_FAMILY_6393, + .name = "Marvell 88E6361", + .num_databases = 4096, + .num_macs = 16384, + .num_ports = 11, + /* Ports 1, 2 and 8 are not routed */ + .invalid_port_mask = BIT(1) | BIT(2) | BIT(8), + .num_internal_phys = 5, + .internal_phys_offset = 3, + .max_vid = 4095, + .max_sid = 63, + .port_base_addr = 0x0, + .phy_base_addr = 0x0, + .global1_addr = 0x1b, + .global2_addr = 0x1c, + .age_time_coeff = 3750, + .g1_irqs = 10, + .g2_irqs = 14, + .atu_move_port_mask = 0x1f, + .pvt = true, + .multi_chip = true, + .ptp_support = true, + .ops = &mv88e6393x_ops, + }, [MV88E6390] = { .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, .family = MV88E6XXX_FAMILY_6390, @@ -6366,7 +6463,8 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { .name = "Marvell 88E6393X", .num_databases = 4096, .num_ports = 11, /* 10 + Z80 */ - .num_internal_phys = 9, + .num_internal_phys = 8, + .internal_phys_offset = 1, .max_vid = 8191, .max_sid = 63, .port_base_addr = 0x0, @@ -7002,7 +7100,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = { .port_teardown = mv88e6xxx_port_teardown, .phylink_get_caps = mv88e6xxx_get_caps, .phylink_mac_link_state = mv88e6xxx_serdes_pcs_get_state, + .phylink_mac_prepare = mv88e6xxx_mac_prepare, .phylink_mac_config = mv88e6xxx_mac_config, + .phylink_mac_finish = mv88e6xxx_mac_finish, .phylink_mac_an_restart = mv88e6xxx_serdes_pcs_an_restart, .phylink_mac_link_down = mv88e6xxx_mac_link_down, .phylink_mac_link_up = mv88e6xxx_mac_link_up, @@ -7170,7 +7270,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) goto out; } if (chip->reset) - usleep_range(1000, 2000); + usleep_range(10000, 20000); /* Detect if the device is configured in single chip addressing mode, * otherwise continue with address specific smi init/detection. diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index da6e1339f809fc..0ad34b2d89137f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -54,6 +54,8 @@ enum mv88e6xxx_frame_mode { /* List of supported models */ enum mv88e6xxx_model { + MV88E6020, + MV88E6071, MV88E6085, MV88E6095, MV88E6097, @@ -82,6 +84,7 @@ enum mv88e6xxx_model { MV88E6350, MV88E6351, MV88E6352, + MV88E6361, MV88E6390, MV88E6390X, MV88E6393X, @@ -94,13 +97,13 @@ enum mv88e6xxx_family { MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ - MV88E6XXX_FAMILY_6250, /* 6220 6250 */ + MV88E6XXX_FAMILY_6250, /* 6220 6250 6020 6071 */ MV88E6XXX_FAMILY_6320, /* 6320 6321 */ MV88E6XXX_FAMILY_6341, /* 6141 6341 */ MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ - MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6393X */ + MV88E6XXX_FAMILY_6393, /* 6191X 6193X 6361 6393X */ }; /** @@ -167,6 +170,11 @@ struct mv88e6xxx_info { /* Supports PTP */ bool ptp_support; + + /* Internal PHY start index. 0 means that internal PHYs range starts at + * port 0, 1 means internal PHYs range starts at port 1, etc + */ + unsigned int internal_phys_offset; }; struct mv88e6xxx_atu_entry { @@ -513,7 +521,8 @@ struct mv88e6xxx_ops { int speed, int duplex); /* What interface mode should be used for maximum speed? */ - phy_interface_t (*port_max_speed_mode)(int port); + phy_interface_t (*port_max_speed_mode)(struct mv88e6xxx_chip *chip, + int port); int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c index 61589689307682..937a01f2ba75eb 100644 --- a/drivers/net/dsa/mv88e6xxx/global2.c +++ b/drivers/net/dsa/mv88e6xxx/global2.c @@ -1196,9 +1196,12 @@ int mv88e6xxx_g2_irq_setup(struct mv88e6xxx_chip *chip) int mv88e6xxx_g2_irq_mdio_setup(struct mv88e6xxx_chip *chip, struct mii_bus *bus) { + int phy_start = chip->info->internal_phys_offset; + int phy_end = chip->info->internal_phys_offset + + chip->info->num_internal_phys; int phy, irq; - for (phy = 0; phy < chip->info->num_internal_phys; phy++) { + for (phy = phy_start; phy < phy_end; phy++) { irq = irq_find_mapping(chip->g2_irq.domain, phy); if (irq < 0) return irq; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index f79cf716c541f0..dd66ec902d4cb5 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -342,7 +342,8 @@ int mv88e6341_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6341_port_max_speed_mode(int port) +phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { if (port == 5) return PHY_INTERFACE_MODE_2500BASEX; @@ -381,7 +382,8 @@ int mv88e6390_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6390_port_max_speed_mode(int port) +phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { if (port == 9 || port == 10) return PHY_INTERFACE_MODE_2500BASEX; @@ -403,7 +405,8 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, duplex); } -phy_interface_t mv88e6390x_port_max_speed_mode(int port) +phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { if (port == 9 || port == 10) return PHY_INTERFACE_MODE_XAUI; @@ -421,6 +424,10 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, u16 reg, ctrl; int err; + if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361 && + speed > 2500) + return -EOPNOTSUPP; + if (speed == 200 && port != 0) return -EOPNOTSUPP; @@ -500,12 +507,17 @@ int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, return 0; } -phy_interface_t mv88e6393x_port_max_speed_mode(int port) +phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port) { - if (port == 0 || port == 9 || port == 10) - return PHY_INTERFACE_MODE_10GBASER; - return PHY_INTERFACE_MODE_NA; + if (port != 0 && port != 9 && port != 10) + return PHY_INTERFACE_MODE_NA; + + if (chip->info->prod_num == MV88E6XXX_PORT_SWITCH_ID_PROD_6361) + return PHY_INTERFACE_MODE_2500BASEX; + + return PHY_INTERFACE_MODE_10GBASER; } static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, @@ -554,6 +566,9 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port, case PHY_INTERFACE_MODE_10GBASER: cmode = MV88E6393X_PORT_STS_CMODE_10GBASER; break; + case PHY_INTERFACE_MODE_USXGMII: + cmode = MV88E6393X_PORT_STS_CMODE_USXGMII; + break; default: cmode = 0; } diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index d19b6303b91f0a..86deeb347cbc1d 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -111,6 +111,8 @@ /* Offset 0x03: Switch Identifier Register */ #define MV88E6XXX_PORT_SWITCH_ID 0x03 #define MV88E6XXX_PORT_SWITCH_ID_PROD_MASK 0xfff0 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6020 0x0200 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6071 0x0710 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6085 0x04a0 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6095 0x0950 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6097 0x0990 @@ -133,6 +135,7 @@ #define MV88E6XXX_PORT_SWITCH_ID_PROD_6220 0x2200 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500 +#define MV88E6XXX_PORT_SWITCH_ID_PROD_6361 0x2610 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 @@ -359,10 +362,14 @@ int mv88e6390x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, int mv88e6393x_port_set_speed_duplex(struct mv88e6xxx_chip *chip, int port, int speed, int duplex); -phy_interface_t mv88e6341_port_max_speed_mode(int port); -phy_interface_t mv88e6390_port_max_speed_mode(int port); -phy_interface_t mv88e6390x_port_max_speed_mode(int port); -phy_interface_t mv88e6393x_port_max_speed_mode(int port); +phy_interface_t mv88e6341_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); +phy_interface_t mv88e6390_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); +phy_interface_t mv88e6390x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); +phy_interface_t mv88e6393x_port_max_speed_mode(struct mv88e6xxx_chip *chip, + int port); int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); diff --git a/drivers/net/dsa/mv88e6xxx/serdes.c b/drivers/net/dsa/mv88e6xxx/serdes.c index 72faec8f44dcae..80167d53212f8b 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.c +++ b/drivers/net/dsa/mv88e6xxx/serdes.c @@ -683,7 +683,8 @@ int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port) cmode == MV88E6XXX_PORT_STS_CMODE_SGMII || cmode == MV88E6XXX_PORT_STS_CMODE_2500BASEX || cmode == MV88E6393X_PORT_STS_CMODE_5GBASER || - cmode == MV88E6393X_PORT_STS_CMODE_10GBASER) + cmode == MV88E6393X_PORT_STS_CMODE_10GBASER || + cmode == MV88E6393X_PORT_STS_CMODE_USXGMII) lane = port; return lane; @@ -984,7 +985,42 @@ static int mv88e6393x_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, state->speed = SPEED_10000; state->duplex = DUPLEX_FULL; } + return 0; +} + +/* USXGMII registers for Marvell switch 88e639x are undocumented and this function is based + * on some educated guesses. It appears that there are no status bits related to + * autonegotiation complete or flow control. + */ +static int mv88e639x_serdes_pcs_get_state_usxgmii(struct mv88e6xxx_chip *chip, + int port, int lane, + struct phylink_link_state *state) +{ + u16 status, lp_status; + int err; + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_USXGMII_PHY_STATUS, &status); + if (err) { + dev_err(chip->dev, "can't read Serdes USXGMII PHY status: %d\n", err); + return err; + } + dev_dbg(chip->dev, "USXGMII PHY status: 0x%x\n", status); + + state->link = !!(status & MDIO_USXGMII_LINK); + state->an_complete = state->link; + + if (state->link) { + err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, + MV88E6390_USXGMII_LP_STATUS, &lp_status); + if (err) { + dev_err(chip->dev, "can't read Serdes USXGMII LP status: %d\n", err); + return err; + } + dev_dbg(chip->dev, "USXGMII LP status: 0x%x\n", lp_status); + /* lp_status appears to include the "link" bit as per USXGMII spec. */ + phylink_decode_usxgmii_word(state, lp_status); + } return 0; } @@ -1020,6 +1056,9 @@ int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, case PHY_INTERFACE_MODE_10GBASER: return mv88e6393x_serdes_pcs_get_state_10g(chip, port, lane, state); + case PHY_INTERFACE_MODE_USXGMII: + return mv88e639x_serdes_pcs_get_state_usxgmii(chip, port, lane, + state); default: return -EOPNOTSUPP; @@ -1173,6 +1212,7 @@ int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, return mv88e6390_serdes_irq_enable_sgmii(chip, lane, enable); case MV88E6393X_PORT_STS_CMODE_5GBASER: case MV88E6393X_PORT_STS_CMODE_10GBASER: + case MV88E6393X_PORT_STS_CMODE_USXGMII: return mv88e6393x_serdes_irq_enable_10g(chip, lane, enable); } @@ -1213,6 +1253,7 @@ irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, break; case MV88E6393X_PORT_STS_CMODE_5GBASER: case MV88E6393X_PORT_STS_CMODE_10GBASER: + case MV88E6393X_PORT_STS_CMODE_USXGMII: err = mv88e6393x_serdes_irq_status_10g(chip, lane, &status); if (err) return err; @@ -1477,7 +1518,8 @@ static int mv88e6393x_serdes_erratum_5_2(struct mv88e6xxx_chip *chip, int lane, * to SERDES operating in 10G mode. These registers only apply to 10G * operation and have no effect on other speeds. */ - if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER) + if (cmode != MV88E6393X_PORT_STS_CMODE_10GBASER && + cmode != MV88E6393X_PORT_STS_CMODE_USXGMII) return 0; for (i = 0; i < ARRAY_SIZE(fixes); ++i) { @@ -1582,6 +1624,7 @@ int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane, break; case MV88E6393X_PORT_STS_CMODE_5GBASER: case MV88E6393X_PORT_STS_CMODE_10GBASER: + case MV88E6393X_PORT_STS_CMODE_USXGMII: err = mv88e6390_serdes_power_10g(chip, lane, on); break; default: diff --git a/drivers/net/dsa/mv88e6xxx/serdes.h b/drivers/net/dsa/mv88e6xxx/serdes.h index 29bb4e91e2f6be..e245687ddb1d0a 100644 --- a/drivers/net/dsa/mv88e6xxx/serdes.h +++ b/drivers/net/dsa/mv88e6xxx/serdes.h @@ -48,6 +48,10 @@ #define MV88E6393X_10G_INT_LINK_CHANGE BIT(2) #define MV88E6393X_10G_INT_STATUS 0x9001 +/* USXGMII */ +#define MV88E6390_USXGMII_LP_STATUS 0xf0a2 +#define MV88E6390_USXGMII_PHY_STATUS 0xf0a6 + /* 1000BASE-X and SGMII */ #define MV88E6390_SGMII_BMCR (0x2000 + MII_BMCR) #define MV88E6390_SGMII_BMSR (0x2000 + MII_BMSR) diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c index cfb3faeaa5bfa9..903532ea9fa42e 100644 --- a/drivers/net/dsa/ocelot/felix_vsc9959.c +++ b/drivers/net/dsa/ocelot/felix_vsc9959.c @@ -1021,7 +1021,6 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) for (port = 0; port < felix->info->num_ports; port++) { struct ocelot_port *ocelot_port = ocelot->ports[port]; struct phylink_pcs *phylink_pcs; - struct mdio_device *mdio_device; if (dsa_is_unused_port(felix->ds, port)) continue; @@ -1029,16 +1028,10 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot) if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL) continue; - mdio_device = mdio_device_create(felix->imdio, port); - if (IS_ERR(mdio_device)) + phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, port); + if (IS_ERR(phylink_pcs)) continue; - phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { - mdio_device_free(mdio_device); - continue; - } - felix->pcs[port] = phylink_pcs; dev_info(dev, "Found PCS at internal MDIO address %d\n", port); @@ -1054,14 +1047,9 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot) for (port = 0; port < ocelot->num_phys_ports; port++) { struct phylink_pcs *phylink_pcs = felix->pcs[port]; - struct mdio_device *mdio_device; - if (!phylink_pcs) - continue; - - mdio_device = lynx_get_mdio_device(phylink_pcs); - mdio_device_free(mdio_device); - lynx_pcs_destroy(phylink_pcs); + if (phylink_pcs) + lynx_pcs_destroy(phylink_pcs); } mdiobus_unregister(felix->imdio); mdiobus_free(felix->imdio); @@ -1423,7 +1411,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, mutex_lock(&ocelot->tas_lock); - if (!taprio->enable) { + if (taprio->cmd == TAPRIO_CMD_DESTROY) { ocelot_port_mqprio(ocelot, port, &taprio->mqprio); ocelot_rmw_rix(ocelot, 0, QSYS_TAG_CONFIG_ENABLE, QSYS_TAG_CONFIG, port); @@ -1435,6 +1423,9 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port, mutex_unlock(&ocelot->tas_lock); return 0; + } else if (taprio->cmd != TAPRIO_CMD_REPLACE) { + ret = -EOPNOTSUPP; + goto err_unlock; } ret = ocelot_port_mqprio(ocelot, port, &taprio->mqprio); diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index 96d4972a62f0f8..15003b2af264d1 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -912,7 +912,6 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) for (port = 0; port < felix->info->num_ports; port++) { struct ocelot_port *ocelot_port = ocelot->ports[port]; struct phylink_pcs *phylink_pcs; - struct mdio_device *mdio_device; int addr = port + 4; if (dsa_is_unused_port(felix->ds, port)) @@ -921,16 +920,10 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot) if (ocelot_port->phy_mode == PHY_INTERFACE_MODE_INTERNAL) continue; - mdio_device = mdio_device_create(felix->imdio, addr); - if (IS_ERR(mdio_device)) + phylink_pcs = lynx_pcs_create_mdiodev(felix->imdio, addr); + if (IS_ERR(phylink_pcs)) continue; - phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { - mdio_device_free(mdio_device); - continue; - } - felix->pcs[port] = phylink_pcs; dev_info(dev, "Found PCS at internal MDIO address %d\n", addr); @@ -946,14 +939,9 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot) for (port = 0; port < ocelot->num_phys_ports; port++) { struct phylink_pcs *phylink_pcs = felix->pcs[port]; - struct mdio_device *mdio_device; - - if (!phylink_pcs) - continue; - mdio_device = lynx_get_mdio_device(phylink_pcs); - mdio_device_free(mdio_device); - lynx_pcs_destroy(phylink_pcs); + if (phylink_pcs) + lynx_pcs_destroy(phylink_pcs); } /* mdiobus_unregister and mdiobus_free handled by devres */ diff --git a/drivers/net/dsa/qca/Kconfig b/drivers/net/dsa/qca/Kconfig index 4347b42c50fd24..de9da469908bcf 100644 --- a/drivers/net/dsa/qca/Kconfig +++ b/drivers/net/dsa/qca/Kconfig @@ -20,6 +20,7 @@ config NET_DSA_QCA8K_LEDS_SUPPORT bool "Qualcomm Atheros QCA8K Ethernet switch family LEDs support" depends on NET_DSA_QCA8K depends on LEDS_CLASS=y || LEDS_CLASS=NET_DSA_QCA8K + depends on LEDS_TRIGGERS help This enabled support for LEDs present on the Qualcomm Atheros QCA8K Ethernet switch chips. diff --git a/drivers/net/dsa/qca/ar9331.c b/drivers/net/dsa/qca/ar9331.c index e7b98b864fa169..b2bf78ac485ebd 100644 --- a/drivers/net/dsa/qca/ar9331.c +++ b/drivers/net/dsa/qca/ar9331.c @@ -391,7 +391,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv) static int ar9331_sw_setup_port(struct dsa_switch *ds, int port) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; u32 port_mask, port_ctrl, val; int ret; @@ -439,7 +439,7 @@ static int ar9331_sw_setup_port(struct dsa_switch *ds, int port) static int ar9331_sw_setup(struct dsa_switch *ds) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; int ret, i; @@ -484,7 +484,7 @@ static int ar9331_sw_setup(struct dsa_switch *ds) static void ar9331_sw_port_disable(struct dsa_switch *ds, int port) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; int ret; @@ -527,7 +527,7 @@ static void ar9331_sw_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct regmap *regmap = priv->regmap; int ret; @@ -542,7 +542,7 @@ static void ar9331_sw_phylink_mac_link_down(struct dsa_switch *ds, int port, unsigned int mode, phy_interface_t interface) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; struct regmap *regmap = priv->regmap; int ret; @@ -562,7 +562,7 @@ static void ar9331_sw_phylink_mac_link_up(struct dsa_switch *ds, int port, int speed, int duplex, bool tx_pause, bool rx_pause) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; struct regmap *regmap = priv->regmap; u32 val; @@ -665,7 +665,7 @@ static void ar9331_do_stats_poll(struct work_struct *work) static void ar9331_get_stats64(struct dsa_switch *ds, int port, struct rtnl_link_stats64 *s) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; spin_lock(&p->stats_lock); @@ -676,7 +676,7 @@ static void ar9331_get_stats64(struct dsa_switch *ds, int port, static void ar9331_get_pause_stats(struct dsa_switch *ds, int port, struct ethtool_pause_stats *pause_stats) { - struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv; + struct ar9331_sw_priv *priv = ds->priv; struct ar9331_sw_port *p = &priv->port[port]; spin_lock(&p->stats_lock); diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c index 6d5ac7588a6917..dee7b6579916a2 100644 --- a/drivers/net/dsa/qca/qca8k-8xxx.c +++ b/drivers/net/dsa/qca/qca8k-8xxx.c @@ -1756,7 +1756,7 @@ static int qca8k_connect_tag_protocol(struct dsa_switch *ds, static int qca8k_setup(struct dsa_switch *ds) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; int cpu_port, ret, i; u32 mask; diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c index 96773e4325582c..8c2dc0e48ff4b9 100644 --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c @@ -760,7 +760,7 @@ int qca8k_port_fdb_add(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, struct dsa_db db) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; u16 port_mask = BIT(port); return qca8k_port_fdb_insert(priv, addr, port_mask, vid); @@ -770,7 +770,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port, const unsigned char *addr, u16 vid, struct dsa_db db) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; u16 port_mask = BIT(port); if (!vid) @@ -782,7 +782,7 @@ int qca8k_port_fdb_del(struct dsa_switch *ds, int port, int qca8k_port_fdb_dump(struct dsa_switch *ds, int port, dsa_fdb_dump_cb_t *cb, void *data) { - struct qca8k_priv *priv = (struct qca8k_priv *)ds->priv; + struct qca8k_priv *priv = ds->priv; struct qca8k_fdb _fdb = { 0 }; int cnt = QCA8K_NUM_FDB_RECORDS; bool is_static; diff --git a/drivers/net/dsa/qca/qca8k-leds.c b/drivers/net/dsa/qca/qca8k-leds.c index b883692b7d8611..6f02029b454bc1 100644 --- a/drivers/net/dsa/qca/qca8k-leds.c +++ b/drivers/net/dsa/qca/qca8k-leds.c @@ -5,6 +5,18 @@ #include "qca8k.h" #include "qca8k_leds.h" +static u32 qca8k_phy_to_port(int phy) +{ + /* Internal PHY 0 has port at index 1. + * Internal PHY 1 has port at index 2. + * Internal PHY 2 has port at index 3. + * Internal PHY 3 has port at index 4. + * Internal PHY 4 has port at index 5. + */ + + return phy + 1; +} + static int qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) { @@ -31,6 +43,43 @@ qca8k_get_enable_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en return 0; } +static int +qca8k_get_control_led_reg(int port_num, int led_num, struct qca8k_led_pattern_en *reg_info) +{ + reg_info->reg = QCA8K_LED_CTRL_REG(led_num); + + /* 6 total control rule: + * 3 control rules for phy0-3 that applies to all their leds + * 3 control rules for phy4 + */ + if (port_num == 4) + reg_info->shift = QCA8K_LED_PHY4_CONTROL_RULE_SHIFT; + else + reg_info->shift = QCA8K_LED_PHY0123_CONTROL_RULE_SHIFT; + + return 0; +} + +static int +qca8k_parse_netdev(unsigned long rules, u32 *offload_trigger) +{ + /* Parsing specific to netdev trigger */ + if (test_bit(TRIGGER_NETDEV_TX, &rules)) + *offload_trigger |= QCA8K_LED_TX_BLINK_MASK; + if (test_bit(TRIGGER_NETDEV_RX, &rules)) + *offload_trigger |= QCA8K_LED_RX_BLINK_MASK; + + if (rules && !*offload_trigger) + return -EOPNOTSUPP; + + /* Enable some default rule by default to the requested mode: + * - Blink at 4Hz by default + */ + *offload_trigger |= QCA8K_LED_BLINK_4HZ; + + return 0; +} + static int qca8k_led_brightness_set(struct qca8k_led *led, enum led_brightness brightness) @@ -164,6 +213,133 @@ qca8k_cled_blink_set(struct led_classdev *ldev, return 0; } +static int +qca8k_cled_trigger_offload(struct led_classdev *ldev, bool enable) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 mask, val = QCA8K_LED_ALWAYS_OFF; + + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); + + if (enable) + val = QCA8K_LED_RULE_CONTROLLED; + + if (led->port_num == 0 || led->port_num == 4) { + mask = QCA8K_LED_PATTERN_EN_MASK; + val <<= QCA8K_LED_PATTERN_EN_SHIFT; + } else { + mask = QCA8K_LED_PHY123_PATTERN_EN_MASK; + } + + return regmap_update_bits(priv->regmap, reg_info.reg, mask << reg_info.shift, + val << reg_info.shift); +} + +static bool +qca8k_cled_hw_control_status(struct led_classdev *ldev) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 val; + + qca8k_get_enable_led_reg(led->port_num, led->led_num, ®_info); + + regmap_read(priv->regmap, reg_info.reg, &val); + + val >>= reg_info.shift; + + if (led->port_num == 0 || led->port_num == 4) { + val &= QCA8K_LED_PATTERN_EN_MASK; + val >>= QCA8K_LED_PATTERN_EN_SHIFT; + } else { + val &= QCA8K_LED_PHY123_PATTERN_EN_MASK; + } + + return val == QCA8K_LED_RULE_CONTROLLED; +} + +static int +qca8k_cled_hw_control_is_supported(struct led_classdev *ldev, unsigned long rules) +{ + u32 offload_trigger = 0; + + return qca8k_parse_netdev(rules, &offload_trigger); +} + +static int +qca8k_cled_hw_control_set(struct led_classdev *ldev, unsigned long rules) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 offload_trigger = 0; + int ret; + + ret = qca8k_parse_netdev(rules, &offload_trigger); + if (ret) + return ret; + + ret = qca8k_cled_trigger_offload(ldev, true); + if (ret) + return ret; + + qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); + + return regmap_update_bits(priv->regmap, reg_info.reg, + QCA8K_LED_RULE_MASK << reg_info.shift, + offload_trigger << reg_info.shift); +} + +static int +qca8k_cled_hw_control_get(struct led_classdev *ldev, unsigned long *rules) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + struct qca8k_led_pattern_en reg_info; + struct qca8k_priv *priv = led->priv; + u32 val; + int ret; + + /* With hw control not active return err */ + if (!qca8k_cled_hw_control_status(ldev)) + return -EINVAL; + + qca8k_get_control_led_reg(led->port_num, led->led_num, ®_info); + + ret = regmap_read(priv->regmap, reg_info.reg, &val); + if (ret) + return ret; + + val >>= reg_info.shift; + val &= QCA8K_LED_RULE_MASK; + + /* Parsing specific to netdev trigger */ + if (val & QCA8K_LED_TX_BLINK_MASK) + set_bit(TRIGGER_NETDEV_TX, rules); + if (val & QCA8K_LED_RX_BLINK_MASK) + set_bit(TRIGGER_NETDEV_RX, rules); + + return 0; +} + +static struct device *qca8k_cled_hw_control_get_device(struct led_classdev *ldev) +{ + struct qca8k_led *led = container_of(ldev, struct qca8k_led, cdev); + struct qca8k_priv *priv = led->priv; + struct dsa_port *dp; + + dp = dsa_to_port(priv->ds, qca8k_phy_to_port(led->port_num)); + if (!dp) + return NULL; + if (dp->slave) + return &dp->slave->dev; + return NULL; +} + static int qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int port_num) { @@ -224,6 +400,11 @@ qca8k_parse_port_leds(struct qca8k_priv *priv, struct fwnode_handle *port, int p port_led->cdev.max_brightness = 1; port_led->cdev.brightness_set_blocking = qca8k_cled_brightness_set_blocking; port_led->cdev.blink_set = qca8k_cled_blink_set; + port_led->cdev.hw_control_is_supported = qca8k_cled_hw_control_is_supported; + port_led->cdev.hw_control_set = qca8k_cled_hw_control_set; + port_led->cdev.hw_control_get = qca8k_cled_hw_control_get; + port_led->cdev.hw_control_get_device = qca8k_cled_hw_control_get_device; + port_led->cdev.hw_control_trigger = "netdev"; init_data.default_label = ":port"; init_data.fwnode = led; init_data.devname_mandatory = true; diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c index 01f1cb71904226..833e55e4b96129 100644 --- a/drivers/net/dsa/sja1105/sja1105_mdio.c +++ b/drivers/net/dsa/sja1105/sja1105_mdio.c @@ -400,7 +400,6 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv) } for (port = 0; port < ds->num_ports; port++) { - struct mdio_device *mdiodev; struct dw_xpcs *xpcs; if (dsa_is_unused_port(ds, port)) @@ -410,13 +409,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv) priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX) continue; - mdiodev = mdio_device_create(bus, port); - if (IS_ERR(mdiodev)) { - rc = PTR_ERR(mdiodev); - goto out_pcs_free; - } - - xpcs = xpcs_create(mdiodev, priv->phy_mode[port]); + xpcs = xpcs_create_mdiodev(bus, port, priv->phy_mode[port]); if (IS_ERR(xpcs)) { rc = PTR_ERR(xpcs); goto out_pcs_free; @@ -434,7 +427,6 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv) if (!priv->xpcs[port]) continue; - mdio_device_free(priv->xpcs[port]->mdiodev); xpcs_destroy(priv->xpcs[port]); priv->xpcs[port] = NULL; } @@ -457,7 +449,6 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv) if (!priv->xpcs[port]) continue; - mdio_device_free(priv->xpcs[port]->mdiodev); xpcs_destroy(priv->xpcs[port]); priv->xpcs[port] = NULL; } diff --git a/drivers/net/dsa/sja1105/sja1105_tas.c b/drivers/net/dsa/sja1105/sja1105_tas.c index e6153848a95094..d7818710bc0283 100644 --- a/drivers/net/dsa/sja1105/sja1105_tas.c +++ b/drivers/net/dsa/sja1105/sja1105_tas.c @@ -516,10 +516,11 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, /* Can't change an already configured port (must delete qdisc first). * Can't delete the qdisc from an unconfigured port. */ - if (!!tas_data->offload[port] == admin->enable) + if ((!!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_REPLACE) || + (!tas_data->offload[port] && admin->cmd == TAPRIO_CMD_DESTROY)) return -EINVAL; - if (!admin->enable) { + if (admin->cmd == TAPRIO_CMD_DESTROY) { taprio_offload_free(tas_data->offload[port]); tas_data->offload[port] = NULL; @@ -528,6 +529,8 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port, return rc; return sja1105_static_config_reload(priv, SJA1105_SCHEDULING); + } else if (admin->cmd != TAPRIO_CMD_REPLACE) { + return -EOPNOTSUPP; } /* The cycle time extension is the amount of time the last cycle from diff --git a/drivers/net/dsa/xrs700x/xrs700x_i2c.c b/drivers/net/dsa/xrs700x/xrs700x_i2c.c index 14ff6887a225dc..c1179d7311f7e4 100644 --- a/drivers/net/dsa/xrs700x/xrs700x_i2c.c +++ b/drivers/net/dsa/xrs700x/xrs700x_i2c.c @@ -147,7 +147,7 @@ static struct i2c_driver xrs700x_i2c_driver = { .name = "xrs700x-i2c", .of_match_table = of_match_ptr(xrs700x_i2c_dt_ids), }, - .probe_new = xrs700x_i2c_probe, + .probe = xrs700x_i2c_probe, .remove = xrs700x_i2c_remove, .shutdown = xrs700x_i2c_shutdown, .id_table = xrs700x_i2c_id, diff --git a/drivers/net/ethernet/3com/3c589_cs.c b/drivers/net/ethernet/3com/3c589_cs.c index 82f94b1635bf81..5267e9dcd87ef9 100644 --- a/drivers/net/ethernet/3com/3c589_cs.c +++ b/drivers/net/ethernet/3com/3c589_cs.c @@ -195,6 +195,7 @@ static int tc589_probe(struct pcmcia_device *link) { struct el3_private *lp; struct net_device *dev; + int ret; dev_dbg(&link->dev, "3c589_attach()\n"); @@ -218,7 +219,15 @@ static int tc589_probe(struct pcmcia_device *link) dev->ethtool_ops = &netdev_ethtool_ops; - return tc589_config(link); + ret = tc589_config(link); + if (ret) + goto err_free_netdev; + + return 0; + +err_free_netdev: + free_netdev(dev); + return ret; } static void tc589_detach(struct pcmcia_device *link) diff --git a/drivers/net/ethernet/altera/Kconfig b/drivers/net/ethernet/altera/Kconfig index dd7fd41ccde5bf..17985319088c1d 100644 --- a/drivers/net/ethernet/altera/Kconfig +++ b/drivers/net/ethernet/altera/Kconfig @@ -4,7 +4,9 @@ config ALTERA_TSE depends on HAS_DMA select PHYLIB select PHYLINK - select PCS_ALTERA_TSE + select PCS_LYNX + select MDIO_REGMAP + select REGMAP_MMIO help This driver supports the Altera Triple-Speed (TSE) Ethernet MAC. diff --git a/drivers/net/ethernet/altera/altera_tse_main.c b/drivers/net/ethernet/altera/altera_tse_main.c index 66e3af73ec41ac..2e15800e53102f 100644 --- a/drivers/net/ethernet/altera/altera_tse_main.c +++ b/drivers/net/ethernet/altera/altera_tse_main.c @@ -27,14 +27,16 @@ #include #include #include +#include #include #include #include #include #include -#include +#include #include #include +#include #include #include @@ -1036,10 +1038,6 @@ static struct net_device_ops altera_tse_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; -static void alt_tse_mac_an_restart(struct phylink_config *config) -{ -} - static void alt_tse_mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state) { @@ -1096,7 +1094,6 @@ static struct phylink_pcs *alt_tse_select_pcs(struct phylink_config *config, } static const struct phylink_mac_ops alt_tse_phylink_ops = { - .mac_an_restart = alt_tse_mac_an_restart, .mac_config = alt_tse_mac_config, .mac_link_down = alt_tse_mac_link_down, .mac_link_up = alt_tse_mac_link_up, @@ -1137,13 +1134,16 @@ static int request_and_map(struct platform_device *pdev, const char *name, static int altera_tse_probe(struct platform_device *pdev) { const struct of_device_id *of_id = NULL; + struct regmap_config pcs_regmap_cfg; struct altera_tse_private *priv; + struct mdio_regmap_config mrc; struct resource *control_port; + struct regmap *pcs_regmap; struct resource *dma_res; struct resource *pcs_res; + struct mii_bus *pcs_bus; struct net_device *ndev; void __iomem *descmap; - int pcs_reg_width = 2; int ret = -ENODEV; ndev = alloc_etherdev(sizeof(struct altera_tse_private)); @@ -1255,18 +1255,41 @@ static int altera_tse_probe(struct platform_device *pdev) if (ret) goto err_free_netdev; + memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg)); + memset(&mrc, 0, sizeof(mrc)); /* SGMII PCS address space. The location can vary depending on how the * IP is integrated. We can have a resource dedicated to it at a specific * address space, but if it's not the case, we fallback to the mdiophy0 * from the MAC's address space */ - ret = request_and_map(pdev, "pcs", &pcs_res, - &priv->pcs_base); + ret = request_and_map(pdev, "pcs", &pcs_res, &priv->pcs_base); if (ret) { + /* If we can't find a dedicated resource for the PCS, fallback + * to the internal PCS, that has a different address stride + */ priv->pcs_base = priv->mac_dev + tse_csroffs(mdio_phy0); - pcs_reg_width = 4; + pcs_regmap_cfg.reg_bits = 32; + /* Values are MDIO-like values, on 16 bits */ + pcs_regmap_cfg.val_bits = 16; + pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(2); + } else { + pcs_regmap_cfg.reg_bits = 16; + pcs_regmap_cfg.val_bits = 16; + pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1); } + /* Create a regmap for the PCS so that it can be used by the PCS driver */ + pcs_regmap = devm_regmap_init_mmio(&pdev->dev, priv->pcs_base, + &pcs_regmap_cfg); + if (IS_ERR(pcs_regmap)) { + ret = PTR_ERR(pcs_regmap); + goto err_free_netdev; + } + mrc.regmap = pcs_regmap; + mrc.parent = &pdev->dev; + mrc.valid_addr = 0x0; + mrc.autoscan = false; + /* Rx IRQ */ priv->rx_irq = platform_get_irq_byname(pdev, "rx_irq"); if (priv->rx_irq == -ENXIO) { @@ -1389,7 +1412,18 @@ static int altera_tse_probe(struct platform_device *pdev) (unsigned long) control_port->start, priv->rx_irq, priv->tx_irq); - priv->pcs = alt_tse_pcs_create(ndev, priv->pcs_base, pcs_reg_width); + snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name); + pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc); + if (IS_ERR(pcs_bus)) { + ret = PTR_ERR(pcs_bus); + goto err_init_pcs; + } + + priv->pcs = lynx_pcs_create_mdiodev(pcs_bus, 0); + if (IS_ERR(priv->pcs)) { + ret = PTR_ERR(priv->pcs); + goto err_init_pcs; + } priv->phylink_config.dev = &ndev->dev; priv->phylink_config.type = PHYLINK_NETDEV; @@ -1412,12 +1446,13 @@ static int altera_tse_probe(struct platform_device *pdev) if (IS_ERR(priv->phylink)) { dev_err(&pdev->dev, "failed to create phylink\n"); ret = PTR_ERR(priv->phylink); - goto err_init_phy; + goto err_init_phylink; } return 0; - -err_init_phy: +err_init_phylink: + lynx_pcs_destroy(priv->pcs); +err_init_pcs: unregister_netdev(ndev); err_register_netdev: netif_napi_del(&priv->napi); @@ -1438,6 +1473,8 @@ static int altera_tse_remove(struct platform_device *pdev) altera_tse_mdio_destroy(ndev); unregister_netdev(ndev); phylink_destroy(priv->phylink); + lynx_pcs_destroy(priv->pcs); + free_netdev(ndev); return 0; diff --git a/drivers/net/ethernet/amd/pds_core/dev.c b/drivers/net/ethernet/amd/pds_core/dev.c index f7c597ea5daf3d..debe5216fe29e2 100644 --- a/drivers/net/ethernet/amd/pds_core/dev.c +++ b/drivers/net/ethernet/amd/pds_core/dev.c @@ -68,9 +68,15 @@ bool pdsc_is_fw_running(struct pdsc *pdsc) bool pdsc_is_fw_good(struct pdsc *pdsc) { - u8 gen = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION; + bool fw_running = pdsc_is_fw_running(pdsc); + u8 gen; - return pdsc_is_fw_running(pdsc) && gen == pdsc->fw_generation; + /* Make sure to update the cached fw_status by calling + * pdsc_is_fw_running() before getting the generation + */ + gen = pdsc->fw_status & PDS_CORE_FW_STS_F_GENERATION; + + return fw_running && gen == pdsc->fw_generation; } static u8 pdsc_devcmd_status(struct pdsc *pdsc) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c index 33a9574e9e0434..32d2c6fac65266 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c @@ -1329,7 +1329,7 @@ static enum xgbe_mode xgbe_phy_status_aneg(struct xgbe_prv_data *pdata) return pdata->phy_if.phy_impl.an_outcome(pdata); } -static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) +static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata) { struct ethtool_link_ksettings *lks = &pdata->phy.lks; enum xgbe_mode mode; @@ -1367,8 +1367,13 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) pdata->phy.duplex = DUPLEX_FULL; - if (xgbe_set_mode(pdata, mode) && pdata->an_again) + if (!xgbe_set_mode(pdata, mode)) + return false; + + if (pdata->an_again) xgbe_phy_reconfig_aneg(pdata); + + return true; } static void xgbe_phy_status(struct xgbe_prv_data *pdata) @@ -1398,7 +1403,8 @@ static void xgbe_phy_status(struct xgbe_prv_data *pdata) return; } - xgbe_phy_status_result(pdata); + if (xgbe_phy_status_result(pdata)) + return; if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) clear_bit(XGBE_LINK_INIT, &pdata->dev_state); diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c index 16e7fb2c0daee6..6a716337f48be1 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c @@ -2782,9 +2782,9 @@ static bool xgbe_phy_valid_speed_baset_mode(struct xgbe_prv_data *pdata, switch (speed) { case SPEED_10: - /* Supported in ver >= 30H */ + /* Supported in ver 21H and ver >= 30H */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - return (ver >= 0x30) ? true : false; + return (ver == 0x21 || ver >= 0x30); case SPEED_100: case SPEED_1000: return true; @@ -2806,9 +2806,10 @@ static bool xgbe_phy_valid_speed_sfp_mode(struct xgbe_prv_data *pdata, switch (speed) { case SPEED_10: - /* Supported in ver >= 30H */ + /* Supported in ver 21H and ver >= 30H */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - return (ver >= 0x30) && (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000); + return ((ver == 0x21 || ver >= 0x30) && + (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000)); case SPEED_100: return (phy_data->sfp_speed == XGBE_SFP_SPEED_100_1000); case SPEED_1000: @@ -3158,9 +3159,9 @@ static bool xgbe_phy_port_mode_mismatch(struct xgbe_prv_data *pdata) struct xgbe_phy_data *phy_data = pdata->phy_data; unsigned int ver; - /* 10 Mbps speed is not supported in ver < 30H */ + /* 10 Mbps speed is supported in ver 21H and ver >= 30H */ ver = XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER); - if (ver < 0x30 && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)) + if ((ver < 0x30 && ver != 0x21) && (phy_data->port_speeds & XGBE_PHY_PORT_SPEED_10)) return true; switch (phy_data->port_mode) { diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 38d0cdaf22a5b3..bf1611cce974a9 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -2531,9 +2531,9 @@ static int bcm_sysport_probe(struct platform_device *pdev) priv->irq0 = platform_get_irq(pdev, 0); if (!priv->is_lite) { priv->irq1 = platform_get_irq(pdev, 1); - priv->wol_irq = platform_get_irq(pdev, 2); + priv->wol_irq = platform_get_irq_optional(pdev, 2); } else { - priv->wol_irq = platform_get_irq(pdev, 1); + priv->wol_irq = platform_get_irq_optional(pdev, 1); } if (priv->irq0 <= 0 || (priv->irq1 <= 0 && !priv->is_lite)) { ret = -EINVAL; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index f42e51bd3e4257..e5b54e6025bece 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -692,7 +692,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts) __netif_txq_completed_wake(txq, nr_pkts, tx_bytes, bnxt_tx_avail(bp, txr), bp->tx_wake_thresh, - READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING); + READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING); } static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping, @@ -2361,6 +2361,9 @@ static int bnxt_async_event_process(struct bnxt *bp, struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; u64 ns; + if (!ptp) + goto async_event_process_exit; + spin_lock_bh(&ptp->ptp_lock); bnxt_ptp_update_current_time(bp); ns = (((u64)BNXT_EVENT_PHC_RTC_UPDATE(data1) << @@ -4759,6 +4762,9 @@ int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap, int bmap_size, if (event_id == ASYNC_EVENT_CMPL_EVENT_ID_ERROR_RECOVERY && !(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)) continue; + if (event_id == ASYNC_EVENT_CMPL_EVENT_ID_PHC_UPDATE && + !bp->ptp_cfg) + continue; __set_bit(bnxt_async_events_arr[i], async_events_bmap); } if (bmap && bmap_size) { @@ -5346,6 +5352,7 @@ static void bnxt_hwrm_update_rss_hash_cfg(struct bnxt *bp) if (hwrm_req_init(bp, req, HWRM_VNIC_RSS_QCFG)) return; + req->vnic_id = cpu_to_le16(vnic->fw_vnic_id); /* all contexts configured to same hash_type, zero always exists */ req->rss_ctx_idx = cpu_to_le16(vnic->fw_rss_cos_lb_ctx[0]); resp = hwrm_req_hold(bp, req); @@ -8808,6 +8815,9 @@ static int bnxt_init_chip(struct bnxt *bp, bool irq_re_init) goto err_out; } + if (BNXT_VF(bp)) + bnxt_hwrm_func_qcfg(bp); + rc = bnxt_setup_vnic(bp, 0); if (rc) goto err_out; @@ -11594,6 +11604,7 @@ static void bnxt_tx_timeout(struct net_device *dev, unsigned int txqueue) static void bnxt_fw_health_check(struct bnxt *bp) { struct bnxt_fw_health *fw_health = bp->fw_health; + struct pci_dev *pdev = bp->pdev; u32 val; if (!fw_health->enabled || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) @@ -11607,7 +11618,7 @@ static void bnxt_fw_health_check(struct bnxt *bp) } val = bnxt_fw_health_readl(bp, BNXT_FW_HEARTBEAT_REG); - if (val == fw_health->last_fw_heartbeat) { + if (val == fw_health->last_fw_heartbeat && pci_device_is_present(pdev)) { fw_health->arrests++; goto fw_reset; } @@ -11615,7 +11626,7 @@ static void bnxt_fw_health_check(struct bnxt *bp) fw_health->last_fw_heartbeat = val; val = bnxt_fw_health_readl(bp, BNXT_FW_RESET_CNT_REG); - if (val != fw_health->last_fw_reset_cnt) { + if (val != fw_health->last_fw_reset_cnt && pci_device_is_present(pdev)) { fw_health->discoveries++; goto fw_reset; } @@ -13021,26 +13032,37 @@ static void bnxt_cfg_ntp_filters(struct bnxt *bp) #endif /* CONFIG_RFS_ACCEL */ -static int bnxt_udp_tunnel_sync(struct net_device *netdev, unsigned int table) +static int bnxt_udp_tunnel_set_port(struct net_device *netdev, unsigned int table, + unsigned int entry, struct udp_tunnel_info *ti) { struct bnxt *bp = netdev_priv(netdev); - struct udp_tunnel_info ti; unsigned int cmd; - udp_tunnel_nic_get_port(netdev, table, 0, &ti); - if (ti.type == UDP_TUNNEL_TYPE_VXLAN) + if (ti->type == UDP_TUNNEL_TYPE_VXLAN) cmd = TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN; else cmd = TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE; - if (ti.port) - return bnxt_hwrm_tunnel_dst_port_alloc(bp, ti.port, cmd); + return bnxt_hwrm_tunnel_dst_port_alloc(bp, ti->port, cmd); +} + +static int bnxt_udp_tunnel_unset_port(struct net_device *netdev, unsigned int table, + unsigned int entry, struct udp_tunnel_info *ti) +{ + struct bnxt *bp = netdev_priv(netdev); + unsigned int cmd; + + if (ti->type == UDP_TUNNEL_TYPE_VXLAN) + cmd = TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_VXLAN; + else + cmd = TUNNEL_DST_PORT_FREE_REQ_TUNNEL_TYPE_GENEVE; return bnxt_hwrm_tunnel_dst_port_free(bp, cmd); } static const struct udp_tunnel_nic_info bnxt_udp_tunnels = { - .sync_table = bnxt_udp_tunnel_sync, + .set_port = bnxt_udp_tunnel_set_port, + .unset_port = bnxt_udp_tunnel_unset_port, .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP | UDP_TUNNEL_NIC_INFO_OPEN_ONLY, .tables = { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 2dd8ee4a6f75b7..8fd5071d8b0995 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -3831,7 +3831,7 @@ static int bnxt_reset(struct net_device *dev, u32 *flags) } } - if (req & BNXT_FW_RESET_AP) { + if (!BNXT_CHIP_P4_PLUS(bp) && (req & BNXT_FW_RESET_AP)) { /* This feature is not supported in older firmware versions */ if (bp->hwrm_spec_code >= 0x10803) { if (!bnxt_firmware_reset_ap(dev)) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c index e46689128e323f..f3886710e77873 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c @@ -952,6 +952,7 @@ int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg) bnxt_ptp_timecounter_init(bp, true); bnxt_ptp_adjfine_rtc(bp, 0); } + bnxt_hwrm_func_drv_rgtr(bp, NULL, 0, true); ptp->ptp_info = bnxt_ptp_caps; if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) { diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index eca0c92c0c84d8..2b5761ad2f92f1 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1272,7 +1272,8 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev, } } -static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) +void bcmgenet_eee_enable_set(struct net_device *dev, bool enable, + bool tx_lpi_enabled) { struct bcmgenet_priv *priv = netdev_priv(dev); u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL; @@ -1292,7 +1293,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) /* Enable EEE and switch to a 27Mhz clock automatically */ reg = bcmgenet_readl(priv->base + off); - if (enable) + if (tx_lpi_enabled) reg |= TBUF_EEE_EN | TBUF_PM_EN; else reg &= ~(TBUF_EEE_EN | TBUF_PM_EN); @@ -1313,6 +1314,7 @@ static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable) priv->eee.eee_enabled = enable; priv->eee.eee_active = enable; + priv->eee.tx_lpi_enabled = tx_lpi_enabled; } static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e) @@ -1328,6 +1330,7 @@ static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e) e->eee_enabled = p->eee_enabled; e->eee_active = p->eee_active; + e->tx_lpi_enabled = p->tx_lpi_enabled; e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER); return phy_ethtool_get_eee(dev->phydev, e); @@ -1337,7 +1340,6 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) { struct bcmgenet_priv *priv = netdev_priv(dev); struct ethtool_eee *p = &priv->eee; - int ret = 0; if (GENET_IS_V1(priv)) return -EOPNOTSUPP; @@ -1348,16 +1350,11 @@ static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e) p->eee_enabled = e->eee_enabled; if (!p->eee_enabled) { - bcmgenet_eee_enable_set(dev, false); + bcmgenet_eee_enable_set(dev, false, false); } else { - ret = phy_init_eee(dev->phydev, false); - if (ret) { - netif_err(priv, hw, dev, "EEE initialization failed\n"); - return ret; - } - + p->eee_active = phy_init_eee(dev->phydev, false) >= 0; bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER); - bcmgenet_eee_enable_set(dev, true); + bcmgenet_eee_enable_set(dev, p->eee_active, e->tx_lpi_enabled); } return phy_ethtool_set_eee(dev->phydev, e); @@ -4279,9 +4276,6 @@ static int bcmgenet_resume(struct device *d) if (!device_may_wakeup(d)) phy_resume(dev->phydev); - if (priv->eee.eee_enabled) - bcmgenet_eee_enable_set(dev, true); - bcmgenet_netif_start(dev); netif_device_attach(dev); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 946f6e283c4e6b..1985c0ec4da2ab 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -703,4 +703,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv, enum bcmgenet_power_mode mode); +void bcmgenet_eee_enable_set(struct net_device *dev, bool enable, + bool tx_lpi_enabled); + #endif /* __BCMGENET_H__ */ diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index be042905ada2a4..c15ed0acdb777d 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -87,6 +87,11 @@ static void bcmgenet_mac_config(struct net_device *dev) reg |= CMD_TX_EN | CMD_RX_EN; } bcmgenet_umac_writel(priv, reg, UMAC_CMD); + + priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0; + bcmgenet_eee_enable_set(dev, + priv->eee.eee_enabled && priv->eee.eee_active, + priv->eee.tx_lpi_enabled); } /* setup netdev link state when PHY link status change and diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 58747292521d81..5e68a6a4b2afb6 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -57,6 +57,7 @@ #include #include +#include #include #include diff --git a/drivers/net/ethernet/cavium/Kconfig b/drivers/net/ethernet/cavium/Kconfig index 1c76c95b0b275f..ca742cc146d798 100644 --- a/drivers/net/ethernet/cavium/Kconfig +++ b/drivers/net/ethernet/cavium/Kconfig @@ -62,6 +62,9 @@ config CAVIUM_PTP Precision Time Protocol or other purposes. Timestamps can be used in BGX, TNS, GTI, and NIC blocks. +config LIQUIDIO_CORE + tristate + config LIQUIDIO tristate "Cavium LiquidIO support" depends on 64BIT && PCI @@ -69,6 +72,7 @@ config LIQUIDIO depends on PTP_1588_CLOCK_OPTIONAL select FW_LOADER select LIBCRC32C + select LIQUIDIO_CORE select NET_DEVLINK help This driver supports Cavium LiquidIO Intelligent Server Adapters @@ -92,6 +96,7 @@ config LIQUIDIO_VF tristate "Cavium LiquidIO VF support" depends on 64BIT && PCI_MSI depends on PTP_1588_CLOCK_OPTIONAL + select LIQUIDIO_CORE help This driver supports Cavium LiquidIO Intelligent Server Adapter based on CN23XX chips. diff --git a/drivers/net/ethernet/cavium/liquidio/Makefile b/drivers/net/ethernet/cavium/liquidio/Makefile index bc99375020431c..4ee80af88e79ee 100644 --- a/drivers/net/ethernet/cavium/liquidio/Makefile +++ b/drivers/net/ethernet/cavium/liquidio/Makefile @@ -3,7 +3,9 @@ # Cavium Liquidio ethernet device driver # -common-objs := lio_ethtool.o \ +obj-$(CONFIG_LIQUIDIO_CORE) += liquidio-core.o +liquidio-core-y := \ + lio_ethtool.o \ lio_core.o \ request_manager.o \ response_manager.o \ @@ -18,7 +20,7 @@ common-objs := lio_ethtool.o \ octeon_nic.o obj-$(CONFIG_LIQUIDIO) += liquidio.o -liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o $(common-objs) +liquidio-y := lio_main.o octeon_console.o lio_vf_rep.o obj-$(CONFIG_LIQUIDIO_VF) += liquidio_vf.o -liquidio_vf-y := lio_vf_main.o $(common-objs) +liquidio_vf-y := lio_vf_main.o diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index 9ed3d1ab2ca580..068ed52b66c94d 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c @@ -719,12 +719,10 @@ static int cn23xx_setup_pf_mbox(struct octeon_device *oct) for (i = 0; i < oct->sriov_info.max_vfs; i++) { q_no = i * oct->sriov_info.rings_per_vf; - mbox = vmalloc(sizeof(*mbox)); + mbox = vzalloc(sizeof(*mbox)); if (!mbox) goto free_mbox; - memset(mbox, 0, sizeof(struct octeon_mbox)); - spin_lock_init(&mbox->lock); mbox->oct_dev = oct; @@ -1377,6 +1375,7 @@ int setup_cn23xx_octeon_pf_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(setup_cn23xx_octeon_pf_device); int validate_cn23xx_pf_config_info(struct octeon_device *oct, struct octeon_config *conf23xx) @@ -1435,6 +1434,7 @@ int cn23xx_fw_loaded(struct octeon_device *oct) val = octeon_read_csr64(oct, CN23XX_SLI_SCRATCH2); return (val >> SCR2_BIT_FW_LOADED) & 1ULL; } +EXPORT_SYMBOL_GPL(cn23xx_fw_loaded); void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, u8 *mac) @@ -1456,6 +1456,7 @@ void cn23xx_tell_vf_its_macaddr_changed(struct octeon_device *oct, int vfidx, octeon_mbox_write(oct, &mbox_cmd); } } +EXPORT_SYMBOL_GPL(cn23xx_tell_vf_its_macaddr_changed); static void cn23xx_get_vf_stats_callback(struct octeon_device *oct, @@ -1510,3 +1511,4 @@ int cn23xx_get_vf_stats(struct octeon_device *oct, int vfidx, return 0; } +EXPORT_SYMBOL_GPL(cn23xx_get_vf_stats); diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c index fda49404968c33..dd5d80fee24f0f 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_vf_device.c @@ -279,12 +279,10 @@ static int cn23xx_setup_vf_mbox(struct octeon_device *oct) { struct octeon_mbox *mbox = NULL; - mbox = vmalloc(sizeof(*mbox)); + mbox = vzalloc(sizeof(*mbox)); if (!mbox) return 1; - memset(mbox, 0, sizeof(struct octeon_mbox)); - spin_lock_init(&mbox->lock); mbox->oct_dev = oct; @@ -386,6 +384,7 @@ void cn23xx_vf_ask_pf_to_do_flr(struct octeon_device *oct) octeon_mbox_write(oct, &mbox_cmd); } +EXPORT_SYMBOL_GPL(cn23xx_vf_ask_pf_to_do_flr); static void octeon_pfvf_hs_callback(struct octeon_device *oct, struct octeon_mbox_cmd *cmd, @@ -468,6 +467,7 @@ int cn23xx_octeon_pfvf_handshake(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(cn23xx_octeon_pfvf_handshake); static void cn23xx_handle_vf_mbox_intr(struct octeon_ioq_vector *ioq_vector) { @@ -680,3 +680,4 @@ int cn23xx_setup_octeon_vf_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(cn23xx_setup_octeon_vf_device); diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c index 39643be8c30a97..93fccfec288d47 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_device.c @@ -697,6 +697,7 @@ int lio_setup_cn66xx_octeon_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(lio_setup_cn66xx_octeon_device); int lio_validate_cn6xxx_config_info(struct octeon_device *oct, struct octeon_config *conf6xxx) diff --git a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c index 30254e4cf70f76..b5103def37613c 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn68xx_device.c @@ -181,3 +181,4 @@ int lio_setup_cn68xx_octeon_device(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(lio_setup_cn68xx_octeon_device); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_core.c b/drivers/net/ethernet/cavium/liquidio/lio_core.c index 882b2be06ea0e0..9cc6303c82ffb7 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_core.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_core.c @@ -26,6 +26,9 @@ #include "octeon_main.h" #include "octeon_network.h" +MODULE_AUTHOR("Cavium Networks, "); +MODULE_LICENSE("GPL"); + /* OOM task polling interval */ #define LIO_OOM_POLL_INTERVAL_MS 250 @@ -71,6 +74,7 @@ void lio_delete_glists(struct lio *lio) kfree(lio->glist); lio->glist = NULL; } +EXPORT_SYMBOL_GPL(lio_delete_glists); /** * lio_setup_glists - Setup gather lists @@ -154,6 +158,7 @@ int lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs) return 0; } +EXPORT_SYMBOL_GPL(lio_setup_glists); int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1) { @@ -180,6 +185,7 @@ int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1) } return ret; } +EXPORT_SYMBOL_GPL(liquidio_set_feature); void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl, unsigned int bytes_compl) @@ -395,6 +401,7 @@ void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr) nctrl->ncmd.s.cmd); } } +EXPORT_SYMBOL_GPL(liquidio_link_ctrl_cmd_completion); void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac) { @@ -478,6 +485,7 @@ int setup_rx_oom_poll_fn(struct net_device *netdev) return 0; } +EXPORT_SYMBOL_GPL(setup_rx_oom_poll_fn); void cleanup_rx_oom_poll_fn(struct net_device *netdev) { @@ -495,6 +503,7 @@ void cleanup_rx_oom_poll_fn(struct net_device *netdev) } } } +EXPORT_SYMBOL_GPL(cleanup_rx_oom_poll_fn); /* Runs in interrupt context. */ static void lio_update_txq_status(struct octeon_device *oct, int iq_num) @@ -899,6 +908,7 @@ int liquidio_setup_io_queues(struct octeon_device *octeon_dev, int ifidx, return 0; } +EXPORT_SYMBOL_GPL(liquidio_setup_io_queues); static int liquidio_schedule_msix_droq_pkt_handler(struct octeon_droq *droq, u64 ret) @@ -1194,6 +1204,7 @@ int octeon_setup_interrupt(struct octeon_device *oct, u32 num_ioqs) } return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_interrupt); /** * liquidio_change_mtu - Net device change_mtu @@ -1256,6 +1267,7 @@ int liquidio_change_mtu(struct net_device *netdev, int new_mtu) WRITE_ONCE(sc->caller_is_done, true); return 0; } +EXPORT_SYMBOL_GPL(liquidio_change_mtu); int lio_wait_for_clean_oq(struct octeon_device *oct) { @@ -1279,6 +1291,7 @@ int lio_wait_for_clean_oq(struct octeon_device *oct) return pending_pkts; } +EXPORT_SYMBOL_GPL(lio_wait_for_clean_oq); static void octnet_nic_stats_callback(struct octeon_device *oct_dev, @@ -1509,6 +1522,7 @@ void lio_fetch_stats(struct work_struct *work) return; } +EXPORT_SYMBOL_GPL(lio_fetch_stats); int liquidio_set_speed(struct lio *lio, int speed) { @@ -1659,6 +1673,7 @@ int liquidio_get_speed(struct lio *lio) return retval; } +EXPORT_SYMBOL_GPL(liquidio_get_speed); int liquidio_set_fec(struct lio *lio, int on_off) { @@ -1812,3 +1827,4 @@ int liquidio_get_fec(struct lio *lio) return retval; } +EXPORT_SYMBOL_GPL(liquidio_get_fec); diff --git a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c index 2c10ae3f7fc143..9d56181a301f12 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_ethtool.c @@ -3180,3 +3180,4 @@ void liquidio_set_ethtool_ops(struct net_device *netdev) else netdev->ethtool_ops = &lio_ethtool_ops; } +EXPORT_SYMBOL_GPL(liquidio_set_ethtool_ops); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_device.c b/drivers/net/ethernet/cavium/liquidio/octeon_device.c index e159194d0aef65..364f4f912dc20a 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_device.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_device.c @@ -564,6 +564,7 @@ void octeon_init_device_list(int conf_type) for (i = 0; i < MAX_OCTEON_DEVICES; i++) oct_set_config_info(i, conf_type); } +EXPORT_SYMBOL_GPL(octeon_init_device_list); static void *__retrieve_octeon_config_info(struct octeon_device *oct, u16 card_type) @@ -633,6 +634,7 @@ char *lio_get_state_string(atomic_t *state_ptr) return oct_dev_state_str[OCT_DEV_STATE_INVALID]; return oct_dev_state_str[istate]; } +EXPORT_SYMBOL_GPL(lio_get_state_string); static char *get_oct_app_string(u32 app_mode) { @@ -661,6 +663,7 @@ void octeon_free_device_mem(struct octeon_device *oct) octeon_device[i] = NULL; octeon_device_count--; } +EXPORT_SYMBOL_GPL(octeon_free_device_mem); static struct octeon_device *octeon_allocate_device_mem(u32 pci_id, u32 priv_size) @@ -747,6 +750,7 @@ struct octeon_device *octeon_allocate_device(u32 pci_id, return oct; } +EXPORT_SYMBOL_GPL(octeon_allocate_device); /** Register a device's bus location at initialization time. * @param octeon_dev - pointer to the octeon device structure. @@ -804,6 +808,7 @@ int octeon_register_device(struct octeon_device *oct, return refcount; } +EXPORT_SYMBOL_GPL(octeon_register_device); /** Deregister a device at de-initialization time. * @param octeon_dev - pointer to the octeon device structure. @@ -821,6 +826,7 @@ int octeon_deregister_device(struct octeon_device *oct) return refcount; } +EXPORT_SYMBOL_GPL(octeon_deregister_device); int octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs) @@ -853,12 +859,14 @@ octeon_allocate_ioq_vector(struct octeon_device *oct, u32 num_ioqs) return 0; } +EXPORT_SYMBOL_GPL(octeon_allocate_ioq_vector); void octeon_free_ioq_vector(struct octeon_device *oct) { vfree(oct->ioq_vector); } +EXPORT_SYMBOL_GPL(octeon_free_ioq_vector); /* this function is only for setting up the first queue */ int octeon_setup_instr_queues(struct octeon_device *oct) @@ -904,6 +912,7 @@ int octeon_setup_instr_queues(struct octeon_device *oct) oct->num_iqs++; return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_instr_queues); int octeon_setup_output_queues(struct octeon_device *oct) { @@ -940,6 +949,7 @@ int octeon_setup_output_queues(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_output_queues); int octeon_set_io_queues_off(struct octeon_device *oct) { @@ -989,6 +999,7 @@ int octeon_set_io_queues_off(struct octeon_device *oct) } return 0; } +EXPORT_SYMBOL_GPL(octeon_set_io_queues_off); void octeon_set_droq_pkt_op(struct octeon_device *oct, u32 q_no, @@ -1027,6 +1038,7 @@ int octeon_init_dispatch_list(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_init_dispatch_list); void octeon_delete_dispatch_list(struct octeon_device *oct) { @@ -1058,6 +1070,7 @@ void octeon_delete_dispatch_list(struct octeon_device *oct) kfree(temp); } } +EXPORT_SYMBOL_GPL(octeon_delete_dispatch_list); octeon_dispatch_fn_t octeon_get_dispatch(struct octeon_device *octeon_dev, u16 opcode, @@ -1180,6 +1193,7 @@ octeon_register_dispatch_fn(struct octeon_device *oct, return 0; } +EXPORT_SYMBOL_GPL(octeon_register_dispatch_fn); int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf) { @@ -1262,6 +1276,7 @@ int octeon_core_drv_init(struct octeon_recv_info *recv_info, void *buf) octeon_free_recv_info(recv_info); return 0; } +EXPORT_SYMBOL_GPL(octeon_core_drv_init); int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no) @@ -1272,6 +1287,7 @@ int octeon_get_tx_qsize(struct octeon_device *oct, u32 q_no) return -1; } +EXPORT_SYMBOL_GPL(octeon_get_tx_qsize); int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no) { @@ -1280,6 +1296,7 @@ int octeon_get_rx_qsize(struct octeon_device *oct, u32 q_no) return oct->droq[q_no]->max_count; return -1; } +EXPORT_SYMBOL_GPL(octeon_get_rx_qsize); /* Retruns the host firmware handshake OCTEON specific configuration */ struct octeon_config *octeon_get_conf(struct octeon_device *oct) @@ -1302,6 +1319,7 @@ struct octeon_config *octeon_get_conf(struct octeon_device *oct) } return default_oct_conf; } +EXPORT_SYMBOL_GPL(octeon_get_conf); /* scratch register address is same in all the OCT-II and CN70XX models */ #define CNXX_SLI_SCRATCH1 0x3C0 @@ -1318,6 +1336,7 @@ struct octeon_device *lio_get_device(u32 octeon_id) else return octeon_device[octeon_id]; } +EXPORT_SYMBOL_GPL(lio_get_device); u64 lio_pci_readq(struct octeon_device *oct, u64 addr) { @@ -1349,6 +1368,7 @@ u64 lio_pci_readq(struct octeon_device *oct, u64 addr) return val64; } +EXPORT_SYMBOL_GPL(lio_pci_readq); void lio_pci_writeq(struct octeon_device *oct, u64 val, @@ -1369,6 +1389,7 @@ void lio_pci_writeq(struct octeon_device *oct, spin_unlock_irqrestore(&oct->pci_win_lock, flags); } +EXPORT_SYMBOL_GPL(lio_pci_writeq); int octeon_mem_access_ok(struct octeon_device *oct) { @@ -1388,6 +1409,7 @@ int octeon_mem_access_ok(struct octeon_device *oct) return access_okay ? 0 : 1; } +EXPORT_SYMBOL_GPL(octeon_mem_access_ok); int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout) { @@ -1408,6 +1430,7 @@ int octeon_wait_for_ddr_init(struct octeon_device *oct, u32 *timeout) return ret; } +EXPORT_SYMBOL_GPL(octeon_wait_for_ddr_init); /* Get the octeon id assigned to the octeon device passed as argument. * This function is exported to other modules. @@ -1462,3 +1485,4 @@ void lio_enable_irq(struct octeon_droq *droq, struct octeon_instr_queue *iq) } } } +EXPORT_SYMBOL_GPL(lio_enable_irq); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c index d4080bddcb6ba7..0d6ee30affb913 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_droq.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_droq.c @@ -107,6 +107,7 @@ u32 octeon_droq_check_hw_for_pkts(struct octeon_droq *droq) return last_count; } +EXPORT_SYMBOL_GPL(octeon_droq_check_hw_for_pkts); static void octeon_droq_compute_max_packet_bufs(struct octeon_droq *droq) { @@ -216,6 +217,7 @@ int octeon_delete_droq(struct octeon_device *oct, u32 q_no) return 0; } +EXPORT_SYMBOL_GPL(octeon_delete_droq); int octeon_init_droq(struct octeon_device *oct, u32 q_no, @@ -773,6 +775,7 @@ octeon_droq_process_packets(struct octeon_device *oct, return 0; } +EXPORT_SYMBOL_GPL(octeon_droq_process_packets); /* * Utility function to poll for packets. check_hw_for_packets must be @@ -921,6 +924,7 @@ int octeon_unregister_droq_ops(struct octeon_device *oct, u32 q_no) return 0; } +EXPORT_SYMBOL_GPL(octeon_unregister_droq_ops); int octeon_create_droq(struct octeon_device *oct, u32 q_no, u32 num_descs, diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c index 7ccab36143c171..d70132437af340 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_mem_ops.c @@ -164,6 +164,7 @@ octeon_pci_read_core_mem(struct octeon_device *oct, { __octeon_pci_rw_core_mem(oct, coreaddr, buf, len, 1); } +EXPORT_SYMBOL_GPL(octeon_pci_read_core_mem); void octeon_pci_write_core_mem(struct octeon_device *oct, @@ -173,6 +174,7 @@ octeon_pci_write_core_mem(struct octeon_device *oct, { __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)buf, len, 0); } +EXPORT_SYMBOL_GPL(octeon_pci_write_core_mem); u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr) { @@ -182,6 +184,7 @@ u64 octeon_read_device_mem64(struct octeon_device *oct, u64 coreaddr) return be64_to_cpu(ret); } +EXPORT_SYMBOL_GPL(octeon_read_device_mem64); u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr) { @@ -191,6 +194,7 @@ u32 octeon_read_device_mem32(struct octeon_device *oct, u64 coreaddr) return be32_to_cpu(ret); } +EXPORT_SYMBOL_GPL(octeon_read_device_mem32); void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr, u32 val) @@ -199,3 +203,4 @@ void octeon_write_device_mem32(struct octeon_device *oct, u64 coreaddr, __octeon_pci_rw_core_mem(oct, coreaddr, (u8 *)&t, 4, 0); } +EXPORT_SYMBOL_GPL(octeon_write_device_mem32); diff --git a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c index 1a706f81bbb0d9..dee56ea740e7c9 100644 --- a/drivers/net/ethernet/cavium/liquidio/octeon_nic.c +++ b/drivers/net/ethernet/cavium/liquidio/octeon_nic.c @@ -79,6 +79,7 @@ octeon_alloc_soft_command_resp(struct octeon_device *oct, return sc; } +EXPORT_SYMBOL_GPL(octeon_alloc_soft_command_resp); int octnet_send_nic_data_pkt(struct octeon_device *oct, struct octnic_data_pkt *ndata, @@ -90,6 +91,7 @@ int octnet_send_nic_data_pkt(struct octeon_device *oct, ndata->buf, ndata->datasize, ndata->reqtype); } +EXPORT_SYMBOL_GPL(octnet_send_nic_data_pkt); static inline struct octeon_soft_command *octnic_alloc_ctrl_pkt_sc(struct octeon_device *oct, @@ -196,3 +198,4 @@ octnet_send_nic_ctrl_pkt(struct octeon_device *oct, return retval; } +EXPORT_SYMBOL_GPL(octnet_send_nic_ctrl_pkt); diff --git a/drivers/net/ethernet/cavium/liquidio/request_manager.c b/drivers/net/ethernet/cavium/liquidio/request_manager.c index 32f854c0cd79bb..de8a6ce86ad7e2 100644 --- a/drivers/net/ethernet/cavium/liquidio/request_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/request_manager.c @@ -185,6 +185,7 @@ int octeon_delete_instr_queue(struct octeon_device *oct, u32 iq_no) } return 1; } +EXPORT_SYMBOL_GPL(octeon_delete_instr_queue); /* Return 0 on success, 1 on failure */ int octeon_setup_iq(struct octeon_device *oct, @@ -258,6 +259,7 @@ int lio_wait_for_instr_fetch(struct octeon_device *oct) return instr_cnt; } +EXPORT_SYMBOL_GPL(lio_wait_for_instr_fetch); static inline void ring_doorbell(struct octeon_device *oct, struct octeon_instr_queue *iq) @@ -282,6 +284,7 @@ octeon_ring_doorbell_locked(struct octeon_device *oct, u32 iq_no) ring_doorbell(oct, iq); spin_unlock(&iq->post_lock); } +EXPORT_SYMBOL_GPL(octeon_ring_doorbell_locked); static inline void __copy_cmd_into_iq(struct octeon_instr_queue *iq, u8 *cmd) @@ -345,6 +348,7 @@ octeon_register_reqtype_free_fn(struct octeon_device *oct, int reqtype, return 0; } +EXPORT_SYMBOL_GPL(octeon_register_reqtype_free_fn); static inline void __add_to_request_list(struct octeon_instr_queue *iq, @@ -430,6 +434,7 @@ lio_process_iq_request_list(struct octeon_device *oct, return inst_count; } +EXPORT_SYMBOL_GPL(lio_process_iq_request_list); /* Can only be called from process context */ int @@ -566,6 +571,7 @@ octeon_send_command(struct octeon_device *oct, u32 iq_no, return st.status; } +EXPORT_SYMBOL_GPL(octeon_send_command); void octeon_prepare_soft_command(struct octeon_device *oct, @@ -673,6 +679,7 @@ octeon_prepare_soft_command(struct octeon_device *oct, } } } +EXPORT_SYMBOL_GPL(octeon_prepare_soft_command); int octeon_send_soft_command(struct octeon_device *oct, struct octeon_soft_command *sc) @@ -726,6 +733,7 @@ int octeon_send_soft_command(struct octeon_device *oct, return (octeon_send_command(oct, sc->iq_no, 1, &sc->cmd, sc, len, REQTYPE_SOFT_COMMAND)); } +EXPORT_SYMBOL_GPL(octeon_send_soft_command); int octeon_setup_sc_buffer_pool(struct octeon_device *oct) { @@ -755,6 +763,7 @@ int octeon_setup_sc_buffer_pool(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_setup_sc_buffer_pool); int octeon_free_sc_done_list(struct octeon_device *oct) { @@ -794,6 +803,7 @@ int octeon_free_sc_done_list(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_free_sc_done_list); int octeon_free_sc_zombie_list(struct octeon_device *oct) { @@ -818,6 +828,7 @@ int octeon_free_sc_zombie_list(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_free_sc_zombie_list); int octeon_free_sc_buffer_pool(struct octeon_device *oct) { @@ -842,6 +853,7 @@ int octeon_free_sc_buffer_pool(struct octeon_device *oct) return 0; } +EXPORT_SYMBOL_GPL(octeon_free_sc_buffer_pool); struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct, u32 datasize, @@ -913,6 +925,7 @@ struct octeon_soft_command *octeon_alloc_soft_command(struct octeon_device *oct, return sc; } +EXPORT_SYMBOL_GPL(octeon_alloc_soft_command); void octeon_free_soft_command(struct octeon_device *oct, struct octeon_soft_command *sc) @@ -925,3 +938,4 @@ void octeon_free_soft_command(struct octeon_device *oct, spin_unlock_bh(&oct->sc_buf_pool.lock); } +EXPORT_SYMBOL_GPL(octeon_free_soft_command); diff --git a/drivers/net/ethernet/cavium/liquidio/response_manager.c b/drivers/net/ethernet/cavium/liquidio/response_manager.c index ac7747ccf56a03..861050966e1807 100644 --- a/drivers/net/ethernet/cavium/liquidio/response_manager.c +++ b/drivers/net/ethernet/cavium/liquidio/response_manager.c @@ -52,12 +52,14 @@ int octeon_setup_response_list(struct octeon_device *oct) return ret; } +EXPORT_SYMBOL_GPL(octeon_setup_response_list); void octeon_delete_response_list(struct octeon_device *oct) { cancel_delayed_work_sync(&oct->dma_comp_wq.wk.work); destroy_workqueue(oct->dma_comp_wq.wq); } +EXPORT_SYMBOL_GPL(octeon_delete_response_list); int lio_process_ordered_list(struct octeon_device *octeon_dev, u32 force_quit) @@ -219,6 +221,7 @@ int lio_process_ordered_list(struct octeon_device *octeon_dev, return 0; } +EXPORT_SYMBOL_GPL(lio_process_ordered_list); static void oct_poll_req_completion(struct work_struct *work) { diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h index 41714203ace898..da4818d2c85647 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls.h @@ -568,6 +568,7 @@ void chtls_destroy_sock(struct sock *sk); int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size); int chtls_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags, int *addr_len); +void chtls_splice_eof(struct socket *sock); int chtls_sendpage(struct sock *sk, struct page *page, int offset, size_t size, int flags); int send_tx_flowc_wr(struct sock *sk, int compl, diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c index ae6b17b96bf122..e08ac960c96709 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c @@ -1092,7 +1092,17 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) if (copy > size) copy = size; - if (skb_tailroom(skb) > 0) { + if (msg->msg_flags & MSG_SPLICE_PAGES) { + err = skb_splice_from_iter(skb, &msg->msg_iter, copy, + sk->sk_allocation); + if (err < 0) { + if (err == -EMSGSIZE) + goto new_buf; + goto do_fault; + } + copy = err; + sk_wmem_queued_add(sk, copy); + } else if (skb_tailroom(skb) > 0) { copy = min(copy, skb_tailroom(skb)); if (is_tls_tx(csk)) copy = min_t(int, copy, csk->tlshws.txleft); @@ -1227,113 +1237,27 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) goto done; } -int chtls_sendpage(struct sock *sk, struct page *page, - int offset, size_t size, int flags) +void chtls_splice_eof(struct socket *sock) { - struct chtls_sock *csk; - struct chtls_dev *cdev; - int mss, err, copied; - struct tcp_sock *tp; - long timeo; + struct sock *sk = sock->sk; - tp = tcp_sk(sk); - copied = 0; - csk = rcu_dereference_sk_user_data(sk); - cdev = csk->cdev; lock_sock(sk); - timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); - - err = sk_stream_wait_connect(sk, &timeo); - if (!sk_in_state(sk, TCPF_ESTABLISHED | TCPF_CLOSE_WAIT) && - err != 0) - goto out_err; - - mss = csk->mss; - csk_set_flag(csk, CSK_TX_MORE_DATA); - - while (size > 0) { - struct sk_buff *skb = skb_peek_tail(&csk->txq); - int copy, i; - - if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) || - (copy = mss - skb->len) <= 0) { -new_buf: - if (!csk_mem_free(cdev, sk)) - goto wait_for_sndbuf; - - if (is_tls_tx(csk)) { - skb = get_record_skb(sk, - select_size(sk, size, - flags, - TX_TLSHDR_LEN), - true); - } else { - skb = get_tx_skb(sk, 0); - } - if (!skb) - goto wait_for_memory; - copy = mss; - } - if (copy > size) - copy = size; - - i = skb_shinfo(skb)->nr_frags; - if (skb_can_coalesce(skb, i, page, offset)) { - skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy); - } else if (i < MAX_SKB_FRAGS) { - get_page(page); - skb_fill_page_desc(skb, i, page, offset, copy); - } else { - tx_skb_finalize(skb); - push_frames_if_head(sk); - goto new_buf; - } - - skb->len += copy; - if (skb->len == mss) - tx_skb_finalize(skb); - skb->data_len += copy; - skb->truesize += copy; - sk->sk_wmem_queued += copy; - tp->write_seq += copy; - copied += copy; - offset += copy; - size -= copy; - - if (corked(tp, flags) && - (sk_stream_wspace(sk) < sk_stream_min_wspace(sk))) - ULP_SKB_CB(skb)->flags |= ULPCB_FLAG_NO_APPEND; - - if (!size) - break; - - if (unlikely(ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND)) - push_frames_if_head(sk); - continue; -wait_for_sndbuf: - set_bit(SOCK_NOSPACE, &sk->sk_socket->flags); -wait_for_memory: - err = csk_wait_memory(cdev, sk, &timeo); - if (err) - goto do_error; - } -out: - csk_reset_flag(csk, CSK_TX_MORE_DATA); - if (copied) - chtls_tcp_push(sk, flags); -done: + chtls_tcp_push(sk, 0); release_sock(sk); - return copied; +} -do_error: - if (copied) - goto out; +int chtls_sendpage(struct sock *sk, struct page *page, + int offset, size_t size, int flags) +{ + struct msghdr msg = { .msg_flags = flags | MSG_SPLICE_PAGES, }; + struct bio_vec bvec; -out_err: - if (csk_conn_inline(csk)) - csk_reset_flag(csk, CSK_TX_MORE_DATA); - copied = sk_stream_error(sk, flags, err); - goto done; + if (flags & MSG_SENDPAGE_NOTLAST) + msg.msg_flags |= MSG_MORE; + + bvec_set_page(&bvec, page, size, offset); + iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, &bvec, 1, size); + return chtls_sendmsg(sk, &msg, size); } static void chtls_select_window(struct sock *sk) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c index 1e55b12fee5168..6b6787eafd2fbf 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c @@ -606,6 +606,7 @@ static void __init chtls_init_ulp_ops(void) chtls_cpl_prot.destroy = chtls_destroy_sock; chtls_cpl_prot.shutdown = chtls_shutdown; chtls_cpl_prot.sendmsg = chtls_sendmsg; + chtls_cpl_prot.splice_eof = chtls_splice_eof; chtls_cpl_prot.sendpage = chtls_sendpage; chtls_cpl_prot.recvmsg = chtls_recvmsg; chtls_cpl_prot.setsockopt = chtls_setsockopt; diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c index 84751bb303a684..6222aaa5157f18 100644 --- a/drivers/net/ethernet/engleder/tsnep_main.c +++ b/drivers/net/ethernet/engleder/tsnep_main.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #define TSNEP_RX_OFFSET (max(NET_SKB_PAD, XDP_PACKET_HEADROOM) + NET_IP_ALIGN) diff --git a/drivers/net/ethernet/engleder/tsnep_selftests.c b/drivers/net/ethernet/engleder/tsnep_selftests.c index 1581d6b2223207..8a9145f93147c6 100644 --- a/drivers/net/ethernet/engleder/tsnep_selftests.c +++ b/drivers/net/ethernet/engleder/tsnep_selftests.c @@ -329,7 +329,7 @@ static bool disable_taprio(struct tsnep_adapter *adapter) int retval; memset(&qopt, 0, sizeof(qopt)); - qopt.enable = 0; + qopt.cmd = TAPRIO_CMD_DESTROY; retval = tsnep_tc_setup(adapter->netdev, TC_SETUP_QDISC_TAPRIO, &qopt); if (retval) return false; @@ -360,7 +360,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter) for (i = 0; i < 255; i++) qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 1500000; qopt->cycle_time_extension = 0; @@ -382,7 +382,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter) if (!run_taprio(adapter, qopt, 100)) goto failed; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 411854; qopt->cycle_time_extension = 0; @@ -406,7 +406,7 @@ static bool tsnep_test_taprio(struct tsnep_adapter *adapter) if (!run_taprio(adapter, qopt, 100)) goto failed; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); delay_base_time(adapter, qopt, 12); qopt->cycle_time = 125000; @@ -457,7 +457,7 @@ static bool tsnep_test_taprio_change(struct tsnep_adapter *adapter) for (i = 0; i < 255; i++) qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 100000; qopt->cycle_time_extension = 0; @@ -610,7 +610,7 @@ static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter) for (i = 0; i < 255; i++) qopt->entries[i].command = TC_TAPRIO_CMD_SET_GATES; - qopt->enable = 1; + qopt->cmd = TAPRIO_CMD_REPLACE; qopt->base_time = ktime_set(0, 0); qopt->cycle_time = 100000; qopt->cycle_time_extension = 50000; diff --git a/drivers/net/ethernet/engleder/tsnep_tc.c b/drivers/net/ethernet/engleder/tsnep_tc.c index d083e6684f1208..745b191a554022 100644 --- a/drivers/net/ethernet/engleder/tsnep_tc.c +++ b/drivers/net/ethernet/engleder/tsnep_tc.c @@ -325,7 +325,7 @@ static int tsnep_taprio(struct tsnep_adapter *adapter, if (!adapter->gate_control) return -EOPNOTSUPP; - if (!qopt->enable) { + if (qopt->cmd == TAPRIO_CMD_DESTROY) { /* disable gate control if active */ mutex_lock(&adapter->gate_control_lock); @@ -337,6 +337,8 @@ static int tsnep_taprio(struct tsnep_adapter *adapter, mutex_unlock(&adapter->gate_control_lock); return 0; + } else if (qopt->cmd != TAPRIO_CMD_REPLACE) { + return -EOPNOTSUPP; } retval = tsnep_validate_gcl(qopt); diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c index b1871e6c400694..d860d9fe73af05 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c @@ -247,8 +247,8 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac, struct fwnode_handle *dpmac_node, int id) { - struct mdio_device *mdiodev; struct fwnode_handle *node; + struct phylink_pcs *pcs; node = fwnode_find_reference(dpmac_node, "pcs-handle", 0); if (IS_ERR(node)) { @@ -257,26 +257,27 @@ static int dpaa2_pcs_create(struct dpaa2_mac *mac, return 0; } - if (!fwnode_device_is_available(node)) { - netdev_err(mac->net_dev, "pcs-handle node not available\n"); - fwnode_handle_put(node); - return -ENODEV; - } - - mdiodev = fwnode_mdio_find_device(node); + pcs = lynx_pcs_create_fwnode(node); fwnode_handle_put(node); - if (!mdiodev) { + + if (pcs == ERR_PTR(-EPROBE_DEFER)) { netdev_dbg(mac->net_dev, "missing PCS device\n"); return -EPROBE_DEFER; } - mac->pcs = lynx_pcs_create(mdiodev); - if (!mac->pcs) { - netdev_err(mac->net_dev, "lynx_pcs_create() failed\n"); - put_device(&mdiodev->dev); - return -ENOMEM; + if (pcs == ERR_PTR(-ENODEV)) { + netdev_err(mac->net_dev, "pcs-handle node not available\n"); + return PTR_ERR(pcs); + } + + if (IS_ERR(pcs)) { + netdev_err(mac->net_dev, + "lynx_pcs_create_fwnode() failed: %pe\n", pcs); + return PTR_ERR(pcs); } + mac->pcs = pcs; + return 0; } @@ -285,11 +286,7 @@ static void dpaa2_pcs_destroy(struct dpaa2_mac *mac) struct phylink_pcs *phylink_pcs = mac->pcs; if (phylink_pcs) { - struct mdio_device *mdio = lynx_get_mdio_device(phylink_pcs); - struct device *dev = &mdio->dev; - lynx_pcs_destroy(phylink_pcs); - put_device(dev); mac->pcs = NULL; } } diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c index 63854294ac33e1..164b73df9f6bd1 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.c +++ b/drivers/net/ethernet/freescale/enetc/enetc.c @@ -1229,7 +1229,13 @@ static int enetc_clean_rx_ring(struct enetc_bdr *rx_ring, if (!skb) break; - rx_byte_cnt += skb->len; + /* When set, the outer VLAN header is extracted and reported + * in the receive buffer descriptor. So rx_byte_cnt should + * add the length of the extracted VLAN header. + */ + if (bd_status & ENETC_RXBD_FLAG_VLAN) + rx_byte_cnt += VLAN_HLEN; + rx_byte_cnt += skb->len + ETH_HLEN; rx_frm_cnt++; napi_gro_receive(napi, skb); @@ -1564,6 +1570,14 @@ static int enetc_clean_rx_ring_xdp(struct enetc_bdr *rx_ring, enetc_build_xdp_buff(rx_ring, bd_status, &rxbd, &i, &cleaned_cnt, &xdp_buff); + /* When set, the outer VLAN header is extracted and reported + * in the receive buffer descriptor. So rx_byte_cnt should + * add the length of the extracted VLAN header. + */ + if (bd_status & ENETC_RXBD_FLAG_VLAN) + rx_byte_cnt += VLAN_HLEN; + rx_byte_cnt += xdp_get_buff_len(&xdp_buff); + xdp_act = bpf_prog_run_xdp(prog, &xdp_buff); switch (xdp_act) { @@ -2624,7 +2638,7 @@ static void enetc_debug_tx_ring_prios(struct enetc_ndev_priv *priv) priv->tx_ring[i]->prio); } -static void enetc_reset_tc_mqprio(struct net_device *ndev) +void enetc_reset_tc_mqprio(struct net_device *ndev) { struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_hw *hw = &priv->si->hw; @@ -2649,6 +2663,7 @@ static void enetc_reset_tc_mqprio(struct net_device *ndev) enetc_change_preemptible_tcs(priv, 0); } +EXPORT_SYMBOL_GPL(enetc_reset_tc_mqprio); int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data) { diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index c97a8e3d7a7fe4..8577cf7699a042 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -429,6 +429,7 @@ struct net_device_stats *enetc_get_stats(struct net_device *ndev); void enetc_set_features(struct net_device *ndev, netdev_features_t features); int enetc_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd); int enetc_setup_tc_mqprio(struct net_device *ndev, void *type_data); +void enetc_reset_tc_mqprio(struct net_device *ndev); int enetc_setup_bpf(struct net_device *ndev, struct netdev_bpf *bpf); int enetc_xdp_xmit(struct net_device *ndev, int num_frames, struct xdp_frame **frames, u32 flags); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 7cd22d370caa3a..1416262d42967a 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -863,7 +863,6 @@ static int enetc_imdio_create(struct enetc_pf *pf) struct device *dev = &pf->si->pdev->dev; struct enetc_mdio_priv *mdio_priv; struct phylink_pcs *phylink_pcs; - struct mdio_device *mdio_device; struct mii_bus *bus; int err; @@ -889,17 +888,9 @@ static int enetc_imdio_create(struct enetc_pf *pf) goto free_mdio_bus; } - mdio_device = mdio_device_create(bus, 0); - if (IS_ERR(mdio_device)) { - err = PTR_ERR(mdio_device); - dev_err(dev, "cannot create mdio device (%d)\n", err); - goto unregister_mdiobus; - } - - phylink_pcs = lynx_pcs_create(mdio_device); - if (!phylink_pcs) { - mdio_device_free(mdio_device); - err = -ENOMEM; + phylink_pcs = lynx_pcs_create_mdiodev(bus, 0); + if (IS_ERR(phylink_pcs)) { + err = PTR_ERR(phylink_pcs); dev_err(dev, "cannot create lynx pcs (%d)\n", err); goto unregister_mdiobus; } @@ -918,13 +909,8 @@ static int enetc_imdio_create(struct enetc_pf *pf) static void enetc_imdio_remove(struct enetc_pf *pf) { - struct mdio_device *mdio_device; - - if (pf->pcs) { - mdio_device = lynx_get_mdio_device(pf->pcs); - mdio_device_free(mdio_device); + if (pf->pcs) lynx_pcs_destroy(pf->pcs); - } if (pf->imdio) { mdiobus_unregister(pf->imdio); mdiobus_free(pf->imdio); diff --git a/drivers/net/ethernet/freescale/enetc/enetc_qos.c b/drivers/net/ethernet/freescale/enetc/enetc_qos.c index 83c27bbbc6edff..9d74104df7c82b 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_qos.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_qos.c @@ -43,10 +43,9 @@ void enetc_sched_speed_set(struct enetc_ndev_priv *priv, int speed) enetc_port_wr(hw, ENETC_PMR, (tmp & ~ENETC_PMR_PSPEED_MASK) | pspeed); } -static int enetc_setup_taprio(struct net_device *ndev, +static int enetc_setup_taprio(struct enetc_ndev_priv *priv, struct tc_taprio_qopt_offload *admin_conf) { - struct enetc_ndev_priv *priv = netdev_priv(ndev); struct enetc_hw *hw = &priv->si->hw; struct enetc_cbd cbd = {.cmd = 0}; struct tgs_gcl_conf *gcl_config; @@ -60,19 +59,13 @@ static int enetc_setup_taprio(struct net_device *ndev, int err; int i; + /* TSD and Qbv are mutually exclusive in hardware */ + for (i = 0; i < priv->num_tx_rings; i++) + if (priv->tx_ring[i]->tsd_enable) + return -EBUSY; + if (admin_conf->num_entries > enetc_get_max_gcl_len(hw)) return -EINVAL; - gcl_len = admin_conf->num_entries; - - tge = enetc_rd(hw, ENETC_PTGCR); - if (!admin_conf->enable) { - enetc_wr(hw, ENETC_PTGCR, tge & ~ENETC_PTGCR_TGE); - enetc_reset_ptcmsdur(hw); - - priv->active_offloads &= ~ENETC_F_QBV; - - return 0; - } if (admin_conf->cycle_time > U32_MAX || admin_conf->cycle_time_extension > U32_MAX) @@ -82,6 +75,7 @@ static int enetc_setup_taprio(struct net_device *ndev, * control BD descriptor. */ gcl_config = &cbd.gcl_conf; + gcl_len = admin_conf->num_entries; data_size = struct_size(gcl_data, entry, gcl_len); tmp = enetc_cbd_alloc_data_mem(priv->si, &cbd, data_size, @@ -115,6 +109,7 @@ static int enetc_setup_taprio(struct net_device *ndev, cbd.cls = BDCR_CMD_PORT_GCL; cbd.status_flags = 0; + tge = enetc_rd(hw, ENETC_PTGCR); enetc_wr(hw, ENETC_PTGCR, tge | ENETC_PTGCR_TGE); err = enetc_send_cmd(priv->si, &cbd); @@ -132,25 +127,95 @@ static int enetc_setup_taprio(struct net_device *ndev, return 0; } -int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) +static void enetc_reset_taprio_stats(struct enetc_ndev_priv *priv) +{ + int i; + + for (i = 0; i < priv->num_tx_rings; i++) + priv->tx_ring[i]->stats.win_drop = 0; +} + +static void enetc_reset_taprio(struct enetc_ndev_priv *priv) +{ + struct enetc_hw *hw = &priv->si->hw; + u32 val; + + val = enetc_rd(hw, ENETC_PTGCR); + enetc_wr(hw, ENETC_PTGCR, val & ~ENETC_PTGCR_TGE); + enetc_reset_ptcmsdur(hw); + + priv->active_offloads &= ~ENETC_F_QBV; +} + +static void enetc_taprio_destroy(struct net_device *ndev) { - struct tc_taprio_qopt_offload *taprio = type_data; struct enetc_ndev_priv *priv = netdev_priv(ndev); - int err, i; - /* TSD and Qbv are mutually exclusive in hardware */ + enetc_reset_taprio(priv); + enetc_reset_tc_mqprio(ndev); + enetc_reset_taprio_stats(priv); +} + +static void enetc_taprio_stats(struct net_device *ndev, + struct tc_taprio_qopt_stats *stats) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + u64 window_drops = 0; + int i; + for (i = 0; i < priv->num_tx_rings; i++) - if (priv->tx_ring[i]->tsd_enable) - return -EBUSY; + window_drops += priv->tx_ring[i]->stats.win_drop; + + stats->window_drops = window_drops; +} + +static void enetc_taprio_queue_stats(struct net_device *ndev, + struct tc_taprio_qopt_queue_stats *queue_stats) +{ + struct tc_taprio_qopt_stats *stats = &queue_stats->stats; + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int queue = queue_stats->queue; - err = enetc_setup_tc_mqprio(ndev, &taprio->mqprio); + stats->window_drops = priv->tx_ring[queue]->stats.win_drop; +} + +static int enetc_taprio_replace(struct net_device *ndev, + struct tc_taprio_qopt_offload *offload) +{ + struct enetc_ndev_priv *priv = netdev_priv(ndev); + int err; + + err = enetc_setup_tc_mqprio(ndev, &offload->mqprio); if (err) return err; - err = enetc_setup_taprio(ndev, taprio); - if (err) { - taprio->mqprio.qopt.num_tc = 0; - enetc_setup_tc_mqprio(ndev, &taprio->mqprio); + err = enetc_setup_taprio(priv, offload); + if (err) + enetc_reset_tc_mqprio(ndev); + + return err; +} + +int enetc_setup_tc_taprio(struct net_device *ndev, void *type_data) +{ + struct tc_taprio_qopt_offload *offload = type_data; + int err = 0; + + switch (offload->cmd) { + case TAPRIO_CMD_REPLACE: + err = enetc_taprio_replace(ndev, offload); + break; + case TAPRIO_CMD_DESTROY: + enetc_taprio_destroy(ndev); + break; + case TAPRIO_CMD_STATS: + enetc_taprio_stats(ndev, &offload->stats); + break; + case TAPRIO_CMD_QUEUE_STATS: + enetc_taprio_queue_stats(ndev, &offload->queue_stats); + break; + default: + err = -EOPNOTSUPP; } return err; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 6d0b46c76924c3..235388c3aa3cbb 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -1011,24 +1012,6 @@ static void fec_enet_enable_ring(struct net_device *ndev) } } -static void fec_enet_reset_skb(struct net_device *ndev) -{ - struct fec_enet_private *fep = netdev_priv(ndev); - struct fec_enet_priv_tx_q *txq; - int i, j; - - for (i = 0; i < fep->num_tx_queues; i++) { - txq = fep->tx_queue[i]; - - for (j = 0; j < txq->bd.ring_size; j++) { - if (txq->tx_skbuff[j]) { - dev_kfree_skb_any(txq->tx_skbuff[j]); - txq->tx_skbuff[j] = NULL; - } - } - } -} - /* * This function is called to start or restart the FEC during a link * change, transmit timeout, or to reconfigure the FEC. The network @@ -1071,9 +1054,6 @@ fec_restart(struct net_device *ndev) fec_enet_enable_ring(ndev); - /* Reset tx SKB buffers. */ - fec_enet_reset_skb(ndev); - /* Enable MII mode */ if (fep->full_duplex == DUPLEX_FULL) { /* FD enable */ @@ -3791,7 +3771,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, struct xdp_frame *frame) { unsigned int index, status, estatus; - struct bufdesc *bdp, *last_bdp; + struct bufdesc *bdp; dma_addr_t dma_addr; int entries_free; @@ -3803,7 +3783,6 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, /* Fill in a Tx ring entry */ bdp = txq->bd.cur; - last_bdp = bdp; status = fec16_to_cpu(bdp->cbd_sc); status &= ~BD_ENET_TX_STATS; @@ -3831,9 +3810,13 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, ebdp->cbd_esc = cpu_to_fec32(estatus); } - index = fec_enet_get_bd_index(last_bdp, &txq->bd); txq->tx_skbuff[index] = NULL; + /* Make sure the updates to rest of the descriptor are performed before + * transferring ownership. + */ + dma_wmb(); + /* Send it on its way. Tell FEC it's ready, interrupt when done, * it's the last BD of the frame, and to put the CRC on the end. */ @@ -3841,10 +3824,16 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep, bdp->cbd_sc = cpu_to_fec16(status); /* If this was the last BD in the ring, start at the beginning again. */ - bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); + bdp = fec_enet_get_nextdesc(bdp, &txq->bd); + + /* Make sure the update to bdp are performed before txq->bd.cur. */ + dma_wmb(); txq->bd.cur = bdp; + /* Trigger transmission start */ + writel(0, txq->bd.reg_desc_active); + return 0; } @@ -3873,12 +3862,6 @@ static int fec_enet_xdp_xmit(struct net_device *dev, sent_frames++; } - /* Make sure the update to bdp and tx_skbuff are performed. */ - wmb(); - - /* Trigger transmission start */ - writel(0, txq->bd.reg_desc_active); - __netif_tx_unlock(nq); return sent_frames; @@ -4030,6 +4013,11 @@ static int fec_enet_init(struct net_device *ndev) ndev->hw_features = ndev->features; + if (!(fep->quirks & FEC_QUIRK_SWAP_FRAME)) + ndev->xdp_features = NETDEV_XDP_ACT_BASIC | + NETDEV_XDP_ACT_REDIRECT | + NETDEV_XDP_ACT_NDO_XMIT; + fec_restart(ndev); if (fep->quirks & FEC_QUIRK_MIB_CLEAR) diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index 625c79d5636fbd..3b75cc543be93f 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -976,14 +976,10 @@ static int memac_init(struct fman_mac *memac) static void pcs_put(struct phylink_pcs *pcs) { - struct mdio_device *mdiodev; - if (IS_ERR_OR_NULL(pcs)) return; - mdiodev = lynx_get_mdio_device(pcs); lynx_pcs_destroy(pcs); - mdio_device_free(mdiodev); } static int memac_free(struct fman_mac *memac) @@ -1043,20 +1039,14 @@ static struct phylink_pcs *memac_pcs_create(struct device_node *mac_node, int index) { struct device_node *node; - struct mdio_device *mdiodev = NULL; struct phylink_pcs *pcs; node = of_parse_phandle(mac_node, "pcsphy-handle", index); - if (node && of_device_is_available(node)) - mdiodev = of_mdio_find_device(node); - of_node_put(node); + if (!node) + return ERR_PTR(-ENODEV); - if (!mdiodev) - return ERR_PTR(-EPROBE_DEFER); - - pcs = lynx_pcs_create(mdiodev); - if (!pcs) - mdio_device_free(mdiodev); + pcs = lynx_pcs_create_fwnode(of_fwnode_handle(node)); + of_node_put(node); return pcs; } diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index caa00c72aeebaa..8fb70db63b8b88 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -31,6 +31,7 @@ // Minimum amount of time between queue kicks in msec (10 seconds) #define MIN_TX_TIMEOUT_GAP (1000 * 10) +#define DQO_TX_MAX 0x3FFFF const char gve_version_str[] = GVE_VERSION; static const char gve_version_prefix[] = GVE_VERSION_PREFIX; @@ -2047,6 +2048,10 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device) goto err; } + /* Big TCP is only supported on DQ*/ + if (!gve_is_gqi(priv)) + netif_set_tso_max_size(priv->dev, DQO_TX_MAX); + priv->num_registered_pages = 0; priv->rx_copybreak = GVE_DEFAULT_RX_COPYBREAK; /* gvnic has one Notification Block per MSI-x vector, except for the diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c index b76143bfd59479..3c09e66ba1ab11 100644 --- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c +++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c @@ -8,6 +8,7 @@ #include "gve_adminq.h" #include "gve_utils.h" #include "gve_dqo.h" +#include #include #include #include @@ -646,6 +647,9 @@ static int gve_try_tx_skb(struct gve_priv *priv, struct gve_tx_ring *tx, goto drop; } + if (unlikely(ipv6_hopopt_jumbo_remove(skb))) + goto drop; + num_buffer_descs = gve_num_buffer_descs_needed(skb); } else { num_buffer_descs = gve_num_buffer_descs_needed(skb); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index b676496ec6d7ce..4e613d5bf1fd1f 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -4925,8 +4925,7 @@ static void hns3_put_ring_config(struct hns3_nic_priv *priv) static void hns3_alloc_page_pool(struct hns3_enet_ring *ring) { struct page_pool_params pp_params = { - .flags = PP_FLAG_DMA_MAP | PP_FLAG_PAGE_FRAG | - PP_FLAG_DMA_SYNC_DEV, + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, .order = hns3_page_order(ring), .pool_size = ring->desc_num * hns3_buf_size(ring) / (PAGE_SIZE << hns3_page_order(ring)), diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 9bc0a951989964..a368afc42b8d18 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig @@ -84,6 +84,13 @@ config E1000E_HWTS devices. The cross-timestamp is available through the PTP clock driver precise cross-timestamp ioctl (PTP_SYS_OFFSET_PRECISE). +config LIBIE + tristate + select PAGE_POOL + help + libie (Intel Ethernet library) is a common library containing + routines shared by several Intel Ethernet drivers. + config IGB tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support" depends on PCI @@ -225,6 +232,7 @@ config I40E depends on PTP_1588_CLOCK_OPTIONAL depends on PCI select AUXILIARY_BUS + select LIBIE help This driver supports Intel(R) Ethernet Controller XL710 Family of devices. For more information on how to identify your adapter, go @@ -254,8 +262,9 @@ config IAVF tristate config I40EVF tristate "Intel(R) Ethernet Adaptive Virtual Function support" - select IAVF depends on PCI_MSI + select IAVF + select LIBIE help This driver supports virtual functions for Intel XL710, X710, X722, XXV710, and all devices advertising support for @@ -282,6 +291,7 @@ config ICE depends on GNSS || GNSS = n select AUXILIARY_BUS select DIMLIB + select LIBIE select NET_DEVLINK select PLDMFW help diff --git a/drivers/net/ethernet/intel/Makefile b/drivers/net/ethernet/intel/Makefile index d80d04132073ca..ce622b4d825df7 100644 --- a/drivers/net/ethernet/intel/Makefile +++ b/drivers/net/ethernet/intel/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_I40E) += i40e/ obj-$(CONFIG_IAVF) += iavf/ obj-$(CONFIG_FM10K) += fm10k/ obj-$(CONFIG_ICE) += ice/ +obj-$(CONFIG_LIBIE) += libie/ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index bd7ef59b1f2e74..771a3c909c459e 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4198,7 +4198,7 @@ void e1000e_reset(struct e1000_adapter *adapter) /** * e1000e_trigger_lsc - trigger an LSC interrupt - * @adapter: + * @adapter: board private structure * * Fire a link status change interrupt to start the watchdog. **/ diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index ed88e38d488b2d..25bb858268fcd6 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -383,259 +383,6 @@ int i40e_aq_set_rss_key(struct i40e_hw *hw, return i40e_aq_get_set_rss_key(hw, vsi_id, key, true); } -/* The i40e_ptype_lookup table is used to convert from the 8-bit ptype in the - * hardware to a bit-field that can be used by SW to more easily determine the - * packet type. - * - * Macros are used to shorten the table lines and make this table human - * readable. - * - * We store the PTYPE in the top byte of the bit field - this is just so that - * we can check that the table doesn't have a row missing, as the index into - * the table should be the PTYPE. - * - * Typical work flow: - * - * IF NOT i40e_ptype_lookup[ptype].known - * THEN - * Packet is unknown - * ELSE IF i40e_ptype_lookup[ptype].outer_ip == I40E_RX_PTYPE_OUTER_IP - * Use the rest of the fields to look at the tunnels, inner protocols, etc - * ELSE - * Use the enum i40e_rx_l2_ptype to decode the packet type - * ENDIF - */ - -/* macro to make the table lines short, use explicit indexing with [PTYPE] */ -#define I40E_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\ - [PTYPE] = { \ - 1, \ - I40E_RX_PTYPE_OUTER_##OUTER_IP, \ - I40E_RX_PTYPE_OUTER_##OUTER_IP_VER, \ - I40E_RX_PTYPE_##OUTER_FRAG, \ - I40E_RX_PTYPE_TUNNEL_##T, \ - I40E_RX_PTYPE_TUNNEL_END_##TE, \ - I40E_RX_PTYPE_##TEF, \ - I40E_RX_PTYPE_INNER_PROT_##I, \ - I40E_RX_PTYPE_PAYLOAD_LAYER_##PL } - -#define I40E_PTT_UNUSED_ENTRY(PTYPE) [PTYPE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } - -/* shorter macros makes the table fit but are terse */ -#define I40E_RX_PTYPE_NOF I40E_RX_PTYPE_NOT_FRAG -#define I40E_RX_PTYPE_FRG I40E_RX_PTYPE_FRAG -#define I40E_RX_PTYPE_INNER_PROT_TS I40E_RX_PTYPE_INNER_PROT_TIMESYNC - -/* Lookup table mapping in the 8-bit HW PTYPE to the bit field for decoding */ -struct i40e_rx_ptype_decoded i40e_ptype_lookup[BIT(8)] = { - /* L2 Packet types */ - I40E_PTT_UNUSED_ENTRY(0), - I40E_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - I40E_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2), - I40E_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - I40E_PTT_UNUSED_ENTRY(4), - I40E_PTT_UNUSED_ENTRY(5), - I40E_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - I40E_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - I40E_PTT_UNUSED_ENTRY(8), - I40E_PTT_UNUSED_ENTRY(9), - I40E_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - I40E_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), - I40E_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - - /* Non Tunneled IPv4 */ - I40E_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(25), - I40E_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4), - I40E_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4), - I40E_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4), - - /* IPv4 --> IPv4 */ - I40E_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3), - I40E_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3), - I40E_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(32), - I40E_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4), - I40E_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), - I40E_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> IPv6 */ - I40E_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3), - I40E_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3), - I40E_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(39), - I40E_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4), - I40E_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), - I40E_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT */ - I40E_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), - - /* IPv4 --> GRE/NAT --> IPv4 */ - I40E_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), - I40E_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), - I40E_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(47), - I40E_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), - I40E_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), - I40E_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> IPv6 */ - I40E_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), - I40E_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), - I40E_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(54), - I40E_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), - I40E_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), - I40E_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> MAC */ - I40E_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), - - /* IPv4 --> GRE/NAT --> MAC --> IPv4 */ - I40E_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), - I40E_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), - I40E_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(62), - I40E_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), - I40E_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), - I40E_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT -> MAC --> IPv6 */ - I40E_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), - I40E_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), - I40E_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(69), - I40E_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), - I40E_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), - I40E_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> MAC/VLAN */ - I40E_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), - - /* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */ - I40E_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), - I40E_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), - I40E_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(77), - I40E_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), - I40E_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), - I40E_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), - - /* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */ - I40E_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), - I40E_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), - I40E_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(84), - I40E_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), - I40E_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), - I40E_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), - - /* Non Tunneled IPv6 */ - I40E_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), - I40E_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(91), - I40E_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), - I40E_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), - I40E_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4), - - /* IPv6 --> IPv4 */ - I40E_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3), - I40E_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3), - I40E_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(98), - I40E_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4), - I40E_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), - I40E_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> IPv6 */ - I40E_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3), - I40E_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3), - I40E_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(105), - I40E_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4), - I40E_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), - I40E_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT */ - I40E_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> IPv4 */ - I40E_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), - I40E_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), - I40E_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(113), - I40E_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), - I40E_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), - I40E_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> IPv6 */ - I40E_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), - I40E_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), - I40E_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(120), - I40E_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), - I40E_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), - I40E_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC */ - I40E_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> MAC -> IPv4 */ - I40E_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), - I40E_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), - I40E_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(128), - I40E_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), - I40E_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), - I40E_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC -> IPv6 */ - I40E_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), - I40E_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), - I40E_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(135), - I40E_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), - I40E_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), - I40E_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC/VLAN */ - I40E_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */ - I40E_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), - I40E_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), - I40E_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(143), - I40E_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), - I40E_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), - I40E_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */ - I40E_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), - I40E_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), - I40E_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), - I40E_PTT_UNUSED_ENTRY(150), - I40E_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), - I40E_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), - I40E_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), - - /* unused entries */ - [154 ... 255] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } -}; - /** * i40e_init_shared_code - Initialize the shared code * @hw: pointer to hardware structure diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index b847bd105b16e7..f3bca6e9bd1837 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -97,6 +97,7 @@ MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver"); +MODULE_IMPORT_NS(LIBIE); MODULE_LICENSE("GPL v2"); static struct workqueue_struct *i40e_wq; diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h index fe845987d99a55..5287d0ef32d5c7 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h +++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h @@ -380,13 +380,6 @@ void i40e_set_pci_config_data(struct i40e_hw *hw, u16 link_status); int i40e_set_mac_type(struct i40e_hw *hw); -extern struct i40e_rx_ptype_decoded i40e_ptype_lookup[]; - -static inline struct i40e_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype) -{ - return i40e_ptype_lookup[ptype]; -} - /** * i40e_virtchnl_link_speed - Convert AdminQ link_speed to virtchnl definition * @link_speed: the speed to convert diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 8b8bf4880faa62..c4b6cdbf361107 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2013 - 2018 Intel Corporation. */ -#include #include +#include +#include #include #include #include "i40e.h" @@ -1758,40 +1759,32 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, struct sk_buff *skb, union i40e_rx_desc *rx_desc) { - struct i40e_rx_ptype_decoded decoded; + struct libie_rx_ptype_parsed parsed; u32 rx_error, rx_status; bool ipv4, ipv6; u8 ptype; u64 qword; + skb->ip_summed = CHECKSUM_NONE; + qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); ptype = (qword & I40E_RXD_QW1_PTYPE_MASK) >> I40E_RXD_QW1_PTYPE_SHIFT; + + parsed = libie_parse_rx_ptype(ptype); + if (!libie_has_rx_checksum(vsi->netdev, parsed)) + return; + rx_error = (qword & I40E_RXD_QW1_ERROR_MASK) >> I40E_RXD_QW1_ERROR_SHIFT; rx_status = (qword & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; - decoded = decode_rx_desc_ptype(ptype); - - skb->ip_summed = CHECKSUM_NONE; - - skb_checksum_none_assert(skb); - - /* Rx csum enabled and ip headers found? */ - if (!(vsi->netdev->features & NETIF_F_RXCSUM)) - return; /* did the hardware decode the packet and checksum? */ if (!(rx_status & BIT(I40E_RX_DESC_STATUS_L3L4P_SHIFT))) return; - /* both known and outer_ip must be set for the below code to work */ - if (!(decoded.known && decoded.outer_ip)) - return; - - ipv4 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) && - (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV4); - ipv6 = (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP) && - (decoded.outer_ip_ver == I40E_RX_PTYPE_OUTER_IPV6); + ipv4 = parsed.outer_ip == LIBIE_RX_PTYPE_OUTER_IPV4; + ipv6 = parsed.outer_ip == LIBIE_RX_PTYPE_OUTER_IPV6; if (ipv4 && (rx_error & (BIT(I40E_RX_DESC_ERROR_IPE_SHIFT) | @@ -1819,49 +1812,16 @@ static inline void i40e_rx_checksum(struct i40e_vsi *vsi, * we need to bump the checksum level by 1 to reflect the fact that * we are indicating we validated the inner checksum. */ - if (decoded.tunnel_type >= I40E_RX_PTYPE_TUNNEL_IP_GRENAT) + if (parsed.tunnel_type >= LIBIE_RX_PTYPE_TUNNEL_IP_GRENAT) skb->csum_level = 1; - /* Only report checksum unnecessary for TCP, UDP, or SCTP */ - switch (decoded.inner_prot) { - case I40E_RX_PTYPE_INNER_PROT_TCP: - case I40E_RX_PTYPE_INNER_PROT_UDP: - case I40E_RX_PTYPE_INNER_PROT_SCTP: - skb->ip_summed = CHECKSUM_UNNECESSARY; - fallthrough; - default: - break; - } - + skb->ip_summed = CHECKSUM_UNNECESSARY; return; checksum_fail: vsi->back->hw_csum_rx_error++; } -/** - * i40e_ptype_to_htype - get a hash type - * @ptype: the ptype value from the descriptor - * - * Returns a hash type to be used by skb_set_hash - **/ -static inline int i40e_ptype_to_htype(u8 ptype) -{ - struct i40e_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype); - - if (!decoded.known) - return PKT_HASH_TYPE_NONE; - - if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP && - decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4) - return PKT_HASH_TYPE_L4; - else if (decoded.outer_ip == I40E_RX_PTYPE_OUTER_IP && - decoded.payload_layer == I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3) - return PKT_HASH_TYPE_L3; - else - return PKT_HASH_TYPE_L2; -} - /** * i40e_rx_hash - set the hash value in the skb * @ring: descriptor ring @@ -1874,17 +1834,19 @@ static inline void i40e_rx_hash(struct i40e_ring *ring, struct sk_buff *skb, u8 rx_ptype) { + struct libie_rx_ptype_parsed parsed; u32 hash; const __le64 rss_mask = cpu_to_le64((u64)I40E_RX_DESC_FLTSTAT_RSS_HASH << I40E_RX_DESC_STATUS_FLTSTAT_SHIFT); - if (!(ring->netdev->features & NETIF_F_RXHASH)) + parsed = libie_parse_rx_ptype(rx_ptype); + if (!libie_has_rx_hash(ring->netdev, parsed)) return; if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) { hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); - skb_set_hash(skb, hash, i40e_ptype_to_htype(rx_ptype)); + libie_skb_set_hash(skb, hash, parsed); } } diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 388c3d36d96a55..05b8510f99a930 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -773,94 +773,6 @@ enum i40e_rx_desc_error_l3l4e_fcoe_masks { #define I40E_RXD_QW1_PTYPE_SHIFT 30 #define I40E_RXD_QW1_PTYPE_MASK (0xFFULL << I40E_RXD_QW1_PTYPE_SHIFT) -/* Packet type non-ip values */ -enum i40e_rx_l2_ptype { - I40E_RX_PTYPE_L2_RESERVED = 0, - I40E_RX_PTYPE_L2_MAC_PAY2 = 1, - I40E_RX_PTYPE_L2_TIMESYNC_PAY2 = 2, - I40E_RX_PTYPE_L2_FIP_PAY2 = 3, - I40E_RX_PTYPE_L2_OUI_PAY2 = 4, - I40E_RX_PTYPE_L2_MACCNTRL_PAY2 = 5, - I40E_RX_PTYPE_L2_LLDP_PAY2 = 6, - I40E_RX_PTYPE_L2_ECP_PAY2 = 7, - I40E_RX_PTYPE_L2_EVB_PAY2 = 8, - I40E_RX_PTYPE_L2_QCN_PAY2 = 9, - I40E_RX_PTYPE_L2_EAPOL_PAY2 = 10, - I40E_RX_PTYPE_L2_ARP = 11, - I40E_RX_PTYPE_L2_FCOE_PAY3 = 12, - I40E_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13, - I40E_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14, - I40E_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15, - I40E_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16, - I40E_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17, - I40E_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18, - I40E_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19, - I40E_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20, - I40E_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21, - I40E_RX_PTYPE_GRENAT4_MAC_PAY3 = 58, - I40E_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87, - I40E_RX_PTYPE_GRENAT6_MAC_PAY3 = 124, - I40E_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153 -}; - -struct i40e_rx_ptype_decoded { - u32 known:1; - u32 outer_ip:1; - u32 outer_ip_ver:1; - u32 outer_frag:1; - u32 tunnel_type:3; - u32 tunnel_end_prot:2; - u32 tunnel_end_frag:1; - u32 inner_prot:4; - u32 payload_layer:3; -}; - -enum i40e_rx_ptype_outer_ip { - I40E_RX_PTYPE_OUTER_L2 = 0, - I40E_RX_PTYPE_OUTER_IP = 1 -}; - -enum i40e_rx_ptype_outer_ip_ver { - I40E_RX_PTYPE_OUTER_NONE = 0, - I40E_RX_PTYPE_OUTER_IPV4 = 0, - I40E_RX_PTYPE_OUTER_IPV6 = 1 -}; - -enum i40e_rx_ptype_outer_fragmented { - I40E_RX_PTYPE_NOT_FRAG = 0, - I40E_RX_PTYPE_FRAG = 1 -}; - -enum i40e_rx_ptype_tunnel_type { - I40E_RX_PTYPE_TUNNEL_NONE = 0, - I40E_RX_PTYPE_TUNNEL_IP_IP = 1, - I40E_RX_PTYPE_TUNNEL_IP_GRENAT = 2, - I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3, - I40E_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4, -}; - -enum i40e_rx_ptype_tunnel_end_prot { - I40E_RX_PTYPE_TUNNEL_END_NONE = 0, - I40E_RX_PTYPE_TUNNEL_END_IPV4 = 1, - I40E_RX_PTYPE_TUNNEL_END_IPV6 = 2, -}; - -enum i40e_rx_ptype_inner_prot { - I40E_RX_PTYPE_INNER_PROT_NONE = 0, - I40E_RX_PTYPE_INNER_PROT_UDP = 1, - I40E_RX_PTYPE_INNER_PROT_TCP = 2, - I40E_RX_PTYPE_INNER_PROT_SCTP = 3, - I40E_RX_PTYPE_INNER_PROT_ICMP = 4, - I40E_RX_PTYPE_INNER_PROT_TIMESYNC = 5 -}; - -enum i40e_rx_ptype_payload_layer { - I40E_RX_PTYPE_PAYLOAD_LAYER_NONE = 0, - I40E_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1, - I40E_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2, - I40E_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3, -}; - #define I40E_RXD_QW1_LENGTH_PBUF_SHIFT 38 #define I40E_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \ I40E_RXD_QW1_LENGTH_PBUF_SHIFT) diff --git a/drivers/net/ethernet/intel/iavf/iavf.h b/drivers/net/ethernet/intel/iavf/iavf.h index 9abaff1f2affbc..a780e7aa1c2f74 100644 --- a/drivers/net/ethernet/intel/iavf/iavf.h +++ b/drivers/net/ethernet/intel/iavf/iavf.h @@ -298,7 +298,7 @@ struct iavf_adapter { #define IAVF_FLAG_CLIENT_NEEDS_L2_PARAMS BIT(12) #define IAVF_FLAG_PROMISC_ON BIT(13) #define IAVF_FLAG_ALLMULTI_ON BIT(14) -#define IAVF_FLAG_LEGACY_RX BIT(15) +/* BIT(15) is free, was IAVF_FLAG_LEGACY_RX */ #define IAVF_FLAG_REINIT_ITR_NEEDED BIT(16) #define IAVF_FLAG_QUEUES_DISABLED BIT(17) #define IAVF_FLAG_SETUP_NETDEV_FEATURES BIT(18) diff --git a/drivers/net/ethernet/intel/iavf/iavf_common.c b/drivers/net/ethernet/intel/iavf/iavf_common.c index dd11dbbd5551a2..ba6c9f154d189a 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_common.c +++ b/drivers/net/ethernet/intel/iavf/iavf_common.c @@ -499,259 +499,6 @@ enum iavf_status iavf_aq_set_rss_key(struct iavf_hw *hw, u16 vsi_id, return iavf_aq_get_set_rss_key(hw, vsi_id, key, true); } -/* The iavf_ptype_lookup table is used to convert from the 8-bit ptype in the - * hardware to a bit-field that can be used by SW to more easily determine the - * packet type. - * - * Macros are used to shorten the table lines and make this table human - * readable. - * - * We store the PTYPE in the top byte of the bit field - this is just so that - * we can check that the table doesn't have a row missing, as the index into - * the table should be the PTYPE. - * - * Typical work flow: - * - * IF NOT iavf_ptype_lookup[ptype].known - * THEN - * Packet is unknown - * ELSE IF iavf_ptype_lookup[ptype].outer_ip == IAVF_RX_PTYPE_OUTER_IP - * Use the rest of the fields to look at the tunnels, inner protocols, etc - * ELSE - * Use the enum iavf_rx_l2_ptype to decode the packet type - * ENDIF - */ - -/* macro to make the table lines short, use explicit indexing with [PTYPE] */ -#define IAVF_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\ - [PTYPE] = { \ - 1, \ - IAVF_RX_PTYPE_OUTER_##OUTER_IP, \ - IAVF_RX_PTYPE_OUTER_##OUTER_IP_VER, \ - IAVF_RX_PTYPE_##OUTER_FRAG, \ - IAVF_RX_PTYPE_TUNNEL_##T, \ - IAVF_RX_PTYPE_TUNNEL_END_##TE, \ - IAVF_RX_PTYPE_##TEF, \ - IAVF_RX_PTYPE_INNER_PROT_##I, \ - IAVF_RX_PTYPE_PAYLOAD_LAYER_##PL } - -#define IAVF_PTT_UNUSED_ENTRY(PTYPE) [PTYPE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } - -/* shorter macros makes the table fit but are terse */ -#define IAVF_RX_PTYPE_NOF IAVF_RX_PTYPE_NOT_FRAG -#define IAVF_RX_PTYPE_FRG IAVF_RX_PTYPE_FRAG -#define IAVF_RX_PTYPE_INNER_PROT_TS IAVF_RX_PTYPE_INNER_PROT_TIMESYNC - -/* Lookup table mapping the 8-bit HW PTYPE to the bit field for decoding */ -struct iavf_rx_ptype_decoded iavf_ptype_lookup[BIT(8)] = { - /* L2 Packet types */ - IAVF_PTT_UNUSED_ENTRY(0), - IAVF_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - IAVF_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, TS, PAY2), - IAVF_PTT(3, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - IAVF_PTT_UNUSED_ENTRY(4), - IAVF_PTT_UNUSED_ENTRY(5), - IAVF_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - IAVF_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - IAVF_PTT_UNUSED_ENTRY(8), - IAVF_PTT_UNUSED_ENTRY(9), - IAVF_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - IAVF_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), - IAVF_PTT(12, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(13, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(14, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(15, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(16, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(17, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(18, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(19, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(20, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(21, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY3), - - /* Non Tunneled IPv4 */ - IAVF_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(25), - IAVF_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4), - IAVF_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4), - IAVF_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4), - - /* IPv4 --> IPv4 */ - IAVF_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3), - IAVF_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3), - IAVF_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(32), - IAVF_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4), - IAVF_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> IPv6 */ - IAVF_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3), - IAVF_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3), - IAVF_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(39), - IAVF_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4), - IAVF_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT */ - IAVF_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), - - /* IPv4 --> GRE/NAT --> IPv4 */ - IAVF_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), - IAVF_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), - IAVF_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(47), - IAVF_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), - IAVF_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> IPv6 */ - IAVF_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), - IAVF_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), - IAVF_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(54), - IAVF_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), - IAVF_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> MAC */ - IAVF_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), - - /* IPv4 --> GRE/NAT --> MAC --> IPv4 */ - IAVF_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), - IAVF_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), - IAVF_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(62), - IAVF_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), - IAVF_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT -> MAC --> IPv6 */ - IAVF_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), - IAVF_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), - IAVF_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(69), - IAVF_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), - IAVF_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> MAC/VLAN */ - IAVF_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), - - /* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */ - IAVF_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), - IAVF_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), - IAVF_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(77), - IAVF_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), - IAVF_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), - - /* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */ - IAVF_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), - IAVF_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), - IAVF_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(84), - IAVF_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), - IAVF_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), - - /* Non Tunneled IPv6 */ - IAVF_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), - IAVF_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(91), - IAVF_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), - IAVF_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), - IAVF_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4), - - /* IPv6 --> IPv4 */ - IAVF_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3), - IAVF_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3), - IAVF_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(98), - IAVF_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4), - IAVF_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> IPv6 */ - IAVF_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3), - IAVF_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3), - IAVF_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(105), - IAVF_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4), - IAVF_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT */ - IAVF_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> IPv4 */ - IAVF_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), - IAVF_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), - IAVF_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(113), - IAVF_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), - IAVF_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> IPv6 */ - IAVF_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), - IAVF_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), - IAVF_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(120), - IAVF_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), - IAVF_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC */ - IAVF_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> MAC -> IPv4 */ - IAVF_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), - IAVF_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), - IAVF_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(128), - IAVF_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), - IAVF_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC -> IPv6 */ - IAVF_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), - IAVF_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), - IAVF_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(135), - IAVF_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), - IAVF_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC/VLAN */ - IAVF_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */ - IAVF_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), - IAVF_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), - IAVF_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(143), - IAVF_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), - IAVF_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), - IAVF_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */ - IAVF_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), - IAVF_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), - IAVF_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), - IAVF_PTT_UNUSED_ENTRY(150), - IAVF_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), - IAVF_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), - IAVF_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), - - /* unused entries */ - [154 ... 255] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } -}; - /** * iavf_aq_send_msg_to_pf * @hw: pointer to the hardware structure diff --git a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c index 6f171d1d85b75f..0dcf50d75f8614 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_ethtool.c +++ b/drivers/net/ethernet/intel/iavf/iavf_ethtool.c @@ -46,16 +46,6 @@ struct iavf_stats { .stat_offset = offsetof(_type, _stat) \ } -/* Helper macro for defining some statistics related to queues */ -#define IAVF_QUEUE_STAT(_name, _stat) \ - IAVF_STAT(struct iavf_ring, _name, _stat) - -/* Stats associated with a Tx or Rx ring */ -static const struct iavf_stats iavf_gstrings_queue_stats[] = { - IAVF_QUEUE_STAT("%s-%u.packets", stats.packets), - IAVF_QUEUE_STAT("%s-%u.bytes", stats.bytes), -}; - /** * iavf_add_one_ethtool_stat - copy the stat into the supplied buffer * @data: location to store the stat value @@ -141,43 +131,6 @@ __iavf_add_ethtool_stats(u64 **data, void *pointer, #define iavf_add_ethtool_stats(data, pointer, stats) \ __iavf_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats)) -/** - * iavf_add_queue_stats - copy queue statistics into supplied buffer - * @data: ethtool stats buffer - * @ring: the ring to copy - * - * Queue statistics must be copied while protected by - * u64_stats_fetch_begin, so we can't directly use iavf_add_ethtool_stats. - * Assumes that queue stats are defined in iavf_gstrings_queue_stats. If the - * ring pointer is null, zero out the queue stat values and update the data - * pointer. Otherwise safely copy the stats from the ring into the supplied - * buffer and update the data pointer when finished. - * - * This function expects to be called while under rcu_read_lock(). - **/ -static void -iavf_add_queue_stats(u64 **data, struct iavf_ring *ring) -{ - const unsigned int size = ARRAY_SIZE(iavf_gstrings_queue_stats); - const struct iavf_stats *stats = iavf_gstrings_queue_stats; - unsigned int start; - unsigned int i; - - /* To avoid invalid statistics values, ensure that we keep retrying - * the copy until we get a consistent value according to - * u64_stats_fetch_retry. But first, make sure our ring is - * non-null before attempting to access its syncp. - */ - do { - start = !ring ? 0 : u64_stats_fetch_begin(&ring->syncp); - for (i = 0; i < size; i++) - iavf_add_one_ethtool_stat(&(*data)[i], ring, &stats[i]); - } while (ring && u64_stats_fetch_retry(&ring->syncp, start)); - - /* Once we successfully copy the stats in, update the data pointer */ - *data += size; -} - /** * __iavf_add_stat_strings - copy stat strings into ethtool buffer * @p: ethtool supplied buffer @@ -237,31 +190,6 @@ static const struct iavf_stats iavf_gstrings_stats[] = { #define IAVF_STATS_LEN ARRAY_SIZE(iavf_gstrings_stats) -#define IAVF_QUEUE_STATS_LEN ARRAY_SIZE(iavf_gstrings_queue_stats) - -/* For now we have one and only one private flag and it is only defined - * when we have support for the SKIP_CPU_SYNC DMA attribute. Instead - * of leaving all this code sitting around empty we will strip it unless - * our one private flag is actually available. - */ -struct iavf_priv_flags { - char flag_string[ETH_GSTRING_LEN]; - u32 flag; - bool read_only; -}; - -#define IAVF_PRIV_FLAG(_name, _flag, _read_only) { \ - .flag_string = _name, \ - .flag = _flag, \ - .read_only = _read_only, \ -} - -static const struct iavf_priv_flags iavf_gstrings_priv_flags[] = { - IAVF_PRIV_FLAG("legacy-rx", IAVF_FLAG_LEGACY_RX, 0), -}; - -#define IAVF_PRIV_FLAGS_STR_LEN ARRAY_SIZE(iavf_gstrings_priv_flags) - /** * iavf_get_link_ksettings - Get Link Speed and Duplex settings * @netdev: network interface device structure @@ -331,20 +259,22 @@ static int iavf_get_link_ksettings(struct net_device *netdev, **/ static int iavf_get_sset_count(struct net_device *netdev, int sset) { - /* Report the maximum number queues, even if not every queue is - * currently configured. Since allocation of queues is in pairs, - * use netdev->real_num_tx_queues * 2. The real_num_tx_queues is set - * at device creation and never changes. - */ + u32 num; - if (sset == ETH_SS_STATS) - return IAVF_STATS_LEN + - (IAVF_QUEUE_STATS_LEN * 2 * - netdev->real_num_tx_queues); - else if (sset == ETH_SS_PRIV_FLAGS) - return IAVF_PRIV_FLAGS_STR_LEN; - else + switch (sset) { + case ETH_SS_STATS: + /* Per-queue */ + num = libie_rq_stats_get_sset_count(); + num += libie_sq_stats_get_sset_count(); + num *= netdev->real_num_tx_queues; + + /* Global */ + num += IAVF_STATS_LEN; + + return num; + default: return -EINVAL; + } } /** @@ -371,37 +301,19 @@ static void iavf_get_ethtool_stats(struct net_device *netdev, * it to iterate over rings' stats. */ for (i = 0; i < adapter->num_active_queues; i++) { - struct iavf_ring *ring; + const struct iavf_ring *ring; /* Tx rings stats */ - ring = &adapter->tx_rings[i]; - iavf_add_queue_stats(&data, ring); + libie_sq_stats_get_data(&data, &adapter->tx_rings[i].sq_stats); /* Rx rings stats */ ring = &adapter->rx_rings[i]; - iavf_add_queue_stats(&data, ring); + libie_rq_stats_get_data(&data, &ring->rq_stats, + ring->rx_pages ? ring->pool : NULL); } rcu_read_unlock(); } -/** - * iavf_get_priv_flag_strings - Get private flag strings - * @netdev: network interface device structure - * @data: buffer for string data - * - * Builds the private flags string table - **/ -static void iavf_get_priv_flag_strings(struct net_device *netdev, u8 *data) -{ - unsigned int i; - - for (i = 0; i < IAVF_PRIV_FLAGS_STR_LEN; i++) { - snprintf(data, ETH_GSTRING_LEN, "%s", - iavf_gstrings_priv_flags[i].flag_string); - data += ETH_GSTRING_LEN; - } -} - /** * iavf_get_stat_strings - Get stat strings * @netdev: network interface device structure @@ -419,10 +331,8 @@ static void iavf_get_stat_strings(struct net_device *netdev, u8 *data) * real_num_tx_queues for both Tx and Rx queues. */ for (i = 0; i < netdev->real_num_tx_queues; i++) { - iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, - "tx", i); - iavf_add_stat_strings(&data, iavf_gstrings_queue_stats, - "rx", i); + libie_sq_stats_get_strings(&data, i); + libie_rq_stats_get_strings(&data, i); } } @@ -440,105 +350,11 @@ static void iavf_get_strings(struct net_device *netdev, u32 sset, u8 *data) case ETH_SS_STATS: iavf_get_stat_strings(netdev, data); break; - case ETH_SS_PRIV_FLAGS: - iavf_get_priv_flag_strings(netdev, data); - break; default: break; } } -/** - * iavf_get_priv_flags - report device private flags - * @netdev: network interface device structure - * - * The get string set count and the string set should be matched for each - * flag returned. Add new strings for each flag to the iavf_gstrings_priv_flags - * array. - * - * Returns a u32 bitmap of flags. - **/ -static u32 iavf_get_priv_flags(struct net_device *netdev) -{ - struct iavf_adapter *adapter = netdev_priv(netdev); - u32 i, ret_flags = 0; - - for (i = 0; i < IAVF_PRIV_FLAGS_STR_LEN; i++) { - const struct iavf_priv_flags *priv_flags; - - priv_flags = &iavf_gstrings_priv_flags[i]; - - if (priv_flags->flag & adapter->flags) - ret_flags |= BIT(i); - } - - return ret_flags; -} - -/** - * iavf_set_priv_flags - set private flags - * @netdev: network interface device structure - * @flags: bit flags to be set - **/ -static int iavf_set_priv_flags(struct net_device *netdev, u32 flags) -{ - struct iavf_adapter *adapter = netdev_priv(netdev); - u32 orig_flags, new_flags, changed_flags; - u32 i; - - orig_flags = READ_ONCE(adapter->flags); - new_flags = orig_flags; - - for (i = 0; i < IAVF_PRIV_FLAGS_STR_LEN; i++) { - const struct iavf_priv_flags *priv_flags; - - priv_flags = &iavf_gstrings_priv_flags[i]; - - if (flags & BIT(i)) - new_flags |= priv_flags->flag; - else - new_flags &= ~(priv_flags->flag); - - if (priv_flags->read_only && - ((orig_flags ^ new_flags) & ~BIT(i))) - return -EOPNOTSUPP; - } - - /* Before we finalize any flag changes, any checks which we need to - * perform to determine if the new flags will be supported should go - * here... - */ - - /* Compare and exchange the new flags into place. If we failed, that - * is if cmpxchg returns anything but the old value, this means - * something else must have modified the flags variable since we - * copied it. We'll just punt with an error and log something in the - * message buffer. - */ - if (cmpxchg(&adapter->flags, orig_flags, new_flags) != orig_flags) { - dev_warn(&adapter->pdev->dev, - "Unable to update adapter->flags as it was modified by another thread...\n"); - return -EAGAIN; - } - - changed_flags = orig_flags ^ new_flags; - - /* Process any additional changes needed as a result of flag changes. - * The changed_flags value reflects the list of bits that were changed - * in the code above. - */ - - /* issue a reset to force legacy-rx change to take effect */ - if (changed_flags & IAVF_FLAG_LEGACY_RX) { - if (netif_running(netdev)) { - adapter->flags |= IAVF_FLAG_RESET_NEEDED; - queue_work(adapter->wq, &adapter->reset_task); - } - } - - return 0; -} - /** * iavf_get_msglevel - Get debug message level * @netdev: network interface device structure @@ -584,7 +400,6 @@ static void iavf_get_drvinfo(struct net_device *netdev, strscpy(drvinfo->driver, iavf_driver_name, 32); strscpy(drvinfo->fw_version, "N/A", 4); strscpy(drvinfo->bus_info, pci_name(adapter->pdev), 32); - drvinfo->n_priv_flags = IAVF_PRIV_FLAGS_STR_LEN; } /** @@ -1969,8 +1784,6 @@ static const struct ethtool_ops iavf_ethtool_ops = { .get_strings = iavf_get_strings, .get_ethtool_stats = iavf_get_ethtool_stats, .get_sset_count = iavf_get_sset_count, - .get_priv_flags = iavf_get_priv_flags, - .set_priv_flags = iavf_set_priv_flags, .get_msglevel = iavf_get_msglevel, .set_msglevel = iavf_set_msglevel, .get_coalesce = iavf_get_coalesce, diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c index 2de4baff4c2050..4a702795ddb32d 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_main.c +++ b/drivers/net/ethernet/intel/iavf/iavf_main.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2013 - 2018 Intel Corporation. */ +#include + #include "iavf.h" #include "iavf_prototype.h" #include "iavf_client.h" @@ -46,6 +48,7 @@ MODULE_DEVICE_TABLE(pci, iavf_pci_tbl); MODULE_ALIAS("i40evf"); MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION("Intel(R) Ethernet Adaptive Virtual Function Network Driver"); +MODULE_IMPORT_NS(LIBIE); MODULE_LICENSE("GPL v2"); static const struct net_device_ops iavf_netdev_ops; @@ -708,40 +711,10 @@ static void iavf_configure_tx(struct iavf_adapter *adapter) **/ static void iavf_configure_rx(struct iavf_adapter *adapter) { - unsigned int rx_buf_len = IAVF_RXBUFFER_2048; struct iavf_hw *hw = &adapter->hw; - int i; - - /* Legacy Rx will always default to a 2048 buffer size. */ -#if (PAGE_SIZE < 8192) - if (!(adapter->flags & IAVF_FLAG_LEGACY_RX)) { - struct net_device *netdev = adapter->netdev; - - /* For jumbo frames on systems with 4K pages we have to use - * an order 1 page, so we might as well increase the size - * of our Rx buffer to make better use of the available space - */ - rx_buf_len = IAVF_RXBUFFER_3072; - - /* We use a 1536 buffer size for configurations with - * standard Ethernet mtu. On x86 this gives us enough room - * for shared info and 192 bytes of padding. - */ - if (!IAVF_2K_TOO_SMALL_WITH_PADDING && - (netdev->mtu <= ETH_DATA_LEN)) - rx_buf_len = IAVF_RXBUFFER_1536 - NET_IP_ALIGN; - } -#endif - for (i = 0; i < adapter->num_active_queues; i++) { + for (u32 i = 0; i < adapter->num_active_queues; i++) adapter->rx_rings[i].tail = hw->hw_addr + IAVF_QRX_TAIL1(i); - adapter->rx_rings[i].rx_buf_len = rx_buf_len; - - if (adapter->flags & IAVF_FLAG_LEGACY_RX) - clear_ring_build_skb_enabled(&adapter->rx_rings[i]); - else - set_ring_build_skb_enabled(&adapter->rx_rings[i]); - } } /** @@ -1243,7 +1216,7 @@ static void iavf_configure(struct iavf_adapter *adapter) for (i = 0; i < adapter->num_active_queues; i++) { struct iavf_ring *ring = &adapter->rx_rings[i]; - iavf_alloc_rx_buffers(ring, IAVF_DESC_UNUSED(ring)); + iavf_alloc_rx_pages(ring); } } @@ -1608,6 +1581,7 @@ static int iavf_alloc_queues(struct iavf_adapter *adapter) tx_ring->itr_setting = IAVF_ITR_TX_DEF; if (adapter->flags & IAVF_FLAG_WB_ON_ITR_CAPABLE) tx_ring->flags |= IAVF_TXR_FLAGS_WB_ON_ITR; + u64_stats_init(&tx_ring->sq_stats.syncp); rx_ring = &adapter->rx_rings[i]; rx_ring->queue_index = i; @@ -1615,6 +1589,7 @@ static int iavf_alloc_queues(struct iavf_adapter *adapter) rx_ring->dev = &adapter->pdev->dev; rx_ring->count = adapter->rx_desc_count; rx_ring->itr_setting = IAVF_ITR_RX_DEF; + u64_stats_init(&rx_ring->rq_stats.syncp); } adapter->num_active_queues = num_active_queues; @@ -2584,11 +2559,7 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter) netdev->netdev_ops = &iavf_netdev_ops; iavf_set_ethtool_ops(netdev); - netdev->watchdog_timeo = 5 * HZ; - - /* MTU range: 68 - 9710 */ - netdev->min_mtu = ETH_MIN_MTU; - netdev->max_mtu = IAVF_MAX_RXBUFFER - IAVF_PACKET_HDR_PAD; + netdev->max_mtu = LIBIE_MAX_MTU; if (!is_valid_ether_addr(adapter->hw.mac.addr)) { dev_info(&pdev->dev, "Invalid MAC address %pM, using random\n", diff --git a/drivers/net/ethernet/intel/iavf/iavf_prototype.h b/drivers/net/ethernet/intel/iavf/iavf_prototype.h index edebfbbcffdc2e..c2e5dbc0a75a35 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_prototype.h +++ b/drivers/net/ethernet/intel/iavf/iavf_prototype.h @@ -51,13 +51,6 @@ enum iavf_status iavf_aq_set_rss_key(struct iavf_hw *hw, u16 seid, enum iavf_status iavf_set_mac_type(struct iavf_hw *hw); -extern struct iavf_rx_ptype_decoded iavf_ptype_lookup[]; - -static inline struct iavf_rx_ptype_decoded decode_rx_desc_ptype(u8 ptype) -{ - return iavf_ptype_lookup[ptype]; -} - void iavf_vf_parse_hw_config(struct iavf_hw *hw, struct virtchnl_vf_resource *msg); enum iavf_status iavf_vf_reset(struct iavf_hw *hw); diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.c b/drivers/net/ethernet/intel/iavf/iavf_txrx.c index e989feda133c1e..12308e7c9ec0a6 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.c +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2013 - 2018 Intel Corporation. */ +#include #include #include "iavf.h" @@ -157,6 +158,9 @@ void iavf_detect_recover_hung(struct iavf_vsi *vsi) for (i = 0; i < vsi->back->num_active_queues; i++) { tx_ring = &vsi->back->tx_rings[i]; if (tx_ring && tx_ring->desc) { + const struct libie_sq_stats *st = &tx_ring->sq_stats; + u32 start; + /* If packet counter has not changed the queue is * likely stalled, so force an interrupt for this * queue. @@ -164,8 +168,13 @@ void iavf_detect_recover_hung(struct iavf_vsi *vsi) * prev_pkt_ctr would be negative if there was no * pending work. */ - packets = tx_ring->stats.packets & INT_MAX; - if (tx_ring->tx_stats.prev_pkt_ctr == packets) { + do { + start = u64_stats_fetch_begin(&st->syncp); + packets = u64_stats_read(&st->packets) & + INT_MAX; + } while (u64_stats_fetch_retry(&st->syncp, start)); + + if (tx_ring->prev_pkt_ctr == packets) { iavf_force_wb(vsi, tx_ring->q_vector); continue; } @@ -174,7 +183,7 @@ void iavf_detect_recover_hung(struct iavf_vsi *vsi) * to iavf_get_tx_pending() */ smp_rmb(); - tx_ring->tx_stats.prev_pkt_ctr = + tx_ring->prev_pkt_ctr = iavf_get_tx_pending(tx_ring, true) ? packets : -1; } } @@ -193,10 +202,10 @@ void iavf_detect_recover_hung(struct iavf_vsi *vsi) static bool iavf_clean_tx_irq(struct iavf_vsi *vsi, struct iavf_ring *tx_ring, int napi_budget) { + struct libie_sq_onstack_stats stats = { }; int i = tx_ring->next_to_clean; struct iavf_tx_buffer *tx_buf; struct iavf_tx_desc *tx_desc; - unsigned int total_bytes = 0, total_packets = 0; unsigned int budget = IAVF_DEFAULT_IRQ_WORK; tx_buf = &tx_ring->tx_bi[i]; @@ -223,8 +232,8 @@ static bool iavf_clean_tx_irq(struct iavf_vsi *vsi, tx_buf->next_to_watch = NULL; /* update the statistics for this packet */ - total_bytes += tx_buf->bytecount; - total_packets += tx_buf->gso_segs; + stats.bytes += tx_buf->bytecount; + stats.packets += tx_buf->gso_segs; /* free the skb */ napi_consume_skb(tx_buf->skb, napi_budget); @@ -281,12 +290,9 @@ static bool iavf_clean_tx_irq(struct iavf_vsi *vsi, i += tx_ring->count; tx_ring->next_to_clean = i; - u64_stats_update_begin(&tx_ring->syncp); - tx_ring->stats.bytes += total_bytes; - tx_ring->stats.packets += total_packets; - u64_stats_update_end(&tx_ring->syncp); - tx_ring->q_vector->tx.total_bytes += total_bytes; - tx_ring->q_vector->tx.total_packets += total_packets; + libie_sq_napi_stats_add(&tx_ring->sq_stats, &stats); + tx_ring->q_vector->tx.total_bytes += stats.bytes; + tx_ring->q_vector->tx.total_packets += stats.packets; if (tx_ring->flags & IAVF_TXR_FLAGS_WB_ON_ITR) { /* check to see if there are < 4 descriptors @@ -300,15 +306,15 @@ static bool iavf_clean_tx_irq(struct iavf_vsi *vsi, ((j / WB_STRIDE) == 0) && (j > 0) && !test_bit(__IAVF_VSI_DOWN, vsi->state) && (IAVF_DESC_UNUSED(tx_ring) != tx_ring->count)) - tx_ring->arm_wb = true; + tx_ring->flags |= IAVF_TXRX_FLAGS_ARM_WB; } /* notify netdev of completed buffers */ netdev_tx_completed_queue(txring_txq(tx_ring), - total_packets, total_bytes); + stats.packets, stats.bytes); #define TX_WAKE_THRESHOLD ((s16)(DESC_NEEDED * 2)) - if (unlikely(total_packets && netif_carrier_ok(tx_ring->netdev) && + if (unlikely(stats.packets && netif_carrier_ok(tx_ring->netdev) && (IAVF_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD))) { /* Make sure that anybody stopping the queue after this * sees the new next_to_clean. @@ -319,7 +325,7 @@ static bool iavf_clean_tx_irq(struct iavf_vsi *vsi, !test_bit(__IAVF_VSI_DOWN, vsi->state)) { netif_wake_subqueue(tx_ring->netdev, tx_ring->queue_index); - ++tx_ring->tx_stats.restart_queue; + libie_stats_inc_one(&tx_ring->sq_stats, restarts); } } @@ -674,7 +680,7 @@ int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring) tx_ring->next_to_use = 0; tx_ring->next_to_clean = 0; - tx_ring->tx_stats.prev_pkt_ctr = -1; + tx_ring->prev_pkt_ctr = -1; return 0; err: @@ -689,11 +695,8 @@ int iavf_setup_tx_descriptors(struct iavf_ring *tx_ring) **/ void iavf_clean_rx_ring(struct iavf_ring *rx_ring) { - unsigned long bi_size; - u16 i; - /* ring already cleared, nothing to do */ - if (!rx_ring->rx_bi) + if (!rx_ring->rx_pages) return; if (rx_ring->skb) { @@ -702,40 +705,19 @@ void iavf_clean_rx_ring(struct iavf_ring *rx_ring) } /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rx_ring->count; i++) { - struct iavf_rx_buffer *rx_bi = &rx_ring->rx_bi[i]; + for (u32 i = 0; i < rx_ring->count; i++) { + struct page *page = rx_ring->rx_pages[i]; - if (!rx_bi->page) + if (!page) continue; /* Invalidate cache lines that may have been written to by * device so that we avoid corrupting memory. */ - dma_sync_single_range_for_cpu(rx_ring->dev, - rx_bi->dma, - rx_bi->page_offset, - rx_ring->rx_buf_len, - DMA_FROM_DEVICE); - - /* free resources associated with mapping */ - dma_unmap_page_attrs(rx_ring->dev, rx_bi->dma, - iavf_rx_pg_size(rx_ring), - DMA_FROM_DEVICE, - IAVF_RX_DMA_ATTR); - - __page_frag_cache_drain(rx_bi->page, rx_bi->pagecnt_bias); - - rx_bi->page = NULL; - rx_bi->page_offset = 0; + page_pool_dma_sync_full_for_cpu(rx_ring->pool, page); + page_pool_put_full_page(rx_ring->pool, page, false); } - bi_size = sizeof(struct iavf_rx_buffer) * rx_ring->count; - memset(rx_ring->rx_bi, 0, bi_size); - - /* Zero out the descriptor ring */ - memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_alloc = 0; rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; } @@ -748,9 +730,14 @@ void iavf_clean_rx_ring(struct iavf_ring *rx_ring) **/ void iavf_free_rx_resources(struct iavf_ring *rx_ring) { + struct device *dev = rx_ring->pool->p.dev; + iavf_clean_rx_ring(rx_ring); - kfree(rx_ring->rx_bi); - rx_ring->rx_bi = NULL; + kfree(rx_ring->rx_pages); + rx_ring->rx_pages = NULL; + + libie_rx_page_pool_destroy(rx_ring->pool, &rx_ring->rq_stats); + rx_ring->dev = dev; if (rx_ring->desc) { dma_free_coherent(rx_ring->dev, rx_ring->size, @@ -768,16 +755,15 @@ void iavf_free_rx_resources(struct iavf_ring *rx_ring) int iavf_setup_rx_descriptors(struct iavf_ring *rx_ring) { struct device *dev = rx_ring->dev; - int bi_size; + struct page_pool *pool; + int ret = -ENOMEM; /* warn if we are about to overwrite the pointer */ - WARN_ON(rx_ring->rx_bi); - bi_size = sizeof(struct iavf_rx_buffer) * rx_ring->count; - rx_ring->rx_bi = kzalloc(bi_size, GFP_KERNEL); - if (!rx_ring->rx_bi) - goto err; - - u64_stats_init(&rx_ring->syncp); + WARN_ON(rx_ring->rx_pages); + rx_ring->rx_pages = kcalloc(rx_ring->count, sizeof(*rx_ring->rx_pages), + GFP_KERNEL); + if (!rx_ring->rx_pages) + return ret; /* Round up to nearest 4K */ rx_ring->size = rx_ring->count * sizeof(union iavf_32byte_rx_desc); @@ -791,15 +777,27 @@ int iavf_setup_rx_descriptors(struct iavf_ring *rx_ring) goto err; } - rx_ring->next_to_alloc = 0; + pool = libie_rx_page_pool_create(&rx_ring->q_vector->napi, + rx_ring->count); + if (IS_ERR(pool)) { + ret = PTR_ERR(pool); + goto err_free_dma; + } + + rx_ring->pool = pool; + rx_ring->next_to_clean = 0; rx_ring->next_to_use = 0; return 0; + +err_free_dma: + dma_free_coherent(dev, rx_ring->size, rx_ring->desc, rx_ring->dma); err: - kfree(rx_ring->rx_bi); - rx_ring->rx_bi = NULL; - return -ENOMEM; + kfree(rx_ring->rx_pages); + rx_ring->rx_pages = NULL; + + return ret; } /** @@ -811,9 +809,6 @@ static inline void iavf_release_rx_desc(struct iavf_ring *rx_ring, u32 val) { rx_ring->next_to_use = val; - /* update next to alloc since we have filled the ring */ - rx_ring->next_to_alloc = val; - /* Force memory writes to complete before letting h/w * know there are new descriptors to fetch. (Only * applicable for weak-ordered memory model archs, @@ -823,69 +818,6 @@ static inline void iavf_release_rx_desc(struct iavf_ring *rx_ring, u32 val) writel(val, rx_ring->tail); } -/** - * iavf_rx_offset - Return expected offset into page to access data - * @rx_ring: Ring we are requesting offset of - * - * Returns the offset value for ring into the data buffer. - */ -static inline unsigned int iavf_rx_offset(struct iavf_ring *rx_ring) -{ - return ring_uses_build_skb(rx_ring) ? IAVF_SKB_PAD : 0; -} - -/** - * iavf_alloc_mapped_page - recycle or make a new page - * @rx_ring: ring to use - * @bi: rx_buffer struct to modify - * - * Returns true if the page was successfully allocated or - * reused. - **/ -static bool iavf_alloc_mapped_page(struct iavf_ring *rx_ring, - struct iavf_rx_buffer *bi) -{ - struct page *page = bi->page; - dma_addr_t dma; - - /* since we are recycling buffers we should seldom need to alloc */ - if (likely(page)) { - rx_ring->rx_stats.page_reuse_count++; - return true; - } - - /* alloc new page for storage */ - page = dev_alloc_pages(iavf_rx_pg_order(rx_ring)); - if (unlikely(!page)) { - rx_ring->rx_stats.alloc_page_failed++; - return false; - } - - /* map page for use */ - dma = dma_map_page_attrs(rx_ring->dev, page, 0, - iavf_rx_pg_size(rx_ring), - DMA_FROM_DEVICE, - IAVF_RX_DMA_ATTR); - - /* if mapping failed free memory back to system since - * there isn't much point in holding memory we can't use - */ - if (dma_mapping_error(rx_ring->dev, dma)) { - __free_pages(page, iavf_rx_pg_order(rx_ring)); - rx_ring->rx_stats.alloc_page_failed++; - return false; - } - - bi->dma = dma; - bi->page = page; - bi->page_offset = iavf_rx_offset(rx_ring); - - /* initialize pagecnt_bias to 1 representing we fully own page */ - bi->pagecnt_bias = 1; - - return true; -} - /** * iavf_receive_skb - Send a completed packet up the stack * @rx_ring: rx ring in play @@ -908,68 +840,63 @@ static void iavf_receive_skb(struct iavf_ring *rx_ring, } /** - * iavf_alloc_rx_buffers - Replace used receive buffers + * __iavf_alloc_rx_pages - Replace used receive pages * @rx_ring: ring to place buffers on - * @cleaned_count: number of buffers to replace + * @to_refill: number of buffers to replace + * @gfp: GFP mask to allocate pages * - * Returns false if all allocations were successful, true if any fail + * Returns 0 if all allocations were successful or the number of buffers left + * to refill in case of an allocation failure. **/ -bool iavf_alloc_rx_buffers(struct iavf_ring *rx_ring, u16 cleaned_count) +static u32 __iavf_alloc_rx_pages(struct iavf_ring *rx_ring, u32 to_refill, + gfp_t gfp) { - u16 ntu = rx_ring->next_to_use; + struct page_pool *pool = rx_ring->pool; + u32 ntu = rx_ring->next_to_use; union iavf_rx_desc *rx_desc; - struct iavf_rx_buffer *bi; /* do nothing if no valid netdev defined */ - if (!rx_ring->netdev || !cleaned_count) - return false; + if (unlikely(!rx_ring->netdev || !to_refill)) + return 0; rx_desc = IAVF_RX_DESC(rx_ring, ntu); - bi = &rx_ring->rx_bi[ntu]; do { - if (!iavf_alloc_mapped_page(rx_ring, bi)) - goto no_buffers; + struct page *page; + dma_addr_t dma; + + page = page_pool_alloc_pages(pool, gfp); + if (!page) + break; - /* sync the buffer for use by the device */ - dma_sync_single_range_for_device(rx_ring->dev, bi->dma, - bi->page_offset, - rx_ring->rx_buf_len, - DMA_FROM_DEVICE); + rx_ring->rx_pages[ntu] = page; + dma = page_pool_get_dma_addr(page); /* Refresh the desc even if buffer_addrs didn't change * because each write-back erases this info. */ - rx_desc->read.pkt_addr = cpu_to_le64(bi->dma + bi->page_offset); + rx_desc->read.pkt_addr = cpu_to_le64(dma + LIBIE_SKB_HEADROOM); rx_desc++; - bi++; ntu++; if (unlikely(ntu == rx_ring->count)) { rx_desc = IAVF_RX_DESC(rx_ring, 0); - bi = rx_ring->rx_bi; ntu = 0; } /* clear the status bits for the next_to_use descriptor */ rx_desc->wb.qword1.status_error_len = 0; - - cleaned_count--; - } while (cleaned_count); + } while (--to_refill); if (rx_ring->next_to_use != ntu) iavf_release_rx_desc(rx_ring, ntu); - return false; - -no_buffers: - if (rx_ring->next_to_use != ntu) - iavf_release_rx_desc(rx_ring, ntu); + return to_refill; +} - /* make sure to come back via polling to try again after - * allocation failure - */ - return true; +void iavf_alloc_rx_pages(struct iavf_ring *rxr) +{ + __iavf_alloc_rx_pages(rxr, IAVF_DESC_UNUSED(rxr), GFP_KERNEL); } /** @@ -982,40 +909,32 @@ static inline void iavf_rx_checksum(struct iavf_vsi *vsi, struct sk_buff *skb, union iavf_rx_desc *rx_desc) { - struct iavf_rx_ptype_decoded decoded; + struct libie_rx_ptype_parsed parsed; u32 rx_error, rx_status; bool ipv4, ipv6; u8 ptype; u64 qword; + skb->ip_summed = CHECKSUM_NONE; + qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); ptype = (qword & IAVF_RXD_QW1_PTYPE_MASK) >> IAVF_RXD_QW1_PTYPE_SHIFT; + + parsed = libie_parse_rx_ptype(ptype); + if (!libie_has_rx_checksum(vsi->netdev, parsed)) + return; + rx_error = (qword & IAVF_RXD_QW1_ERROR_MASK) >> IAVF_RXD_QW1_ERROR_SHIFT; rx_status = (qword & IAVF_RXD_QW1_STATUS_MASK) >> IAVF_RXD_QW1_STATUS_SHIFT; - decoded = decode_rx_desc_ptype(ptype); - - skb->ip_summed = CHECKSUM_NONE; - - skb_checksum_none_assert(skb); - - /* Rx csum enabled and ip headers found? */ - if (!(vsi->netdev->features & NETIF_F_RXCSUM)) - return; /* did the hardware decode the packet and checksum? */ if (!(rx_status & BIT(IAVF_RX_DESC_STATUS_L3L4P_SHIFT))) return; - /* both known and outer_ip must be set for the below code to work */ - if (!(decoded.known && decoded.outer_ip)) - return; - - ipv4 = (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP) && - (decoded.outer_ip_ver == IAVF_RX_PTYPE_OUTER_IPV4); - ipv6 = (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP) && - (decoded.outer_ip_ver == IAVF_RX_PTYPE_OUTER_IPV6); + ipv4 = parsed.outer_ip == LIBIE_RX_PTYPE_OUTER_IPV4; + ipv6 = parsed.outer_ip == LIBIE_RX_PTYPE_OUTER_IPV6; if (ipv4 && (rx_error & (BIT(IAVF_RX_DESC_ERROR_IPE_SHIFT) | @@ -1039,46 +958,13 @@ static inline void iavf_rx_checksum(struct iavf_vsi *vsi, if (rx_error & BIT(IAVF_RX_DESC_ERROR_PPRS_SHIFT)) return; - /* Only report checksum unnecessary for TCP, UDP, or SCTP */ - switch (decoded.inner_prot) { - case IAVF_RX_PTYPE_INNER_PROT_TCP: - case IAVF_RX_PTYPE_INNER_PROT_UDP: - case IAVF_RX_PTYPE_INNER_PROT_SCTP: - skb->ip_summed = CHECKSUM_UNNECESSARY; - fallthrough; - default: - break; - } - + skb->ip_summed = CHECKSUM_UNNECESSARY; return; checksum_fail: vsi->back->hw_csum_rx_error++; } -/** - * iavf_ptype_to_htype - get a hash type - * @ptype: the ptype value from the descriptor - * - * Returns a hash type to be used by skb_set_hash - **/ -static inline int iavf_ptype_to_htype(u8 ptype) -{ - struct iavf_rx_ptype_decoded decoded = decode_rx_desc_ptype(ptype); - - if (!decoded.known) - return PKT_HASH_TYPE_NONE; - - if (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP && - decoded.payload_layer == IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY4) - return PKT_HASH_TYPE_L4; - else if (decoded.outer_ip == IAVF_RX_PTYPE_OUTER_IP && - decoded.payload_layer == IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY3) - return PKT_HASH_TYPE_L3; - else - return PKT_HASH_TYPE_L2; -} - /** * iavf_rx_hash - set the hash value in the skb * @ring: descriptor ring @@ -1091,17 +977,19 @@ static inline void iavf_rx_hash(struct iavf_ring *ring, struct sk_buff *skb, u8 rx_ptype) { + struct libie_rx_ptype_parsed parsed; u32 hash; const __le64 rss_mask = cpu_to_le64((u64)IAVF_RX_DESC_FLTSTAT_RSS_HASH << IAVF_RX_DESC_STATUS_FLTSTAT_SHIFT); - if (!(ring->netdev->features & NETIF_F_RXHASH)) + parsed = libie_parse_rx_ptype(rx_ptype); + if (!libie_has_rx_hash(ring->netdev, parsed)) return; if ((rx_desc->wb.qword1.status_error_len & rss_mask) == rss_mask) { hash = le32_to_cpu(rx_desc->wb.qword0.hi_dword.rss); - skb_set_hash(skb, hash, iavf_ptype_to_htype(rx_ptype)); + libie_skb_set_hash(skb, hash, parsed); } } @@ -1153,331 +1041,73 @@ static bool iavf_cleanup_headers(struct iavf_ring *rx_ring, struct sk_buff *skb) return false; } -/** - * iavf_reuse_rx_page - page flip buffer and store it back on the ring - * @rx_ring: rx descriptor ring to store buffers on - * @old_buff: donor buffer to have page reused - * - * Synchronizes page for reuse by the adapter - **/ -static void iavf_reuse_rx_page(struct iavf_ring *rx_ring, - struct iavf_rx_buffer *old_buff) -{ - struct iavf_rx_buffer *new_buff; - u16 nta = rx_ring->next_to_alloc; - - new_buff = &rx_ring->rx_bi[nta]; - - /* update, and store next to alloc */ - nta++; - rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; - - /* transfer page from old buffer to new buffer */ - new_buff->dma = old_buff->dma; - new_buff->page = old_buff->page; - new_buff->page_offset = old_buff->page_offset; - new_buff->pagecnt_bias = old_buff->pagecnt_bias; -} - -/** - * iavf_can_reuse_rx_page - Determine if this page can be reused by - * the adapter for another receive - * - * @rx_buffer: buffer containing the page - * - * If page is reusable, rx_buffer->page_offset is adjusted to point to - * an unused region in the page. - * - * For small pages, @truesize will be a constant value, half the size - * of the memory at page. We'll attempt to alternate between high and - * low halves of the page, with one half ready for use by the hardware - * and the other half being consumed by the stack. We use the page - * ref count to determine whether the stack has finished consuming the - * portion of this page that was passed up with a previous packet. If - * the page ref count is >1, we'll assume the "other" half page is - * still busy, and this page cannot be reused. - * - * For larger pages, @truesize will be the actual space used by the - * received packet (adjusted upward to an even multiple of the cache - * line size). This will advance through the page by the amount - * actually consumed by the received packets while there is still - * space for a buffer. Each region of larger pages will be used at - * most once, after which the page will not be reused. - * - * In either case, if the page is reusable its refcount is increased. - **/ -static bool iavf_can_reuse_rx_page(struct iavf_rx_buffer *rx_buffer) -{ - unsigned int pagecnt_bias = rx_buffer->pagecnt_bias; - struct page *page = rx_buffer->page; - - /* Is any reuse possible? */ - if (!dev_page_is_reusable(page)) - return false; - -#if (PAGE_SIZE < 8192) - /* if we are only owner of page we can reuse it */ - if (unlikely((page_count(page) - pagecnt_bias) > 1)) - return false; -#else -#define IAVF_LAST_OFFSET \ - (SKB_WITH_OVERHEAD(PAGE_SIZE) - IAVF_RXBUFFER_2048) - if (rx_buffer->page_offset > IAVF_LAST_OFFSET) - return false; -#endif - - /* If we have drained the page fragment pool we need to update - * the pagecnt_bias and page count so that we fully restock the - * number of references the driver holds. - */ - if (unlikely(!pagecnt_bias)) { - page_ref_add(page, USHRT_MAX); - rx_buffer->pagecnt_bias = USHRT_MAX; - } - - return true; -} - /** * iavf_add_rx_frag - Add contents of Rx buffer to sk_buff - * @rx_ring: rx descriptor ring to transact packets on - * @rx_buffer: buffer containing page to add * @skb: sk_buff to place the data into + * @page: page containing data to add * @size: packet length from rx_desc * - * This function will add the data contained in rx_buffer->page to the skb. + * This function will add the data contained in page to the skb. * It will just attach the page as a frag to the skb. * * The function will then update the page offset. **/ -static void iavf_add_rx_frag(struct iavf_ring *rx_ring, - struct iavf_rx_buffer *rx_buffer, - struct sk_buff *skb, - unsigned int size) +static void iavf_add_rx_frag(struct sk_buff *skb, struct page *page, u32 size) { -#if (PAGE_SIZE < 8192) - unsigned int truesize = iavf_rx_pg_size(rx_ring) / 2; -#else - unsigned int truesize = SKB_DATA_ALIGN(size + iavf_rx_offset(rx_ring)); -#endif - - if (!size) - return; - - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, rx_buffer->page, - rx_buffer->page_offset, size, truesize); - - /* page is being used so we must update the page offset */ -#if (PAGE_SIZE < 8192) - rx_buffer->page_offset ^= truesize; -#else - rx_buffer->page_offset += truesize; -#endif -} - -/** - * iavf_get_rx_buffer - Fetch Rx buffer and synchronize data for use - * @rx_ring: rx descriptor ring to transact packets on - * @size: size of buffer to add to skb - * - * This function will pull an Rx buffer from the ring and synchronize it - * for use by the CPU. - */ -static struct iavf_rx_buffer *iavf_get_rx_buffer(struct iavf_ring *rx_ring, - const unsigned int size) -{ - struct iavf_rx_buffer *rx_buffer; - - rx_buffer = &rx_ring->rx_bi[rx_ring->next_to_clean]; - prefetchw(rx_buffer->page); - if (!size) - return rx_buffer; - - /* we are reusing so sync this buffer for CPU use */ - dma_sync_single_range_for_cpu(rx_ring->dev, - rx_buffer->dma, - rx_buffer->page_offset, - size, - DMA_FROM_DEVICE); - - /* We have pulled a buffer for use, so decrement pagecnt_bias */ - rx_buffer->pagecnt_bias--; - - return rx_buffer; -} - -/** - * iavf_construct_skb - Allocate skb and populate it - * @rx_ring: rx descriptor ring to transact packets on - * @rx_buffer: rx buffer to pull data from - * @size: size of buffer to add to skb - * - * This function allocates an skb. It then populates it with the page - * data from the current receive descriptor, taking care to set up the - * skb correctly. - */ -static struct sk_buff *iavf_construct_skb(struct iavf_ring *rx_ring, - struct iavf_rx_buffer *rx_buffer, - unsigned int size) -{ - void *va; -#if (PAGE_SIZE < 8192) - unsigned int truesize = iavf_rx_pg_size(rx_ring) / 2; -#else - unsigned int truesize = SKB_DATA_ALIGN(size); -#endif - unsigned int headlen; - struct sk_buff *skb; - - if (!rx_buffer) - return NULL; - /* prefetch first cache line of first page */ - va = page_address(rx_buffer->page) + rx_buffer->page_offset; - net_prefetch(va); - - /* allocate a skb to store the frags */ - skb = __napi_alloc_skb(&rx_ring->q_vector->napi, - IAVF_RX_HDR_SIZE, - GFP_ATOMIC | __GFP_NOWARN); - if (unlikely(!skb)) - return NULL; - - /* Determine available headroom for copy */ - headlen = size; - if (headlen > IAVF_RX_HDR_SIZE) - headlen = eth_get_headlen(skb->dev, va, IAVF_RX_HDR_SIZE); - - /* align pull length to size of long to optimize memcpy performance */ - memcpy(__skb_put(skb, headlen), va, ALIGN(headlen, sizeof(long))); - - /* update all of the pointers */ - size -= headlen; - if (size) { - skb_add_rx_frag(skb, 0, rx_buffer->page, - rx_buffer->page_offset + headlen, - size, truesize); - - /* buffer is used by skb, update page_offset */ -#if (PAGE_SIZE < 8192) - rx_buffer->page_offset ^= truesize; -#else - rx_buffer->page_offset += truesize; -#endif - } else { - /* buffer is unused, reset bias back to rx_buffer */ - rx_buffer->pagecnt_bias++; - } - - return skb; + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, + LIBIE_SKB_HEADROOM, size, LIBIE_RX_TRUESIZE); } /** * iavf_build_skb - Build skb around an existing buffer - * @rx_ring: Rx descriptor ring to transact packets on - * @rx_buffer: Rx buffer to pull data from - * @size: size of buffer to add to skb + * @page: Rx page to with the data + * @size: size of the data * * This function builds an skb around an existing Rx buffer, taking care * to set up the skb correctly and avoid any memcpy overhead. */ -static struct sk_buff *iavf_build_skb(struct iavf_ring *rx_ring, - struct iavf_rx_buffer *rx_buffer, - unsigned int size) +static struct sk_buff *iavf_build_skb(struct page *page, u32 size) { - void *va; -#if (PAGE_SIZE < 8192) - unsigned int truesize = iavf_rx_pg_size(rx_ring) / 2; -#else - unsigned int truesize = SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + - SKB_DATA_ALIGN(IAVF_SKB_PAD + size); -#endif struct sk_buff *skb; + void *va; - if (!rx_buffer || !size) - return NULL; /* prefetch first cache line of first page */ - va = page_address(rx_buffer->page) + rx_buffer->page_offset; - net_prefetch(va); + va = page_address(page); + net_prefetch(va + LIBIE_SKB_HEADROOM); /* build an skb around the page buffer */ - skb = napi_build_skb(va - IAVF_SKB_PAD, truesize); + skb = napi_build_skb(va, LIBIE_RX_TRUESIZE); if (unlikely(!skb)) return NULL; + skb_mark_for_recycle(skb); + /* update pointers within the skb to store the data */ - skb_reserve(skb, IAVF_SKB_PAD); + skb_reserve(skb, LIBIE_SKB_HEADROOM); __skb_put(skb, size); - /* buffer is used by skb, update page_offset */ -#if (PAGE_SIZE < 8192) - rx_buffer->page_offset ^= truesize; -#else - rx_buffer->page_offset += truesize; -#endif - return skb; } -/** - * iavf_put_rx_buffer - Clean up used buffer and either recycle or free - * @rx_ring: rx descriptor ring to transact packets on - * @rx_buffer: rx buffer to pull data from - * - * This function will clean up the contents of the rx_buffer. It will - * either recycle the buffer or unmap it and free the associated resources. - */ -static void iavf_put_rx_buffer(struct iavf_ring *rx_ring, - struct iavf_rx_buffer *rx_buffer) -{ - if (!rx_buffer) - return; - - if (iavf_can_reuse_rx_page(rx_buffer)) { - /* hand second half of page back to the ring */ - iavf_reuse_rx_page(rx_ring, rx_buffer); - rx_ring->rx_stats.page_reuse_count++; - } else { - /* we are not reusing the buffer so unmap it */ - dma_unmap_page_attrs(rx_ring->dev, rx_buffer->dma, - iavf_rx_pg_size(rx_ring), - DMA_FROM_DEVICE, IAVF_RX_DMA_ATTR); - __page_frag_cache_drain(rx_buffer->page, - rx_buffer->pagecnt_bias); - } - - /* clear contents of buffer_info */ - rx_buffer->page = NULL; -} - /** * iavf_is_non_eop - process handling of non-EOP buffers - * @rx_ring: Rx ring being processed * @rx_desc: Rx descriptor for current buffer - * @skb: Current socket buffer containing buffer in progress + * @stats: NAPI poll local stats to update * * This function updates next to clean. If the buffer is an EOP buffer * this function exits returning false, otherwise it will place the * sk_buff in the next buffer to be chained and return true indicating * that this is in fact a non-EOP buffer. **/ -static bool iavf_is_non_eop(struct iavf_ring *rx_ring, - union iavf_rx_desc *rx_desc, - struct sk_buff *skb) +static bool iavf_is_non_eop(union iavf_rx_desc *rx_desc, + struct libie_rq_onstack_stats *stats) { - u32 ntc = rx_ring->next_to_clean + 1; - - /* fetch, update, and store next to clean */ - ntc = (ntc < rx_ring->count) ? ntc : 0; - rx_ring->next_to_clean = ntc; - - prefetch(IAVF_RX_DESC(rx_ring, ntc)); - /* if we are the last buffer then there is nothing else to do */ #define IAVF_RXD_EOF BIT(IAVF_RX_DESC_STATUS_EOF_SHIFT) if (likely(iavf_test_staterr(rx_desc, IAVF_RXD_EOF))) return false; - rx_ring->rx_stats.non_eop_descs++; + stats->fragments++; return true; } @@ -1496,27 +1126,33 @@ static bool iavf_is_non_eop(struct iavf_ring *rx_ring, **/ static int iavf_clean_rx_irq(struct iavf_ring *rx_ring, int budget) { - unsigned int total_rx_bytes = 0, total_rx_packets = 0; + const gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN; + struct libie_rq_onstack_stats stats = { }; + u32 to_refill = IAVF_DESC_UNUSED(rx_ring); + struct page_pool *pool = rx_ring->pool; struct sk_buff *skb = rx_ring->skb; - u16 cleaned_count = IAVF_DESC_UNUSED(rx_ring); - bool failure = false; + u32 ntc = rx_ring->next_to_clean; + u32 ring_size = rx_ring->count; + u32 cleaned_count = 0; - while (likely(total_rx_packets < (unsigned int)budget)) { - struct iavf_rx_buffer *rx_buffer; + while (likely(cleaned_count < budget)) { union iavf_rx_desc *rx_desc; + struct page *page; unsigned int size; u16 vlan_tag = 0; u8 rx_ptype; u64 qword; /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= IAVF_RX_BUFFER_WRITE) { - failure = failure || - iavf_alloc_rx_buffers(rx_ring, cleaned_count); - cleaned_count = 0; + if (to_refill >= IAVF_RX_BUFFER_WRITE) { + to_refill = __iavf_alloc_rx_pages(rx_ring, to_refill, + gfp); + if (unlikely(to_refill)) + libie_stats_inc_one(&rx_ring->rq_stats, + alloc_page_fail); } - rx_desc = IAVF_RX_DESC(rx_ring, rx_ring->next_to_clean); + rx_desc = IAVF_RX_DESC(rx_ring, ntc); /* status_error_len will always be zero for unused descriptors * because it's cleared in cleanup, and overlaps with hdr_addr @@ -1538,28 +1174,44 @@ static int iavf_clean_rx_irq(struct iavf_ring *rx_ring, int budget) IAVF_RXD_QW1_LENGTH_PBUF_SHIFT; iavf_trace(clean_rx_irq, rx_ring, rx_desc, skb); - rx_buffer = iavf_get_rx_buffer(rx_ring, size); + + page = rx_ring->rx_pages[ntc]; + rx_ring->rx_pages[ntc] = NULL; + + /* Very rare, but possible case. The most common reason: + * the last fragment contained FCS only, which was then + * stripped by the HW. + */ + if (unlikely(!size)) { + page_pool_recycle_direct(pool, page); + goto skip_data; + } + + page_pool_dma_sync_for_cpu(pool, page, size); /* retrieve a buffer from the ring */ if (skb) - iavf_add_rx_frag(rx_ring, rx_buffer, skb, size); - else if (ring_uses_build_skb(rx_ring)) - skb = iavf_build_skb(rx_ring, rx_buffer, size); + iavf_add_rx_frag(skb, page, size); else - skb = iavf_construct_skb(rx_ring, rx_buffer, size); + skb = iavf_build_skb(page, size); /* exit if we failed to retrieve a buffer */ if (!skb) { - rx_ring->rx_stats.alloc_buff_failed++; - if (rx_buffer && size) - rx_buffer->pagecnt_bias++; + page_pool_put_page(pool, page, size, true); + libie_stats_inc_one(&rx_ring->rq_stats, + build_skb_fail); break; } - iavf_put_rx_buffer(rx_ring, rx_buffer); +skip_data: cleaned_count++; + to_refill++; + if (unlikely(++ntc == ring_size)) + ntc = 0; - if (iavf_is_non_eop(rx_ring, rx_desc, skb)) + prefetch(IAVF_RX_DESC(rx_ring, ntc)); + + if (iavf_is_non_eop(rx_desc, &stats)) continue; /* ERR_MASK will only have valid bits if EOP set, and @@ -1579,7 +1231,7 @@ static int iavf_clean_rx_irq(struct iavf_ring *rx_ring, int budget) } /* probably a little skewed due to removing CRC */ - total_rx_bytes += skb->len; + stats.bytes += skb->len; qword = le64_to_cpu(rx_desc->wb.qword1.status_error_len); rx_ptype = (qword & IAVF_RXD_QW1_PTYPE_MASK) >> @@ -1601,20 +1253,29 @@ static int iavf_clean_rx_irq(struct iavf_ring *rx_ring, int budget) skb = NULL; /* update budget accounting */ - total_rx_packets++; + stats.packets++; } + rx_ring->next_to_clean = ntc; rx_ring->skb = skb; - u64_stats_update_begin(&rx_ring->syncp); - rx_ring->stats.packets += total_rx_packets; - rx_ring->stats.bytes += total_rx_bytes; - u64_stats_update_end(&rx_ring->syncp); - rx_ring->q_vector->rx.total_packets += total_rx_packets; - rx_ring->q_vector->rx.total_bytes += total_rx_bytes; + if (to_refill >= IAVF_RX_BUFFER_WRITE) { + to_refill = __iavf_alloc_rx_pages(rx_ring, to_refill, gfp); + /* guarantee a trip back through this routine if there was + * a failure + */ + if (unlikely(to_refill)) { + libie_stats_inc_one(&rx_ring->rq_stats, + alloc_page_fail); + cleaned_count = budget; + } + } + + libie_rq_napi_stats_add(&rx_ring->rq_stats, &stats); + rx_ring->q_vector->rx.total_packets += stats.packets; + rx_ring->q_vector->rx.total_bytes += stats.bytes; - /* guarantee a trip back through this routine if there was a failure */ - return failure ? budget : (int)total_rx_packets; + return cleaned_count; } static inline u32 iavf_buildreg_itr(const int type, u16 itr) @@ -1747,8 +1408,8 @@ int iavf_napi_poll(struct napi_struct *napi, int budget) clean_complete = false; continue; } - arm_wb |= ring->arm_wb; - ring->arm_wb = false; + arm_wb |= !!(ring->flags & IAVF_TXRX_FLAGS_ARM_WB); + ring->flags &= ~IAVF_TXRX_FLAGS_ARM_WB; } /* Handle case where we are called by netpoll with a budget of 0 */ @@ -1791,10 +1452,8 @@ int iavf_napi_poll(struct napi_struct *napi, int budget) return budget - 1; } tx_only: - if (arm_wb) { - q_vector->tx.ring[0].tx_stats.tx_force_wb++; + if (arm_wb) iavf_enable_wb_on_itr(vsi, q_vector); - } return budget; } @@ -2253,6 +1912,7 @@ bool __iavf_chk_linearize(struct sk_buff *skb) int __iavf_maybe_stop_tx(struct iavf_ring *tx_ring, int size) { netif_stop_subqueue(tx_ring->netdev, tx_ring->queue_index); + libie_stats_inc_one(&tx_ring->sq_stats, stops); /* Memory barrier before checking head and tail */ smp_mb(); @@ -2262,7 +1922,8 @@ int __iavf_maybe_stop_tx(struct iavf_ring *tx_ring, int size) /* A reprieve! - use start_queue because it doesn't call schedule */ netif_start_subqueue(tx_ring->netdev, tx_ring->queue_index); - ++tx_ring->tx_stats.restart_queue; + libie_stats_inc_one(&tx_ring->sq_stats, restarts); + return 0; } @@ -2443,7 +2104,7 @@ static netdev_tx_t iavf_xmit_frame_ring(struct sk_buff *skb, return NETDEV_TX_OK; } count = iavf_txd_use_count(skb->len); - tx_ring->tx_stats.tx_linearize++; + libie_stats_inc_one(&tx_ring->sq_stats, linearized); } /* need: 1 descriptor per page * PAGE_SIZE/IAVF_MAX_DATA_PER_TXD, @@ -2453,7 +2114,7 @@ static netdev_tx_t iavf_xmit_frame_ring(struct sk_buff *skb, * otherwise try next time */ if (iavf_maybe_stop_tx(tx_ring, count + 4 + 1)) { - tx_ring->tx_stats.tx_busy++; + libie_stats_inc_one(&tx_ring->sq_stats, busy); return NETDEV_TX_BUSY; } diff --git a/drivers/net/ethernet/intel/iavf/iavf_txrx.h b/drivers/net/ethernet/intel/iavf/iavf_txrx.h index 2624bf6d009e36..64c93d6fa54d09 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_txrx.h +++ b/drivers/net/ethernet/intel/iavf/iavf_txrx.h @@ -4,6 +4,8 @@ #ifndef _IAVF_TXRX_H_ #define _IAVF_TXRX_H_ +#include + /* Interrupt Throttling and Rate Limiting Goodies */ #define IAVF_DEFAULT_IRQ_WORK 256 @@ -81,79 +83,8 @@ enum iavf_dyn_idx_t { BIT_ULL(IAVF_FILTER_PCTYPE_NONF_UNICAST_IPV6_UDP) | \ BIT_ULL(IAVF_FILTER_PCTYPE_NONF_MULTICAST_IPV6_UDP)) -/* Supported Rx Buffer Sizes (a multiple of 128) */ -#define IAVF_RXBUFFER_256 256 -#define IAVF_RXBUFFER_1536 1536 /* 128B aligned standard Ethernet frame */ -#define IAVF_RXBUFFER_2048 2048 -#define IAVF_RXBUFFER_3072 3072 /* Used for large frames w/ padding */ -#define IAVF_MAX_RXBUFFER 9728 /* largest size for single descriptor */ - -/* NOTE: netdev_alloc_skb reserves up to 64 bytes, NET_IP_ALIGN means we - * reserve 2 more, and skb_shared_info adds an additional 384 bytes more, - * this adds up to 512 bytes of extra data meaning the smallest allocation - * we could have is 1K. - * i.e. RXBUFFER_256 --> 960 byte skb (size-1024 slab) - * i.e. RXBUFFER_512 --> 1216 byte skb (size-2048 slab) - */ -#define IAVF_RX_HDR_SIZE IAVF_RXBUFFER_256 -#define IAVF_PACKET_HDR_PAD (ETH_HLEN + ETH_FCS_LEN + (VLAN_HLEN * 2)) #define iavf_rx_desc iavf_32byte_rx_desc -#define IAVF_RX_DMA_ATTR \ - (DMA_ATTR_SKIP_CPU_SYNC | DMA_ATTR_WEAK_ORDERING) - -/* Attempt to maximize the headroom available for incoming frames. We - * use a 2K buffer for receives and need 1536/1534 to store the data for - * the frame. This leaves us with 512 bytes of room. From that we need - * to deduct the space needed for the shared info and the padding needed - * to IP align the frame. - * - * Note: For cache line sizes 256 or larger this value is going to end - * up negative. In these cases we should fall back to the legacy - * receive path. - */ -#if (PAGE_SIZE < 8192) -#define IAVF_2K_TOO_SMALL_WITH_PADDING \ -((NET_SKB_PAD + IAVF_RXBUFFER_1536) > SKB_WITH_OVERHEAD(IAVF_RXBUFFER_2048)) - -static inline int iavf_compute_pad(int rx_buf_len) -{ - int page_size, pad_size; - - page_size = ALIGN(rx_buf_len, PAGE_SIZE / 2); - pad_size = SKB_WITH_OVERHEAD(page_size) - rx_buf_len; - - return pad_size; -} - -static inline int iavf_skb_pad(void) -{ - int rx_buf_len; - - /* If a 2K buffer cannot handle a standard Ethernet frame then - * optimize padding for a 3K buffer instead of a 1.5K buffer. - * - * For a 3K buffer we need to add enough padding to allow for - * tailroom due to NET_IP_ALIGN possibly shifting us out of - * cache-line alignment. - */ - if (IAVF_2K_TOO_SMALL_WITH_PADDING) - rx_buf_len = IAVF_RXBUFFER_3072 + SKB_DATA_ALIGN(NET_IP_ALIGN); - else - rx_buf_len = IAVF_RXBUFFER_1536; - - /* if needed make room for NET_IP_ALIGN */ - rx_buf_len -= NET_IP_ALIGN; - - return iavf_compute_pad(rx_buf_len); -} - -#define IAVF_SKB_PAD iavf_skb_pad() -#else -#define IAVF_2K_TOO_SMALL_WITH_PADDING false -#define IAVF_SKB_PAD (NET_SKB_PAD + NET_IP_ALIGN) -#endif - /** * iavf_test_staterr - tests bits in Rx descriptor status and error fields * @rx_desc: pointer to receive descriptor (in le64 format) @@ -272,46 +203,6 @@ struct iavf_tx_buffer { u32 tx_flags; }; -struct iavf_rx_buffer { - dma_addr_t dma; - struct page *page; -#if (BITS_PER_LONG > 32) || (PAGE_SIZE >= 65536) - __u32 page_offset; -#else - __u16 page_offset; -#endif - __u16 pagecnt_bias; -}; - -struct iavf_queue_stats { - u64 packets; - u64 bytes; -}; - -struct iavf_tx_queue_stats { - u64 restart_queue; - u64 tx_busy; - u64 tx_done_old; - u64 tx_linearize; - u64 tx_force_wb; - int prev_pkt_ctr; - u64 tx_lost_interrupt; -}; - -struct iavf_rx_queue_stats { - u64 non_eop_descs; - u64 alloc_page_failed; - u64 alloc_buff_failed; - u64 page_reuse_count; - u64 realloc_count; -}; - -enum iavf_ring_state_t { - __IAVF_TX_FDIR_INIT_DONE, - __IAVF_TX_XPS_INIT_DONE, - __IAVF_RING_STATE_NBITS /* must be last */ -}; - /* some useful defines for virtchannel interface, which * is the only remaining user of header split */ @@ -327,16 +218,18 @@ enum iavf_ring_state_t { struct iavf_ring { struct iavf_ring *next; /* pointer to next ring in q_vector */ void *desc; /* Descriptor ring memory */ - struct device *dev; /* Used for DMA mapping */ + union { + struct page_pool *pool; /* Used for Rx page management */ + struct device *dev; /* Used for DMA mapping on Tx */ + }; struct net_device *netdev; /* netdev ring maps to */ union { struct iavf_tx_buffer *tx_bi; - struct iavf_rx_buffer *rx_bi; + struct page **rx_pages; }; - DECLARE_BITMAP(state, __IAVF_RING_STATE_NBITS); + u8 __iomem *tail; u16 queue_index; /* Queue number of ring */ u8 dcb_tc; /* Traffic class of ring */ - u8 __iomem *tail; /* high bit set means dynamic, use accessors routines to read/write. * hardware only supports 2us resolution for the ITR registers. @@ -345,44 +238,24 @@ struct iavf_ring { */ u16 itr_setting; - u16 count; /* Number of descriptors */ u16 reg_idx; /* HW register index of the ring */ - u16 rx_buf_len; + u16 count; /* Number of descriptors */ /* used in interrupt processing */ u16 next_to_use; u16 next_to_clean; - u8 atr_sample_rate; - u8 atr_count; - - bool ring_active; /* is ring online or not */ - bool arm_wb; /* do something to arm write back */ - u8 packet_stride; - u16 flags; #define IAVF_TXR_FLAGS_WB_ON_ITR BIT(0) -#define IAVF_RXR_FLAGS_BUILD_SKB_ENABLED BIT(1) +#define IAVF_TXRX_FLAGS_ARM_WB BIT(1) +/* BIT(2) is free */ #define IAVF_TXRX_FLAGS_VLAN_TAG_LOC_L2TAG1 BIT(3) #define IAVF_TXR_FLAGS_VLAN_TAG_LOC_L2TAG2 BIT(4) #define IAVF_RXR_FLAGS_VLAN_TAG_LOC_L2TAG2_2 BIT(5) - /* stats structs */ - struct iavf_queue_stats stats; - struct u64_stats_sync syncp; - union { - struct iavf_tx_queue_stats tx_stats; - struct iavf_rx_queue_stats rx_stats; - }; - - unsigned int size; /* length of descriptor ring in bytes */ - dma_addr_t dma; /* physical address of ring */ - struct iavf_vsi *vsi; /* Backreference to associated VSI */ struct iavf_q_vector *q_vector; /* Backreference to associated vector */ - struct rcu_head rcu; /* to avoid race on free */ - u16 next_to_alloc; struct sk_buff *skb; /* When iavf_clean_rx_ring_irq() must * return before it sees the EOP for * the current packet, we save that skb @@ -391,22 +264,19 @@ struct iavf_ring { * iavf_clean_rx_ring_irq() is called * for this ring. */ -} ____cacheline_internodealigned_in_smp; -static inline bool ring_uses_build_skb(struct iavf_ring *ring) -{ - return !!(ring->flags & IAVF_RXR_FLAGS_BUILD_SKB_ENABLED); -} + /* stats structs */ + union { + struct libie_sq_stats sq_stats; + struct libie_rq_stats rq_stats; + }; -static inline void set_ring_build_skb_enabled(struct iavf_ring *ring) -{ - ring->flags |= IAVF_RXR_FLAGS_BUILD_SKB_ENABLED; -} + int prev_pkt_ctr; /* For stall detection */ + unsigned int size; /* length of descriptor ring in bytes */ + dma_addr_t dma; /* physical address of ring */ -static inline void clear_ring_build_skb_enabled(struct iavf_ring *ring) -{ - ring->flags &= ~IAVF_RXR_FLAGS_BUILD_SKB_ENABLED; -} + struct rcu_head rcu; /* to avoid race on free */ +} ____cacheline_internodealigned_in_smp; #define IAVF_ITR_ADAPTIVE_MIN_INC 0x0002 #define IAVF_ITR_ADAPTIVE_MIN_USECS 0x0002 @@ -429,18 +299,7 @@ struct iavf_ring_container { #define iavf_for_each_ring(pos, head) \ for (pos = (head).ring; pos != NULL; pos = pos->next) -static inline unsigned int iavf_rx_pg_order(struct iavf_ring *ring) -{ -#if (PAGE_SIZE < 8192) - if (ring->rx_buf_len > (PAGE_SIZE / 2)) - return 1; -#endif - return 0; -} - -#define iavf_rx_pg_size(_ring) (PAGE_SIZE << iavf_rx_pg_order(_ring)) - -bool iavf_alloc_rx_buffers(struct iavf_ring *rxr, u16 cleaned_count); +void iavf_alloc_rx_pages(struct iavf_ring *rxr); netdev_tx_t iavf_xmit_frame(struct sk_buff *skb, struct net_device *netdev); void iavf_clean_tx_ring(struct iavf_ring *tx_ring); void iavf_clean_rx_ring(struct iavf_ring *rx_ring); diff --git a/drivers/net/ethernet/intel/iavf/iavf_type.h b/drivers/net/ethernet/intel/iavf/iavf_type.h index 9f1f523807c4e6..bb90d8f3ad7efe 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_type.h +++ b/drivers/net/ethernet/intel/iavf/iavf_type.h @@ -10,8 +10,6 @@ #include "iavf_adminq.h" #include "iavf_devids.h" -#define IAVF_RXQ_CTX_DBUFF_SHIFT 7 - /* IAVF_MASK is a macro used on 32 bit registers */ #define IAVF_MASK(mask, shift) ((u32)(mask) << (shift)) @@ -339,94 +337,6 @@ enum iavf_rx_desc_error_l3l4e_fcoe_masks { #define IAVF_RXD_QW1_PTYPE_SHIFT 30 #define IAVF_RXD_QW1_PTYPE_MASK (0xFFULL << IAVF_RXD_QW1_PTYPE_SHIFT) -/* Packet type non-ip values */ -enum iavf_rx_l2_ptype { - IAVF_RX_PTYPE_L2_RESERVED = 0, - IAVF_RX_PTYPE_L2_MAC_PAY2 = 1, - IAVF_RX_PTYPE_L2_TIMESYNC_PAY2 = 2, - IAVF_RX_PTYPE_L2_FIP_PAY2 = 3, - IAVF_RX_PTYPE_L2_OUI_PAY2 = 4, - IAVF_RX_PTYPE_L2_MACCNTRL_PAY2 = 5, - IAVF_RX_PTYPE_L2_LLDP_PAY2 = 6, - IAVF_RX_PTYPE_L2_ECP_PAY2 = 7, - IAVF_RX_PTYPE_L2_EVB_PAY2 = 8, - IAVF_RX_PTYPE_L2_QCN_PAY2 = 9, - IAVF_RX_PTYPE_L2_EAPOL_PAY2 = 10, - IAVF_RX_PTYPE_L2_ARP = 11, - IAVF_RX_PTYPE_L2_FCOE_PAY3 = 12, - IAVF_RX_PTYPE_L2_FCOE_FCDATA_PAY3 = 13, - IAVF_RX_PTYPE_L2_FCOE_FCRDY_PAY3 = 14, - IAVF_RX_PTYPE_L2_FCOE_FCRSP_PAY3 = 15, - IAVF_RX_PTYPE_L2_FCOE_FCOTHER_PA = 16, - IAVF_RX_PTYPE_L2_FCOE_VFT_PAY3 = 17, - IAVF_RX_PTYPE_L2_FCOE_VFT_FCDATA = 18, - IAVF_RX_PTYPE_L2_FCOE_VFT_FCRDY = 19, - IAVF_RX_PTYPE_L2_FCOE_VFT_FCRSP = 20, - IAVF_RX_PTYPE_L2_FCOE_VFT_FCOTHER = 21, - IAVF_RX_PTYPE_GRENAT4_MAC_PAY3 = 58, - IAVF_RX_PTYPE_GRENAT4_MACVLAN_IPV6_ICMP_PAY4 = 87, - IAVF_RX_PTYPE_GRENAT6_MAC_PAY3 = 124, - IAVF_RX_PTYPE_GRENAT6_MACVLAN_IPV6_ICMP_PAY4 = 153 -}; - -struct iavf_rx_ptype_decoded { - u32 known:1; - u32 outer_ip:1; - u32 outer_ip_ver:1; - u32 outer_frag:1; - u32 tunnel_type:3; - u32 tunnel_end_prot:2; - u32 tunnel_end_frag:1; - u32 inner_prot:4; - u32 payload_layer:3; -}; - -enum iavf_rx_ptype_outer_ip { - IAVF_RX_PTYPE_OUTER_L2 = 0, - IAVF_RX_PTYPE_OUTER_IP = 1 -}; - -enum iavf_rx_ptype_outer_ip_ver { - IAVF_RX_PTYPE_OUTER_NONE = 0, - IAVF_RX_PTYPE_OUTER_IPV4 = 0, - IAVF_RX_PTYPE_OUTER_IPV6 = 1 -}; - -enum iavf_rx_ptype_outer_fragmented { - IAVF_RX_PTYPE_NOT_FRAG = 0, - IAVF_RX_PTYPE_FRAG = 1 -}; - -enum iavf_rx_ptype_tunnel_type { - IAVF_RX_PTYPE_TUNNEL_NONE = 0, - IAVF_RX_PTYPE_TUNNEL_IP_IP = 1, - IAVF_RX_PTYPE_TUNNEL_IP_GRENAT = 2, - IAVF_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3, - IAVF_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4, -}; - -enum iavf_rx_ptype_tunnel_end_prot { - IAVF_RX_PTYPE_TUNNEL_END_NONE = 0, - IAVF_RX_PTYPE_TUNNEL_END_IPV4 = 1, - IAVF_RX_PTYPE_TUNNEL_END_IPV6 = 2, -}; - -enum iavf_rx_ptype_inner_prot { - IAVF_RX_PTYPE_INNER_PROT_NONE = 0, - IAVF_RX_PTYPE_INNER_PROT_UDP = 1, - IAVF_RX_PTYPE_INNER_PROT_TCP = 2, - IAVF_RX_PTYPE_INNER_PROT_SCTP = 3, - IAVF_RX_PTYPE_INNER_PROT_ICMP = 4, - IAVF_RX_PTYPE_INNER_PROT_TIMESYNC = 5 -}; - -enum iavf_rx_ptype_payload_layer { - IAVF_RX_PTYPE_PAYLOAD_LAYER_NONE = 0, - IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1, - IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2, - IAVF_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3, -}; - #define IAVF_RXD_QW1_LENGTH_PBUF_SHIFT 38 #define IAVF_RXD_QW1_LENGTH_PBUF_MASK (0x3FFFULL << \ IAVF_RXD_QW1_LENGTH_PBUF_SHIFT) diff --git a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c index 7c0578b5457b96..c726d0c91cd8c7 100644 --- a/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c +++ b/drivers/net/ethernet/intel/iavf/iavf_virtchnl.c @@ -1,6 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright(c) 2013 - 2018 Intel Corporation. */ +#include + #include "iavf.h" #include "iavf_prototype.h" #include "iavf_client.h" @@ -269,13 +271,12 @@ int iavf_get_vf_vlan_v2_caps(struct iavf_adapter *adapter) void iavf_configure_queues(struct iavf_adapter *adapter) { struct virtchnl_vsi_queue_config_info *vqci; - int i, max_frame = adapter->vf_res->max_mtu; + u32 i, max_frame = adapter->vf_res->max_mtu; int pairs = adapter->num_active_queues; struct virtchnl_queue_pair_info *vqpi; size_t len; - if (max_frame > IAVF_MAX_RXBUFFER || !max_frame) - max_frame = IAVF_MAX_RXBUFFER; + max_frame = min_not_zero(max_frame, LIBIE_MAX_RX_FRM_LEN); if (adapter->current_op != VIRTCHNL_OP_UNKNOWN) { /* bail because we already have a command pending */ @@ -289,11 +290,6 @@ void iavf_configure_queues(struct iavf_adapter *adapter) if (!vqci) return; - /* Limit maximum frame size when jumbo frames is not enabled */ - if (!(adapter->flags & IAVF_FLAG_LEGACY_RX) && - (adapter->netdev->mtu <= ETH_DATA_LEN)) - max_frame = IAVF_RXBUFFER_1536 - NET_IP_ALIGN; - vqci->vsi_id = adapter->vsi_res->vsi_id; vqci->num_queue_pairs = pairs; vqpi = vqci->qpair; @@ -310,9 +306,7 @@ void iavf_configure_queues(struct iavf_adapter *adapter) vqpi->rxq.ring_len = adapter->rx_rings[i].count; vqpi->rxq.dma_ring_addr = adapter->rx_rings[i].dma; vqpi->rxq.max_pkt_size = max_frame; - vqpi->rxq.databuffer_size = - ALIGN(adapter->rx_rings[i].rx_buf_len, - BIT_ULL(IAVF_RXQ_CTX_DBUFF_SHIFT)); + vqpi->rxq.databuffer_size = LIBIE_RX_BUF_LEN; vqpi++; } diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index b4bca1d964a949..4ba3d99439a0ab 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -508,6 +508,12 @@ enum ice_pf_flags { ICE_PF_FLAGS_NBITS /* must be last */ }; +enum ice_misc_thread_tasks { + ICE_MISC_THREAD_EXTTS_EVENT, + ICE_MISC_THREAD_TX_TSTAMP, + ICE_MISC_THREAD_NBITS /* must be last */ +}; + struct ice_switchdev_info { struct ice_vsi *control_vsi; struct ice_vsi *uplink_vsi; @@ -550,6 +556,7 @@ struct ice_pf { DECLARE_BITMAP(features, ICE_F_MAX); DECLARE_BITMAP(state, ICE_STATE_NBITS); DECLARE_BITMAP(flags, ICE_PF_FLAGS_NBITS); + DECLARE_BITMAP(misc_thread, ICE_MISC_THREAD_NBITS); unsigned long *avail_txqs; /* bitmap to track PF Tx queue usage */ unsigned long *avail_rxqs; /* bitmap to track PF Rx queue usage */ unsigned long serv_tmr_period; diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 0157f6e98d3e24..eb2dc09837769c 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -5160,7 +5160,7 @@ ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, */ int ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, - u16 bus_addr, __le16 addr, u8 params, u8 *data, + u16 bus_addr, __le16 addr, u8 params, const u8 *data, struct ice_sq_cd *cd) { struct ice_aq_desc desc = { 0 }; diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h index 8ba5f935a092bf..81961a7d65985c 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.h +++ b/drivers/net/ethernet/intel/ice/ice_common.h @@ -229,7 +229,7 @@ ice_aq_read_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, struct ice_sq_cd *cd); int ice_aq_write_i2c(struct ice_hw *hw, struct ice_aqc_link_topo_addr topo_addr, - u16 bus_addr, __le16 addr, u8 params, u8 *data, + u16 bus_addr, __le16 addr, u8 params, const u8 *data, struct ice_sq_cd *cd); bool ice_fw_supports_report_dflt_cfg(struct ice_hw *hw); #endif /* _ICE_COMMON_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_devlink.c b/drivers/net/ethernet/intel/ice/ice_devlink.c index bc44cc22081807..80dc5445b50d45 100644 --- a/drivers/net/ethernet/intel/ice/ice_devlink.c +++ b/drivers/net/ethernet/intel/ice/ice_devlink.c @@ -1256,8 +1256,6 @@ static const struct devlink_ops ice_devlink_ops = { BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), .reload_down = ice_devlink_reload_down, .reload_up = ice_devlink_reload_up, - .port_split = ice_devlink_port_split, - .port_unsplit = ice_devlink_port_unsplit, .eswitch_mode_get = ice_eswitch_mode_get, .eswitch_mode_set = ice_eswitch_mode_set, .info_get = ice_devlink_info_get, @@ -1512,6 +1510,11 @@ ice_devlink_set_port_split_options(struct ice_pf *pf, ice_active_port_option = active_idx; } +static const struct devlink_port_ops ice_devlink_port_ops = { + .port_split = ice_devlink_port_split, + .port_unsplit = ice_devlink_port_unsplit, +}; + /** * ice_devlink_create_pf_port - Create a devlink port for this PF * @pf: the PF to create a devlink port for @@ -1551,7 +1554,8 @@ int ice_devlink_create_pf_port(struct ice_pf *pf) devlink_port_attrs_set(devlink_port, &attrs); devlink = priv_to_devlink(pf); - err = devlink_port_register(devlink, devlink_port, vsi->idx); + err = devlink_port_register_with_ops(devlink, devlink_port, vsi->idx, + &ice_devlink_port_ops); if (err) { dev_err(dev, "Failed to create devlink port for PF %d, error %d\n", pf->hw.pf_id, err); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.c b/drivers/net/ethernet/intel/ice/ice_eswitch.c index f6dd3f8fd936e0..ad0a007b739881 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.c +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.c @@ -10,16 +10,15 @@ #include "ice_tc_lib.h" /** - * ice_eswitch_add_vf_mac_rule - add adv rule with VF's MAC + * ice_eswitch_add_vf_sp_rule - add adv rule with VF's VSI index * @pf: pointer to PF struct * @vf: pointer to VF struct - * @mac: VF's MAC address * * This function adds advanced rule that forwards packets with - * VF's MAC address (src MAC) to the corresponding switchdev ctrl VSI queue. + * VF's VSI index to the corresponding switchdev ctrl VSI queue. */ -int -ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac) +static int +ice_eswitch_add_vf_sp_rule(struct ice_pf *pf, struct ice_vf *vf) { struct ice_vsi *ctrl_vsi = pf->switchdev.control_vsi; struct ice_adv_rule_info rule_info = { 0 }; @@ -32,76 +31,41 @@ ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, const u8 *mac) if (!list) return -ENOMEM; - list[0].type = ICE_MAC_OFOS; - ether_addr_copy(list[0].h_u.eth_hdr.src_addr, mac); - eth_broadcast_addr(list[0].m_u.eth_hdr.src_addr); + ice_rule_add_src_vsi_metadata(list); - rule_info.sw_act.flag |= ICE_FLTR_TX; + rule_info.sw_act.flag = ICE_FLTR_TX; rule_info.sw_act.vsi_handle = ctrl_vsi->idx; rule_info.sw_act.fltr_act = ICE_FWD_TO_Q; - rule_info.rx = false; rule_info.sw_act.fwd_id.q_id = hw->func_caps.common_cap.rxq_first_id + ctrl_vsi->rxq_map[vf->vf_id]; rule_info.flags_info.act |= ICE_SINGLE_ACT_LB_ENABLE; rule_info.flags_info.act_valid = true; rule_info.tun_type = ICE_SW_TUN_AND_NON_TUN; + rule_info.src_vsi = vf->lan_vsi_idx; err = ice_add_adv_rule(hw, list, lkups_cnt, &rule_info, - vf->repr->mac_rule); + &vf->repr->sp_rule); if (err) - dev_err(ice_pf_to_dev(pf), "Unable to add VF mac rule in switchdev mode for VF %d", + dev_err(ice_pf_to_dev(pf), "Unable to add VF slow-path rule in switchdev mode for VF %d", vf->vf_id); - else - vf->repr->rule_added = true; kfree(list); return err; } /** - * ice_eswitch_replay_vf_mac_rule - replay adv rule with VF's MAC - * @vf: pointer to vF struct - * - * This function replays VF's MAC rule after reset. - */ -void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf) -{ - int err; - - if (!ice_is_switchdev_running(vf->pf)) - return; - - if (is_valid_ether_addr(vf->hw_lan_addr)) { - err = ice_eswitch_add_vf_mac_rule(vf->pf, vf, - vf->hw_lan_addr); - if (err) { - dev_err(ice_pf_to_dev(vf->pf), "Failed to add MAC %pM for VF %d\n, error %d\n", - vf->hw_lan_addr, vf->vf_id, err); - return; - } - vf->num_mac++; - - ether_addr_copy(vf->dev_lan_addr, vf->hw_lan_addr); - } -} - -/** - * ice_eswitch_del_vf_mac_rule - delete adv rule with VF's MAC + * ice_eswitch_del_vf_sp_rule - delete adv rule with VF's VSI index * @vf: pointer to the VF struct * - * Delete the advanced rule that was used to forward packets with the VF's MAC - * address (src MAC) to the corresponding switchdev ctrl VSI queue. + * Delete the advanced rule that was used to forward packets with the VF's VSI + * index to the corresponding switchdev ctrl VSI queue. */ -void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf) +static void ice_eswitch_del_vf_sp_rule(struct ice_vf *vf) { - if (!ice_is_switchdev_running(vf->pf)) - return; - - if (!vf->repr->rule_added) + if (!vf->repr) return; - ice_rem_adv_rule_by_id(&vf->pf->hw, vf->repr->mac_rule); - vf->repr->rule_added = false; + ice_rem_adv_rule_by_id(&vf->pf->hw, &vf->repr->sp_rule); } /** @@ -237,6 +201,7 @@ ice_eswitch_release_reprs(struct ice_pf *pf, struct ice_vsi *ctrl_vsi) ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof); metadata_dst_free(vf->repr->dst); vf->repr->dst = NULL; + ice_eswitch_del_vf_sp_rule(vf); ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); @@ -264,25 +229,30 @@ static int ice_eswitch_setup_reprs(struct ice_pf *pf) vf->repr->dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX, GFP_KERNEL); if (!vf->repr->dst) { - ice_fltr_add_mac_and_broadcast(vsi, - vf->hw_lan_addr, + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, + ICE_FWD_TO_VSI); + goto err; + } + + if (ice_eswitch_add_vf_sp_rule(pf, vf)) { + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); goto err; } if (ice_vsi_update_security(vsi, ice_vsi_ctx_clear_antispoof)) { - ice_fltr_add_mac_and_broadcast(vsi, - vf->hw_lan_addr, + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); + ice_eswitch_del_vf_sp_rule(vf); metadata_dst_free(vf->repr->dst); vf->repr->dst = NULL; goto err; } if (ice_vsi_add_vlan_zero(vsi)) { - ice_fltr_add_mac_and_broadcast(vsi, - vf->hw_lan_addr, + ice_fltr_add_mac_and_broadcast(vsi, vf->hw_lan_addr, ICE_FWD_TO_VSI); + ice_eswitch_del_vf_sp_rule(vf); metadata_dst_free(vf->repr->dst); vf->repr->dst = NULL; ice_vsi_update_security(vsi, ice_vsi_ctx_set_antispoof); diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h index 6a413331572b6a..b18bf83a2f5b29 100644 --- a/drivers/net/ethernet/intel/ice/ice_eswitch.h +++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h @@ -20,11 +20,6 @@ bool ice_is_eswitch_mode_switchdev(struct ice_pf *pf); void ice_eswitch_update_repr(struct ice_vsi *vsi); void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf); -int -ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, - const u8 *mac); -void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf); -void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf); void ice_eswitch_set_target_vsi(struct sk_buff *skb, struct ice_tx_offload_params *off); @@ -34,15 +29,6 @@ ice_eswitch_port_start_xmit(struct sk_buff *skb, struct net_device *netdev); static inline void ice_eswitch_release(struct ice_pf *pf) { } static inline void ice_eswitch_stop_all_tx_queues(struct ice_pf *pf) { } -static inline void ice_eswitch_replay_vf_mac_rule(struct ice_vf *vf) { } -static inline void ice_eswitch_del_vf_mac_rule(struct ice_vf *vf) { } - -static inline int -ice_eswitch_add_vf_mac_rule(struct ice_pf *pf, struct ice_vf *vf, - const u8 *mac) -{ - return -EOPNOTSUPP; -} static inline void ice_eswitch_set_target_vsi(struct sk_buff *skb, diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.c b/drivers/net/ethernet/intel/ice/ice_gnss.c index 2ea8a2b11bcda7..bd0ed155e11b62 100644 --- a/drivers/net/ethernet/intel/ice/ice_gnss.c +++ b/drivers/net/ethernet/intel/ice/ice_gnss.c @@ -16,8 +16,8 @@ * * number of bytes written - success * * negative - error code */ -static unsigned int -ice_gnss_do_write(struct ice_pf *pf, unsigned char *buf, unsigned int size) +static int +ice_gnss_do_write(struct ice_pf *pf, const unsigned char *buf, unsigned int size) { struct ice_aqc_link_topo_addr link_topo; struct ice_hw *hw = &pf->hw; @@ -72,39 +72,7 @@ ice_gnss_do_write(struct ice_pf *pf, unsigned char *buf, unsigned int size) dev_err(ice_pf_to_dev(pf), "GNSS failed to write, offset=%u, size=%u, err=%d\n", offset, size, err); - return offset; -} - -/** - * ice_gnss_write_pending - Write all pending data to internal GNSS - * @work: GNSS write work structure - */ -static void ice_gnss_write_pending(struct kthread_work *work) -{ - struct gnss_serial *gnss = container_of(work, struct gnss_serial, - write_work); - struct ice_pf *pf = gnss->back; - - if (!pf) - return; - - if (!test_bit(ICE_FLAG_GNSS, pf->flags)) - return; - - if (!list_empty(&gnss->queue)) { - struct gnss_write_buf *write_buf = NULL; - unsigned int bytes; - - write_buf = list_first_entry(&gnss->queue, - struct gnss_write_buf, queue); - - bytes = ice_gnss_do_write(pf, write_buf->buf, write_buf->size); - dev_dbg(ice_pf_to_dev(pf), "%u bytes written to GNSS\n", bytes); - - list_del(&write_buf->queue); - kfree(write_buf->buf); - kfree(write_buf); - } + return err; } /** @@ -220,8 +188,6 @@ static struct gnss_serial *ice_gnss_struct_init(struct ice_pf *pf) pf->gnss_serial = gnss; kthread_init_delayed_work(&gnss->read_work, ice_gnss_read); - INIT_LIST_HEAD(&gnss->queue); - kthread_init_work(&gnss->write_work, ice_gnss_write_pending); kworker = kthread_create_worker(0, "ice-gnss-%s", dev_name(dev)); if (IS_ERR(kworker)) { kfree(gnss); @@ -281,7 +247,6 @@ static void ice_gnss_close(struct gnss_device *gdev) if (!gnss) return; - kthread_cancel_work_sync(&gnss->write_work); kthread_cancel_delayed_work_sync(&gnss->read_work); } @@ -300,10 +265,7 @@ ice_gnss_write(struct gnss_device *gdev, const unsigned char *buf, size_t count) { struct ice_pf *pf = gnss_get_drvdata(gdev); - struct gnss_write_buf *write_buf; struct gnss_serial *gnss; - unsigned char *cmd_buf; - int err = count; /* We cannot write a single byte using our I2C implementation. */ if (count <= 1 || count > ICE_GNSS_TTY_WRITE_BUF) @@ -319,24 +281,7 @@ ice_gnss_write(struct gnss_device *gdev, const unsigned char *buf, if (!gnss) return -ENODEV; - cmd_buf = kcalloc(count, sizeof(*buf), GFP_KERNEL); - if (!cmd_buf) - return -ENOMEM; - - memcpy(cmd_buf, buf, count); - write_buf = kzalloc(sizeof(*write_buf), GFP_KERNEL); - if (!write_buf) { - kfree(cmd_buf); - return -ENOMEM; - } - - write_buf->buf = cmd_buf; - write_buf->size = count; - INIT_LIST_HEAD(&write_buf->queue); - list_add_tail(&write_buf->queue, &gnss->queue); - kthread_queue_work(gnss->kworker, &gnss->write_work); - - return err; + return ice_gnss_do_write(pf, buf, count); } static const struct gnss_operations ice_gnss_ops = { @@ -432,7 +377,6 @@ void ice_gnss_exit(struct ice_pf *pf) if (pf->gnss_serial) { struct gnss_serial *gnss = pf->gnss_serial; - kthread_cancel_work_sync(&gnss->write_work); kthread_cancel_delayed_work_sync(&gnss->read_work); kthread_destroy_worker(gnss->kworker); gnss->kworker = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_gnss.h b/drivers/net/ethernet/intel/ice/ice_gnss.h index b8bb8b63d08172..75e567ad705945 100644 --- a/drivers/net/ethernet/intel/ice/ice_gnss.h +++ b/drivers/net/ethernet/intel/ice/ice_gnss.h @@ -22,26 +22,16 @@ */ #define ICE_GNSS_UBX_WRITE_BYTES (ICE_MAX_I2C_WRITE_BYTES + 1) -struct gnss_write_buf { - struct list_head queue; - unsigned int size; - unsigned char *buf; -}; - /** * struct gnss_serial - data used to initialize GNSS TTY port * @back: back pointer to PF * @kworker: kwork thread for handling periodic work * @read_work: read_work function for handling GNSS reads - * @write_work: write_work function for handling GNSS writes - * @queue: write buffers queue */ struct gnss_serial { struct ice_pf *back; struct kthread_worker *kworker; struct kthread_delayed_work read_work; - struct kthread_work write_work; - struct list_head queue; }; #if IS_ENABLED(CONFIG_GNSS) diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index 89f986a75cc855..611577ebc29d82 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -160,64 +160,6 @@ struct ice_fltr_desc { (0x1ULL << ICE_FXD_FLTR_WB_QW1_FAIL_PROF_S) #define ICE_FXD_FLTR_WB_QW1_FAIL_PROF_YES 0x1ULL -struct ice_rx_ptype_decoded { - u32 known:1; - u32 outer_ip:1; - u32 outer_ip_ver:2; - u32 outer_frag:1; - u32 tunnel_type:3; - u32 tunnel_end_prot:2; - u32 tunnel_end_frag:1; - u32 inner_prot:4; - u32 payload_layer:3; -}; - -enum ice_rx_ptype_outer_ip { - ICE_RX_PTYPE_OUTER_L2 = 0, - ICE_RX_PTYPE_OUTER_IP = 1, -}; - -enum ice_rx_ptype_outer_ip_ver { - ICE_RX_PTYPE_OUTER_NONE = 0, - ICE_RX_PTYPE_OUTER_IPV4 = 1, - ICE_RX_PTYPE_OUTER_IPV6 = 2, -}; - -enum ice_rx_ptype_outer_fragmented { - ICE_RX_PTYPE_NOT_FRAG = 0, - ICE_RX_PTYPE_FRAG = 1, -}; - -enum ice_rx_ptype_tunnel_type { - ICE_RX_PTYPE_TUNNEL_NONE = 0, - ICE_RX_PTYPE_TUNNEL_IP_IP = 1, - ICE_RX_PTYPE_TUNNEL_IP_GRENAT = 2, - ICE_RX_PTYPE_TUNNEL_IP_GRENAT_MAC = 3, - ICE_RX_PTYPE_TUNNEL_IP_GRENAT_MAC_VLAN = 4, -}; - -enum ice_rx_ptype_tunnel_end_prot { - ICE_RX_PTYPE_TUNNEL_END_NONE = 0, - ICE_RX_PTYPE_TUNNEL_END_IPV4 = 1, - ICE_RX_PTYPE_TUNNEL_END_IPV6 = 2, -}; - -enum ice_rx_ptype_inner_prot { - ICE_RX_PTYPE_INNER_PROT_NONE = 0, - ICE_RX_PTYPE_INNER_PROT_UDP = 1, - ICE_RX_PTYPE_INNER_PROT_TCP = 2, - ICE_RX_PTYPE_INNER_PROT_SCTP = 3, - ICE_RX_PTYPE_INNER_PROT_ICMP = 4, - ICE_RX_PTYPE_INNER_PROT_TIMESYNC = 5, -}; - -enum ice_rx_ptype_payload_layer { - ICE_RX_PTYPE_PAYLOAD_LAYER_NONE = 0, - ICE_RX_PTYPE_PAYLOAD_LAYER_PAY2 = 1, - ICE_RX_PTYPE_PAYLOAD_LAYER_PAY3 = 2, - ICE_RX_PTYPE_PAYLOAD_LAYER_PAY4 = 3, -}; - /* Rx Flex Descriptor * This descriptor is used instead of the legacy version descriptor when * ice_rlan_ctx.adv_desc is set @@ -651,262 +593,4 @@ struct ice_tlan_ctx { u8 int_q_state; /* width not needed - internal - DO NOT WRITE!!! */ }; -/* The ice_ptype_lkup table is used to convert from the 10-bit ptype in the - * hardware to a bit-field that can be used by SW to more easily determine the - * packet type. - * - * Macros are used to shorten the table lines and make this table human - * readable. - * - * We store the PTYPE in the top byte of the bit field - this is just so that - * we can check that the table doesn't have a row missing, as the index into - * the table should be the PTYPE. - * - * Typical work flow: - * - * IF NOT ice_ptype_lkup[ptype].known - * THEN - * Packet is unknown - * ELSE IF ice_ptype_lkup[ptype].outer_ip == ICE_RX_PTYPE_OUTER_IP - * Use the rest of the fields to look at the tunnels, inner protocols, etc - * ELSE - * Use the enum ice_rx_l2_ptype to decode the packet type - * ENDIF - */ - -/* macro to make the table lines short, use explicit indexing with [PTYPE] */ -#define ICE_PTT(PTYPE, OUTER_IP, OUTER_IP_VER, OUTER_FRAG, T, TE, TEF, I, PL)\ - [PTYPE] = { \ - 1, \ - ICE_RX_PTYPE_OUTER_##OUTER_IP, \ - ICE_RX_PTYPE_OUTER_##OUTER_IP_VER, \ - ICE_RX_PTYPE_##OUTER_FRAG, \ - ICE_RX_PTYPE_TUNNEL_##T, \ - ICE_RX_PTYPE_TUNNEL_END_##TE, \ - ICE_RX_PTYPE_##TEF, \ - ICE_RX_PTYPE_INNER_PROT_##I, \ - ICE_RX_PTYPE_PAYLOAD_LAYER_##PL } - -#define ICE_PTT_UNUSED_ENTRY(PTYPE) [PTYPE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } - -/* shorter macros makes the table fit but are terse */ -#define ICE_RX_PTYPE_NOF ICE_RX_PTYPE_NOT_FRAG -#define ICE_RX_PTYPE_FRG ICE_RX_PTYPE_FRAG - -/* Lookup table mapping in the 10-bit HW PTYPE to the bit field for decoding */ -static const struct ice_rx_ptype_decoded ice_ptype_lkup[BIT(10)] = { - /* L2 Packet types */ - ICE_PTT_UNUSED_ENTRY(0), - ICE_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - ICE_PTT_UNUSED_ENTRY(2), - ICE_PTT_UNUSED_ENTRY(3), - ICE_PTT_UNUSED_ENTRY(4), - ICE_PTT_UNUSED_ENTRY(5), - ICE_PTT(6, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), - ICE_PTT(7, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), - ICE_PTT_UNUSED_ENTRY(8), - ICE_PTT_UNUSED_ENTRY(9), - ICE_PTT(10, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), - ICE_PTT(11, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), - ICE_PTT_UNUSED_ENTRY(12), - ICE_PTT_UNUSED_ENTRY(13), - ICE_PTT_UNUSED_ENTRY(14), - ICE_PTT_UNUSED_ENTRY(15), - ICE_PTT_UNUSED_ENTRY(16), - ICE_PTT_UNUSED_ENTRY(17), - ICE_PTT_UNUSED_ENTRY(18), - ICE_PTT_UNUSED_ENTRY(19), - ICE_PTT_UNUSED_ENTRY(20), - ICE_PTT_UNUSED_ENTRY(21), - - /* Non Tunneled IPv4 */ - ICE_PTT(22, IP, IPV4, FRG, NONE, NONE, NOF, NONE, PAY3), - ICE_PTT(23, IP, IPV4, NOF, NONE, NONE, NOF, NONE, PAY3), - ICE_PTT(24, IP, IPV4, NOF, NONE, NONE, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(25), - ICE_PTT(26, IP, IPV4, NOF, NONE, NONE, NOF, TCP, PAY4), - ICE_PTT(27, IP, IPV4, NOF, NONE, NONE, NOF, SCTP, PAY4), - ICE_PTT(28, IP, IPV4, NOF, NONE, NONE, NOF, ICMP, PAY4), - - /* IPv4 --> IPv4 */ - ICE_PTT(29, IP, IPV4, NOF, IP_IP, IPV4, FRG, NONE, PAY3), - ICE_PTT(30, IP, IPV4, NOF, IP_IP, IPV4, NOF, NONE, PAY3), - ICE_PTT(31, IP, IPV4, NOF, IP_IP, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(32), - ICE_PTT(33, IP, IPV4, NOF, IP_IP, IPV4, NOF, TCP, PAY4), - ICE_PTT(34, IP, IPV4, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), - ICE_PTT(35, IP, IPV4, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> IPv6 */ - ICE_PTT(36, IP, IPV4, NOF, IP_IP, IPV6, FRG, NONE, PAY3), - ICE_PTT(37, IP, IPV4, NOF, IP_IP, IPV6, NOF, NONE, PAY3), - ICE_PTT(38, IP, IPV4, NOF, IP_IP, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(39), - ICE_PTT(40, IP, IPV4, NOF, IP_IP, IPV6, NOF, TCP, PAY4), - ICE_PTT(41, IP, IPV4, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), - ICE_PTT(42, IP, IPV4, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT */ - ICE_PTT(43, IP, IPV4, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), - - /* IPv4 --> GRE/NAT --> IPv4 */ - ICE_PTT(44, IP, IPV4, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), - ICE_PTT(45, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), - ICE_PTT(46, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(47), - ICE_PTT(48, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), - ICE_PTT(49, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), - ICE_PTT(50, IP, IPV4, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> IPv6 */ - ICE_PTT(51, IP, IPV4, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), - ICE_PTT(52, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), - ICE_PTT(53, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(54), - ICE_PTT(55, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), - ICE_PTT(56, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), - ICE_PTT(57, IP, IPV4, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> MAC */ - ICE_PTT(58, IP, IPV4, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), - - /* IPv4 --> GRE/NAT --> MAC --> IPv4 */ - ICE_PTT(59, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), - ICE_PTT(60, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), - ICE_PTT(61, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(62), - ICE_PTT(63, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), - ICE_PTT(64, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), - ICE_PTT(65, IP, IPV4, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT -> MAC --> IPv6 */ - ICE_PTT(66, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), - ICE_PTT(67, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), - ICE_PTT(68, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(69), - ICE_PTT(70, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), - ICE_PTT(71, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), - ICE_PTT(72, IP, IPV4, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), - - /* IPv4 --> GRE/NAT --> MAC/VLAN */ - ICE_PTT(73, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), - - /* IPv4 ---> GRE/NAT -> MAC/VLAN --> IPv4 */ - ICE_PTT(74, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), - ICE_PTT(75, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), - ICE_PTT(76, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(77), - ICE_PTT(78, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), - ICE_PTT(79, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), - ICE_PTT(80, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), - - /* IPv4 -> GRE/NAT -> MAC/VLAN --> IPv6 */ - ICE_PTT(81, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), - ICE_PTT(82, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), - ICE_PTT(83, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(84), - ICE_PTT(85, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), - ICE_PTT(86, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), - ICE_PTT(87, IP, IPV4, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), - - /* Non Tunneled IPv6 */ - ICE_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), - ICE_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), - ICE_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(91), - ICE_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), - ICE_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), - ICE_PTT(94, IP, IPV6, NOF, NONE, NONE, NOF, ICMP, PAY4), - - /* IPv6 --> IPv4 */ - ICE_PTT(95, IP, IPV6, NOF, IP_IP, IPV4, FRG, NONE, PAY3), - ICE_PTT(96, IP, IPV6, NOF, IP_IP, IPV4, NOF, NONE, PAY3), - ICE_PTT(97, IP, IPV6, NOF, IP_IP, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(98), - ICE_PTT(99, IP, IPV6, NOF, IP_IP, IPV4, NOF, TCP, PAY4), - ICE_PTT(100, IP, IPV6, NOF, IP_IP, IPV4, NOF, SCTP, PAY4), - ICE_PTT(101, IP, IPV6, NOF, IP_IP, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> IPv6 */ - ICE_PTT(102, IP, IPV6, NOF, IP_IP, IPV6, FRG, NONE, PAY3), - ICE_PTT(103, IP, IPV6, NOF, IP_IP, IPV6, NOF, NONE, PAY3), - ICE_PTT(104, IP, IPV6, NOF, IP_IP, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(105), - ICE_PTT(106, IP, IPV6, NOF, IP_IP, IPV6, NOF, TCP, PAY4), - ICE_PTT(107, IP, IPV6, NOF, IP_IP, IPV6, NOF, SCTP, PAY4), - ICE_PTT(108, IP, IPV6, NOF, IP_IP, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT */ - ICE_PTT(109, IP, IPV6, NOF, IP_GRENAT, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> IPv4 */ - ICE_PTT(110, IP, IPV6, NOF, IP_GRENAT, IPV4, FRG, NONE, PAY3), - ICE_PTT(111, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, NONE, PAY3), - ICE_PTT(112, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(113), - ICE_PTT(114, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, TCP, PAY4), - ICE_PTT(115, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, SCTP, PAY4), - ICE_PTT(116, IP, IPV6, NOF, IP_GRENAT, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> IPv6 */ - ICE_PTT(117, IP, IPV6, NOF, IP_GRENAT, IPV6, FRG, NONE, PAY3), - ICE_PTT(118, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, NONE, PAY3), - ICE_PTT(119, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(120), - ICE_PTT(121, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, TCP, PAY4), - ICE_PTT(122, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, SCTP, PAY4), - ICE_PTT(123, IP, IPV6, NOF, IP_GRENAT, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC */ - ICE_PTT(124, IP, IPV6, NOF, IP_GRENAT_MAC, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> MAC -> IPv4 */ - ICE_PTT(125, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, FRG, NONE, PAY3), - ICE_PTT(126, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, NONE, PAY3), - ICE_PTT(127, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(128), - ICE_PTT(129, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, TCP, PAY4), - ICE_PTT(130, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, SCTP, PAY4), - ICE_PTT(131, IP, IPV6, NOF, IP_GRENAT_MAC, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC -> IPv6 */ - ICE_PTT(132, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, FRG, NONE, PAY3), - ICE_PTT(133, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, NONE, PAY3), - ICE_PTT(134, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(135), - ICE_PTT(136, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, TCP, PAY4), - ICE_PTT(137, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, SCTP, PAY4), - ICE_PTT(138, IP, IPV6, NOF, IP_GRENAT_MAC, IPV6, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC/VLAN */ - ICE_PTT(139, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, NONE, NOF, NONE, PAY3), - - /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv4 */ - ICE_PTT(140, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, FRG, NONE, PAY3), - ICE_PTT(141, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, NONE, PAY3), - ICE_PTT(142, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(143), - ICE_PTT(144, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, TCP, PAY4), - ICE_PTT(145, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, SCTP, PAY4), - ICE_PTT(146, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV4, NOF, ICMP, PAY4), - - /* IPv6 --> GRE/NAT -> MAC/VLAN --> IPv6 */ - ICE_PTT(147, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, FRG, NONE, PAY3), - ICE_PTT(148, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, NONE, PAY3), - ICE_PTT(149, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, UDP, PAY4), - ICE_PTT_UNUSED_ENTRY(150), - ICE_PTT(151, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, TCP, PAY4), - ICE_PTT(152, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, SCTP, PAY4), - ICE_PTT(153, IP, IPV6, NOF, IP_GRENAT_MAC_VLAN, IPV6, NOF, ICMP, PAY4), - - /* unused entries */ - [154 ... 1023] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 } -}; - -static inline struct ice_rx_ptype_decoded ice_decode_rx_desc_ptype(u16 ptype) -{ - return ice_ptype_lkup[ptype]; -} - - #endif /* _ICE_LAN_TX_RX_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 62e91512aeabca..0d9a63fb47f7f2 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -34,6 +34,7 @@ static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation."; MODULE_AUTHOR("Intel Corporation, "); MODULE_DESCRIPTION(DRV_SUMMARY); +MODULE_IMPORT_NS(LIBIE); MODULE_LICENSE("GPL v2"); MODULE_FIRMWARE(ICE_DDP_PKG_FILE); @@ -3058,7 +3059,6 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) { struct ice_pf *pf = (struct ice_pf *)data; struct ice_hw *hw = &pf->hw; - irqreturn_t ret = IRQ_NONE; struct device *dev; u32 oicr, ena_mask; @@ -3140,19 +3140,24 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) if (oicr & PFINT_OICR_TSYN_TX_M) { ena_mask &= ~PFINT_OICR_TSYN_TX_M; if (!hw->reset_ongoing) - ret = IRQ_WAKE_THREAD; + set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread); } if (oicr & PFINT_OICR_TSYN_EVNT_M) { u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned; u32 gltsyn_stat = rd32(hw, GLTSYN_STAT(tmr_idx)); - /* Save EVENTs from GTSYN register */ - pf->ptp.ext_ts_irq |= gltsyn_stat & (GLTSYN_STAT_EVENT0_M | - GLTSYN_STAT_EVENT1_M | - GLTSYN_STAT_EVENT2_M); ena_mask &= ~PFINT_OICR_TSYN_EVNT_M; - kthread_queue_work(pf->ptp.kworker, &pf->ptp.extts_work); + + if (hw->func_caps.ts_func_info.src_tmr_owned) { + /* Save EVENTs from GLTSYN register */ + pf->ptp.ext_ts_irq |= gltsyn_stat & + (GLTSYN_STAT_EVENT0_M | + GLTSYN_STAT_EVENT1_M | + GLTSYN_STAT_EVENT2_M); + + set_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread); + } } #define ICE_AUX_CRIT_ERR (PFINT_OICR_PE_CRITERR_M | PFINT_OICR_HMC_ERR_M | PFINT_OICR_PE_PUSH_M) @@ -3172,16 +3177,10 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) if (oicr & (PFINT_OICR_PCI_EXCEPTION_M | PFINT_OICR_ECC_ERR_M)) { set_bit(ICE_PFR_REQ, pf->state); - ice_service_task_schedule(pf); } } - if (!ret) - ret = IRQ_HANDLED; - ice_service_task_schedule(pf); - ice_irq_dynamic_ena(hw, NULL, NULL); - - return ret; + return IRQ_WAKE_THREAD; } /** @@ -3192,12 +3191,29 @@ static irqreturn_t ice_misc_intr(int __always_unused irq, void *data) static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) { struct ice_pf *pf = data; + struct ice_hw *hw; + + hw = &pf->hw; if (ice_is_reset_in_progress(pf->state)) return IRQ_HANDLED; - while (!ice_ptp_process_ts(pf)) - usleep_range(50, 100); + ice_service_task_schedule(pf); + + if (test_and_clear_bit(ICE_MISC_THREAD_EXTTS_EVENT, pf->misc_thread)) + ice_ptp_extts_event(pf); + + if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { + /* Process outstanding Tx timestamps. If there is more work, + * re-arm the interrupt to trigger again. + */ + if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) { + wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); + ice_flush(hw); + } + } + + ice_irq_dynamic_ena(hw, NULL, NULL); return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/intel/ice/ice_protocol_type.h b/drivers/net/ethernet/intel/ice/ice_protocol_type.h index 02a4e1cf624e9a..6a9364761165d2 100644 --- a/drivers/net/ethernet/intel/ice/ice_protocol_type.h +++ b/drivers/net/ethernet/intel/ice/ice_protocol_type.h @@ -47,6 +47,7 @@ enum ice_protocol_type { ICE_L2TPV3, ICE_VLAN_EX, ICE_VLAN_IN, + ICE_HW_METADATA, ICE_VXLAN_GPE, ICE_SCTP_IL, ICE_PROTOCOL_LAST @@ -115,17 +116,7 @@ enum ice_prot_id { #define ICE_L2TPV3_HW 104 #define ICE_UDP_OF_HW 52 /* UDP Tunnels */ -#define ICE_META_DATA_ID_HW 255 /* this is used for tunnel and VLAN type */ -#define ICE_MDID_SIZE 2 - -#define ICE_TUN_FLAG_MDID 21 -#define ICE_TUN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_TUN_FLAG_MDID) -#define ICE_TUN_FLAG_MASK 0xFF - -#define ICE_VLAN_FLAG_MDID 20 -#define ICE_VLAN_FLAG_MDID_OFF (ICE_MDID_SIZE * ICE_VLAN_FLAG_MDID) -#define ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK 0xD000 #define ICE_TUN_FLAG_FV_IND 2 @@ -230,6 +221,191 @@ struct ice_nvgre_hdr { __be32 tni_flow; }; +/* Metadata information + * + * Not all MDIDs can be used by switch block. It depends on package version. + * + * MDID 16 (Rx offset) + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | A | B | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = Source port where the transaction came from (3b). + * + * B = Destination TC of the packet. The TC is relative to a port (5b). + * + * MDID 17 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | PTYPE | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * PTYPE = Encodes the packet type (10b). + * + * MDID 18 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Packet length | R | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Packet length = Length of the packet in bytes + * (packet always carriers CRC) (14b). + * R = Reserved (2b). + * + * MDID 19 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Source VSI | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Source VSI = Source VSI of packet loopbacked in switch (for egress) (10b). + */ +#define ICE_MDID_SOURCE_VSI_MASK GENMASK(9, 0) + +/* + * MDID 20 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D|E|F|R|R|G|H|I|J|K|L|M|N| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = DSI - set for DSI RX pkts. + * B = ipsec_decrypted - invalid on NIC. + * C = marker - this is a marker packet. + * D = from_network - for TX sets to 0 + * for RX: + * * 1 - packet is from external link + * * 0 - packet source is from internal + * E = source_interface_is_rx - reflect the physical interface from where the + * packet was received: + * * 1 - Rx + * * 0 - Tx + * F = from_mng - The bit signals that the packet's origin is the management. + * G = ucast - Outer L2 MAC address is unicast. + * H = mcast - Outer L2 MAC address is multicast. + * I = bcast - Outer L2 MAC address is broadcast. + * J = second_outer_mac_present - 2 outer MAC headers are present in the packet. + * K = STAG or BVLAN - Outer L2 header has STAG (ethernet type 0x88a8) or + * BVLAN (ethernet type 0x88a8). + * L = ITAG - Outer L2 header has ITAG *ethernet type 0x88e7) + * M = EVLAN (0x8100) - Outer L2 header has EVLAN (ethernet type 0x8100) + * N = EVLAN (0x9100) - Outer L2 header has EVLAN (ethernet type 0x9100) + */ +#define ICE_PKT_VLAN_STAG BIT(12) +#define ICE_PKT_VLAN_ITAG BIT(13) +#define ICE_PKT_VLAN_EVLAN (BIT(14) | BIT(15)) +#define ICE_PKT_VLAN_MASK (ICE_PKT_VLAN_STAG | ICE_PKT_VLAN_ITAG | \ + ICE_PKT_VLAN_EVLAN) +/* MDID 21 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D|E|F|G|H|I|J|R|R|K|L|M|N| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = VLAN (0x8100) - Outer L2 header has VLAN (ethernet type 0x8100) + * B = NSHoE - Outer L2 header has NSH (ethernet type 0x894f) + * C = MPLS (0x8847) - There is at least 1 MPLS tag in the outer header + * (ethernet type 0x8847) + * D = MPLS (0x8848) - There is at least 1 MPLS tag in the outer header + * (ethernet type 0x8848) + * E = multi MPLS - There is more than a single MPLS tag in the outer header + * F = inner MPLS - There is inner MPLS tag in the packet + * G = tunneled MAC - Set if the packet includes a tunneled MAC + * H = tunneled VLAN - Same as VLAN, but for a tunneled header + * I = pkt_is_frag - Packet is fragmented (ipv4 or ipv6) + * J = ipv6_ext - The packet has routing or destination ipv6 extension in inner + * or outer ipv6 headers + * K = RoCE - UDP packet detected as RoCEv2 + * L = UDP_XSUM_0 - Set to 1 if L4 checksum is 0 in a UDP packet + * M = ESP - This is a ESP packet + * N = NAT_ESP - This is a ESP packet encapsulated in UDP NAT + */ +#define ICE_PKT_TUNNEL_MAC BIT(6) +#define ICE_PKT_TUNNEL_VLAN BIT(7) +#define ICE_PKT_TUNNEL_MASK (ICE_PKT_TUNNEL_MAC | ICE_PKT_TUNNEL_VLAN) + +/* MDID 22 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D|E|F| G |H|I|J| K |L|M| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = fin - fin flag in tcp header + * B = sync - sync flag in tcp header + * C = rst - rst flag in tcp header + * D = psh - psh flag in tcp header + * E = ack - ack flag in tcp header + * F = urg - urg flag in tcp header + * G = tunnel type (3b) - Flags used to decode tunnel type: + * * b000 - not a VXLAN/Geneve/GRE tunnel + * * b001 - VXLAN-GPE + * * b010 - VXLAN (non-GPE) + * * b011 - Geneve + * * b100 - GRE (no key, no xsum) + * * b101 - GREK (key, no xsum) + * * b110 - GREC (no key, xsum) + * * b111 - GREKC (key, xsum) + * H = UDP_GRE - Packet is UDP (VXLAN or VLAN_GPE or Geneve or MPLSoUDP or GRE) + * tunnel + * I = OAM - VXLAN/Geneve/tunneled NSH packet with the OAM bit set + * J = tunneled NSH - Packet has NSHoGRE or NSHoUDP + * K = switch (2b) - Direction on switch + * * b00 - normal + * * b01 - TX force only LAN + * * b10 - TX disable LAN + * * b11 - direct to VSI + * L = swpe - Represents SWPE bit in TX command + * M = sw_cmd - Switch command + * + * MDID 23 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |A|B|C|D| R |E|F|R| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * A = MAC error - Produced by MAC according to L2 error conditions + * B = PPRS no offload - FIFO overflow in PPRS or any problematic condition in + * PPRS ANA + * C = abort - Set when malicious packet is detected + * D = partial analysis - ANA's analysing got cut in the middle + * (header > 504B etc.) + * E = FLM - Flow director hit indication + * F = FDLONG - Flow direector long bucket indication + * + */ +#define ICE_MDID_SIZE 2 +#define ICE_META_DATA_ID_HW 255 + +enum ice_hw_metadata_id { + ICE_SOURCE_PORT_MDID = 16, + ICE_PTYPE_MDID = 17, + ICE_PACKET_LENGTH_MDID = 18, + ICE_SOURCE_VSI_MDID = 19, + ICE_PKT_VLAN_MDID = 20, + ICE_PKT_TUNNEL_MDID = 21, + ICE_PKT_TCP_MDID = 22, + ICE_PKT_ERROR_MDID = 23, +}; + +enum ice_hw_metadata_offset { + ICE_SOURCE_PORT_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_PORT_MDID, + ICE_PTYPE_MDID_OFFSET = ICE_MDID_SIZE * ICE_PTYPE_MDID, + ICE_PACKET_LENGTH_MDID_OFFSET = ICE_MDID_SIZE * ICE_PACKET_LENGTH_MDID, + ICE_SOURCE_VSI_MDID_OFFSET = ICE_MDID_SIZE * ICE_SOURCE_VSI_MDID, + ICE_PKT_VLAN_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_VLAN_MDID, + ICE_PKT_TUNNEL_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TUNNEL_MDID, + ICE_PKT_TCP_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_TCP_MDID, + ICE_PKT_ERROR_MDID_OFFSET = ICE_MDID_SIZE * ICE_PKT_ERROR_MDID, +}; + +enum ice_pkt_flags { + ICE_PKT_FLAGS_VLAN = 0, + ICE_PKT_FLAGS_TUNNEL = 1, + ICE_PKT_FLAGS_TCP = 2, + ICE_PKT_FLAGS_ERROR = 3, +}; + +struct ice_hw_metadata { + __be16 source_port; + __be16 ptype; + __be16 packet_length; + __be16 source_vsi; + __be16 flags[4]; +}; + union ice_prot_hdr { struct ice_ether_hdr eth_hdr; struct ice_ethtype_hdr ethertype; @@ -243,6 +419,7 @@ union ice_prot_hdr { struct ice_udp_gtp_hdr gtp_hdr; struct ice_pppoe_hdr pppoe_hdr; struct ice_l2tpv3_sess_hdr l2tpv3_sess_hdr; + struct ice_hw_metadata metadata; }; /* This is mapping table entry that maps every word within a given protocol diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index d4b6c997141dd7..81d96a40d5a743 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -617,7 +617,7 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) } /** - * ice_ptp_tx_tstamp - Process Tx timestamps for a port + * ice_ptp_process_tx_tstamp - Process Tx timestamps for a port * @tx: the PTP Tx timestamp tracker * * Process timestamps captured by the PHY associated with this port. To do @@ -633,15 +633,6 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) * 6) extend the 40 bit timestamp value to get a 64 bit timestamp value * 7) send this 64 bit timestamp to the stack * - * Returns true if all timestamps were handled, and false if any slots remain - * without a timestamp. - * - * After looping, if we still have waiting SKBs, return false. This may cause - * us effectively poll even when not strictly necessary. We do this because - * it's possible a new timestamp was requested around the same time as the - * interrupt. In some cases hardware might not interrupt us again when the - * timestamp is captured. - * * Note that we do not hold the tracking lock while reading the Tx timestamp. * This is because reading the timestamp requires taking a mutex that might * sleep. @@ -673,10 +664,9 @@ ice_ptp_is_tx_tracker_up(struct ice_ptp_tx *tx) * the packet will never be sent by hardware and discard it without reading * the timestamp register. */ -static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) +static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) { struct ice_ptp_port *ptp_port; - bool more_timestamps; struct ice_pf *pf; struct ice_hw *hw; u64 tstamp_ready; @@ -685,7 +675,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) u8 idx; if (!tx->init) - return true; + return; ptp_port = container_of(tx, struct ice_ptp_port, tx); pf = ptp_port_to_pf(ptp_port); @@ -694,7 +684,7 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) /* Read the Tx ready status first */ err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); if (err) - return false; + return; /* Drop packets if the link went down */ link_up = ptp_port->link_up; @@ -782,15 +772,34 @@ static bool ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) skb_tstamp_tx(skb, &shhwtstamps); dev_kfree_skb_any(skb); } +} - /* Check if we still have work to do. If so, re-queue this task to - * poll for remaining timestamps. - */ +/** + * ice_ptp_tx_tstamp - Process Tx timestamps for this function. + * @tx: Tx tracking structure to initialize + * + * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding incomplete + * Tx timestamps, or ICE_TX_TSTAMP_WORK_DONE otherwise. + */ +static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) +{ + bool more_timestamps; + + if (!tx->init) + return ICE_TX_TSTAMP_WORK_DONE; + + /* Process the Tx timestamp tracker */ + ice_ptp_process_tx_tstamp(tx); + + /* Check if there are outstanding Tx timestamps */ spin_lock(&tx->lock); more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len); spin_unlock(&tx->lock); - return !more_timestamps; + if (more_timestamps) + return ICE_TX_TSTAMP_WORK_PENDING; + + return ICE_TX_TSTAMP_WORK_DONE; } /** @@ -1458,15 +1467,11 @@ static int ice_ptp_adjfine(struct ptp_clock_info *info, long scaled_ppm) } /** - * ice_ptp_extts_work - Workqueue task function - * @work: external timestamp work structure - * - * Service for PTP external clock event + * ice_ptp_extts_event - Process PTP external clock event + * @pf: Board private structure */ -static void ice_ptp_extts_work(struct kthread_work *work) +void ice_ptp_extts_event(struct ice_pf *pf) { - struct ice_ptp *ptp = container_of(work, struct ice_ptp, extts_work); - struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp); struct ptp_clock_event event; struct ice_hw *hw = &pf->hw; u8 chan, tmr_idx; @@ -2430,9 +2435,10 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) * ice_ptp_process_ts - Process the PTP Tx timestamps * @pf: Board private structure * - * Returns true if timestamps are processed. + * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding Tx + * timestamps that need processing, and ICE_TX_TSTAMP_WORK_DONE otherwise. */ -bool ice_ptp_process_ts(struct ice_pf *pf) +enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) { return ice_ptp_tx_tstamp(&pf->ptp.port.tx); } @@ -2558,7 +2564,6 @@ void ice_ptp_prepare_for_reset(struct ice_pf *pf) ice_ptp_cfg_timestamp(pf, false); kthread_cancel_delayed_work_sync(&ptp->work); - kthread_cancel_work_sync(&ptp->extts_work); if (test_bit(ICE_PFR_REQ, pf->state)) return; @@ -2656,7 +2661,6 @@ static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp) /* Initialize work functions */ kthread_init_delayed_work(&ptp->work, ice_ptp_periodic_work); - kthread_init_work(&ptp->extts_work, ice_ptp_extts_work); /* Allocate a kworker for handling work required for the ports * connected to the PTP hardware clock. diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index 9cda2f43e0e562..995a57019ba767 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h @@ -108,6 +108,16 @@ struct ice_tx_tstamp { u64 cached_tstamp; }; +/** + * enum ice_tx_tstamp_work - Status of Tx timestamp work function + * @ICE_TX_TSTAMP_WORK_DONE: Tx timestamp processing is complete + * @ICE_TX_TSTAMP_WORK_PENDING: More Tx timestamps are pending + */ +enum ice_tx_tstamp_work { + ICE_TX_TSTAMP_WORK_DONE = 0, + ICE_TX_TSTAMP_WORK_PENDING, +}; + /** * struct ice_ptp_tx - Tracking structure for all Tx timestamp requests on a port * @lock: lock to prevent concurrent access to fields of this struct @@ -169,7 +179,6 @@ struct ice_ptp_port { * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK * @port: data for the PHY port initialization procedure * @work: delayed work function for periodic tasks - * @extts_work: work function for handling external Tx timestamps * @cached_phc_time: a cached copy of the PHC time for timestamp extension * @cached_phc_jiffies: jiffies when cached_phc_time was last updated * @ext_ts_chan: the external timestamp channel in use @@ -190,7 +199,6 @@ struct ice_ptp_port { struct ice_ptp { struct ice_ptp_port port; struct kthread_delayed_work work; - struct kthread_work extts_work; u64 cached_phc_time; unsigned long cached_phc_jiffies; u8 ext_ts_chan; @@ -256,8 +264,9 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr); void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena); int ice_get_ptp_clock_index(struct ice_pf *pf); +void ice_ptp_extts_event(struct ice_pf *pf); s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); -bool ice_ptp_process_ts(struct ice_pf *pf); +enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); void ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring, @@ -284,6 +293,7 @@ static inline int ice_get_ptp_clock_index(struct ice_pf *pf) return -1; } +static inline void ice_ptp_extts_event(struct ice_pf *pf) { } static inline s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) { diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c index fd1f8b0ad0ab45..e30e12321abd45 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.c +++ b/drivers/net/ethernet/intel/ice/ice_repr.c @@ -298,14 +298,6 @@ static int ice_repr_add(struct ice_vf *vf) if (!repr) return -ENOMEM; -#ifdef CONFIG_ICE_SWITCHDEV - repr->mac_rule = kzalloc(sizeof(*repr->mac_rule), GFP_KERNEL); - if (!repr->mac_rule) { - err = -ENOMEM; - goto err_alloc_rule; - } -#endif - repr->netdev = alloc_etherdev(sizeof(struct ice_netdev_priv)); if (!repr->netdev) { err = -ENOMEM; @@ -351,11 +343,6 @@ static int ice_repr_add(struct ice_vf *vf) free_netdev(repr->netdev); repr->netdev = NULL; err_alloc: -#ifdef CONFIG_ICE_SWITCHDEV - kfree(repr->mac_rule); - repr->mac_rule = NULL; -err_alloc_rule: -#endif kfree(repr); vf->repr = NULL; return err; @@ -376,10 +363,6 @@ static void ice_repr_rem(struct ice_vf *vf) ice_devlink_destroy_vf_port(vf); free_netdev(vf->repr->netdev); vf->repr->netdev = NULL; -#ifdef CONFIG_ICE_SWITCHDEV - kfree(vf->repr->mac_rule); - vf->repr->mac_rule = NULL; -#endif kfree(vf->repr); vf->repr = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_repr.h b/drivers/net/ethernet/intel/ice/ice_repr.h index 378a45bfa25646..9c2a6f496b3b97 100644 --- a/drivers/net/ethernet/intel/ice/ice_repr.h +++ b/drivers/net/ethernet/intel/ice/ice_repr.h @@ -13,9 +13,8 @@ struct ice_repr { struct net_device *netdev; struct metadata_dst *dst; #ifdef CONFIG_ICE_SWITCHDEV - /* info about slow path MAC rule */ - struct ice_rule_query_data *mac_rule; - u8 rule_added; + /* info about slow path rule */ + struct ice_rule_query_data sp_rule; #endif }; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 46b36851af460e..2ea9e1ae55174a 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -4540,6 +4540,11 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, return status; } +#define ICE_PROTOCOL_ENTRY(id, ...) { \ + .prot_type = id, \ + .offs = {__VA_ARGS__}, \ +} + /* This is mapping table entry that maps every word within a given protocol * structure to the real byte offset as per the specification of that * protocol header. @@ -4550,29 +4555,38 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, * structure is added to that union. */ static const struct ice_prot_ext_tbl_entry ice_prot_ext[ICE_PROTOCOL_LAST] = { - { ICE_MAC_OFOS, { 0, 2, 4, 6, 8, 10, 12 } }, - { ICE_MAC_IL, { 0, 2, 4, 6, 8, 10, 12 } }, - { ICE_ETYPE_OL, { 0 } }, - { ICE_ETYPE_IL, { 0 } }, - { ICE_VLAN_OFOS, { 2, 0 } }, - { ICE_IPV4_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, - { ICE_IPV4_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 } }, - { ICE_IPV6_OFOS, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, - 26, 28, 30, 32, 34, 36, 38 } }, - { ICE_IPV6_IL, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, - 26, 28, 30, 32, 34, 36, 38 } }, - { ICE_TCP_IL, { 0, 2 } }, - { ICE_UDP_OF, { 0, 2 } }, - { ICE_UDP_ILOS, { 0, 2 } }, - { ICE_VXLAN, { 8, 10, 12, 14 } }, - { ICE_GENEVE, { 8, 10, 12, 14 } }, - { ICE_NVGRE, { 0, 2, 4, 6 } }, - { ICE_GTP, { 8, 10, 12, 14, 16, 18, 20, 22 } }, - { ICE_GTP_NO_PAY, { 8, 10, 12, 14 } }, - { ICE_PPPOE, { 0, 2, 4, 6 } }, - { ICE_L2TPV3, { 0, 2, 4, 6, 8, 10 } }, - { ICE_VLAN_EX, { 2, 0 } }, - { ICE_VLAN_IN, { 2, 0 } }, + ICE_PROTOCOL_ENTRY(ICE_MAC_OFOS, 0, 2, 4, 6, 8, 10, 12), + ICE_PROTOCOL_ENTRY(ICE_MAC_IL, 0, 2, 4, 6, 8, 10, 12), + ICE_PROTOCOL_ENTRY(ICE_ETYPE_OL, 0), + ICE_PROTOCOL_ENTRY(ICE_ETYPE_IL, 0), + ICE_PROTOCOL_ENTRY(ICE_VLAN_OFOS, 2, 0), + ICE_PROTOCOL_ENTRY(ICE_IPV4_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18), + ICE_PROTOCOL_ENTRY(ICE_IPV4_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18), + ICE_PROTOCOL_ENTRY(ICE_IPV6_OFOS, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, + 20, 22, 24, 26, 28, 30, 32, 34, 36, 38), + ICE_PROTOCOL_ENTRY(ICE_IPV6_IL, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, + 22, 24, 26, 28, 30, 32, 34, 36, 38), + ICE_PROTOCOL_ENTRY(ICE_TCP_IL, 0, 2), + ICE_PROTOCOL_ENTRY(ICE_UDP_OF, 0, 2), + ICE_PROTOCOL_ENTRY(ICE_UDP_ILOS, 0, 2), + ICE_PROTOCOL_ENTRY(ICE_VXLAN, 8, 10, 12, 14), + ICE_PROTOCOL_ENTRY(ICE_GENEVE, 8, 10, 12, 14), + ICE_PROTOCOL_ENTRY(ICE_NVGRE, 0, 2, 4, 6), + ICE_PROTOCOL_ENTRY(ICE_GTP, 8, 10, 12, 14, 16, 18, 20, 22), + ICE_PROTOCOL_ENTRY(ICE_GTP_NO_PAY, 8, 10, 12, 14), + ICE_PROTOCOL_ENTRY(ICE_PPPOE, 0, 2, 4, 6), + ICE_PROTOCOL_ENTRY(ICE_L2TPV3, 0, 2, 4, 6, 8, 10), + ICE_PROTOCOL_ENTRY(ICE_VLAN_EX, 2, 0), + ICE_PROTOCOL_ENTRY(ICE_VLAN_IN, 2, 0), + ICE_PROTOCOL_ENTRY(ICE_HW_METADATA, + ICE_SOURCE_PORT_MDID_OFFSET, + ICE_PTYPE_MDID_OFFSET, + ICE_PACKET_LENGTH_MDID_OFFSET, + ICE_SOURCE_VSI_MDID_OFFSET, + ICE_PKT_VLAN_MDID_OFFSET, + ICE_PKT_TUNNEL_MDID_OFFSET, + ICE_PKT_TCP_MDID_OFFSET, + ICE_PKT_ERROR_MDID_OFFSET), }; static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { @@ -4597,6 +4611,7 @@ static struct ice_protocol_entry ice_prot_id_tbl[ICE_PROTOCOL_LAST] = { { ICE_L2TPV3, ICE_L2TPV3_HW }, { ICE_VLAN_EX, ICE_VLAN_OF_HW }, { ICE_VLAN_IN, ICE_VLAN_OL_HW }, + { ICE_HW_METADATA, ICE_META_DATA_ID_HW }, }; /** @@ -5255,71 +5270,6 @@ ice_create_recipe_group(struct ice_hw *hw, struct ice_sw_recipe *rm, return status; } -/** - * ice_tun_type_match_word - determine if tun type needs a match mask - * @tun_type: tunnel type - * @mask: mask to be used for the tunnel - */ -static bool ice_tun_type_match_word(enum ice_sw_tunnel_type tun_type, u16 *mask) -{ - switch (tun_type) { - case ICE_SW_TUN_GENEVE: - case ICE_SW_TUN_VXLAN: - case ICE_SW_TUN_NVGRE: - case ICE_SW_TUN_GTPU: - case ICE_SW_TUN_GTPC: - *mask = ICE_TUN_FLAG_MASK; - return true; - - default: - *mask = 0; - return false; - } -} - -/** - * ice_add_special_words - Add words that are not protocols, such as metadata - * @rinfo: other information regarding the rule e.g. priority and action info - * @lkup_exts: lookup word structure - * @dvm_ena: is double VLAN mode enabled - */ -static int -ice_add_special_words(struct ice_adv_rule_info *rinfo, - struct ice_prot_lkup_ext *lkup_exts, bool dvm_ena) -{ - u16 mask; - - /* If this is a tunneled packet, then add recipe index to match the - * tunnel bit in the packet metadata flags. - */ - if (ice_tun_type_match_word(rinfo->tun_type, &mask)) { - if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) { - u8 word = lkup_exts->n_val_words++; - - lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW; - lkup_exts->fv_words[word].off = ICE_TUN_FLAG_MDID_OFF; - lkup_exts->field_mask[word] = mask; - } else { - return -ENOSPC; - } - } - - if (rinfo->vlan_type != 0 && dvm_ena) { - if (lkup_exts->n_val_words < ICE_MAX_CHAIN_WORDS) { - u8 word = lkup_exts->n_val_words++; - - lkup_exts->fv_words[word].prot_id = ICE_META_DATA_ID_HW; - lkup_exts->fv_words[word].off = ICE_VLAN_FLAG_MDID_OFF; - lkup_exts->field_mask[word] = - ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK; - } else { - return -ENOSPC; - } - } - - return 0; -} - /* ice_get_compat_fv_bitmap - Get compatible field vector bitmap for rule * @hw: pointer to hardware structure * @rinfo: other information regarding the rule e.g. priority and action info @@ -5433,13 +5383,6 @@ ice_add_adv_recipe(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (status) goto err_unroll; - /* Create any special protocol/offset pairs, such as looking at tunnel - * bits by extracting metadata - */ - status = ice_add_special_words(rinfo, lkup_exts, ice_is_dvm_ena(hw)); - if (status) - goto err_unroll; - /* Group match words into recipes using preferred recipe grouping * criteria. */ @@ -5725,6 +5668,10 @@ ice_fill_adv_dummy_packet(struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, * was already checked when search for the dummy packet */ type = lkups[i].type; + /* metadata isn't present in the packet */ + if (type == ICE_HW_METADATA) + continue; + for (j = 0; offsets[j].type != ICE_PROTOCOL_LAST; j++) { if (type == offsets[j].type) { offset = offsets[j].offset; @@ -5860,16 +5807,21 @@ ice_fill_adv_packet_tun(struct ice_hw *hw, enum ice_sw_tunnel_type tun_type, /** * ice_fill_adv_packet_vlan - fill dummy packet with VLAN tag type + * @hw: pointer to hw structure * @vlan_type: VLAN tag type * @pkt: dummy packet to fill in * @offsets: offset info for the dummy packet */ static int -ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt, +ice_fill_adv_packet_vlan(struct ice_hw *hw, u16 vlan_type, u8 *pkt, const struct ice_dummy_pkt_offsets *offsets) { u16 i; + /* Check if there is something to do */ + if (!vlan_type || !ice_is_dvm_ena(hw)) + return 0; + /* Find VLAN header and insert VLAN TPID */ for (i = 0; offsets[i].type != ICE_PROTOCOL_LAST; i++) { if (offsets[i].type == ICE_VLAN_OFOS || @@ -5888,6 +5840,15 @@ ice_fill_adv_packet_vlan(u16 vlan_type, u8 *pkt, return -EIO; } +static bool ice_rules_equal(const struct ice_adv_rule_info *first, + const struct ice_adv_rule_info *second) +{ + return first->sw_act.flag == second->sw_act.flag && + first->tun_type == second->tun_type && + first->vlan_type == second->vlan_type && + first->src_vsi == second->src_vsi; +} + /** * ice_find_adv_rule_entry - Search a rule entry * @hw: pointer to the hardware structure @@ -5921,9 +5882,7 @@ ice_find_adv_rule_entry(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, lkups_matched = false; break; } - if (rinfo->sw_act.flag == list_itr->rule_info.sw_act.flag && - rinfo->tun_type == list_itr->rule_info.tun_type && - rinfo->vlan_type == list_itr->rule_info.vlan_type && + if (ice_rules_equal(rinfo, &list_itr->rule_info) && lkups_matched) return list_itr; } @@ -6039,6 +5998,26 @@ ice_adv_add_update_vsi_list(struct ice_hw *hw, return status; } +void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_TUNNEL] = + cpu_to_be16(ICE_PKT_TUNNEL_MASK); +} + +void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.flags[ICE_PKT_FLAGS_VLAN] = + cpu_to_be16(ICE_PKT_VLAN_MASK); +} + +void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup) +{ + lkup->type = ICE_HW_METADATA; + lkup->m_u.metadata.source_vsi = cpu_to_be16(ICE_MDID_SOURCE_VSI_MASK); +} + /** * ice_add_adv_rule - helper function to create an advanced switch rule * @hw: pointer to the hardware structure @@ -6120,7 +6099,10 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (rinfo->sw_act.fltr_act == ICE_FWD_TO_VSI) rinfo->sw_act.fwd_id.hw_vsi_id = ice_get_hw_vsi_num(hw, vsi_handle); - if (rinfo->sw_act.flag & ICE_FLTR_TX) + + if (rinfo->src_vsi) + rinfo->sw_act.src = ice_get_hw_vsi_num(hw, rinfo->src_vsi); + else rinfo->sw_act.src = ice_get_hw_vsi_num(hw, vsi_handle); status = ice_add_adv_recipe(hw, lkups, lkups_cnt, rinfo, &rid); @@ -6189,19 +6171,20 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, goto err_ice_add_adv_rule; } - /* set the rule LOOKUP type based on caller specified 'Rx' - * instead of hardcoding it to be either LOOKUP_TX/RX + /* If there is no matching criteria for direction there + * is only one difference between Rx and Tx: + * - get switch id base on VSI number from source field (Tx) + * - get switch id base on port number (Rx) * - * for 'Rx' set the source to be the port number - * for 'Tx' set the source to be the source HW VSI number (determined - * by caller) + * If matching on direction metadata is chose rule direction is + * extracted from type value set here. */ - if (rinfo->rx) { - s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); - s_rule->src = cpu_to_le16(hw->port_info->lport); - } else { + if (rinfo->sw_act.flag & ICE_FLTR_TX) { s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_TX); s_rule->src = cpu_to_le16(rinfo->sw_act.src); + } else { + s_rule->hdr.type = cpu_to_le16(ICE_AQC_SW_RULES_T_LKUP_RX); + s_rule->src = cpu_to_le16(hw->port_info->lport); } s_rule->recipe_id = cpu_to_le16(rid); @@ -6211,22 +6194,16 @@ ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, if (status) goto err_ice_add_adv_rule; - if (rinfo->tun_type != ICE_NON_TUN && - rinfo->tun_type != ICE_SW_TUN_AND_NON_TUN) { - status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, - s_rule->hdr_data, - profile->offsets); - if (status) - goto err_ice_add_adv_rule; - } + status = ice_fill_adv_packet_tun(hw, rinfo->tun_type, s_rule->hdr_data, + profile->offsets); + if (status) + goto err_ice_add_adv_rule; - if (rinfo->vlan_type != 0 && ice_is_dvm_ena(hw)) { - status = ice_fill_adv_packet_vlan(rinfo->vlan_type, - s_rule->hdr_data, - profile->offsets); - if (status) - goto err_ice_add_adv_rule; - } + status = ice_fill_adv_packet_vlan(hw, rinfo->vlan_type, + s_rule->hdr_data, + profile->offsets); + if (status) + goto err_ice_add_adv_rule; status = ice_aq_sw_rules(hw, (struct ice_aqc_sw_rules *)s_rule, rule_buf_sz, 1, ice_aqc_opc_add_sw_rules, @@ -6469,13 +6446,6 @@ ice_rem_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, return -EIO; } - /* Create any special protocol/offset pairs, such as looking at tunnel - * bits by extracting metadata - */ - status = ice_add_special_words(rinfo, &lkup_exts, ice_is_dvm_ena(hw)); - if (status) - return status; - rid = ice_find_recp(hw, &lkup_exts, rinfo->tun_type); /* If did not find a recipe that match the existing criteria */ if (rid == ICE_MAX_NUM_RECIPES) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index 68d8e8a6a1896d..c84b56fe84a5e0 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -10,7 +10,6 @@ #define ICE_DFLT_VSI_INVAL 0xff #define ICE_FLTR_RX BIT(0) #define ICE_FLTR_TX BIT(1) -#define ICE_FLTR_TX_RX (ICE_FLTR_RX | ICE_FLTR_TX) #define ICE_VSI_INVAL_ID 0xffff #define ICE_INVAL_Q_HANDLE 0xFFFF @@ -187,12 +186,13 @@ struct ice_adv_rule_flags_info { }; struct ice_adv_rule_info { + /* Store metadata values in rule info */ enum ice_sw_tunnel_type tun_type; - struct ice_sw_act_ctrl sw_act; - u32 priority; - u8 rx; /* true means LOOKUP_RX otherwise LOOKUP_TX */ - u16 fltr_rule_id; u16 vlan_type; + u16 fltr_rule_id; + u32 priority; + u16 src_vsi; + struct ice_sw_act_ctrl sw_act; struct ice_adv_rule_flags_info flags_info; }; @@ -342,6 +342,9 @@ ice_free_res_cntr(struct ice_hw *hw, u8 type, u8 alloc_shared, u16 num_items, u16 counter_id); /* Switch/bridge related commands */ +void ice_rule_add_tunnel_metadata(struct ice_adv_lkup_elem *lkup); +void ice_rule_add_vlan_metadata(struct ice_adv_lkup_elem *lkup); +void ice_rule_add_src_vsi_metadata(struct ice_adv_lkup_elem *lkup); int ice_add_adv_rule(struct ice_hw *hw, struct ice_adv_lkup_elem *lkups, u16 lkups_cnt, struct ice_adv_rule_info *rinfo, diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.c b/drivers/net/ethernet/intel/ice/ice_tc_lib.c index d1a31f236d26ad..b54052ef6050d8 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.c @@ -54,6 +54,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) lkups_cnt++; + /* is VLAN TPID specified */ + if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) + lkups_cnt++; + /* is CVLAN specified? */ if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) lkups_cnt++; @@ -80,6 +84,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers, ICE_TC_FLWR_FIELD_SRC_L4_PORT)) lkups_cnt++; + /* matching for tunneled packets in metadata */ + if (fltr->tunnel_type != TNL_LAST) + lkups_cnt++; + return lkups_cnt; } @@ -320,6 +328,10 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr, i++; } + /* always fill matching on tunneled packets in metadata */ + ice_rule_add_tunnel_metadata(&list[i]); + i++; + return i; } @@ -390,10 +402,6 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, /* copy VLAN info */ if (flags & (ICE_TC_FLWR_FIELD_VLAN | ICE_TC_FLWR_FIELD_VLAN_PRIO)) { - vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid); - rule_info->vlan_type = - ice_check_supported_vlan_tpid(vlan_tpid); - if (flags & ICE_TC_FLWR_FIELD_CVLAN) list[i].type = ICE_VLAN_EX; else @@ -418,6 +426,15 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags, i++; } + if (flags & ICE_TC_FLWR_FIELD_VLAN_TPID) { + vlan_tpid = be16_to_cpu(headers->vlan_hdr.vlan_tpid); + rule_info->vlan_type = + ice_check_supported_vlan_tpid(vlan_tpid); + + ice_rule_add_vlan_metadata(&list[i]); + i++; + } + if (flags & (ICE_TC_FLWR_FIELD_CVLAN | ICE_TC_FLWR_FIELD_CVLAN_PRIO)) { list[i].type = ICE_VLAN_IN; @@ -698,12 +715,10 @@ ice_eswitch_add_tc_fltr(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr) if (fltr->direction == ICE_ESWITCH_FLTR_INGRESS) { rule_info.sw_act.flag |= ICE_FLTR_RX; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; rule_info.flags_info.act = ICE_SINGLE_ACT_LB_ENABLE; } else { rule_info.sw_act.flag |= ICE_FLTR_TX; rule_info.sw_act.src = vsi->idx; - rule_info.rx = false; rule_info.flags_info.act = ICE_SINGLE_ACT_LAN_ENABLE; } @@ -910,7 +925,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi, rule_info.sw_act.vsi_handle = dest_vsi->idx; rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; dev_dbg(dev, "add switch rule for TC:%u vsi_idx:%u, lkups_cnt:%u\n", tc_fltr->action.fwd.tc.tc_class, rule_info.sw_act.vsi_handle, lkups_cnt); @@ -921,7 +935,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi, rule_info.sw_act.vsi_handle = dest_vsi->idx; rule_info.priority = ICE_SWITCH_FLTR_PRIO_QUEUE; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; dev_dbg(dev, "add switch rule action to forward to queue:%u (HW queue %u), lkups_cnt:%u\n", tc_fltr->action.fwd.q.queue, tc_fltr->action.fwd.q.hw_queue, lkups_cnt); @@ -929,7 +942,6 @@ ice_add_tc_flower_adv_fltr(struct ice_vsi *vsi, case ICE_DROP_PACKET: rule_info.sw_act.flag |= ICE_FLTR_RX; rule_info.sw_act.src = hw->pf_id; - rule_info.rx = true; rule_info.priority = ICE_SWITCH_FLTR_PRIO_VSI; break; default: @@ -1460,8 +1472,10 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi, VLAN_PRIO_MASK); } - if (match.mask->vlan_tpid) + if (match.mask->vlan_tpid) { headers->vlan_hdr.vlan_tpid = match.key->vlan_tpid; + fltr->flags |= ICE_TC_FLWR_FIELD_VLAN_TPID; + } } if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_CVLAN)) { diff --git a/drivers/net/ethernet/intel/ice/ice_tc_lib.h b/drivers/net/ethernet/intel/ice/ice_tc_lib.h index 8d5e22ac7023ca..8bbc1a62bdb1c0 100644 --- a/drivers/net/ethernet/intel/ice/ice_tc_lib.h +++ b/drivers/net/ethernet/intel/ice/ice_tc_lib.h @@ -33,6 +33,7 @@ #define ICE_TC_FLWR_FIELD_L2TPV3_SESSID BIT(26) #define ICE_TC_FLWR_FIELD_VLAN_PRIO BIT(27) #define ICE_TC_FLWR_FIELD_CVLAN_PRIO BIT(28) +#define ICE_TC_FLWR_FIELD_VLAN_TPID BIT(29) #define ICE_TC_FLOWER_MASK_32 0xFFFFFFFF diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 059bd911c51d85..52d0a126eb6161 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1152,11 +1152,11 @@ int ice_clean_rx_irq(struct ice_rx_ring *rx_ring, int budget) unsigned int total_rx_bytes = 0, total_rx_pkts = 0; unsigned int offset = rx_ring->rx_offset; struct xdp_buff *xdp = &rx_ring->xdp; + u32 cached_ntc = rx_ring->first_desc; struct ice_tx_ring *xdp_ring = NULL; struct bpf_prog *xdp_prog = NULL; u32 ntc = rx_ring->next_to_clean; u32 cnt = rx_ring->count; - u32 cached_ntc = ntc; u32 xdp_xmit = 0; u32 cached_ntu; bool failure; diff --git a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c index c8322fb6f2b37f..7543aba4ff9fe8 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx_lib.c @@ -2,6 +2,7 @@ /* Copyright (c) 2019, Intel Corporation. */ #include +#include #include "ice_txrx_lib.h" #include "ice_eswitch.h" @@ -38,30 +39,6 @@ void ice_release_rx_desc(struct ice_rx_ring *rx_ring, u16 val) } } -/** - * ice_ptype_to_htype - get a hash type - * @ptype: the ptype value from the descriptor - * - * Returns appropriate hash type (such as PKT_HASH_TYPE_L2/L3/L4) to be used by - * skb_set_hash based on PTYPE as parsed by HW Rx pipeline and is part of - * Rx desc. - */ -static enum pkt_hash_types ice_ptype_to_htype(u16 ptype) -{ - struct ice_rx_ptype_decoded decoded = ice_decode_rx_desc_ptype(ptype); - - if (!decoded.known) - return PKT_HASH_TYPE_NONE; - if (decoded.payload_layer == ICE_RX_PTYPE_PAYLOAD_LAYER_PAY4) - return PKT_HASH_TYPE_L4; - if (decoded.payload_layer == ICE_RX_PTYPE_PAYLOAD_LAYER_PAY3) - return PKT_HASH_TYPE_L3; - if (decoded.outer_ip == ICE_RX_PTYPE_OUTER_L2) - return PKT_HASH_TYPE_L2; - - return PKT_HASH_TYPE_NONE; -} - /** * ice_rx_hash - set the hash value in the skb * @rx_ring: descriptor ring @@ -74,9 +51,11 @@ ice_rx_hash(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb, u16 rx_ptype) { struct ice_32b_rx_flex_desc_nic *nic_mdid; + struct libie_rx_ptype_parsed parsed; u32 hash; - if (!(rx_ring->netdev->features & NETIF_F_RXHASH)) + parsed = libie_parse_rx_ptype(rx_ptype); + if (!libie_has_rx_hash(rx_ring->netdev, parsed)) return; if (rx_desc->wb.rxdid != ICE_RXDID_FLEX_NIC) @@ -84,7 +63,7 @@ ice_rx_hash(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc, nic_mdid = (struct ice_32b_rx_flex_desc_nic *)rx_desc; hash = le32_to_cpu(nic_mdid->rss_hash); - skb_set_hash(skb, hash, ice_ptype_to_htype(rx_ptype)); + libie_skb_set_hash(skb, hash, parsed); } /** @@ -92,7 +71,7 @@ ice_rx_hash(struct ice_rx_ring *rx_ring, union ice_32b_rx_flex_desc *rx_desc, * @ring: the ring we care about * @skb: skb currently being received and modified * @rx_desc: the receive descriptor - * @ptype: the packet type decoded by hardware + * @ptype: the packet type parsed by hardware * * skb->protocol must be set before this function is called */ @@ -100,34 +79,26 @@ static void ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb, union ice_32b_rx_flex_desc *rx_desc, u16 ptype) { - struct ice_rx_ptype_decoded decoded; + struct libie_rx_ptype_parsed parsed; u16 rx_status0, rx_status1; bool ipv4, ipv6; - rx_status0 = le16_to_cpu(rx_desc->wb.status_error0); - rx_status1 = le16_to_cpu(rx_desc->wb.status_error1); - - decoded = ice_decode_rx_desc_ptype(ptype); - /* Start with CHECKSUM_NONE and by default csum_level = 0 */ skb->ip_summed = CHECKSUM_NONE; - skb_checksum_none_assert(skb); - /* check if Rx checksum is enabled */ - if (!(ring->netdev->features & NETIF_F_RXCSUM)) + parsed = libie_parse_rx_ptype(ptype); + if (!libie_has_rx_checksum(ring->netdev, parsed)) return; - /* check if HW has decoded the packet and checksum */ - if (!(rx_status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S))) - return; + rx_status0 = le16_to_cpu(rx_desc->wb.status_error0); + rx_status1 = le16_to_cpu(rx_desc->wb.status_error1); - if (!(decoded.known && decoded.outer_ip)) + /* check if HW has parsed the packet and checksum */ + if (!(rx_status0 & BIT(ICE_RX_FLEX_DESC_STATUS0_L3L4P_S))) return; - ipv4 = (decoded.outer_ip == ICE_RX_PTYPE_OUTER_IP) && - (decoded.outer_ip_ver == ICE_RX_PTYPE_OUTER_IPV4); - ipv6 = (decoded.outer_ip == ICE_RX_PTYPE_OUTER_IP) && - (decoded.outer_ip_ver == ICE_RX_PTYPE_OUTER_IPV6); + ipv4 = parsed.outer_ip == LIBIE_RX_PTYPE_OUTER_IPV4; + ipv6 = parsed.outer_ip == LIBIE_RX_PTYPE_OUTER_IPV6; if (ipv4 && (rx_status0 & (BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_IPE_S) | BIT(ICE_RX_FLEX_DESC_STATUS0_XSUM_EIPE_S)))) @@ -151,19 +122,10 @@ ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb, * we need to bump the checksum level by 1 to reflect the fact that * we are indicating we validated the inner checksum. */ - if (decoded.tunnel_type >= ICE_RX_PTYPE_TUNNEL_IP_GRENAT) + if (parsed.tunnel_type >= LIBIE_RX_PTYPE_TUNNEL_IP_GRENAT) skb->csum_level = 1; - /* Only report checksum unnecessary for TCP, UDP, or SCTP */ - switch (decoded.inner_prot) { - case ICE_RX_PTYPE_INNER_PROT_TCP: - case ICE_RX_PTYPE_INNER_PROT_UDP: - case ICE_RX_PTYPE_INNER_PROT_SCTP: - skb->ip_summed = CHECKSUM_UNNECESSARY; - break; - default: - break; - } + skb->ip_summed = CHECKSUM_UNNECESSARY; return; checksum_fail: @@ -175,7 +137,7 @@ ice_rx_csum(struct ice_rx_ring *ring, struct sk_buff *skb, * @rx_ring: Rx descriptor ring packet is being transacted on * @rx_desc: pointer to the EOP Rx descriptor * @skb: pointer to current skb being populated - * @ptype: the packet type decoded by hardware + * @ptype: the packet type parsed by hardware * * This function checks the ring, descriptor, and packet information in * order to populate the hash, checksum, VLAN, protocol, and diff --git a/drivers/net/ethernet/intel/ice/ice_vf_lib.c b/drivers/net/ethernet/intel/ice/ice_vf_lib.c index e441968a70aebe..b26ce4425f4559 100644 --- a/drivers/net/ethernet/intel/ice/ice_vf_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_vf_lib.c @@ -689,8 +689,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) */ ice_vf_clear_all_promisc_modes(vf, vsi); - ice_eswitch_del_vf_mac_rule(vf); - ice_vf_fdir_exit(vf); ice_vf_fdir_init(vf); /* clean VF control VSI when resetting VF since it should be setup @@ -716,7 +714,6 @@ int ice_reset_vf(struct ice_vf *vf, u32 flags) } ice_eswitch_update_repr(vsi); - ice_eswitch_replay_vf_mac_rule(vf); /* if the VF has been reset allow it to come up again */ ice_mbx_clear_malvf(&vf->mbx_info); diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c index f4a524f80b110f..efbc2968a7bf6a 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c @@ -3730,7 +3730,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg) for (i = 0; i < al->num_elements; i++) { u8 *mac_addr = al->list[i].addr; - int result; if (!is_unicast_ether_addr(mac_addr) || ether_addr_equal(mac_addr, vf->hw_lan_addr)) @@ -3742,13 +3741,6 @@ static int ice_vc_repr_add_mac(struct ice_vf *vf, u8 *msg) goto handle_mac_exit; } - result = ice_eswitch_add_vf_mac_rule(pf, vf, mac_addr); - if (result) { - dev_err(ice_pf_to_dev(pf), "Failed to add MAC %pM for VF %d\n, error %d\n", - mac_addr, vf->vf_id, result); - goto handle_mac_exit; - } - ice_vfhw_mac_add(vf, &al->list[i]); vf->num_mac++; break; diff --git a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c index bcda2e0048073d..1279c1ffe31c39 100644 --- a/drivers/net/ethernet/intel/ice/ice_vlan_mode.c +++ b/drivers/net/ethernet/intel/ice/ice_vlan_mode.c @@ -219,7 +219,7 @@ static struct ice_update_recipe_lkup_idx_params ice_dvm_dflt_recipes[] = { .rid = ICE_SW_LKUP_VLAN, .fv_idx = ICE_PKT_FLAGS_0_TO_15_FV_IDX, .ignore_valid = false, - .mask = ICE_PKT_FLAGS_0_TO_15_VLAN_FLAGS_MASK, + .mask = ICE_PKT_VLAN_MASK, .mask_valid = true, .lkup_idx = ICE_SW_LKUP_VLAN_PKT_FLAGS_LKUP_IDX, }, diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 58872a4c254015..c5cdb880774d44 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -183,11 +183,13 @@ static int igb_resume(struct device *); static int igb_runtime_suspend(struct device *dev); static int igb_runtime_resume(struct device *dev); static int igb_runtime_idle(struct device *dev); +#ifdef CONFIG_PM static const struct dev_pm_ops igb_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume) SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume, igb_runtime_idle) }; +#endif static void igb_shutdown(struct pci_dev *); static int igb_pci_sriov_configure(struct pci_dev *dev, int num_vfs); #ifdef CONFIG_IGB_DCA diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 38d113b48111a8..88145c30c919be 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c @@ -2411,6 +2411,8 @@ static int igc_xdp_xmit_back(struct igc_adapter *adapter, struct xdp_buff *xdp) nq = txring_txq(ring); __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); res = igc_xdp_init_tx_descriptor(ring, xdpf); __netif_tx_unlock(nq); return res; @@ -2829,6 +2831,9 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring) __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); + budget = igc_desc_unused(ring); while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) { @@ -6108,9 +6113,18 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter, size_t n; int i; - adapter->qbv_enable = qopt->enable; + switch (qopt->cmd) { + case TAPRIO_CMD_REPLACE: + adapter->qbv_enable = true; + break; + case TAPRIO_CMD_DESTROY: + adapter->qbv_enable = false; + break; + default: + return -EOPNOTSUPP; + } - if (!qopt->enable) + if (!adapter->qbv_enable) return igc_tsn_clear_schedule(adapter); if (qopt->base_time < 0) @@ -6354,6 +6368,9 @@ static int igc_xdp_xmit(struct net_device *dev, int num_frames, __netif_tx_lock(nq, cpu); + /* Avoid transmit queue timeout since we share it with the slow path */ + txq_trans_cond_update(nq); + drops = 0; for (i = 0; i < num_frames; i++) { int err; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 5d83c887a3fceb..1726297f2e0df0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1256,7 +1256,7 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_q_vector *q_vector, if (!__netif_txq_completed_wake(txq, total_packets, total_bytes, ixgbe_desc_unused(tx_ring), TX_WAKE_THRESHOLD, - netif_carrier_ok(tx_ring->netdev) && + !netif_carrier_ok(tx_ring->netdev) || test_bit(__IXGBE_DOWN, &adapter->state))) ++tx_ring->tx_stats.restart_queue; diff --git a/drivers/net/ethernet/intel/libie/Makefile b/drivers/net/ethernet/intel/libie/Makefile new file mode 100644 index 00000000000000..76f32253481b70 --- /dev/null +++ b/drivers/net/ethernet/intel/libie/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Copyright(c) 2023 Intel Corporation. + +obj-$(CONFIG_LIBIE) += libie.o + +libie-objs += rx.o +libie-objs += stats.o diff --git a/drivers/net/ethernet/intel/libie/internal.h b/drivers/net/ethernet/intel/libie/internal.h new file mode 100644 index 00000000000000..083398dc37c63d --- /dev/null +++ b/drivers/net/ethernet/intel/libie/internal.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* libie internal declarations not to be used in drivers. + * + * Copyright(c) 2023 Intel Corporation. + */ + +#ifndef __LIBIE_INTERNAL_H +#define __LIBIE_INTERNAL_H + +struct libie_rq_stats; +struct page_pool; + +#ifdef CONFIG_PAGE_POOL_STATS +void libie_rq_stats_sync_pp(struct libie_rq_stats *stats, + struct page_pool *pool); +#else +static inline void libie_rq_stats_sync_pp(struct libie_rq_stats *stats, + struct page_pool *pool) +{ +} +#endif + +#endif /* __LIBIE_INTERNAL_H */ diff --git a/drivers/net/ethernet/intel/libie/rx.c b/drivers/net/ethernet/intel/libie/rx.c new file mode 100644 index 00000000000000..128f134aca6dac --- /dev/null +++ b/drivers/net/ethernet/intel/libie/rx.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation. */ + +#include + +#include "internal.h" + +/* O(1) converting i40e/ice/iavf's 8/10-bit hardware packet type to a parsed + * bitfield struct. + */ + +#define LIBIE_RX_PTYPE(oip, ofrag, tun, tp, tefr, iprot, pl) { \ + .outer_ip = LIBIE_RX_PTYPE_OUTER_##oip, \ + .outer_frag = LIBIE_RX_PTYPE_##ofrag, \ + .tunnel_type = LIBIE_RX_PTYPE_TUNNEL_IP_##tun, \ + .tunnel_end_prot = LIBIE_RX_PTYPE_TUNNEL_END_##tp, \ + .tunnel_end_frag = LIBIE_RX_PTYPE_##tefr, \ + .inner_prot = LIBIE_RX_PTYPE_INNER_##iprot, \ + .payload_layer = LIBIE_RX_PTYPE_PAYLOAD_##pl, \ + } + +#define LIBIE_RX_PTYPE_UNUSED { } + +#define __LIBIE_RX_PTYPE_L2(iprot, pl) \ + LIBIE_RX_PTYPE(L2, NOT_FRAG, NONE, NONE, NOT_FRAG, iprot, pl) +#define LIBIE_RX_PTYPE_L2 __LIBIE_RX_PTYPE_L2(NONE, L2) +#define LIBIE_RX_PTYPE_TS __LIBIE_RX_PTYPE_L2(TIMESYNC, L2) +#define LIBIE_RX_PTYPE_L3 __LIBIE_RX_PTYPE_L2(NONE, L3) + +#define LIBIE_RX_PTYPE_IP_FRAG(oip) \ + LIBIE_RX_PTYPE(IPV##oip, FRAG, NONE, NONE, NOT_FRAG, NONE, L3) +#define LIBIE_RX_PTYPE_IP_L3(oip, tun, teprot, tefr) \ + LIBIE_RX_PTYPE(IPV##oip, NOT_FRAG, tun, teprot, tefr, NONE, L3) +#define LIBIE_RX_PTYPE_IP_L4(oip, tun, teprot, iprot) \ + LIBIE_RX_PTYPE(IPV##oip, NOT_FRAG, tun, teprot, NOT_FRAG, iprot, L4) + +#define LIBIE_RX_PTYPE_IP_NOF(oip, tun, ver) \ + LIBIE_RX_PTYPE_IP_L3(oip, tun, ver, NOT_FRAG), \ + LIBIE_RX_PTYPE_IP_L4(oip, tun, ver, UDP), \ + LIBIE_RX_PTYPE_UNUSED, \ + LIBIE_RX_PTYPE_IP_L4(oip, tun, ver, TCP), \ + LIBIE_RX_PTYPE_IP_L4(oip, tun, ver, SCTP), \ + LIBIE_RX_PTYPE_IP_L4(oip, tun, ver, ICMP) + +/* IPv oip --> tun --> IPv ver */ +#define LIBIE_RX_PTYPE_IP_TUN_VER(oip, tun, ver) \ + LIBIE_RX_PTYPE_IP_L3(oip, tun, ver, FRAG), \ + LIBIE_RX_PTYPE_IP_NOF(oip, tun, ver) + +/* Non Tunneled IPv oip */ +#define LIBIE_RX_PTYPE_IP_RAW(oip) \ + LIBIE_RX_PTYPE_IP_FRAG(oip), \ + LIBIE_RX_PTYPE_IP_NOF(oip, NONE, NONE) + +/* IPv oip --> tun --> { IPv4, IPv6 } */ +#define LIBIE_RX_PTYPE_IP_TUN(oip, tun) \ + LIBIE_RX_PTYPE_IP_TUN_VER(oip, tun, IPV4), \ + LIBIE_RX_PTYPE_IP_TUN_VER(oip, tun, IPV6) + +/* IPv oip --> GRE/NAT tun --> { x, IPv4, IPv6 } */ +#define LIBIE_RX_PTYPE_IP_GRE(oip, tun) \ + LIBIE_RX_PTYPE_IP_L3(oip, tun, NONE, NOT_FRAG), \ + LIBIE_RX_PTYPE_IP_TUN(oip, tun) + +/* Non Tunneled IPv oip + * IPv oip --> { IPv4, IPv6 } + * IPv oip --> GRE/NAT --> { x, IPv4, IPv6 } + * IPv oip --> GRE/NAT --> MAC --> { x, IPv4, IPv6 } + * IPv oip --> GRE/NAT --> MAC/VLAN --> { x, IPv4, IPv6 } + */ +#define LIBIE_RX_PTYPE_IP(oip) \ + LIBIE_RX_PTYPE_IP_RAW(oip), \ + LIBIE_RX_PTYPE_IP_TUN(oip, IP), \ + LIBIE_RX_PTYPE_IP_GRE(oip, GRENAT), \ + LIBIE_RX_PTYPE_IP_GRE(oip, GRENAT_MAC), \ + LIBIE_RX_PTYPE_IP_GRE(oip, GRENAT_MAC_VLAN) + +/* Lookup table mapping for O(1) parsing */ +const struct libie_rx_ptype_parsed libie_rx_ptype_lut[LIBIE_RX_PTYPE_NUM] = { + /* L2 packet types */ + LIBIE_RX_PTYPE_UNUSED, + LIBIE_RX_PTYPE_L2, + LIBIE_RX_PTYPE_TS, + LIBIE_RX_PTYPE_L2, + LIBIE_RX_PTYPE_UNUSED, + LIBIE_RX_PTYPE_UNUSED, + LIBIE_RX_PTYPE_L2, + LIBIE_RX_PTYPE_L2, + LIBIE_RX_PTYPE_UNUSED, + LIBIE_RX_PTYPE_UNUSED, + LIBIE_RX_PTYPE_L2, + LIBIE_RX_PTYPE_UNUSED, + + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + LIBIE_RX_PTYPE_L3, + + LIBIE_RX_PTYPE_IP(4), + LIBIE_RX_PTYPE_IP(6), +}; +EXPORT_SYMBOL_NS_GPL(libie_rx_ptype_lut, LIBIE); + +/* Page Pool */ + +/** + * libie_rx_page_pool_create - create a PP with the default libie settings + * @napi: &napi_struct covering this PP (no usage outside its poll loops) + * @size: size of the PP, usually simply Rx queue len + * + * Returns &page_pool on success, casted -errno on failure. + */ +struct page_pool *libie_rx_page_pool_create(struct napi_struct *napi, + u32 size) +{ + const struct page_pool_params pp = { + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .order = LIBIE_RX_PAGE_ORDER, + .pool_size = size, + .nid = NUMA_NO_NODE, + .dev = napi->dev->dev.parent, + .napi = napi, + .dma_dir = DMA_FROM_DEVICE, + .max_len = LIBIE_RX_BUF_LEN, + .offset = LIBIE_SKB_HEADROOM, + }; + + return page_pool_create(&pp); +} +EXPORT_SYMBOL_NS_GPL(libie_rx_page_pool_create, LIBIE); + +/** + * libie_rx_page_pool_destroy - destroy a &page_pool created by libie + * @pool: pool to destroy + * @stats: RQ stats from the ring (or %NULL to skip updating PP stats) + * + * As the stats usually has the same lifetime as the device, but PP is usually + * created/destroyed on ifup/ifdown, in order to not lose the stats accumulated + * during the last ifup, the PP stats need to be added to the driver stats + * container. Then the PP gets destroyed. + */ +void libie_rx_page_pool_destroy(struct page_pool *pool, + struct libie_rq_stats *stats) +{ + libie_rq_stats_sync_pp(stats, pool); + page_pool_destroy(pool); +} +EXPORT_SYMBOL_NS_GPL(libie_rx_page_pool_destroy, LIBIE); + +MODULE_AUTHOR("Intel Corporation"); +MODULE_DESCRIPTION("Intel(R) Ethernet common library"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/intel/libie/stats.c b/drivers/net/ethernet/intel/libie/stats.c new file mode 100644 index 00000000000000..71c7ce14edcaed --- /dev/null +++ b/drivers/net/ethernet/intel/libie/stats.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright(c) 2023 Intel Corporation. */ + +#include +#include +#include + +#include "internal.h" + +/* Rx per-queue stats */ + +static const char * const libie_rq_stats_str[] = { +#define act(s) __stringify(s), + DECLARE_LIBIE_RQ_STATS(act) +#undef act +}; + +#define LIBIE_RQ_STATS_NUM ARRAY_SIZE(libie_rq_stats_str) + +#ifdef CONFIG_PAGE_POOL_STATS +/** + * libie_rq_stats_get_pp - get the current stats from a &page_pool + * @sarr: local array to add stats to + * @pool: pool to get the stats from + * + * Adds the current "live" stats from an online PP to the stats read from + * the RQ container, so that the actual totals will be returned. + */ +static void libie_rq_stats_get_pp(u64 *sarr, struct page_pool *pool) +{ + struct page_pool_stats *pps; + /* Used only to calculate pos below */ + struct libie_rq_stats tmp; + u32 pos; + + /* Validate the libie PP stats array can be casted <-> PP struct */ + static_assert(sizeof(tmp.pp) == sizeof(*pps)); + + if (!pool) + return; + + /* Position of the first Page Pool stats field */ + pos = (u64_stats_t *)&tmp.pp - tmp.raw; + pps = (typeof(pps))&sarr[pos]; + + page_pool_get_stats(pool, pps); +} + +/** + * libie_rq_stats_sync_pp - add the current PP stats to the RQ stats container + * @stats: stats structure to update + * @pool: pool to read the stats + * + * Called by libie_rx_page_pool_destroy() to save the stats before destroying + * the pool. + */ +void libie_rq_stats_sync_pp(struct libie_rq_stats *stats, + struct page_pool *pool) +{ + u64_stats_t *qarr = (u64_stats_t *)&stats->pp; + struct page_pool_stats pps = { }; + u64 *sarr = (u64 *)&pps; + + if (!stats) + return; + + page_pool_get_stats(pool, &pps); + + u64_stats_update_begin(&stats->syncp); + + for (u32 i = 0; i < sizeof(pps) / sizeof(*sarr); i++) + u64_stats_add(&qarr[i], sarr[i]); + + u64_stats_update_end(&stats->syncp); +} +#else +static void libie_rq_stats_get_pp(u64 *sarr, struct page_pool *pool) +{ +} + +/* static inline void libie_rq_stats_sync_pp() is declared in "internal.h" */ +#endif + +/** + * libie_rq_stats_get_sset_count - get the number of Ethtool RQ stats provided + * + * Returns the number of per-queue Rx stats supported by the library. + */ +u32 libie_rq_stats_get_sset_count(void) +{ + return LIBIE_RQ_STATS_NUM; +} +EXPORT_SYMBOL_NS_GPL(libie_rq_stats_get_sset_count, LIBIE); + +/** + * libie_rq_stats_get_strings - get the name strings of Ethtool RQ stats + * @data: reference to the cursor pointing to the output buffer + * @qid: RQ number to print in the prefix + */ +void libie_rq_stats_get_strings(u8 **data, u32 qid) +{ + for (u32 i = 0; i < LIBIE_RQ_STATS_NUM; i++) + ethtool_sprintf(data, "rq%u_%s", qid, libie_rq_stats_str[i]); +} +EXPORT_SYMBOL_NS_GPL(libie_rq_stats_get_strings, LIBIE); + +/** + * libie_rq_stats_get_data - get the RQ stats in Ethtool format + * @data: reference to the cursor pointing to the output array + * @stats: RQ stats container from the queue + * @pool: &page_pool from the queue (%NULL to ignore PP "live" stats) + */ +void libie_rq_stats_get_data(u64 **data, const struct libie_rq_stats *stats, + struct page_pool *pool) +{ + u64 sarr[LIBIE_RQ_STATS_NUM]; + u32 start; + + do { + start = u64_stats_fetch_begin(&stats->syncp); + + for (u32 i = 0; i < LIBIE_RQ_STATS_NUM; i++) + sarr[i] = u64_stats_read(&stats->raw[i]); + } while (u64_stats_fetch_retry(&stats->syncp, start)); + + libie_rq_stats_get_pp(sarr, pool); + + for (u32 i = 0; i < LIBIE_RQ_STATS_NUM; i++) + (*data)[i] += sarr[i]; + + *data += LIBIE_RQ_STATS_NUM; +} +EXPORT_SYMBOL_NS_GPL(libie_rq_stats_get_data, LIBIE); + +/* Tx per-queue stats */ + +static const char * const libie_sq_stats_str[] = { +#define act(s) __stringify(s), + DECLARE_LIBIE_SQ_STATS(act) +#undef act +}; + +#define LIBIE_SQ_STATS_NUM ARRAY_SIZE(libie_sq_stats_str) + +/** + * libie_sq_stats_get_sset_count - get the number of Ethtool SQ stats provided + * + * Returns the number of per-queue Tx stats supported by the library. + */ +u32 libie_sq_stats_get_sset_count(void) +{ + return LIBIE_SQ_STATS_NUM; +} +EXPORT_SYMBOL_NS_GPL(libie_sq_stats_get_sset_count, LIBIE); + +/** + * libie_sq_stats_get_strings - get the name strings of Ethtool SQ stats + * @data: reference to the cursor pointing to the output buffer + * @qid: SQ number to print in the prefix + */ +void libie_sq_stats_get_strings(u8 **data, u32 qid) +{ + for (u32 i = 0; i < LIBIE_SQ_STATS_NUM; i++) + ethtool_sprintf(data, "sq%u_%s", qid, libie_sq_stats_str[i]); +} +EXPORT_SYMBOL_NS_GPL(libie_sq_stats_get_strings, LIBIE); + +/** + * libie_sq_stats_get_data - get the SQ stats in Ethtool format + * @data: reference to the cursor pointing to the output array + * @stats: SQ stats container from the queue + */ +void libie_sq_stats_get_data(u64 **data, const struct libie_sq_stats *stats) +{ + u64 sarr[LIBIE_SQ_STATS_NUM]; + u32 start; + + do { + start = u64_stats_fetch_begin(&stats->syncp); + + for (u32 i = 0; i < LIBIE_SQ_STATS_NUM; i++) + sarr[i] = u64_stats_read(&stats->raw[i]); + } while (u64_stats_fetch_retry(&stats->syncp, start)); + + for (u32 i = 0; i < LIBIE_SQ_STATS_NUM; i++) + (*data)[i] += sarr[i]; + + *data += LIBIE_SQ_STATS_NUM; +} +EXPORT_SYMBOL_NS_GPL(libie_sq_stats_get_data, LIBIE); diff --git a/drivers/net/ethernet/marvell/octeontx2/Kconfig b/drivers/net/ethernet/marvell/octeontx2/Kconfig index 993ac180a5db83..a32d85d6f599f2 100644 --- a/drivers/net/ethernet/marvell/octeontx2/Kconfig +++ b/drivers/net/ethernet/marvell/octeontx2/Kconfig @@ -32,6 +32,7 @@ config OCTEONTX2_PF tristate "Marvell OcteonTX2 NIC Physical Function driver" select OCTEONTX2_MBOX select NET_DEVLINK + select PAGE_POOL depends on (64BIT && COMPILE_TEST) || ARM64 select DIMLIB depends on PCI diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h index f5bf719a6ccf6b..2436c1ff9ba4cf 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/common.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h @@ -145,6 +145,13 @@ enum nix_scheduler { #define TXSCH_TL1_DFLT_RR_PRIO (0x7ull) #define CN10K_MAX_DWRR_WEIGHT 16384 /* Weight is 14bit on CN10K */ +/* Don't change the order as on CN10K (except CN10KB) + * SMQX_CFG[SDP] value should be 1 for SDP flows. + */ +#define SMQ_LINK_TYPE_RPM 0 +#define SMQ_LINK_TYPE_SDP 1 +#define SMQ_LINK_TYPE_LBK 2 + /* Min/Max packet sizes, excluding FCS */ #define NIC_HW_MIN_FRS 40 #define NIC_HW_MAX_FRS 9212 diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h index 6389ed83637dc6..eba307eee2b2b9 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h @@ -1080,6 +1080,8 @@ struct nix_vtag_config_rsp { */ }; +#define NIX_FLOW_KEY_TYPE_L3_L4_MASK (~(0xf << 28)) + struct nix_rss_flowkey_cfg { struct mbox_msghdr hdr; int mcam_index; /* MCAM entry index to modify */ @@ -1105,6 +1107,10 @@ struct nix_rss_flowkey_cfg { #define NIX_FLOW_KEY_TYPE_IPV4_PROTO BIT(21) #define NIX_FLOW_KEY_TYPE_AH BIT(22) #define NIX_FLOW_KEY_TYPE_ESP BIT(23) +#define NIX_FLOW_KEY_TYPE_L4_DST_ONLY BIT(28) +#define NIX_FLOW_KEY_TYPE_L4_SRC_ONLY BIT(29) +#define NIX_FLOW_KEY_TYPE_L3_DST_ONLY BIT(30) +#define NIX_FLOW_KEY_TYPE_L3_SRC_ONLY BIT(31) u32 flowkey_cfg; /* Flowkey types selected */ u8 group; /* RSS context or group */ }; @@ -1151,6 +1157,7 @@ struct nix_rx_cfg { struct mbox_msghdr hdr; #define NIX_RX_OL3_VERIFY BIT(0) #define NIX_RX_OL4_VERIFY BIT(1) +#define NIX_RX_DROP_RE BIT(2) u8 len_verify; /* Outer L3/L4 len check */ #define NIX_RX_CSUM_OL4_VERIFY BIT(0) u8 csum_verify; /* Outer L4 checksum verification */ @@ -1239,7 +1246,9 @@ struct nix_hw_info { u16 min_mtu; u32 rpm_dwrr_mtu; u32 sdp_dwrr_mtu; - u64 rsvd[16]; /* Add reserved fields for future expansion */ + u32 lbk_dwrr_mtu; + u32 rsvd32[1]; + u64 rsvd[15]; /* Add reserved fields for future expansion */ }; struct nix_bandprof_alloc_req { diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h index d655bf04a483dd..b5a7ee63508c6a 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu.h @@ -285,6 +285,22 @@ struct nix_mark_format { u32 *cfg; }; +/* smq(flush) to tl1 cir/pir info */ +struct nix_smq_tree_ctx { + u64 cir_off; + u64 cir_val; + u64 pir_off; + u64 pir_val; +}; + +/* smq flush context */ +struct nix_smq_flush_ctx { + int smq; + u16 tl1_schq; + u16 tl2_schq; + struct nix_smq_tree_ctx smq_tree_ctx[NIX_TXSCH_LVL_CNT]; +}; + struct npc_pkind { struct rsrc_bmap rsrc; u32 *pfchan_map; @@ -346,6 +362,7 @@ struct hw_cap { bool per_pf_mbox_regs; /* PF mbox specified in per PF registers ? */ bool programmable_chans; /* Channels programmable ? */ bool ipolicer; + bool nix_multiple_dwrr_mtu; /* Multiple DWRR_MTU to choose from */ bool npc_hash_extract; /* Hash extract enabled ? */ bool npc_exact_match_enabled; /* Exact match supported ? */ }; @@ -802,8 +819,11 @@ int nix_aq_context_read(struct rvu *rvu, struct nix_hw *nix_hw, struct nix_cn10k_aq_enq_rsp *aq_rsp, u16 pcifunc, u8 ctype, u32 qidx); int rvu_get_nix_blkaddr(struct rvu *rvu, u16 pcifunc); +int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type); u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu); u32 convert_bytes_to_dwrr_mtu(u32 bytes); +void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc, + struct nix_txsch *txsch, bool enable); /* NPC APIs */ void rvu_npc_freemem(struct rvu *rvu); diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c index e4407f09c9d34b..41df5ac23f927f 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_devlink.c @@ -1413,7 +1413,8 @@ static int rvu_af_dl_dwrr_mtu_set(struct devlink *devlink, u32 id, u64 dwrr_mtu; dwrr_mtu = convert_bytes_to_dwrr_mtu(ctx->val.vu32); - rvu_write64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU, dwrr_mtu); + rvu_write64(rvu, BLKADDR_NIX0, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), dwrr_mtu); return 0; } @@ -1428,7 +1429,8 @@ static int rvu_af_dl_dwrr_mtu_get(struct devlink *devlink, u32 id, if (!rvu->hw->cap.nix_common_dwrr_mtu) return -EOPNOTSUPP; - dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); + dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM)); ctx->val.vu32 = convert_dwrr_mtu_to_bytes(dwrr_mtu); return 0; @@ -1438,6 +1440,7 @@ enum rvu_af_dl_param_id { RVU_AF_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX, RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, RVU_AF_DEVLINK_PARAM_ID_NPC_EXACT_FEATURE_DISABLE, + RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT, }; static int rvu_af_npc_exact_feature_get(struct devlink *devlink, u32 id, @@ -1494,6 +1497,67 @@ static int rvu_af_npc_exact_feature_validate(struct devlink *devlink, u32 id, return -EFAULT; } +static int rvu_af_dl_npc_mcam_high_zone_percent_get(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct rvu_devlink *rvu_dl = devlink_priv(devlink); + struct rvu *rvu = rvu_dl->rvu; + struct npc_mcam *mcam; + u32 percent; + + mcam = &rvu->hw->mcam; + percent = (mcam->hprio_count * 100) / mcam->bmap_entries; + ctx->val.vu8 = (u8)percent; + + return 0; +} + +static int rvu_af_dl_npc_mcam_high_zone_percent_set(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct rvu_devlink *rvu_dl = devlink_priv(devlink); + struct rvu *rvu = rvu_dl->rvu; + struct npc_mcam *mcam; + u32 percent; + + percent = ctx->val.vu8; + mcam = &rvu->hw->mcam; + mcam->hprio_count = (mcam->bmap_entries * percent) / 100; + mcam->hprio_end = mcam->hprio_count; + mcam->lprio_count = (mcam->bmap_entries - mcam->hprio_count) / 2; + mcam->lprio_start = mcam->bmap_entries - mcam->lprio_count; + + return 0; +} + +static int rvu_af_dl_npc_mcam_high_zone_percent_validate(struct devlink *devlink, u32 id, + union devlink_param_value val, + struct netlink_ext_ack *extack) +{ + struct rvu_devlink *rvu_dl = devlink_priv(devlink); + struct rvu *rvu = rvu_dl->rvu; + struct npc_mcam *mcam; + + /* The percent of high prio zone must range from 12% to 100% of unreserved mcam space */ + if (val.vu8 < 12 || val.vu8 > 100) { + NL_SET_ERR_MSG_MOD(extack, + "mcam high zone percent must be between 12% to 100%"); + return -EINVAL; + } + + /* Do not allow user to modify the high priority zone entries while mcam entries + * have already been assigned. + */ + mcam = &rvu->hw->mcam; + if (mcam->bmap_fcnt < mcam->bmap_entries) { + NL_SET_ERR_MSG_MOD(extack, + "mcam entries have already been assigned, can't resize"); + return -EPERM; + } + + return 0; +} + static const struct devlink_param rvu_af_dl_params[] = { DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_DWRR_MTU, "dwrr_mtu", DEVLINK_PARAM_TYPE_U32, @@ -1509,6 +1573,12 @@ static const struct devlink_param rvu_af_dl_param_exact_match[] = { rvu_af_npc_exact_feature_get, rvu_af_npc_exact_feature_disable, rvu_af_npc_exact_feature_validate), + DEVLINK_PARAM_DRIVER(RVU_AF_DEVLINK_PARAM_ID_NPC_MCAM_ZONE_PERCENT, + "npc_mcam_high_zone_percent", DEVLINK_PARAM_TYPE_U8, + BIT(DEVLINK_PARAM_CMODE_RUNTIME), + rvu_af_dl_npc_mcam_high_zone_percent_get, + rvu_af_dl_npc_mcam_high_zone_percent_set, + rvu_af_dl_npc_mcam_high_zone_percent_validate), }; /* Devlink switch mode */ diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c index 79ed7af0b0a4e8..601ef269aa29e4 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c @@ -191,6 +191,18 @@ struct nix_hw *get_nix_hw(struct rvu_hwinfo *hw, int blkaddr) return NULL; } +int nix_get_dwrr_mtu_reg(struct rvu_hwinfo *hw, int smq_link_type) +{ + if (hw->cap.nix_multiple_dwrr_mtu) + return NIX_AF_DWRR_MTUX(smq_link_type); + + if (smq_link_type == SMQ_LINK_TYPE_SDP) + return NIX_AF_DWRR_SDP_MTU; + + /* Here it's same reg for RPM and LBK */ + return NIX_AF_DWRR_RPM_MTU; +} + u32 convert_dwrr_mtu_to_bytes(u8 dwrr_mtu) { dwrr_mtu &= 0x1FULL; @@ -2102,9 +2114,121 @@ int rvu_mbox_handler_nix_txsch_alloc(struct rvu *rvu, return rc; } +static void nix_smq_flush_fill_ctx(struct rvu *rvu, int blkaddr, int smq, + struct nix_smq_flush_ctx *smq_flush_ctx) +{ + struct nix_smq_tree_ctx *smq_tree_ctx; + u64 parent_off, regval; + u16 schq; + int lvl; + + smq_flush_ctx->smq = smq; + + schq = smq; + for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) { + smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl]; + if (lvl == NIX_TXSCH_LVL_TL1) { + smq_flush_ctx->tl1_schq = schq; + smq_tree_ctx->cir_off = NIX_AF_TL1X_CIR(schq); + smq_tree_ctx->pir_off = 0; + smq_tree_ctx->pir_val = 0; + parent_off = 0; + } else if (lvl == NIX_TXSCH_LVL_TL2) { + smq_flush_ctx->tl2_schq = schq; + smq_tree_ctx->cir_off = NIX_AF_TL2X_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_TL2X_PIR(schq); + parent_off = NIX_AF_TL2X_PARENT(schq); + } else if (lvl == NIX_TXSCH_LVL_TL3) { + smq_tree_ctx->cir_off = NIX_AF_TL3X_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_TL3X_PIR(schq); + parent_off = NIX_AF_TL3X_PARENT(schq); + } else if (lvl == NIX_TXSCH_LVL_TL4) { + smq_tree_ctx->cir_off = NIX_AF_TL4X_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_TL4X_PIR(schq); + parent_off = NIX_AF_TL4X_PARENT(schq); + } else if (lvl == NIX_TXSCH_LVL_MDQ) { + smq_tree_ctx->cir_off = NIX_AF_MDQX_CIR(schq); + smq_tree_ctx->pir_off = NIX_AF_MDQX_PIR(schq); + parent_off = NIX_AF_MDQX_PARENT(schq); + } + /* save cir/pir register values */ + smq_tree_ctx->cir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->cir_off); + if (smq_tree_ctx->pir_off) + smq_tree_ctx->pir_val = rvu_read64(rvu, blkaddr, smq_tree_ctx->pir_off); + + /* get parent txsch node */ + if (parent_off) { + regval = rvu_read64(rvu, blkaddr, parent_off); + schq = (regval >> 16) & 0x1FF; + } + } +} + +static void nix_smq_flush_enadis_xoff(struct rvu *rvu, int blkaddr, + struct nix_smq_flush_ctx *smq_flush_ctx, bool enable) +{ + struct nix_txsch *txsch; + struct nix_hw *nix_hw; + u64 regoff; + int tl2; + + nix_hw = get_nix_hw(rvu->hw, blkaddr); + if (!nix_hw) + return; + + /* loop through all TL2s with matching PF_FUNC */ + txsch = &nix_hw->txsch[NIX_TXSCH_LVL_TL2]; + for (tl2 = 0; tl2 < txsch->schq.max; tl2++) { + /* skip the smq(flush) TL2 */ + if (tl2 == smq_flush_ctx->tl2_schq) + continue; + /* skip unused TL2s */ + if (TXSCH_MAP_FLAGS(txsch->pfvf_map[tl2]) & NIX_TXSCHQ_FREE) + continue; + /* skip if PF_FUNC doesn't match */ + if ((TXSCH_MAP_FUNC(txsch->pfvf_map[tl2]) & ~RVU_PFVF_FUNC_MASK) != + (TXSCH_MAP_FUNC(txsch->pfvf_map[smq_flush_ctx->tl2_schq] & + ~RVU_PFVF_FUNC_MASK))) + continue; + /* enable/disable XOFF */ + regoff = NIX_AF_TL2X_SW_XOFF(tl2); + if (enable) + rvu_write64(rvu, blkaddr, regoff, 0x1); + else + rvu_write64(rvu, blkaddr, regoff, 0x0); + } +} + +static void nix_smq_flush_enadis_rate(struct rvu *rvu, int blkaddr, + struct nix_smq_flush_ctx *smq_flush_ctx, bool enable) +{ + u64 cir_off, pir_off, cir_val, pir_val; + struct nix_smq_tree_ctx *smq_tree_ctx; + int lvl; + + for (lvl = NIX_TXSCH_LVL_SMQ; lvl <= NIX_TXSCH_LVL_TL1; lvl++) { + smq_tree_ctx = &smq_flush_ctx->smq_tree_ctx[lvl]; + cir_off = smq_tree_ctx->cir_off; + cir_val = smq_tree_ctx->cir_val; + pir_off = smq_tree_ctx->pir_off; + pir_val = smq_tree_ctx->pir_val; + + if (enable) { + rvu_write64(rvu, blkaddr, cir_off, cir_val); + if (lvl != NIX_TXSCH_LVL_TL1) + rvu_write64(rvu, blkaddr, pir_off, pir_val); + } else { + rvu_write64(rvu, blkaddr, cir_off, 0x0); + if (lvl != NIX_TXSCH_LVL_TL1) + rvu_write64(rvu, blkaddr, pir_off, 0x0); + } + } +} + static int nix_smq_flush(struct rvu *rvu, int blkaddr, int smq, u16 pcifunc, int nixlf) { + struct nix_smq_flush_ctx *smq_flush_ctx; int pf = rvu_get_pf(pcifunc); u8 cgx_id = 0, lmac_id = 0; int err, restore_tx_en = 0; @@ -2124,6 +2248,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, lmac_id, true); } + /* XOFF all TL2s whose parent TL1 matches SMQ tree TL1 */ + smq_flush_ctx = kzalloc(sizeof(*smq_flush_ctx), GFP_KERNEL); + if (!smq_flush_ctx) + return -ENOMEM; + nix_smq_flush_fill_ctx(rvu, blkaddr, smq, smq_flush_ctx); + nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, true); + nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, false); + cfg = rvu_read64(rvu, blkaddr, NIX_AF_SMQX_CFG(smq)); /* Do SMQ flush and set enqueue xoff */ cfg |= BIT_ULL(50) | BIT_ULL(49); @@ -2138,8 +2270,14 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, err = rvu_poll_reg(rvu, blkaddr, NIX_AF_SMQX_CFG(smq), BIT_ULL(49), true); if (err) - dev_err(rvu->dev, - "NIXLF%d: SMQ%d flush failed\n", nixlf, smq); + dev_info(rvu->dev, + "NIXLF%d: SMQ%d flush failed, txlink might be busy\n", + nixlf, smq); + + /* clear XOFF on TL2s */ + nix_smq_flush_enadis_rate(rvu, blkaddr, smq_flush_ctx, true); + nix_smq_flush_enadis_xoff(rvu, blkaddr, smq_flush_ctx, false); + kfree(smq_flush_ctx); rvu_cgx_enadis_rx_bp(rvu, pf, true); /* restore cgx tx state */ @@ -2448,17 +2586,19 @@ static int nix_txschq_cfg_read(struct rvu *rvu, struct nix_hw *nix_hw, return 0; } -static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, - u16 pcifunc, struct nix_txsch *txsch) +void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, u16 pcifunc, + struct nix_txsch *txsch, bool enable) { struct rvu_hwinfo *hw = rvu->hw; int lbk_link_start, lbk_links; u8 pf = rvu_get_pf(pcifunc); int schq; + u64 cfg; if (!is_pf_cgxmapped(rvu, pf)) return; + cfg = enable ? (BIT_ULL(12) | RVU_SWITCH_LBK_CHAN) : 0; lbk_link_start = hw->cgx_links; for (schq = 0; schq < txsch->schq.max; schq++) { @@ -2472,8 +2612,7 @@ static void rvu_nix_tx_tl2_cfg(struct rvu *rvu, int blkaddr, rvu_write64(rvu, blkaddr, NIX_AF_TL3_TL2X_LINKX_CFG(schq, lbk_link_start + - lbk_links), - BIT_ULL(12) | RVU_SWITCH_LBK_CHAN); + lbk_links), cfg); } } @@ -2579,8 +2718,6 @@ int rvu_mbox_handler_nix_txschq_cfg(struct rvu *rvu, rvu_write64(rvu, blkaddr, reg, regval); } - rvu_nix_tx_tl2_cfg(rvu, blkaddr, pcifunc, - &nix_hw->txsch[NIX_TXSCH_LVL_TL2]); return 0; } @@ -3191,10 +3328,16 @@ static int nix_setup_txschq(struct rvu *rvu, struct nix_hw *nix_hw, int blkaddr) } /* Setup a default value of 8192 as DWRR MTU */ - if (rvu->hw->cap.nix_common_dwrr_mtu) { - rvu_write64(rvu, blkaddr, NIX_AF_DWRR_RPM_MTU, + if (rvu->hw->cap.nix_common_dwrr_mtu || + rvu->hw->cap.nix_multiple_dwrr_mtu) { + rvu_write64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM), convert_bytes_to_dwrr_mtu(8192)); - rvu_write64(rvu, blkaddr, NIX_AF_DWRR_SDP_MTU, + rvu_write64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK), + convert_bytes_to_dwrr_mtu(8192)); + rvu_write64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP), convert_bytes_to_dwrr_mtu(8192)); } @@ -3292,19 +3435,28 @@ int rvu_mbox_handler_nix_get_hw_info(struct rvu *rvu, struct msg_req *req, rsp->min_mtu = NIC_HW_MIN_FRS; - if (!rvu->hw->cap.nix_common_dwrr_mtu) { + if (!rvu->hw->cap.nix_common_dwrr_mtu && + !rvu->hw->cap.nix_multiple_dwrr_mtu) { /* Return '1' on OTx2 */ rsp->rpm_dwrr_mtu = 1; rsp->sdp_dwrr_mtu = 1; + rsp->lbk_dwrr_mtu = 1; return 0; } - dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_RPM_MTU); + /* Return DWRR_MTU for TLx_SCHEDULE[RR_WEIGHT] config */ + dwrr_mtu = rvu_read64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_RPM)); rsp->rpm_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); - dwrr_mtu = rvu_read64(rvu, BLKADDR_NIX0, NIX_AF_DWRR_SDP_MTU); + dwrr_mtu = rvu_read64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_SDP)); rsp->sdp_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); + dwrr_mtu = rvu_read64(rvu, blkaddr, + nix_get_dwrr_mtu_reg(rvu->hw, SMQ_LINK_TYPE_LBK)); + rsp->lbk_dwrr_mtu = convert_dwrr_mtu_to_bytes(dwrr_mtu); + return 0; } @@ -3353,6 +3505,7 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) struct nix_rx_flowkey_alg *field; struct nix_rx_flowkey_alg tmp; u32 key_type, valid_key; + u32 l3_l4_src_dst; int l4_key_offset = 0; if (!alg) @@ -3380,6 +3533,15 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) * group_member - Enabled when protocol is part of a group. */ + /* Last 4 bits (31:28) are reserved to specify SRC, DST + * selection for L3, L4 i.e IPV[4,6]_SRC, IPV[4,6]_DST, + * [TCP,UDP,SCTP]_SRC, [TCP,UDP,SCTP]_DST + * 31 => L3_SRC, 30 => L3_DST, 29 => L4_SRC, 28 => L4_DST + */ + l3_l4_src_dst = flow_cfg; + /* Reset these 4 bits, so that these won't be part of key */ + flow_cfg &= NIX_FLOW_KEY_TYPE_L3_L4_MASK; + keyoff_marker = 0; max_key_off = 0; group_member = 0; nr_field = 0; key_off = 0; field_marker = 1; field = &tmp; max_bit_pos = fls(flow_cfg); @@ -3417,6 +3579,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) } field->hdr_offset = 12; /* SIP offset */ field->bytesm1 = 7; /* SIP + DIP, 8 bytes */ + + /* Only SIP */ + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY) + field->bytesm1 = 3; /* SIP, 4 bytes */ + + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) { + /* Both SIP + DIP */ + if (field->bytesm1 == 3) { + field->bytesm1 = 7; /* SIP + DIP, 8B */ + } else { + /* Only DIP */ + field->hdr_offset = 16; /* DIP off */ + field->bytesm1 = 3; /* DIP, 4 bytes */ + } + } + field->ltype_mask = 0xF; /* Match only IPv4 */ keyoff_marker = false; break; @@ -3430,6 +3608,22 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) } field->hdr_offset = 8; /* SIP offset */ field->bytesm1 = 31; /* SIP + DIP, 32 bytes */ + + /* Only SIP */ + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_SRC_ONLY) + field->bytesm1 = 15; /* SIP, 16 bytes */ + + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L3_DST_ONLY) { + /* Both SIP + DIP */ + if (field->bytesm1 == 15) { + /* SIP + DIP, 32 bytes */ + field->bytesm1 = 31; + } else { + /* Only DIP */ + field->hdr_offset = 24; /* DIP off */ + field->bytesm1 = 15; /* DIP,16 bytes */ + } + } field->ltype_mask = 0xF; /* Match only IPv6 */ break; case NIX_FLOW_KEY_TYPE_TCP: @@ -3445,6 +3639,21 @@ static int set_flowkey_fields(struct nix_rx_flowkey_alg *alg, u32 flow_cfg) field->lid = NPC_LID_LH; field->bytesm1 = 3; /* Sport + Dport, 4 bytes */ + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_SRC_ONLY) + field->bytesm1 = 1; /* SRC, 2 bytes */ + + if (l3_l4_src_dst & NIX_FLOW_KEY_TYPE_L4_DST_ONLY) { + /* Both SRC + DST */ + if (field->bytesm1 == 1) { + /* SRC + DST, 4 bytes */ + field->bytesm1 = 3; + } else { + /* Only DIP */ + field->hdr_offset = 2; /* DST off */ + field->bytesm1 = 1; /* DST, 2 bytes */ + } + } + /* Enum values for NPC_LID_LD and NPC_LID_LG are same, * so no need to change the ltype_match, just change * the lid for inner protocols @@ -4113,6 +4322,11 @@ int rvu_mbox_handler_nix_set_rx_cfg(struct rvu *rvu, struct nix_rx_cfg *req, else cfg &= ~BIT_ULL(40); + if (req->len_verify & NIX_RX_DROP_RE) + cfg |= BIT_ULL(32); + else + cfg &= ~BIT_ULL(32); + if (req->csum_verify & BIT(0)) cfg |= BIT_ULL(37); else @@ -4314,8 +4528,11 @@ static void rvu_nix_setup_capabilities(struct rvu *rvu, int blkaddr) * Check if HW uses a common MTU for all DWRR quantum configs. * On OcteonTx2 this register field is '0'. */ - if (((hw_const >> 56) & 0x10) == 0x10) + if ((((hw_const >> 56) & 0x10) == 0x10) && !(hw_const & BIT_ULL(61))) hw->cap.nix_common_dwrr_mtu = true; + + if (hw_const & BIT_ULL(61)) + hw->cap.nix_multiple_dwrr_mtu = true; } static int rvu_nix_block_init(struct rvu *rvu, struct nix_hw *nix_hw) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h index 7007f0b8e6591a..b42e631e52d0fd 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_reg.h @@ -272,7 +272,8 @@ #define NIX_AF_DEBUG_NPC_RESP_DATAX(a) (0x680 | (a) << 3) #define NIX_AF_SMQX_CFG(a) (0x700 | (a) << 16) #define NIX_AF_SQM_DBG_CTL_STATUS (0x750) -#define NIX_AF_DWRR_SDP_MTU (0x790) +#define NIX_AF_DWRR_SDP_MTU (0x790) /* All CN10K except CN10KB */ +#define NIX_AF_DWRR_MTUX(a) (0x790 | (a) << 16) /* Only for CN10KB */ #define NIX_AF_DWRR_RPM_MTU (0x7A0) #define NIX_AF_PSE_CHANNEL_LEVEL (0x800) #define NIX_AF_PSE_SHAPER_CFG (0x810) diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c index 3392487f6b47b8..592b317f46376e 100644 --- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c +++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_switch.c @@ -8,6 +8,17 @@ #include #include "rvu.h" +static void rvu_switch_enable_lbk_link(struct rvu *rvu, u16 pcifunc, bool enable) +{ + struct rvu_pfvf *pfvf = rvu_get_pfvf(rvu, pcifunc); + struct nix_hw *nix_hw; + + nix_hw = get_nix_hw(rvu->hw, pfvf->nix_blkaddr); + /* Enable LBK links with channel 63 for TX MCAM rule */ + rvu_nix_tx_tl2_cfg(rvu, pfvf->nix_blkaddr, pcifunc, + &nix_hw->txsch[NIX_TXSCH_LVL_TL2], enable); +} + static int rvu_switch_install_rx_rule(struct rvu *rvu, u16 pcifunc, u16 chan_mask) { @@ -52,6 +63,8 @@ static int rvu_switch_install_tx_rule(struct rvu *rvu, u16 pcifunc, u16 entry) if (!test_bit(NIXLF_INITIALIZED, &pfvf->flags)) return 0; + rvu_switch_enable_lbk_link(rvu, pcifunc, true); + lbkid = pfvf->nix_blkaddr == BLKADDR_NIX0 ? 0 : 1; ether_addr_copy(req.packet.dmac, pfvf->mac_addr); eth_broadcast_addr((u8 *)&req.mask.dmac); @@ -218,6 +231,9 @@ void rvu_switch_disable(struct rvu *rvu) "Reverting RX rule for PF%d failed(%d)\n", pf, err); + /* Disable LBK link */ + rvu_switch_enable_lbk_link(rvu, pcifunc, false); + rvu_get_pf_numvfs(rvu, pf, &numvfs, NULL); for (vf = 0; vf < numvfs; vf++) { pcifunc = pf << 10 | ((vf + 1) & 0x3FF); @@ -226,6 +242,8 @@ void rvu_switch_disable(struct rvu *rvu) dev_err(rvu->dev, "Reverting RX rule for PF%dVF%d failed(%d)\n", pf, vf, err); + + rvu_switch_enable_lbk_link(rvu, pcifunc, false); } } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c index f9286648e45cd9..d17a0ebc9036a5 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c @@ -7,7 +7,9 @@ #include #include +#include #include +#include #include "otx2_reg.h" #include "otx2_common.h" @@ -518,11 +520,32 @@ void otx2_config_irq_coalescing(struct otx2_nic *pfvf, int qidx) (pfvf->hw.cq_ecount_wait - 1)); } +static int otx2_alloc_pool_buf(struct otx2_nic *pfvf, struct otx2_pool *pool, + dma_addr_t *dma) +{ + unsigned int offset = 0; + struct page *page; + size_t sz; + + sz = SKB_DATA_ALIGN(pool->rbsize); + sz = ALIGN(sz, OTX2_ALIGN); + + page = page_pool_alloc_frag(pool->page_pool, &offset, sz, GFP_ATOMIC); + if (unlikely(!page)) + return -ENOMEM; + + *dma = page_pool_get_dma_addr(page) + offset; + return 0; +} + static int __otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, dma_addr_t *dma) { u8 *buf; + if (pool->page_pool) + return otx2_alloc_pool_buf(pfvf, pool, dma); + buf = napi_alloc_frag_align(pool->rbsize, OTX2_ALIGN); if (unlikely(!buf)) return -ENOMEM; @@ -621,6 +644,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for req->regval[0] = ((u64)pfvf->tx_max_pktlen << 8) | OTX2_MIN_MTU; req->regval[0] |= (0x20ULL << 51) | (0x80ULL << 39) | (0x2ULL << 36); + /* Set link type for DWRR MTU selection on CN10K silicons */ + if (!is_dev_otx2(pfvf->pdev)) + req->regval[0] |= FIELD_PREP(GENMASK_ULL(58, 57), + (u64)hw->smq_link_type); req->num_regs++; /* MDQ config */ parent = schq_list[NIX_TXSCH_LVL_TL4][prio]; @@ -1205,10 +1232,31 @@ void otx2_sq_free_sqbs(struct otx2_nic *pfvf) } } +void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool, + u64 iova, int size) +{ + struct page *page; + u64 pa; + + pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); + page = virt_to_head_page(phys_to_virt(pa)); + + if (pool->page_pool) { + page_pool_put_full_page(pool->page_pool, page, true); + } else { + dma_unmap_page_attrs(pfvf->dev, iova, size, + DMA_FROM_DEVICE, + DMA_ATTR_SKIP_CPU_SYNC); + + put_page(page); + } +} + void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type) { int pool_id, pool_start = 0, pool_end = 0, size = 0; - u64 iova, pa; + struct otx2_pool *pool; + u64 iova; if (type == AURA_NIX_SQ) { pool_start = otx2_get_pool_idx(pfvf, type, 0); @@ -1224,15 +1272,13 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type) /* Free SQB and RQB pointers from the aura pool */ for (pool_id = pool_start; pool_id < pool_end; pool_id++) { iova = otx2_aura_allocptr(pfvf, pool_id); + pool = &pfvf->qset.pool[pool_id]; while (iova) { if (type == AURA_NIX_RQ) iova -= OTX2_HEAD_ROOM; - pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); - dma_unmap_page_attrs(pfvf->dev, iova, size, - DMA_FROM_DEVICE, - DMA_ATTR_SKIP_CPU_SYNC); - put_page(virt_to_page(phys_to_virt(pa))); + otx2_free_bufs(pfvf, pool, iova, size); + iova = otx2_aura_allocptr(pfvf, pool_id); } } @@ -1250,6 +1296,8 @@ void otx2_aura_pool_free(struct otx2_nic *pfvf) pool = &pfvf->qset.pool[pool_id]; qmem_free(pfvf->dev, pool->stack); qmem_free(pfvf->dev, pool->fc_addr); + page_pool_destroy(pool->page_pool); + pool->page_pool = NULL; } devm_kfree(pfvf->dev, pfvf->qset.pool); pfvf->qset.pool = NULL; @@ -1333,8 +1381,9 @@ int otx2_aura_init(struct otx2_nic *pfvf, int aura_id, } int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, - int stack_pages, int numptrs, int buf_size) + int stack_pages, int numptrs, int buf_size, int type) { + struct page_pool_params pp_params = { 0 }; struct npa_aq_enq_req *aq; struct otx2_pool *pool; int err; @@ -1378,6 +1427,22 @@ int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, aq->ctype = NPA_AQ_CTYPE_POOL; aq->op = NPA_AQ_INSTOP_INIT; + if (type != AURA_NIX_RQ) { + pool->page_pool = NULL; + return 0; + } + + pp_params.flags = PP_FLAG_DMA_MAP; + pp_params.pool_size = numptrs; + pp_params.nid = NUMA_NO_NODE; + pp_params.dev = pfvf->dev; + pp_params.dma_dir = DMA_FROM_DEVICE; + pool->page_pool = page_pool_create(&pp_params); + if (IS_ERR(pool->page_pool)) { + netdev_err(pfvf->netdev, "Creation of page pool failed\n"); + return PTR_ERR(pool->page_pool); + } + return 0; } @@ -1412,7 +1477,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) /* Initialize pool context */ err = otx2_pool_init(pfvf, pool_id, stack_pages, - num_sqbs, hw->sqb_size); + num_sqbs, hw->sqb_size, AURA_NIX_SQ); if (err) goto fail; } @@ -1475,7 +1540,7 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf) } for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) { err = otx2_pool_init(pfvf, pool_id, stack_pages, - num_ptrs, pfvf->rbsize); + num_ptrs, pfvf->rbsize, AURA_NIX_RQ); if (err) goto fail; } @@ -1659,7 +1724,6 @@ int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable) req->bpid_per_chan = 0; #endif - return otx2_sync_mbox_msg(&pfvf->mbox); } EXPORT_SYMBOL(otx2_nix_config_bp); @@ -1766,6 +1830,17 @@ void otx2_set_cints_affinity(struct otx2_nic *pfvf) } } +static u32 get_dwrr_mtu(struct otx2_nic *pfvf, struct nix_hw_info *hw) +{ + if (is_otx2_lbkvf(pfvf->pdev)) { + pfvf->hw.smq_link_type = SMQ_LINK_TYPE_LBK; + return hw->lbk_dwrr_mtu; + } + + pfvf->hw.smq_link_type = SMQ_LINK_TYPE_RPM; + return hw->rpm_dwrr_mtu; +} + u16 otx2_get_max_mtu(struct otx2_nic *pfvf) { struct nix_hw_info *rsp; @@ -1795,7 +1870,7 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf) max_mtu = rsp->max_mtu - 8 - OTX2_ETH_HLEN; /* Also save DWRR MTU, needed for DWRR weight calculation */ - pfvf->hw.dwrr_mtu = rsp->rpm_dwrr_mtu; + pfvf->hw.dwrr_mtu = get_dwrr_mtu(pfvf, rsp); if (!pfvf->hw.dwrr_mtu) pfvf->hw.dwrr_mtu = 1; } diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h index b2267c8bec37ae..ba8091131ec084 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h @@ -227,6 +227,7 @@ struct otx2_hw { u16 txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC]; u16 matchall_ipolicer; u32 dwrr_mtu; + u8 smq_link_type; /* HW settings, coalescing etc */ u16 rx_chan_base; @@ -976,7 +977,7 @@ int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool, int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable); void otx2_ctx_disable(struct mbox *mbox, int type, bool npa); int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable); -void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq); +void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx); void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq); int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura); int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura); @@ -984,7 +985,7 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura); int otx2_alloc_buffer(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, dma_addr_t *dma); int otx2_pool_init(struct otx2_nic *pfvf, u16 pool_id, - int stack_pages, int numptrs, int buf_size); + int stack_pages, int numptrs, int buf_size, int type); int otx2_aura_init(struct otx2_nic *pfvf, int aura_id, int pool_id, int numptrs); @@ -1054,6 +1055,8 @@ u16 otx2_get_max_mtu(struct otx2_nic *pfvf); int otx2_handle_ntuple_tc_features(struct net_device *netdev, netdev_features_t features); int otx2_smq_flush(struct otx2_nic *pfvf, int smq); +void otx2_free_bufs(struct otx2_nic *pfvf, struct otx2_pool *pool, + u64 iova, int size); /* tc support */ int otx2_init_tc(struct otx2_nic *nic); diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c index e1883c3edda3b0..93f0c8e3ce9180 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c @@ -16,6 +16,7 @@ #include #include #include +#include #include "otx2_reg.h" #include "otx2_common.h" @@ -1555,7 +1556,9 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) struct nix_lf_free_req *free_req; struct mbox *mbox = &pf->mbox; struct otx2_cq_queue *cq; + struct otx2_pool *pool; struct msg_req *req; + int pool_id; int qidx; /* Ensure all SQE are processed */ @@ -1584,7 +1587,7 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) for (qidx = 0; qidx < qset->cq_cnt; qidx++) { cq = &qset->cq[qidx]; if (cq->cq_type == CQ_RX) - otx2_cleanup_rx_cqes(pf, cq); + otx2_cleanup_rx_cqes(pf, cq, qidx); else otx2_cleanup_tx_cqes(pf, cq); } @@ -1594,6 +1597,13 @@ static void otx2_free_hw_resources(struct otx2_nic *pf) /* Free RQ buffer pointers*/ otx2_free_aura_ptr(pf, AURA_NIX_RQ); + for (qidx = 0; qidx < pf->hw.rx_queues; qidx++) { + pool_id = otx2_get_pool_idx(pf, AURA_NIX_RQ, qidx); + pool = &pf->qset.pool[pool_id]; + page_pool_destroy(pool->page_pool); + pool->page_pool = NULL; + } + otx2_free_cq_res(pf); /* Free all ingress bandwidth profiles allocated */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c index e288f46b23a8de..e369baf115301d 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c @@ -217,9 +217,6 @@ static bool otx2_skb_add_frag(struct otx2_nic *pfvf, struct sk_buff *skb, skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, va - page_address(page) + off, len - off, pfvf->rbsize); - - otx2_dma_unmap_page(pfvf, iova - OTX2_HEAD_ROOM, - pfvf->rbsize, DMA_FROM_DEVICE); return true; } @@ -382,6 +379,8 @@ static void otx2_rcv_pkt_handler(struct otx2_nic *pfvf, if (pfvf->netdev->features & NETIF_F_RXCSUM) skb->ip_summed = CHECKSUM_UNNECESSARY; + skb_mark_for_recycle(skb); + napi_gro_frags(napi); } @@ -657,9 +656,7 @@ static void otx2_sqe_add_ext(struct otx2_nic *pfvf, struct otx2_snd_queue *sq, htons(ext->lso_sb - skb_network_offset(skb)); } else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) { ext->lso_format = pfvf->hw.lso_tsov6_idx; - - ipv6_hdr(skb)->payload_len = - htons(ext->lso_sb - skb_network_offset(skb)); + ipv6_hdr(skb)->payload_len = htons(tcp_hdrlen(skb)); } else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4) { __be16 l3_proto = vlan_get_protocol(skb); struct udphdr *udph = udp_hdr(skb); @@ -1186,11 +1183,13 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq, } EXPORT_SYMBOL(otx2_sq_append_skb); -void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) +void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx) { struct nix_cqe_rx_s *cqe; + struct otx2_pool *pool; int processed_cqe = 0; - u64 iova, pa; + u16 pool_id; + u64 iova; if (pfvf->xdp_prog) xdp_rxq_info_unreg(&cq->xdp_rxq); @@ -1198,6 +1197,9 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) if (otx2_nix_cq_op_status(pfvf, cq) || !cq->pend_cqe) return; + pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_RQ, qidx); + pool = &pfvf->qset.pool[pool_id]; + while (cq->pend_cqe) { cqe = (struct nix_cqe_rx_s *)otx2_get_next_cqe(cq); processed_cqe++; @@ -1210,9 +1212,8 @@ void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq) continue; } iova = cqe->sg.seg_addr - OTX2_HEAD_ROOM; - pa = otx2_iova_to_phys(pfvf->iommu_domain, iova); - otx2_dma_unmap_page(pfvf, iova, pfvf->rbsize, DMA_FROM_DEVICE); - put_page(virt_to_page(phys_to_virt(pa))); + + otx2_free_bufs(pfvf, pool, iova, pfvf->rbsize); } /* Free CQEs to HW */ diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h index 7ab6db9a986fa2..b5d689eeff80b8 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h +++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h @@ -118,6 +118,7 @@ struct otx2_cq_poll { struct otx2_pool { struct qmem *stack; struct qmem *fc_addr; + struct page_pool *page_pool; u16 rbsize; }; diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c index d96ed29c1567f9..9d887bfc31089c 100644 --- a/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c +++ b/drivers/net/ethernet/marvell/octeontx2/nic/qos_sq.c @@ -63,7 +63,7 @@ static int otx2_qos_sq_aura_pool_init(struct otx2_nic *pfvf, int qidx) /* Initialize pool context */ err = otx2_pool_init(pfvf, pool_id, stack_pages, - num_sqbs, hw->sqb_size); + num_sqbs, hw->sqb_size, AURA_NIX_SQ); if (err) goto aura_free; diff --git a/drivers/net/ethernet/marvell/prestera/prestera_flower.c b/drivers/net/ethernet/marvell/prestera/prestera_flower.c index 91a478b75cbf00..3e20e71b0f81a7 100644 --- a/drivers/net/ethernet/marvell/prestera/prestera_flower.c +++ b/drivers/net/ethernet/marvell/prestera/prestera_flower.c @@ -148,6 +148,12 @@ static int prestera_flower_parse_meta(struct prestera_acl_rule *rule, __be16 key, mask; flow_rule_match_meta(f_rule, &match); + + if (match.mask->l2_miss) { + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\""); + return -EOPNOTSUPP; + } + if (match.mask->ingress_ifindex != 0xFFFFFFFF) { NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask"); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index a75fd072082c6e..834c644b67db51 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -3269,18 +3269,14 @@ static int mtk_open(struct net_device *dev) eth->dsa_meta[i] = md_dst; } } else { - /* Hardware special tag parsing needs to be disabled if at least - * one MAC does not use DSA. + /* Hardware DSA untagging and VLAN RX offloading need to be + * disabled if at least one MAC does not use DSA. */ u32 val = mtk_r32(eth, MTK_CDMP_IG_CTRL); val &= ~MTK_CDMP_STAG_EN; mtk_w32(eth, val, MTK_CDMP_IG_CTRL); - val = mtk_r32(eth, MTK_CDMQ_IG_CTRL); - val &= ~MTK_CDMQ_STAG_EN; - mtk_w32(eth, val, MTK_CDMQ_IG_CTRL); - mtk_w32(eth, 0, MTK_CDMP_EG_CTRL); } diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 277738c50c56e9..61286b0d9b0cb6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1374,16 +1374,13 @@ static int mlx4_mf_bond(struct mlx4_dev *dev) int nvfs; struct mlx4_slaves_pport slaves_port1; struct mlx4_slaves_pport slaves_port2; - DECLARE_BITMAP(slaves_port_1_2, MLX4_MFUNC_MAX); slaves_port1 = mlx4_phys_to_slaves_pport(dev, 1); slaves_port2 = mlx4_phys_to_slaves_pport(dev, 2); - bitmap_and(slaves_port_1_2, - slaves_port1.slaves, slaves_port2.slaves, - dev->persist->num_vfs + 1); /* only single port vfs are allowed */ - if (bitmap_weight(slaves_port_1_2, dev->persist->num_vfs + 1) > 1) { + if (bitmap_weight_and(slaves_port1.slaves, slaves_port2.slaves, + dev->persist->num_vfs + 1) > 1) { mlx4_warn(dev, "HA mode unsupported for dual ported VFs\n"); return -EINVAL; } @@ -3027,13 +3024,43 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) } } +static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port, + enum devlink_port_type port_type) +{ + struct mlx4_port_info *info = container_of(devlink_port, + struct mlx4_port_info, + devlink_port); + enum mlx4_port_type mlx4_port_type; + + switch (port_type) { + case DEVLINK_PORT_TYPE_AUTO: + mlx4_port_type = MLX4_PORT_TYPE_AUTO; + break; + case DEVLINK_PORT_TYPE_ETH: + mlx4_port_type = MLX4_PORT_TYPE_ETH; + break; + case DEVLINK_PORT_TYPE_IB: + mlx4_port_type = MLX4_PORT_TYPE_IB; + break; + default: + return -EOPNOTSUPP; + } + + return __set_port_type(info, mlx4_port_type); +} + +static const struct devlink_port_ops mlx4_devlink_port_ops = { + .port_type_set = mlx4_devlink_port_type_set, +}; + static int mlx4_init_port_info(struct mlx4_dev *dev, int port) { struct devlink *devlink = priv_to_devlink(mlx4_priv(dev)); struct mlx4_port_info *info = &mlx4_priv(dev)->port[port]; int err; - err = devl_port_register(devlink, &info->devlink_port, port); + err = devl_port_register_with_ops(devlink, &info->devlink_port, port, + &mlx4_devlink_port_ops); if (err) return err; @@ -3877,31 +3904,6 @@ static int __mlx4_init_one(struct pci_dev *pdev, int pci_dev_data, return err; } -static int mlx4_devlink_port_type_set(struct devlink_port *devlink_port, - enum devlink_port_type port_type) -{ - struct mlx4_port_info *info = container_of(devlink_port, - struct mlx4_port_info, - devlink_port); - enum mlx4_port_type mlx4_port_type; - - switch (port_type) { - case DEVLINK_PORT_TYPE_AUTO: - mlx4_port_type = MLX4_PORT_TYPE_AUTO; - break; - case DEVLINK_PORT_TYPE_ETH: - mlx4_port_type = MLX4_PORT_TYPE_ETH; - break; - case DEVLINK_PORT_TYPE_IB: - mlx4_port_type = MLX4_PORT_TYPE_IB; - break; - default: - return -EOPNOTSUPP; - } - - return __set_port_type(info, mlx4_port_type); -} - static void mlx4_devlink_param_load_driverinit_values(struct devlink *devlink) { struct mlx4_priv *priv = devlink_priv(devlink); @@ -3986,7 +3988,6 @@ static int mlx4_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a } static const struct devlink_ops mlx4_devlink_ops = { - .port_type_set = mlx4_devlink_port_type_set, .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT), .reload_down = mlx4_devlink_reload_down, .reload_up = mlx4_devlink_reload_up, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c index d53de39539a8fd..d532883b42d7c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c @@ -1920,9 +1920,10 @@ static void mlx5_cmd_err_trace(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod static void cmd_status_log(struct mlx5_core_dev *dev, u16 opcode, u8 status, u32 syndrome, int err) { + const char *namep = mlx5_command_str(opcode); struct mlx5_cmd_stats *stats; - if (!err) + if (!err || !(strcmp(namep, "unknown command opcode"))) return; stats = &dev->cmd.stats[opcode]; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c index bb95b40d25eb5d..fc13b41cc9b283 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/debugfs.c @@ -246,6 +246,7 @@ void mlx5_pages_debugfs_init(struct mlx5_core_dev *dev) debugfs_create_u32("fw_pages_total", 0400, pages, &dev->priv.fw_pages); debugfs_create_u32("fw_pages_vfs", 0400, pages, &dev->priv.page_counters[MLX5_VF]); + debugfs_create_u32("fw_pages_ec_vfs", 0400, pages, &dev->priv.page_counters[MLX5_EC_VF]); debugfs_create_u32("fw_pages_sfs", 0400, pages, &dev->priv.page_counters[MLX5_SF]); debugfs_create_u32("fw_pages_host_pf", 0400, pages, &dev->priv.page_counters[MLX5_HOST_PF]); debugfs_create_u32("fw_pages_alloc_failed", 0400, pages, &dev->priv.fw_pages_alloc_failed); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index 1b33533b15dea9..617ac7e5d75ccc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -323,6 +323,18 @@ static void del_adev(struct auxiliary_device *adev) auxiliary_device_uninit(adev); } +void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev) +{ + mutex_lock(&mlx5_intf_mutex); + dev->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; + mutex_unlock(&mlx5_intf_mutex); +} + +bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev) +{ + return dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV; +} + int mlx5_attach_device(struct mlx5_core_dev *dev) { struct mlx5_priv *priv = &dev->priv; @@ -457,6 +469,10 @@ static int add_drivers(struct mlx5_core_dev *dev) if (priv->adev[i]) continue; + if (mlx5_adev_devices[i].is_enabled && + !(mlx5_adev_devices[i].is_enabled(dev))) + continue; + if (mlx5_adev_devices[i].is_supported) is_supported = mlx5_adev_devices[i].is_supported(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index 4b607785d694c5..3d82ec89066605 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -7,7 +7,6 @@ #include "fw_reset.h" #include "fs_core.h" #include "eswitch.h" -#include "lag/lag.h" #include "esw/qos.h" #include "sf/dev/dev.h" #include "sf/sf.h" @@ -142,6 +141,13 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, bool sf_dev_allocated; int ret = 0; + if (mlx5_dev_is_lightweight(dev)) { + if (action != DEVLINK_RELOAD_ACTION_DRIVER_REINIT) + return -EOPNOTSUPP; + mlx5_unload_one_light(dev); + return 0; + } + sf_dev_allocated = mlx5_sf_dev_allocated(dev); if (sf_dev_allocated) { /* Reload results in deleting SF device which further results in @@ -162,9 +168,8 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change, return -EOPNOTSUPP; } - if (pci_num_vf(pdev)) { + if (mlx5_core_is_pf(dev) && pci_num_vf(pdev)) NL_SET_ERR_MSG_MOD(extack, "reload while VFs are present is unfavorable"); - } switch (action) { case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: @@ -195,6 +200,10 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a *actions_performed = BIT(action); switch (action) { case DEVLINK_RELOAD_ACTION_DRIVER_REINIT: + if (mlx5_dev_is_lightweight(dev)) { + mlx5_fw_reporters_create(dev); + return mlx5_init_one_devl_locked(dev); + } ret = mlx5_load_one_devl_locked(dev, false); break; case DEVLINK_RELOAD_ACTION_FW_ACTIVATE: @@ -311,8 +320,6 @@ static const struct devlink_ops mlx5_devlink_ops = { .eswitch_inline_mode_get = mlx5_devlink_eswitch_inline_mode_get, .eswitch_encap_mode_set = mlx5_devlink_eswitch_encap_mode_set, .eswitch_encap_mode_get = mlx5_devlink_eswitch_encap_mode_get, - .port_function_hw_addr_get = mlx5_devlink_port_function_hw_addr_get, - .port_function_hw_addr_set = mlx5_devlink_port_function_hw_addr_set, .rate_leaf_tx_share_set = mlx5_esw_devlink_rate_leaf_tx_share_set, .rate_leaf_tx_max_set = mlx5_esw_devlink_rate_leaf_tx_max_set, .rate_node_tx_share_set = mlx5_esw_devlink_rate_node_tx_share_set, @@ -320,16 +327,9 @@ static const struct devlink_ops mlx5_devlink_ops = { .rate_node_new = mlx5_esw_devlink_rate_node_new, .rate_node_del = mlx5_esw_devlink_rate_node_del, .rate_leaf_parent_set = mlx5_esw_devlink_rate_parent_set, - .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, - .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, - .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, - .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, #endif #ifdef CONFIG_MLX5_SF_MANAGER .port_new = mlx5_devlink_sf_port_new, - .port_del = mlx5_devlink_sf_port_del, - .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, - .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, #endif .flash_update = mlx5_devlink_flash_update, .info_get = mlx5_devlink_info_get, @@ -437,54 +437,6 @@ static int mlx5_devlink_large_group_num_validate(struct devlink *devlink, u32 id return 0; } - -static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct mlx5_core_dev *dev = devlink_priv(devlink); - - if (!MLX5_ESWITCH_MANAGER(dev)) - return -EOPNOTSUPP; - - if (ctx->val.vbool) - return mlx5_lag_mpesw_enable(dev); - - mlx5_lag_mpesw_disable(dev); - return 0; -} - -static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, - struct devlink_param_gset_ctx *ctx) -{ - struct mlx5_core_dev *dev = devlink_priv(devlink); - - if (!MLX5_ESWITCH_MANAGER(dev)) - return -EOPNOTSUPP; - - ctx->val.vbool = mlx5_lag_is_mpesw(dev); - return 0; -} - -static int mlx5_devlink_esw_multiport_validate(struct devlink *devlink, u32 id, - union devlink_param_value val, - struct netlink_ext_ack *extack) -{ - struct mlx5_core_dev *dev = devlink_priv(devlink); - - if (!MLX5_ESWITCH_MANAGER(dev)) { - NL_SET_ERR_MSG_MOD(extack, "E-Switch is unsupported"); - return -EOPNOTSUPP; - } - - if (mlx5_eswitch_mode(dev) != MLX5_ESWITCH_OFFLOADS) { - NL_SET_ERR_MSG_MOD(extack, - "E-Switch must be in switchdev mode"); - return -EBUSY; - } - - return 0; -} - #endif static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id, @@ -558,12 +510,6 @@ static const struct devlink_param mlx5_devlink_params[] = { BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, mlx5_devlink_large_group_num_validate), - DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, - "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, - BIT(DEVLINK_PARAM_CMODE_RUNTIME), - mlx5_devlink_esw_multiport_get, - mlx5_devlink_esw_multiport_set, - mlx5_devlink_esw_multiport_validate), #endif DEVLINK_PARAM_GENERIC(IO_EQ_SIZE, BIT(DEVLINK_PARAM_CMODE_DRIVERINIT), NULL, NULL, mlx5_devlink_eq_depth_validate), @@ -576,7 +522,7 @@ static void mlx5_devlink_set_params_init_values(struct devlink *devlink) struct mlx5_core_dev *dev = devlink_priv(devlink); union devlink_param_value value; - value.vbool = MLX5_CAP_GEN(dev, roce); + value.vbool = MLX5_CAP_GEN(dev, roce) && !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE, value); @@ -626,7 +572,7 @@ static int mlx5_devlink_eth_params_register(struct devlink *devlink) if (err) return err; - value.vbool = true; + value.vbool = !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH, value); @@ -666,6 +612,7 @@ static const struct devlink_param mlx5_devlink_rdma_params[] = { static int mlx5_devlink_rdma_params_register(struct devlink *devlink) { + struct mlx5_core_dev *dev = devlink_priv(devlink); union devlink_param_value value; int err; @@ -677,7 +624,7 @@ static int mlx5_devlink_rdma_params_register(struct devlink *devlink) if (err) return err; - value.vbool = true; + value.vbool = !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA, value); @@ -712,7 +659,7 @@ static int mlx5_devlink_vnet_params_register(struct devlink *devlink) if (err) return err; - value.vbool = true; + value.vbool = !mlx5_dev_is_lightweight(dev); devl_param_driverinit_value_set(devlink, DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET, value); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c index f40497823e65fa..7c0f2adbea000d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c @@ -490,7 +490,7 @@ static void poll_trace(struct mlx5_fw_tracer *tracer, (u64)timestamp_low; break; default: - if (tracer_event->event_id >= tracer->str_db.first_string_trace || + if (tracer_event->event_id >= tracer->str_db.first_string_trace && tracer_event->event_id <= tracer->str_db.first_string_trace + tracer->str_db.num_string_trace) { tracer_event->type = TRACER_EVENT_TYPE_STRING; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c index 9114661cd96791..b0128336ff01a0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/reporter_vnic.c @@ -76,6 +76,16 @@ int mlx5_reporter_vnic_diagnose_counters(struct mlx5_core_dev *dev, if (err) return err; + err = devlink_fmsg_u64_pair_put(fmsg, "generated_pkt_steering_fail", + VNIC_ENV_GET64(&vnic, generated_pkt_steering_fail)); + if (err) + return err; + + err = devlink_fmsg_u64_pair_put(fmsg, "handled_pkt_steering_fail", + VNIC_ENV_GET64(&vnic, handled_pkt_steering_fail)); + if (err) + return err; + err = devlink_fmsg_obj_nest_end(fmsg); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index b8987a404d7526..ceabe57c511a3c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -327,6 +327,7 @@ struct mlx5e_params { unsigned int sw_mtu; int hard_mtu; bool ptp_rx; + __be32 terminate_lkey_be; }; static inline u8 mlx5e_get_dcb_num_tc(struct mlx5e_params *params) @@ -593,13 +594,6 @@ struct mlx5e_mpw_info { #define MLX5E_MAX_RX_FRAGS 4 -/* a single cache unit is capable to serve one napi call (for non-striding rq) - * or a MPWQE (for striding rq). - */ -#define MLX5E_CACHE_UNIT (MLX5_MPWRQ_MAX_PAGES_PER_WQE > NAPI_POLL_WEIGHT ? \ - MLX5_MPWRQ_MAX_PAGES_PER_WQE : NAPI_POLL_WEIGHT) -#define MLX5E_CACHE_SIZE (4 * roundup_pow_of_two(MLX5E_CACHE_UNIT)) - struct mlx5e_rq; typedef void (*mlx5e_fp_handle_rx_cqe)(struct mlx5e_rq*, struct mlx5_cqe64*); typedef struct sk_buff * diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c index 9c94807097cb84..3235a3a4ed08aa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/params.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/params.c @@ -6,6 +6,7 @@ #include "en/port.h" #include "en_accel/en_accel.h" #include "en_accel/ipsec.h" +#include #include static u8 mlx5e_mpwrq_min_page_shift(struct mlx5_core_dev *mdev) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c index 7ac1ad9c46de03..7e8e96cc5cd083 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c @@ -51,7 +51,7 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, if (err) goto out; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]); port_buffer->buffer[i].lossy = MLX5_GET(bufferx_reg, buffer, lossy); @@ -73,14 +73,24 @@ int mlx5e_port_query_buffer(struct mlx5e_priv *priv, port_buffer->buffer[i].lossy); } - port_buffer->headroom_size = total_used; + port_buffer->internal_buffers_size = 0; + for (i = MLX5E_MAX_NETWORK_BUFFER; i < MLX5E_TOTAL_BUFFERS; i++) { + buffer = MLX5_ADDR_OF(pbmc_reg, out, buffer[i]); + port_buffer->internal_buffers_size += + MLX5_GET(bufferx_reg, buffer, size) * port_buff_cell_sz; + } + port_buffer->port_buffer_size = MLX5_GET(pbmc_reg, out, port_buffer_size) * port_buff_cell_sz; - port_buffer->spare_buffer_size = - port_buffer->port_buffer_size - total_used; - - mlx5e_dbg(HW, priv, "total buffer size=%d, spare buffer size=%d\n", - port_buffer->port_buffer_size, + port_buffer->headroom_size = total_used; + port_buffer->spare_buffer_size = port_buffer->port_buffer_size - + port_buffer->internal_buffers_size - + port_buffer->headroom_size; + + mlx5e_dbg(HW, priv, + "total buffer size=%u, headroom buffer size=%u, internal buffers size=%u, spare buffer size=%u\n", + port_buffer->port_buffer_size, port_buffer->headroom_size, + port_buffer->internal_buffers_size, port_buffer->spare_buffer_size); out: kfree(out); @@ -206,11 +216,11 @@ static int port_update_pool_cfg(struct mlx5_core_dev *mdev, if (!MLX5_CAP_GEN(mdev, sbcam_reg)) return 0; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) lossless_buff_count += ((port_buffer->buffer[i].size) && (!(port_buffer->buffer[i].lossy))); - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { p = select_sbcm_params(&port_buffer->buffer[i], lossless_buff_count); err = mlx5e_port_set_sbcm(mdev, 0, i, MLX5_INGRESS_DIR, @@ -293,7 +303,7 @@ static int port_set_buffer(struct mlx5e_priv *priv, if (err) goto out; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { void *buffer = MLX5_ADDR_OF(pbmc_reg, in, buffer[i]); u64 size = port_buffer->buffer[i].size; u64 xoff = port_buffer->buffer[i].xoff; @@ -351,7 +361,7 @@ static int update_xoff_threshold(struct mlx5e_port_buffer *port_buffer, { int i; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { if (port_buffer->buffer[i].lossy) { port_buffer->buffer[i].xoff = 0; port_buffer->buffer[i].xon = 0; @@ -408,7 +418,7 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev, int err; int i; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { prio_count = 0; lossy_count = 0; @@ -432,11 +442,11 @@ static int update_buffer_lossy(struct mlx5_core_dev *mdev, } if (changed) { - err = port_update_pool_cfg(mdev, port_buffer); + err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz); if (err) return err; - err = update_xoff_threshold(port_buffer, xoff, max_mtu, port_buff_cell_sz); + err = port_update_pool_cfg(mdev, port_buffer); if (err) return err; @@ -515,7 +525,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, if (change & MLX5E_PORT_BUFFER_PRIO2BUFFER) { update_prio2buffer = true; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) mlx5e_dbg(HW, priv, "%s: requested to map prio[%d] to buffer %d\n", __func__, i, prio2buffer[i]); @@ -530,7 +540,7 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, } if (change & MLX5E_PORT_BUFFER_SIZE) { - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { mlx5e_dbg(HW, priv, "%s: buffer[%d]=%d\n", __func__, i, buffer_size[i]); if (!port_buffer.buffer[i].lossy && !buffer_size[i]) { mlx5e_dbg(HW, priv, "%s: lossless buffer[%d] size cannot be zero\n", @@ -544,7 +554,9 @@ int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, mlx5e_dbg(HW, priv, "%s: total buffer requested=%d\n", __func__, total_used); - if (total_used > port_buffer.port_buffer_size) + if (total_used > port_buffer.headroom_size && + (total_used - port_buffer.headroom_size) > + port_buffer.spare_buffer_size) return -EINVAL; update_buffer = true; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h index a6ef118de758f8..f4a19ffbb641c0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.h @@ -35,7 +35,8 @@ #include "en.h" #include "port.h" -#define MLX5E_MAX_BUFFER 8 +#define MLX5E_MAX_NETWORK_BUFFER 8 +#define MLX5E_TOTAL_BUFFERS 10 #define MLX5E_DEFAULT_CABLE_LEN 7 /* 7 meters */ #define MLX5_BUFFER_SUPPORTED(mdev) (MLX5_CAP_GEN(mdev, pcam_reg) && \ @@ -60,8 +61,9 @@ struct mlx5e_bufferx_reg { struct mlx5e_port_buffer { u32 port_buffer_size; u32 spare_buffer_size; - u32 headroom_size; - struct mlx5e_bufferx_reg buffer[MLX5E_MAX_BUFFER]; + u32 headroom_size; /* Buffers 0-7 */ + u32 internal_buffers_size; /* Buffers 8-9 */ + struct mlx5e_bufferx_reg buffer[MLX5E_MAX_NETWORK_BUFFER]; }; int mlx5e_port_manual_buffer_config(struct mlx5e_priv *priv, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c index eb5abd0e55d906..3cbebfba582bdb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c @@ -175,6 +175,8 @@ static bool mlx5e_ptp_poll_ts_cq(struct mlx5e_cq *cq, int budget) /* ensure cq space is freed before enabling more cqes */ wmb(); + mlx5e_txqsq_wake(&ptpsq->txqsq); + return work_done == budget; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c index fc923a99b6a483..0380a04c3691cb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.c @@ -84,7 +84,7 @@ mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state, int mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state, - struct flow_action *flow_action, + struct flow_action *flow_action, int from, int to, struct mlx5_flow_attr *attr, enum mlx5_flow_namespace_type ns_type) { @@ -96,6 +96,11 @@ mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state, priv = parse_state->flow->priv; flow_action_for_each(i, act, flow_action) { + if (i < from) + continue; + else if (i > to) + break; + tc_act = mlx5e_tc_act_get(act->id, ns_type); if (!tc_act || !tc_act->post_parse) continue; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h index 0e6e1872ac62e2..d6c12d0ea55ba5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/act.h @@ -112,7 +112,7 @@ mlx5e_tc_act_init_parse_state(struct mlx5e_tc_act_parse_state *parse_state, int mlx5e_tc_act_post_parse(struct mlx5e_tc_act_parse_state *parse_state, - struct flow_action *flow_action, + struct flow_action *flow_action, int from, int to, struct mlx5_flow_attr *attr, enum mlx5_flow_namespace_type ns_type); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c index 07c1895a2b2341..7aa926e542d32a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/act_stats.c @@ -25,8 +25,8 @@ struct mlx5e_tc_act_stats { static const struct rhashtable_params act_counters_ht_params = { .head_offset = offsetof(struct mlx5e_tc_act_stats, hash), - .key_offset = 0, - .key_len = offsetof(struct mlx5e_tc_act_stats, counter), + .key_offset = offsetof(struct mlx5e_tc_act_stats, tc_act_cookie), + .key_len = sizeof_field(struct mlx5e_tc_act_stats, tc_act_cookie), .automatic_shrinking = true, }; @@ -169,14 +169,11 @@ mlx5e_tc_act_stats_fill_stats(struct mlx5e_tc_act_stats_handle *handle, { struct rhashtable *ht = &handle->ht; struct mlx5e_tc_act_stats *item; - struct mlx5e_tc_act_stats key; u64 pkts, bytes, lastused; int err = 0; - key.tc_act_cookie = fl_act->cookie; - rcu_read_lock(); - item = rhashtable_lookup(ht, &key, act_counters_ht_params); + item = rhashtable_lookup(ht, &fl_act->cookie, act_counters_ht_params); if (!item) { rcu_read_unlock(); err = -ENOENT; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c index 0290e0dea53903..4e923a2874aefe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc/post_act.c @@ -112,10 +112,8 @@ mlx5e_tc_post_act_add(struct mlx5e_post_act *post_act, struct mlx5_flow_attr *po int err; handle = kzalloc(sizeof(*handle), GFP_KERNEL); - if (!handle) { - kfree(handle); + if (!handle) return ERR_PTR(-ENOMEM); - } post_attr->chain = 0; post_attr->prio = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h index ba2b1f24ff14ad..6cc23af66b5be0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_priv.h @@ -94,13 +94,13 @@ struct mlx5e_tc_flow { * destinations. */ struct encap_flow_item encaps[MLX5_MAX_FLOW_FWD_VPORTS]; - struct mlx5e_tc_flow *peer_flow; struct mlx5e_hairpin_entry *hpe; /* attached hairpin instance */ struct list_head hairpin; /* flows sharing the same hairpin */ - struct list_head peer; /* flows with peer flow */ + struct list_head peer[MLX5_MAX_PORTS]; /* flows with peer flow */ struct list_head unready; /* flows not ready to be offloaded (e.g * due to missing route) */ + struct list_head peer_flows; /* flows on peer */ struct net_device *orig_dev; /* netdev adding flow first */ int tmp_entry_index; struct list_head tmp_list; /* temporary flow list used by neigh update */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c index 20c2d2ecaf9356..f0c3464f037f4a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c @@ -492,6 +492,19 @@ void mlx5e_encap_put(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) mlx5e_encap_dealloc(priv, e); } +static void mlx5e_encap_put_locked(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) +{ + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + + lockdep_assert_held(&esw->offloads.encap_tbl_lock); + + if (!refcount_dec_and_test(&e->refcnt)) + return; + list_del(&e->route_list); + hash_del_rcu(&e->encap_hlist); + mlx5e_encap_dealloc(priv, e); +} + static void mlx5e_decap_put(struct mlx5e_priv *priv, struct mlx5e_decap_entry *d) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; @@ -816,6 +829,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, uintptr_t hash_key; int err = 0; + lockdep_assert_held(&esw->offloads.encap_tbl_lock); + parse_attr = attr->parse_attr; tun_info = parse_attr->tun_info[out_index]; mpls_info = &parse_attr->mpls_info[out_index]; @@ -829,7 +844,6 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, hash_key = hash_encap_info(&key); - mutex_lock(&esw->offloads.encap_tbl_lock); e = mlx5e_encap_get(priv, &key, hash_key); /* must verify if encap is valid or not */ @@ -840,15 +854,6 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, goto out_err; } - mutex_unlock(&esw->offloads.encap_tbl_lock); - wait_for_completion(&e->res_ready); - - /* Protect against concurrent neigh update. */ - mutex_lock(&esw->offloads.encap_tbl_lock); - if (e->compl_result < 0) { - err = -EREMOTEIO; - goto out_err; - } goto attach_flow; } @@ -877,15 +882,12 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, INIT_LIST_HEAD(&e->flows); hash_add_rcu(esw->offloads.encap_tbl, &e->encap_hlist, hash_key); tbl_time_before = mlx5e_route_tbl_get_last_update(priv); - mutex_unlock(&esw->offloads.encap_tbl_lock); if (family == AF_INET) err = mlx5e_tc_tun_create_header_ipv4(priv, mirred_dev, e); else if (family == AF_INET6) err = mlx5e_tc_tun_create_header_ipv6(priv, mirred_dev, e); - /* Protect against concurrent neigh update. */ - mutex_lock(&esw->offloads.encap_tbl_lock); complete_all(&e->res_ready); if (err) { e->compl_result = err; @@ -920,18 +922,15 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, } else { flow_flag_set(flow, SLOW); } - mutex_unlock(&esw->offloads.encap_tbl_lock); return err; out_err: - mutex_unlock(&esw->offloads.encap_tbl_lock); if (e) - mlx5e_encap_put(priv, e); + mlx5e_encap_put_locked(priv, e); return err; out_err_init: - mutex_unlock(&esw->offloads.encap_tbl_lock); kfree(tun_info); kfree(e); return err; @@ -1016,6 +1015,93 @@ int mlx5e_attach_decap(struct mlx5e_priv *priv, return err; } +int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow, + struct mlx5_flow_attr *attr, + struct netlink_ext_ack *extack, + bool *vf_tun) +{ + struct mlx5e_tc_flow_parse_attr *parse_attr; + struct mlx5_esw_flow_attr *esw_attr; + struct net_device *encap_dev = NULL; + struct mlx5e_rep_priv *rpriv; + struct mlx5e_priv *out_priv; + struct mlx5_eswitch *esw; + int out_index; + int err = 0; + + if (!mlx5e_is_eswitch_flow(flow)) + return 0; + + parse_attr = attr->parse_attr; + esw_attr = attr->esw_attr; + *vf_tun = false; + + esw = priv->mdev->priv.eswitch; + mutex_lock(&esw->offloads.encap_tbl_lock); + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { + struct net_device *out_dev; + int mirred_ifindex; + + if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) + continue; + + mirred_ifindex = parse_attr->mirred_ifindex[out_index]; + out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex); + if (!out_dev) { + NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found"); + err = -ENODEV; + goto out; + } + err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index, + extack, &encap_dev); + dev_put(out_dev); + if (err) + goto out; + + if (esw_attr->dests[out_index].flags & + MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE && + !esw_attr->dest_int_port) + *vf_tun = true; + + out_priv = netdev_priv(encap_dev); + rpriv = out_priv->ppriv; + esw_attr->dests[out_index].rep = rpriv->rep; + esw_attr->dests[out_index].mdev = out_priv->mdev; + } + + if (*vf_tun && esw_attr->out_count > 1) { + NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported"); + err = -EOPNOTSUPP; + goto out; + } + +out: + mutex_unlock(&esw->offloads.encap_tbl_lock); + return err; +} + +void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow, + struct mlx5_flow_attr *attr) +{ + struct mlx5_esw_flow_attr *esw_attr; + int out_index; + + if (!mlx5e_is_eswitch_flow(flow)) + return; + + esw_attr = attr->esw_attr; + + for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { + if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) + continue; + + mlx5e_detach_encap(flow->priv, flow, attr, out_index); + kfree(attr->parse_attr->tun_info[out_index]); + } +} + static int cmp_route_info(struct mlx5e_route_key *a, struct mlx5e_route_key *b) { @@ -1369,11 +1455,13 @@ static void mlx5e_invalidate_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow; list_for_each_entry(flow, encap_flows, tmp_list) { - struct mlx5_flow_attr *attr = flow->attr; struct mlx5_esw_flow_attr *esw_attr; + struct mlx5_flow_attr *attr; if (!mlx5e_is_offloaded_flow(flow)) continue; + + attr = mlx5e_tc_get_encap_attr(flow); esw_attr = attr->esw_attr; if (flow_flag_test(flow, SLOW)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.h index 8ad273dde40ee5..5d7d67687cbcd2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.h @@ -30,6 +30,15 @@ int mlx5e_attach_decap_route(struct mlx5e_priv *priv, void mlx5e_detach_decap_route(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow); +int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow, + struct mlx5_flow_attr *attr, + struct netlink_ext_ack *extack, + bool *vf_tun); +void mlx5e_tc_tun_encap_dests_unset(struct mlx5e_priv *priv, + struct mlx5e_tc_flow *flow, + struct mlx5_flow_attr *attr); + struct ip_tunnel_info *mlx5e_dup_tun_info(const struct ip_tunnel_info *tun_info); int mlx5e_tc_set_attr_rx_tun(struct mlx5e_tc_flow *flow, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index 47381e949f1f5f..879d698b611930 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -193,6 +193,8 @@ static inline u16 mlx5e_txqsq_get_next_pi(struct mlx5e_txqsq *sq, u16 size) return pi; } +void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq); + static inline u16 mlx5e_shampo_get_cqe_header_index(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) { return be16_to_cpu(cqe->shampo.header_entry_index) & (rq->mpwqe.shampo->hd_per_wq - 1); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c index f0e6095809faf1..1bd91bc09eb8a5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c @@ -35,6 +35,7 @@ #include "en/xdp.h" #include "en/params.h" #include +#include int mlx5e_xdp_max_mtu(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c index 1f90594499c609..41c396e7645794 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_common.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_common.c @@ -150,10 +150,8 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb, inlen = MLX5_ST_SZ_BYTES(modify_tir_in); in = kvzalloc(inlen, GFP_KERNEL); - if (!in) { - err = -ENOMEM; - goto out; - } + if (!in) + return -ENOMEM; if (enable_uc_lb) lb_flags = MLX5_TIRC_SELF_LB_BLOCK_BLOCK_UNICAST; @@ -171,14 +169,13 @@ int mlx5e_refresh_tirs(struct mlx5e_priv *priv, bool enable_uc_lb, tirn = tir->tirn; err = mlx5_core_modify_tir(mdev, tirn, in); if (err) - goto out; + break; } + mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock); -out: kvfree(in); if (err) netdev_err(priv->netdev, "refresh tir(0x%x) failed, %d\n", tirn, err); - mutex_unlock(&mdev->mlx5e_res.hw_objs.td.list_lock); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index 89de92d0648363..ebee52a8361aa7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -926,9 +926,10 @@ static int mlx5e_dcbnl_getbuffer(struct net_device *dev, if (err) return err; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) dcb_buffer->buffer_size[i] = port_buffer.buffer[i].size; - dcb_buffer->total_size = port_buffer.port_buffer_size; + dcb_buffer->total_size = port_buffer.port_buffer_size - + port_buffer.internal_buffers_size; return 0; } @@ -970,7 +971,7 @@ static int mlx5e_dcbnl_setbuffer(struct net_device *dev, if (err) return err; - for (i = 0; i < MLX5E_MAX_BUFFER; i++) { + for (i = 0; i < MLX5E_MAX_NETWORK_BUFFER; i++) { if (port_buffer.buffer[i].size != dcb_buffer->buffer_size[i]) { changed |= MLX5E_PORT_BUFFER_SIZE; buffer_size = dcb_buffer->buffer_size; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index 33bfe4d7338be9..934b0d5ce1b3f5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -283,7 +283,7 @@ static int __mlx5e_add_vlan_rule(struct mlx5e_flow_steering *fs, if (IS_ERR(*rule_p)) { err = PTR_ERR(*rule_p); *rule_p = NULL; - fs_err(fs, "%s: add rule failed\n", __func__); + fs_err(fs, "add rule failed\n"); } return err; @@ -395,8 +395,7 @@ int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num if (IS_ERR(rule)) { err = PTR_ERR(rule); fs->vlan->trap_rule = NULL; - fs_err(fs, "%s: add VLAN trap rule failed, err %d\n", - __func__, err); + fs_err(fs, "add VLAN trap rule failed, err %d\n", err); return err; } fs->vlan->trap_rule = rule; @@ -421,8 +420,7 @@ int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num) if (IS_ERR(rule)) { err = PTR_ERR(rule); fs->l2.trap_rule = NULL; - fs_err(fs, "%s: add MAC trap rule failed, err %d\n", - __func__, err); + fs_err(fs, "add MAC trap rule failed, err %d\n", err); return err; } fs->l2.trap_rule = rule; @@ -763,7 +761,7 @@ static int mlx5e_add_promisc_rule(struct mlx5e_flow_steering *fs) if (IS_ERR(*rule_p)) { err = PTR_ERR(*rule_p); *rule_p = NULL; - fs_err(fs, "%s: add promiscuous rule failed\n", __func__); + fs_err(fs, "add promiscuous rule failed\n"); } kvfree(spec); return err; @@ -995,7 +993,7 @@ static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs, ai->rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1); if (IS_ERR(ai->rule)) { - fs_err(fs, "%s: add l2 rule(mac:%pM) failed\n", __func__, mv_dmac); + fs_err(fs, "add l2 rule(mac:%pM) failed\n", mv_dmac); err = PTR_ERR(ai->rule); ai->rule = NULL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 2944691f06adde..79f2f5e51ae034 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -727,26 +727,6 @@ static void mlx5e_rq_free_shampo(struct mlx5e_rq *rq) mlx5e_rq_shampo_hd_free(rq); } -static __be32 mlx5e_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev) -{ - u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {}; - u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {}; - int res; - - if (!MLX5_CAP_GEN(dev, terminate_scatter_list_mkey)) - return MLX5_TERMINATE_SCATTER_LIST_LKEY; - - MLX5_SET(query_special_contexts_in, in, opcode, - MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS); - res = mlx5_cmd_exec_inout(dev, query_special_contexts, in, out); - if (res) - return MLX5_TERMINATE_SCATTER_LIST_LKEY; - - res = MLX5_GET(query_special_contexts_out, out, - terminate_scatter_list_mkey); - return cpu_to_be32(res); -} - static int mlx5e_alloc_rq(struct mlx5e_params *params, struct mlx5e_xsk_param *xsk, struct mlx5e_rq_param *rqp, @@ -852,8 +832,18 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params, /* Create a page_pool and register it with rxq */ struct page_pool_params pp_params = { 0 }; + /* Return error here to avoid writing to page->pp_frag_count in + * mlx5e_page_release_fragmented() for page->pp_frag_count is + * not usable for arch with PAGE_POOL_DMA_USE_PP_FRAG_COUNT + * being true. + */ + if (PAGE_POOL_DMA_USE_PP_FRAG_COUNT) { + err = -EINVAL; + goto err_free_by_rq_type; + } + pp_params.order = 0; - pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV | PP_FLAG_PAGE_FRAG; + pp_params.flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV; pp_params.pool_size = pool_size; pp_params.nid = node; pp_params.dev = rq->pdev; @@ -908,7 +898,7 @@ static int mlx5e_alloc_rq(struct mlx5e_params *params, /* check if num_frags is not a pow of two */ if (rq->wqe.info.num_frags < (1 << rq->wqe.info.log_num_frags)) { wqe->data[f].byte_count = 0; - wqe->data[f].lkey = mlx5e_get_terminate_scatter_list_mkey(mdev); + wqe->data[f].lkey = params->terminate_lkey_be; wqe->data[f].addr = 0; } } @@ -5007,6 +4997,8 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16 /* RQ */ mlx5e_build_rq_params(mdev, params); + params->terminate_lkey_be = mlx5_core_get_terminate_scatter_list_mkey(mdev); + params->packet_merge.timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT); /* CQ moderation params */ @@ -5279,12 +5271,16 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, mlx5e_timestamp_init(priv); + priv->dfs_root = debugfs_create_dir("nic", + mlx5_debugfs_get_dev_root(mdev)); + fs = mlx5e_fs_init(priv->profile, mdev, !test_bit(MLX5E_STATE_DESTROYING, &priv->state), priv->dfs_root); if (!fs) { err = -ENOMEM; mlx5_core_err(mdev, "FS initialization failed, %d\n", err); + debugfs_remove_recursive(priv->dfs_root); return err; } priv->fs = fs; @@ -5305,6 +5301,7 @@ static void mlx5e_nic_cleanup(struct mlx5e_priv *priv) mlx5e_health_destroy_reporters(priv); mlx5e_ktls_cleanup(priv); mlx5e_fs_cleanup(priv->fs); + debugfs_remove_recursive(priv->dfs_root); priv->fs = NULL; } @@ -5851,8 +5848,8 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv) } static int -mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mdev, - const struct mlx5e_profile *new_profile, void *new_ppriv) +mlx5e_netdev_init_profile(struct net_device *netdev, struct mlx5_core_dev *mdev, + const struct mlx5e_profile *new_profile, void *new_ppriv) { struct mlx5e_priv *priv = netdev_priv(netdev); int err; @@ -5868,6 +5865,25 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde err = new_profile->init(priv->mdev, priv->netdev); if (err) goto priv_cleanup; + + return 0; + +priv_cleanup: + mlx5e_priv_cleanup(priv); + return err; +} + +static int +mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mdev, + const struct mlx5e_profile *new_profile, void *new_ppriv) +{ + struct mlx5e_priv *priv = netdev_priv(netdev); + int err; + + err = mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv); + if (err) + return err; + err = mlx5e_attach_netdev(priv); if (err) goto profile_cleanup; @@ -5875,7 +5891,6 @@ mlx5e_netdev_attach_profile(struct net_device *netdev, struct mlx5_core_dev *mde profile_cleanup: new_profile->cleanup(priv); -priv_cleanup: mlx5e_priv_cleanup(priv); return err; } @@ -5894,6 +5909,12 @@ int mlx5e_netdev_change_profile(struct mlx5e_priv *priv, priv->profile->cleanup(priv); mlx5e_priv_cleanup(priv); + if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR) { + mlx5e_netdev_init_profile(netdev, mdev, new_profile, new_ppriv); + set_bit(MLX5E_STATE_DESTROYING, &priv->state); + return -EIO; + } + err = mlx5e_netdev_attach_profile(netdev, mdev, new_profile, new_ppriv); if (err) { /* roll back to original profile */ netdev_warn(netdev, "%s: new profile init failed, %d\n", __func__, err); @@ -5955,8 +5976,11 @@ static int mlx5e_suspend(struct auxiliary_device *adev, pm_message_t state) struct net_device *netdev = priv->netdev; struct mlx5_core_dev *mdev = priv->mdev; - if (!netif_device_present(netdev)) + if (!netif_device_present(netdev)) { + if (test_bit(MLX5E_STATE_DESTROYING, &priv->state)) + mlx5e_destroy_mdev_resources(mdev); return -ENODEV; + } mlx5e_detach_netdev(priv); mlx5e_destroy_mdev_resources(mdev); @@ -6002,9 +6026,6 @@ static int mlx5e_probe(struct auxiliary_device *adev, priv->profile = profile; priv->ppriv = NULL; - priv->dfs_root = debugfs_create_dir("nic", - mlx5_debugfs_get_dev_root(priv->mdev)); - err = profile->init(mdev, netdev); if (err) { mlx5_core_err(mdev, "mlx5e_nic_profile init failed, %d\n", err); @@ -6033,7 +6054,6 @@ static int mlx5e_probe(struct auxiliary_device *adev, err_profile_cleanup: profile->cleanup(priv); err_destroy_netdev: - debugfs_remove_recursive(priv->dfs_root); mlx5e_destroy_netdev(priv); err_devlink_port_unregister: mlx5e_devlink_port_unregister(mlx5e_dev); @@ -6053,7 +6073,6 @@ static void mlx5e_remove(struct auxiliary_device *adev) unregister_netdev(priv->netdev); mlx5e_suspend(adev, state); priv->profile->cleanup(priv); - debugfs_remove_recursive(priv->dfs_root); mlx5e_destroy_netdev(priv); mlx5e_devlink_port_unregister(mlx5e_dev); mlx5e_destroy_devlink(mlx5e_dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 1fc386eccaf8f9..965a8261c99b7f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -30,6 +30,7 @@ * SOFTWARE. */ +#include #include #include #include @@ -373,7 +374,9 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep) { struct mlx5e_rep_sq *rep_sq, *tmp; + struct mlx5e_rep_sq_peer *sq_peer; struct mlx5e_rep_priv *rpriv; + unsigned long i; if (esw->mode != MLX5_ESWITCH_OFFLOADS) return; @@ -381,31 +384,78 @@ static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw, rpriv = mlx5e_rep_to_rep_priv(rep); list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) { mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); - if (rep_sq->send_to_vport_rule_peer) - mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); + xa_for_each(&rep_sq->sq_peer, i, sq_peer) { + if (sq_peer->rule) + mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule); + + xa_erase(&rep_sq->sq_peer, i); + kfree(sq_peer); + } + + xa_destroy(&rep_sq->sq_peer); list_del(&rep_sq->list); kfree(rep_sq); } } +static int mlx5e_sqs2vport_add_peers_rules(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, + struct mlx5_devcom *devcom, + struct mlx5e_rep_sq *rep_sq, int i) +{ + struct mlx5_eswitch *peer_esw = NULL; + struct mlx5_flow_handle *flow_rule; + int tmp; + + mlx5_devcom_for_each_peer_entry(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + peer_esw, tmp) { + int peer_rule_idx = mlx5_get_dev_index(peer_esw->dev); + struct mlx5e_rep_sq_peer *sq_peer; + int err; + + sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL); + if (!sq_peer) + return -ENOMEM; + + flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, + rep, rep_sq->sqn); + if (IS_ERR(flow_rule)) { + kfree(sq_peer); + return PTR_ERR(flow_rule); + } + + sq_peer->rule = flow_rule; + sq_peer->peer = peer_esw; + err = xa_insert(&rep_sq->sq_peer, peer_rule_idx, sq_peer, GFP_KERNEL); + if (err) { + kfree(sq_peer); + mlx5_eswitch_del_send_to_vport_rule(flow_rule); + return err; + } + } + + return 0; +} + static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, u32 *sqns_array, int sqns_num) { - struct mlx5_eswitch *peer_esw = NULL; struct mlx5_flow_handle *flow_rule; struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; + struct mlx5_devcom *devcom; + bool devcom_locked = false; int err; int i; if (esw->mode != MLX5_ESWITCH_OFFLOADS) return 0; + devcom = esw->dev->priv.devcom; rpriv = mlx5e_rep_to_rep_priv(rep); - if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS)) - peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS); + if (mlx5_devcom_comp_is_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS) && + mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + devcom_locked = true; for (i = 0; i < sqns_num; i++) { rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL); @@ -425,31 +475,30 @@ static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw, rep_sq->send_to_vport_rule = flow_rule; rep_sq->sqn = sqns_array[i]; - if (peer_esw) { - flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, - rep, sqns_array[i]); - if (IS_ERR(flow_rule)) { - err = PTR_ERR(flow_rule); + xa_init(&rep_sq->sq_peer); + if (devcom_locked) { + err = mlx5e_sqs2vport_add_peers_rules(esw, rep, devcom, rep_sq, i); + if (err) { mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule); + xa_destroy(&rep_sq->sq_peer); kfree(rep_sq); goto out_err; } - rep_sq->send_to_vport_rule_peer = flow_rule; } list_add(&rep_sq->list, &rpriv->vport_sqs_list); } - if (peer_esw) - mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); + if (devcom_locked) + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return 0; out_err: mlx5e_sqs2vport_stop(esw, rep); - if (peer_esw) - mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS); + if (devcom_locked) + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return err; } @@ -812,11 +861,15 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev, { struct mlx5e_priv *priv = netdev_priv(netdev); + priv->dfs_root = debugfs_create_dir("nic", + mlx5_debugfs_get_dev_root(mdev)); + priv->fs = mlx5e_fs_init(priv->profile, mdev, !test_bit(MLX5E_STATE_DESTROYING, &priv->state), priv->dfs_root); if (!priv->fs) { netdev_err(priv->netdev, "FS allocation failed\n"); + debugfs_remove_recursive(priv->dfs_root); return -ENOMEM; } @@ -829,6 +882,7 @@ static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev, static void mlx5e_cleanup_rep(struct mlx5e_priv *priv) { mlx5e_fs_cleanup(priv->fs); + debugfs_remove_recursive(priv->dfs_root); priv->fs = NULL; } @@ -1524,17 +1578,24 @@ static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep) return rpriv->netdev; } -static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep) +static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep, + struct mlx5_eswitch *peer_esw) { + int i = mlx5_get_dev_index(peer_esw->dev); struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; + WARN_ON_ONCE(!peer_esw); rpriv = mlx5e_rep_to_rep_priv(rep); list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { - if (!rep_sq->send_to_vport_rule_peer) + struct mlx5e_rep_sq_peer *sq_peer = xa_load(&rep_sq->sq_peer, i); + + if (!sq_peer || sq_peer->peer != peer_esw) continue; - mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer); - rep_sq->send_to_vport_rule_peer = NULL; + + mlx5_eswitch_del_send_to_vport_rule(sq_peer->rule); + xa_erase(&rep_sq->sq_peer, i); + kfree(sq_peer); } } @@ -1542,24 +1603,52 @@ static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep, struct mlx5_eswitch *peer_esw) { + int i = mlx5_get_dev_index(peer_esw->dev); struct mlx5_flow_handle *flow_rule; + struct mlx5e_rep_sq_peer *sq_peer; struct mlx5e_rep_priv *rpriv; struct mlx5e_rep_sq *rep_sq; + int err; rpriv = mlx5e_rep_to_rep_priv(rep); list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) { - if (rep_sq->send_to_vport_rule_peer) + sq_peer = xa_load(&rep_sq->sq_peer, i); + + if (sq_peer && sq_peer->peer) continue; - flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn); - if (IS_ERR(flow_rule)) + + flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, + rep_sq->sqn); + if (IS_ERR(flow_rule)) { + err = PTR_ERR(flow_rule); goto err_out; - rep_sq->send_to_vport_rule_peer = flow_rule; + } + + if (sq_peer) { + sq_peer->rule = flow_rule; + sq_peer->peer = peer_esw; + continue; + } + sq_peer = kzalloc(sizeof(*sq_peer), GFP_KERNEL); + if (!sq_peer) { + err = -ENOMEM; + goto err_sq_alloc; + } + err = xa_insert(&rep_sq->sq_peer, i, sq_peer, GFP_KERNEL); + if (err) + goto err_xa; + sq_peer->rule = flow_rule; + sq_peer->peer = peer_esw; } return 0; +err_xa: + kfree(sq_peer); +err_sq_alloc: + mlx5_eswitch_del_send_to_vport_rule(flow_rule); err_out: - mlx5e_vport_rep_event_unpair(rep); - return PTR_ERR(flow_rule); + mlx5e_vport_rep_event_unpair(rep, peer_esw); + return err; } static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw, @@ -1572,7 +1661,7 @@ static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw, if (event == MLX5_SWITCHDEV_EVENT_PAIR) err = mlx5e_vport_rep_event_pair(esw, rep, data); else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR) - mlx5e_vport_rep_event_unpair(rep); + mlx5e_vport_rep_event_unpair(rep, data); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index 80b7f5079a5a54..70640fa1ad7bc0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -225,9 +225,14 @@ struct mlx5e_encap_entry { struct rcu_head rcu; }; +struct mlx5e_rep_sq_peer { + struct mlx5_flow_handle *rule; + void *peer; +}; + struct mlx5e_rep_sq { struct mlx5_flow_handle *send_to_vport_rule; - struct mlx5_flow_handle *send_to_vport_rule_peer; + struct xarray sq_peer; u32 sqn; struct list_head list; }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 728b82ce4031a2..88631fb9f96629 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1665,11 +1665,12 @@ bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *route_dev, u16 *vport) { struct mlx5e_priv *out_priv, *route_priv; - struct mlx5_devcom *devcom = NULL; struct mlx5_core_dev *route_mdev; + struct mlx5_devcom *devcom; struct mlx5_eswitch *esw; u16 vhca_id; int err; + int i; out_priv = netdev_priv(out_dev); esw = out_priv->mdev->priv.eswitch; @@ -1677,112 +1678,27 @@ int mlx5e_tc_query_route_vport(struct net_device *out_dev, struct net_device *ro route_mdev = route_priv->mdev; vhca_id = MLX5_CAP_GEN(route_mdev, vhca_id); - if (mlx5_lag_is_active(out_priv->mdev)) { - /* In lag case we may get devices from different eswitch instances. - * If we failed to get vport num, it means, mostly, that we on the wrong - * eswitch. - */ - err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); - if (err != -ENOENT) - return err; - - devcom = out_priv->mdev->priv.devcom; - esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!esw) - return -ENODEV; - } - err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); - if (devcom) - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - return err; -} - -static int -set_encap_dests(struct mlx5e_priv *priv, - struct mlx5e_tc_flow *flow, - struct mlx5_flow_attr *attr, - struct netlink_ext_ack *extack, - bool *vf_tun) -{ - struct mlx5e_tc_flow_parse_attr *parse_attr; - struct mlx5_esw_flow_attr *esw_attr; - struct net_device *encap_dev = NULL; - struct mlx5e_rep_priv *rpriv; - struct mlx5e_priv *out_priv; - int out_index; - int err = 0; - - if (!mlx5e_is_eswitch_flow(flow)) - return 0; - - parse_attr = attr->parse_attr; - esw_attr = attr->esw_attr; - *vf_tun = false; - - for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { - struct net_device *out_dev; - int mirred_ifindex; - - if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) - continue; - - mirred_ifindex = parse_attr->mirred_ifindex[out_index]; - out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex); - if (!out_dev) { - NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found"); - err = -ENODEV; - goto out; - } - err = mlx5e_attach_encap(priv, flow, attr, out_dev, out_index, - extack, &encap_dev); - dev_put(out_dev); - if (err) - goto out; - - if (esw_attr->dests[out_index].flags & - MLX5_ESW_DEST_CHAIN_WITH_SRC_PORT_CHANGE && - !esw_attr->dest_int_port) - *vf_tun = true; + if (!err) + return err; - out_priv = netdev_priv(encap_dev); - rpriv = out_priv->ppriv; - esw_attr->dests[out_index].rep = rpriv->rep; - esw_attr->dests[out_index].mdev = out_priv->mdev; - } + if (!mlx5_lag_is_active(out_priv->mdev)) + return err; - if (*vf_tun && esw_attr->out_count > 1) { - NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported"); - err = -EOPNOTSUPP; - goto out; + rcu_read_lock(); + devcom = out_priv->mdev->priv.devcom; + err = -ENODEV; + mlx5_devcom_for_each_peer_entry_rcu(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + esw, i) { + err = mlx5_eswitch_vhca_id_to_vport(esw, vhca_id, vport); + if (!err) + break; } + rcu_read_unlock(); -out: return err; } -static void -clean_encap_dests(struct mlx5e_priv *priv, - struct mlx5e_tc_flow *flow, - struct mlx5_flow_attr *attr) -{ - struct mlx5_esw_flow_attr *esw_attr; - int out_index; - - if (!mlx5e_is_eswitch_flow(flow)) - return; - - esw_attr = attr->esw_attr; - - for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) { - if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) - continue; - - mlx5e_detach_encap(priv, flow, attr, out_index); - kfree(attr->parse_attr->tun_info[out_index]); - } -} - static int verify_attr_actions(u32 actions, struct netlink_ext_ack *extack) { @@ -1819,7 +1735,7 @@ post_process_attr(struct mlx5e_tc_flow *flow, if (err) goto err_out; - err = set_encap_dests(flow->priv, flow, attr, extack, &vf_tun); + err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun); if (err) goto err_out; @@ -2070,47 +1986,59 @@ void mlx5e_put_flow_list(struct mlx5e_priv *priv, struct list_head *flow_list) mlx5e_flow_put(priv, flow); } -static void __mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) +static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow, + int peer_index) { struct mlx5_eswitch *esw = flow->priv->mdev->priv.eswitch; + struct mlx5e_tc_flow *peer_flow; + struct mlx5e_tc_flow *tmp; if (!flow_flag_test(flow, ESWITCH) || !flow_flag_test(flow, DUP)) return; mutex_lock(&esw->offloads.peer_mutex); - list_del(&flow->peer); + list_del(&flow->peer[peer_index]); mutex_unlock(&esw->offloads.peer_mutex); - flow_flag_clear(flow, DUP); - - if (refcount_dec_and_test(&flow->peer_flow->refcnt)) { - mlx5e_tc_del_fdb_flow(flow->peer_flow->priv, flow->peer_flow); - kfree(flow->peer_flow); + list_for_each_entry_safe(peer_flow, tmp, &flow->peer_flows, peer_flows) { + if (peer_index != mlx5_get_dev_index(peer_flow->priv->mdev)) + continue; + if (refcount_dec_and_test(&peer_flow->refcnt)) { + mlx5e_tc_del_fdb_flow(peer_flow->priv, peer_flow); + list_del(&peer_flow->peer_flows); + kfree(peer_flow); + } } - flow->peer_flow = NULL; + if (list_empty(&flow->peer_flows)) + flow_flag_clear(flow, DUP); } -static void mlx5e_tc_del_fdb_peer_flow(struct mlx5e_tc_flow *flow) +static void mlx5e_tc_del_fdb_peers_flow(struct mlx5e_tc_flow *flow) { - struct mlx5_core_dev *dev = flow->priv->mdev; - struct mlx5_devcom *devcom = dev->priv.devcom; - struct mlx5_eswitch *peer_esw; - - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) - return; + int i; - __mlx5e_tc_del_fdb_peer_flow(flow); - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + for (i = 0; i < MLX5_MAX_PORTS; i++) { + if (i == mlx5_get_dev_index(flow->priv->mdev)) + continue; + mlx5e_tc_del_fdb_peer_flow(flow, i); + } } static void mlx5e_tc_del_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow) { if (mlx5e_is_eswitch_flow(flow)) { - mlx5e_tc_del_fdb_peer_flow(flow); + struct mlx5_devcom *devcom = flow->priv->mdev->priv.devcom; + + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { + mlx5e_tc_del_fdb_flow(priv, flow); + return; + } + + mlx5e_tc_del_fdb_peers_flow(flow); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); mlx5e_tc_del_fdb_flow(priv, flow); } else { mlx5e_tc_del_nic_flow(priv, flow); @@ -2586,6 +2514,12 @@ static int mlx5e_flower_parse_meta(struct net_device *filter_dev, return 0; flow_rule_match_meta(rule, &match); + + if (match.mask->l2_miss) { + NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on \"l2_miss\""); + return -EOPNOTSUPP; + } + if (!match.mask->ingress_ifindex) return 0; @@ -3943,8 +3877,8 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state, struct mlx5_flow_attr *prev_attr; struct flow_action_entry *act; struct mlx5e_tc_act *tc_act; + int err, i, i_split = 0; bool is_missable; - int err, i; ns_type = mlx5e_get_flow_namespace(flow); list_add(&attr->list, &flow->attrs); @@ -3985,7 +3919,8 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state, i < flow_action->num_entries - 1)) { is_missable = tc_act->is_missable ? tc_act->is_missable(act) : false; - err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type); + err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr, + ns_type); if (err) goto out_free_post_acts; @@ -3995,6 +3930,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state, goto out_free_post_acts; } + i_split = i + 1; list_add(&attr->list, &flow->attrs); } @@ -4009,7 +3945,7 @@ parse_tc_actions(struct mlx5e_tc_act_parse_state *parse_state, } } - err = mlx5e_tc_act_post_parse(parse_state, flow_action, attr, ns_type); + err = mlx5e_tc_act_post_parse(parse_state, flow_action, i_split, i, attr, ns_type); if (err) goto out_free_post_acts; @@ -4279,8 +4215,8 @@ static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow) flow_flag_test(flow, INGRESS); bool act_is_encap = !!(attr->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT); - bool esw_paired = mlx5_devcom_is_paired(esw_attr->in_mdev->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS); + bool esw_paired = mlx5_devcom_comp_is_ready(esw_attr->in_mdev->priv.devcom, + MLX5_DEVCOM_ESW_OFFLOADS); if (!esw_paired) return false; @@ -4323,7 +4259,7 @@ mlx5_free_flow_attr_actions(struct mlx5e_tc_flow *flow, struct mlx5_flow_attr *a if (attr->post_act_handle) mlx5e_tc_post_act_del(get_post_action(flow->priv), attr->post_act_handle); - clean_encap_dests(flow->priv, flow, attr); + mlx5e_tc_tun_encap_dests_unset(flow->priv, flow, attr); if (attr->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) mlx5_fc_destroy(counter_dev, attr->counter); @@ -4371,6 +4307,7 @@ mlx5e_alloc_flow(struct mlx5e_priv *priv, int attr_size, INIT_LIST_HEAD(&flow->hairpin); INIT_LIST_HEAD(&flow->l3_to_l2_reformat); INIT_LIST_HEAD(&flow->attrs); + INIT_LIST_HEAD(&flow->peer_flows); refcount_set(&flow->refcnt, 1); init_completion(&flow->init_done); init_completion(&flow->del_hw_done); @@ -4479,22 +4416,19 @@ __mlx5e_add_fdb_flow(struct mlx5e_priv *priv, static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, struct mlx5e_tc_flow *flow, - unsigned long flow_flags) + unsigned long flow_flags, + struct mlx5_eswitch *peer_esw) { struct mlx5e_priv *priv = flow->priv, *peer_priv; - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch, *peer_esw; + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr *attr = flow->attr->esw_attr; - struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct mlx5e_tc_flow_parse_attr *parse_attr; + int i = mlx5_get_dev_index(peer_esw->dev); struct mlx5e_rep_priv *peer_urpriv; struct mlx5e_tc_flow *peer_flow; struct mlx5_core_dev *in_mdev; int err = 0; - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) - return -ENODEV; - peer_urpriv = mlx5_eswitch_get_uplink_priv(peer_esw, REP_ETH); peer_priv = netdev_priv(peer_urpriv->netdev); @@ -4519,14 +4453,13 @@ static int mlx5e_tc_add_fdb_peer_flow(struct flow_cls_offload *f, goto out; } - flow->peer_flow = peer_flow; + list_add_tail(&peer_flow->peer_flows, &flow->peer_flows); flow_flag_set(flow, DUP); mutex_lock(&esw->offloads.peer_mutex); - list_add_tail(&flow->peer, &esw->offloads.peer_flows); + list_add_tail(&flow->peer[i], &esw->offloads.peer_flows[i]); mutex_unlock(&esw->offloads.peer_mutex); out: - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return err; } @@ -4537,30 +4470,48 @@ mlx5e_add_fdb_flow(struct mlx5e_priv *priv, struct net_device *filter_dev, struct mlx5e_tc_flow **__flow) { + struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct mlx5e_rep_priv *rpriv = priv->ppriv; struct mlx5_eswitch_rep *in_rep = rpriv->rep; struct mlx5_core_dev *in_mdev = priv->mdev; + struct mlx5_eswitch *peer_esw; struct mlx5e_tc_flow *flow; int err; + int i; flow = __mlx5e_add_fdb_flow(priv, f, flow_flags, filter_dev, in_rep, in_mdev); if (IS_ERR(flow)) return PTR_ERR(flow); - if (is_peer_flow_needed(flow)) { - err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags); - if (err) { - mlx5e_tc_del_fdb_flow(priv, flow); - goto out; - } + if (!is_peer_flow_needed(flow)) { + *__flow = flow; + return 0; } - *__flow = flow; + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) { + err = -ENODEV; + goto clean_flow; + } + mlx5_devcom_for_each_peer_entry(devcom, + MLX5_DEVCOM_ESW_OFFLOADS, + peer_esw, i) { + err = mlx5e_tc_add_fdb_peer_flow(f, flow, flow_flags, peer_esw); + if (err) + goto peer_clean; + } + + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + + *__flow = flow; return 0; -out: +peer_clean: + mlx5e_tc_del_fdb_peers_flow(flow); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); +clean_flow: + mlx5e_tc_del_fdb_flow(priv, flow); return err; } @@ -4778,7 +4729,6 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, { struct mlx5_devcom *devcom = priv->mdev->priv.devcom; struct rhashtable *tc_ht = get_tc_ht(priv, flags); - struct mlx5_eswitch *peer_esw; struct mlx5e_tc_flow *flow; struct mlx5_fc *counter; u64 lastuse = 0; @@ -4813,23 +4763,29 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, /* Under multipath it's possible for one rule to be currently * un-offloaded while the other rule is offloaded. */ - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) goto out; - if (flow_flag_test(flow, DUP) && - flow_flag_test(flow->peer_flow, OFFLOADED)) { - u64 bytes2; - u64 packets2; - u64 lastuse2; + if (flow_flag_test(flow, DUP)) { + struct mlx5e_tc_flow *peer_flow; - if (flow_flag_test(flow, USE_ACT_STATS)) { - f->use_act_stats = true; - } else { - counter = mlx5e_tc_get_counter(flow->peer_flow); + list_for_each_entry(peer_flow, &flow->peer_flows, peer_flows) { + u64 packets2; + u64 lastuse2; + u64 bytes2; + + if (!flow_flag_test(peer_flow, OFFLOADED)) + continue; + if (flow_flag_test(flow, USE_ACT_STATS)) { + f->use_act_stats = true; + break; + } + + counter = mlx5e_tc_get_counter(peer_flow); if (!counter) goto no_peer_counter; - mlx5_fc_query_cached(counter, &bytes2, &packets2, &lastuse2); + mlx5_fc_query_cached(counter, &bytes2, &packets2, + &lastuse2); bytes += bytes2; packets += packets2; @@ -4838,7 +4794,7 @@ int mlx5e_stats_flower(struct net_device *dev, struct mlx5e_priv *priv, } no_peer_counter: - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); out: flow_stats_update(&f->stats, bytes, packets, 0, lastuse, FLOW_ACTION_HW_STATS_DELAYED); @@ -5301,6 +5257,8 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv) goto err_action_counter; } + mlx5_esw_offloads_devcom_init(esw); + return 0; err_action_counter: @@ -5329,7 +5287,7 @@ void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv) priv = netdev_priv(rpriv->netdev); esw = priv->mdev->priv.eswitch; - mlx5e_tc_clean_fdb_peer_flows(esw); + mlx5_esw_offloads_devcom_cleanup(esw); mlx5e_tc_tun_cleanup(uplink_priv->encap); @@ -5354,9 +5312,14 @@ int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags) void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw) { struct mlx5e_tc_flow *flow, *tmp; + int i; - list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows, peer) - __mlx5e_tc_del_fdb_peer_flow(flow); + for (i = 0; i < MLX5_MAX_PORTS; i++) { + if (i == mlx5_get_dev_index(esw->dev)) + continue; + list_for_each_entry_safe(flow, tmp, &esw->offloads.peer_flows[i], peer[i]) + mlx5e_tc_del_fdb_peers_flow(flow); + } } void mlx5e_tc_reoffload_flows_work(struct work_struct *work) @@ -5643,22 +5606,43 @@ bool mlx5e_tc_update_skb_nic(struct mlx5_cqe64 *cqe, struct sk_buff *skb) 0, NULL); } +static struct mapping_ctx * +mlx5e_get_priv_obj_mapping(struct mlx5e_priv *priv) +{ + struct mlx5e_tc_table *tc; + struct mlx5_eswitch *esw; + struct mapping_ctx *ctx; + + if (is_mdev_switchdev_mode(priv->mdev)) { + esw = priv->mdev->priv.eswitch; + ctx = esw->offloads.reg_c0_obj_pool; + } else { + tc = mlx5e_fs_get_tc(priv->fs); + ctx = tc->mapping; + } + + return ctx; +} + int mlx5e_tc_action_miss_mapping_get(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr, u64 act_miss_cookie, u32 *act_miss_mapping) { - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_mapped_obj mapped_obj = {}; + struct mlx5_eswitch *esw; struct mapping_ctx *ctx; int err; - ctx = esw->offloads.reg_c0_obj_pool; - + ctx = mlx5e_get_priv_obj_mapping(priv); mapped_obj.type = MLX5_MAPPED_OBJ_ACT_MISS; mapped_obj.act_miss_cookie = act_miss_cookie; err = mapping_add(ctx, &mapped_obj, act_miss_mapping); if (err) return err; + if (!is_mdev_switchdev_mode(priv->mdev)) + return 0; + + esw = priv->mdev->priv.eswitch; attr->act_id_restore_rule = esw_add_restore_rule(esw, *act_miss_mapping); if (IS_ERR(attr->act_id_restore_rule)) goto err_rule; @@ -5673,10 +5657,9 @@ int mlx5e_tc_action_miss_mapping_get(struct mlx5e_priv *priv, struct mlx5_flow_a void mlx5e_tc_action_miss_mapping_put(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr, u32 act_miss_mapping) { - struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; - struct mapping_ctx *ctx; + struct mapping_ctx *ctx = mlx5e_get_priv_obj_mapping(priv); - ctx = esw->offloads.reg_c0_obj_pool; - mlx5_del_flow_rules(attr->act_id_restore_rule); + if (is_mdev_switchdev_mode(priv->mdev)) + mlx5_del_flow_rules(attr->act_id_restore_rule); mapping_remove(ctx, act_miss_mapping); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index df5e780e8e6a65..c7eb6b238c2ba1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -762,6 +762,17 @@ static void mlx5e_tx_wi_consume_fifo_skbs(struct mlx5e_txqsq *sq, struct mlx5e_t } } +void mlx5e_txqsq_wake(struct mlx5e_txqsq *sq) +{ + if (netif_tx_queue_stopped(sq->txq) && + mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) && + mlx5e_ptpsq_fifo_has_room(sq) && + !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) { + netif_tx_wake_queue(sq->txq); + sq->stats->wake++; + } +} + bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) { struct mlx5e_sq_stats *stats; @@ -861,13 +872,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget) netdev_tx_completed_queue(sq->txq, npkts, nbytes); - if (netif_tx_queue_stopped(sq->txq) && - mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, sq->stop_room) && - mlx5e_ptpsq_fifo_has_room(sq) && - !test_bit(MLX5E_SQ_STATE_RECOVERING, &sq->state)) { - netif_tx_wake_queue(sq->txq); - stats->wake++; - } + mlx5e_txqsq_wake(sq); return (i == MLX5E_TX_CQ_POLL_BUDGET); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c index a50bfda18e96d9..a7d9b7cb4297fc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_txrx.c @@ -161,20 +161,22 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget) } } + /* budget=0 means we may be in IRQ context, do as little as possible */ + if (unlikely(!budget)) + goto out; + busy |= mlx5e_poll_xdpsq_cq(&c->xdpsq.cq); if (c->xdp) busy |= mlx5e_poll_xdpsq_cq(&c->rq_xdpsq.cq); - if (likely(budget)) { /* budget=0 means: don't poll rx rings */ - if (xsk_open) - work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget); + if (xsk_open) + work_done = mlx5e_poll_rx_cq(&xskrq->cq, budget); - if (likely(budget - work_done)) - work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done); + if (likely(budget - work_done)) + work_done += mlx5e_poll_rx_cq(&rq->cq, budget - work_done); - busy |= work_done == budget; - } + busy |= work_done == budget; mlx5e_poll_ico_cq(&c->icosq.cq); if (mlx5e_poll_ico_cq(&c->async_icosq.cq)) @@ -205,7 +207,7 @@ int mlx5e_napi_poll(struct napi_struct *napi, int budget) } ch_stats->aff_change++; aff_change = true; - if (budget && work_done == budget) + if (work_done == budget) work_done--; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 1c35d721a31d7d..3db4866d7880fc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -824,7 +824,7 @@ static int comp_irqs_request_pci(struct mlx5_core_dev *dev) ncomp_eqs = table->num_comp_eqs; cpus = kcalloc(ncomp_eqs, sizeof(*cpus), GFP_KERNEL); if (!cpus) - ret = -ENOMEM; + return -ENOMEM; i = 0; rcu_read_lock(); @@ -1104,7 +1104,7 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev) struct mlx5_eq_table *table = dev->priv.eq_table; mutex_lock(&table->lock); /* sync with create/destroy_async_eq */ - mlx5_irq_table_destroy(dev); + mlx5_irq_table_free_irqs(dev); mutex_unlock(&table->lock); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c index 2e504c7461c657..24b1ca4e4ff874 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_ofld.c @@ -15,13 +15,27 @@ static void esw_acl_egress_ofld_fwd2vport_destroy(struct mlx5_vport *vport) vport->egress.offloads.fwd_rule = NULL; } -static void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport) +void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index) { - if (!vport->egress.offloads.bounce_rule) + struct mlx5_flow_handle *bounce_rule = + xa_load(&vport->egress.offloads.bounce_rules, rule_index); + + if (!bounce_rule) return; - mlx5_del_flow_rules(vport->egress.offloads.bounce_rule); - vport->egress.offloads.bounce_rule = NULL; + mlx5_del_flow_rules(bounce_rule); + xa_erase(&vport->egress.offloads.bounce_rules, rule_index); +} + +static void esw_acl_egress_ofld_bounce_rules_destroy(struct mlx5_vport *vport) +{ + struct mlx5_flow_handle *bounce_rule; + unsigned long i; + + xa_for_each(&vport->egress.offloads.bounce_rules, i, bounce_rule) { + mlx5_del_flow_rules(bounce_rule); + xa_erase(&vport->egress.offloads.bounce_rules, i); + } } static int esw_acl_egress_ofld_fwd2vport_create(struct mlx5_eswitch *esw, @@ -96,7 +110,7 @@ static void esw_acl_egress_ofld_rules_destroy(struct mlx5_vport *vport) { esw_acl_egress_vlan_destroy(vport); esw_acl_egress_ofld_fwd2vport_destroy(vport); - esw_acl_egress_ofld_bounce_rule_destroy(vport); + esw_acl_egress_ofld_bounce_rules_destroy(vport); } static int esw_acl_egress_ofld_groups_create(struct mlx5_eswitch *esw, @@ -194,6 +208,7 @@ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport vport->egress.acl = NULL; return err; } + vport->egress.type = VPORT_EGRESS_ACL_TYPE_DEFAULT; err = esw_acl_egress_ofld_groups_create(esw, vport); if (err) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c index 45b839116212df..d599e50af346be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c @@ -35,7 +35,8 @@ esw_acl_table_create(struct mlx5_eswitch *esw, struct mlx5_vport *vport, int ns, } ft_attr.max_fte = size; - ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT; + if (vport_num || mlx5_core_is_ecpf(esw->dev)) + ft_attr.flags = MLX5_FLOW_TABLE_OTHER_VPORT; acl = mlx5_create_vport_flow_table(root_ns, &ft_attr, vport_num); if (IS_ERR(acl)) { err = PTR_ERR(acl); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h index c9f8469e9a4740..536b04e8361868 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ofld.h @@ -10,6 +10,7 @@ /* Eswitch acl egress external APIs */ int esw_acl_egress_ofld_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport); void esw_acl_egress_ofld_cleanup(struct mlx5_vport *vport); +void esw_acl_egress_ofld_bounce_rule_destroy(struct mlx5_vport *vport, int rule_index); int mlx5_esw_acl_egress_vport_bond(struct mlx5_eswitch *esw, u16 active_vport_num, u16 passive_vport_num); int mlx5_esw_acl_egress_vport_unbond(struct mlx5_eswitch *esw, u16 vport_num); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c index 1ba03e219111a7..bea7cc6454617b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c @@ -647,22 +647,35 @@ mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr, } static struct mlx5_flow_handle * -mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, const unsigned char *addr, +mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id, + const unsigned char *addr, struct mlx5_esw_bridge_vlan *vlan, u32 counter_id, struct mlx5_esw_bridge *bridge) { struct mlx5_devcom *devcom = bridge->br_offloads->esw->dev->priv.devcom; + struct mlx5_eswitch *tmp, *peer_esw = NULL; static struct mlx5_flow_handle *handle; - struct mlx5_eswitch *peer_esw; + int i; - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) return ERR_PTR(-ENODEV); + mlx5_devcom_for_each_peer_entry(devcom, + MLX5_DEVCOM_ESW_OFFLOADS, + tmp, i) { + if (mlx5_esw_is_owner(tmp, vport_num, esw_owner_vhca_id)) { + peer_esw = tmp; + break; + } + } + if (!peer_esw) { + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + return ERR_PTR(-ENODEV); + } + handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id, bridge, peer_esw); - - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return handle; } @@ -1369,8 +1382,9 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow entry->ingress_counter = counter; handle = peer ? - mlx5_esw_bridge_ingress_flow_peer_create(vport_num, addr, vlan, - mlx5_fc_id(counter), bridge) : + mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id, + addr, vlan, mlx5_fc_id(counter), + bridge) : mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan, mlx5_fc_id(counter), bridge); if (IS_ERR(handle)) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c index 2eae594a5e80fd..2455f8b93c1e50 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_mcast.c @@ -540,16 +540,29 @@ static struct mlx5_flow_handle * mlx5_esw_bridge_mcast_filter_flow_peer_create(struct mlx5_esw_bridge_port *port) { struct mlx5_devcom *devcom = port->bridge->br_offloads->esw->dev->priv.devcom; + struct mlx5_eswitch *tmp, *peer_esw = NULL; static struct mlx5_flow_handle *handle; - struct mlx5_eswitch *peer_esw; + int i; - peer_esw = mlx5_devcom_get_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); - if (!peer_esw) + if (!mlx5_devcom_for_each_peer_begin(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) return ERR_PTR(-ENODEV); + mlx5_devcom_for_each_peer_entry(devcom, + MLX5_DEVCOM_ESW_OFFLOADS, + tmp, i) { + if (mlx5_esw_is_owner(tmp, port->vport_num, port->esw_owner_vhca_id)) { + peer_esw = tmp; + break; + } + } + if (!peer_esw) { + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + return ERR_PTR(-ENODEV); + } + handle = mlx5_esw_bridge_mcast_flow_with_esw_create(port, peer_esw); - mlx5_devcom_release_peer_data(devcom, MLX5_DEVCOM_ESW_OFFLOADS); + mlx5_devcom_for_each_peer_end(devcom, MLX5_DEVCOM_ESW_OFFLOADS); return handle; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c index 084a910bb4e740..af779c700278ed 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c @@ -18,7 +18,8 @@ static bool mlx5_esw_devlink_port_supported(struct mlx5_eswitch *esw, u16 vport_ { return vport_num == MLX5_VPORT_UPLINK || (mlx5_core_is_ecpf(esw->dev) && vport_num == MLX5_VPORT_PF) || - mlx5_eswitch_is_vf_vport(esw, vport_num); + mlx5_eswitch_is_vf_vport(esw, vport_num) || + mlx5_core_is_ec_vf_vport(esw->dev, vport_num); } static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 vport_num) @@ -56,6 +57,11 @@ static struct devlink_port *mlx5_esw_dl_port_alloc(struct mlx5_eswitch *esw, u16 dl_port->attrs.switch_id.id_len = ppid.id_len; devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, vport_num - 1, external); + } else if (mlx5_core_is_ec_vf_vport(esw->dev, vport_num)) { + memcpy(dl_port->attrs.switch_id.id, ppid.id, ppid.id_len); + dl_port->attrs.switch_id.id_len = ppid.id_len; + devlink_port_attrs_pci_vf_set(dl_port, controller_num, pfnum, + vport_num - 1, false); } return dl_port; } @@ -65,6 +71,15 @@ static void mlx5_esw_dl_port_free(struct devlink_port *dl_port) kfree(dl_port); } +static const struct devlink_port_ops mlx5_esw_dl_port_ops = { + .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, + .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, + .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, + .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, + .port_fn_migratable_get = mlx5_devlink_port_fn_migratable_get, + .port_fn_migratable_set = mlx5_devlink_port_fn_migratable_set, +}; + int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_core_dev *dev = esw->dev; @@ -87,7 +102,8 @@ int mlx5_esw_offloads_devlink_port_register(struct mlx5_eswitch *esw, u16 vport_ devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register(devlink, dl_port, dl_port_index); + err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, + &mlx5_esw_dl_port_ops); if (err) goto reg_err; @@ -134,6 +150,20 @@ struct devlink_port *mlx5_esw_offloads_devlink_port(struct mlx5_eswitch *esw, u1 return IS_ERR(vport) ? ERR_CAST(vport) : vport->dl_port; } +static const struct devlink_port_ops mlx5_esw_dl_sf_port_ops = { +#ifdef CONFIG_MLX5_SF_MANAGER + .port_del = mlx5_devlink_sf_port_del, +#endif + .port_fn_hw_addr_get = mlx5_devlink_port_fn_hw_addr_get, + .port_fn_hw_addr_set = mlx5_devlink_port_fn_hw_addr_set, + .port_fn_roce_get = mlx5_devlink_port_fn_roce_get, + .port_fn_roce_set = mlx5_devlink_port_fn_roce_set, +#ifdef CONFIG_MLX5_SF_MANAGER + .port_fn_state_get = mlx5_devlink_sf_port_fn_state_get, + .port_fn_state_set = mlx5_devlink_sf_port_fn_state_set, +#endif +}; + int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_port *dl_port, u16 vport_num, u32 controller, u32 sfnum) { @@ -156,7 +186,8 @@ int mlx5_esw_devlink_sf_port_register(struct mlx5_eswitch *esw, struct devlink_p devlink_port_attrs_pci_sf_set(dl_port, controller, pfnum, sfnum, !!controller); devlink = priv_to_devlink(dev); dl_port_index = mlx5_esw_vport_to_devlink_port_index(dev, vport_num); - err = devl_port_register(devlink, dl_port, dl_port_index); + err = devl_port_register_with_ops(devlink, dl_port, dl_port_index, + &mlx5_esw_dl_sf_port_ops); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 901c53751b0aa2..2af9c4646bc7fe 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -41,6 +41,7 @@ #include "esw/qos.h" #include "mlx5_core.h" #include "lib/eq.h" +#include "lag/lag.h" #include "eswitch.h" #include "fs_core.h" #include "devlink.h" @@ -92,7 +93,7 @@ mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num) { struct mlx5_vport *vport; - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager)) + if (!esw) return ERR_PTR(-EPERM); vport = xa_load(&esw->vports, vport_num); @@ -113,7 +114,8 @@ static int arm_vport_context_events_cmd(struct mlx5_core_dev *dev, u16 vport, opcode, MLX5_CMD_OP_MODIFY_NIC_VPORT_CONTEXT); MLX5_SET(modify_nic_vport_context_in, in, field_select.change_event, 1); MLX5_SET(modify_nic_vport_context_in, in, vport_number, vport); - MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); + if (vport || mlx5_core_is_ecpf(dev)) + MLX5_SET(modify_nic_vport_context_in, in, other_vport, 1); nic_vport_ctx = MLX5_ADDR_OF(modify_nic_vport_context_in, in, nic_vport_context); @@ -309,11 +311,12 @@ static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) fdb_add: /* SRIOV is enabled: Forward UC MAC to vport */ - if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) + if (esw->fdb_table.legacy.fdb && esw->mode == MLX5_ESWITCH_LEGACY) { vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); - esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", - vport, mac, vaddr->flow_rule); + esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", + vport, mac, vaddr->flow_rule); + } return 0; } @@ -710,6 +713,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport) struct mlx5_eswitch *esw = dev->priv.eswitch; u8 mac[ETH_ALEN]; + if (!MLX5_CAP_GEN(dev, log_max_l2_table)) + return; + mlx5_query_nic_vport_mac_address(dev, vport->vport, true, mac); esw_debug(dev, "vport[%d] Context Changed: perm mac: %pM\n", vport->vport, mac); @@ -946,7 +952,8 @@ void mlx5_esw_vport_disable(struct mlx5_eswitch *esw, u16 vport_num) vport->enabled = false; /* Disable events from this vport */ - arm_vport_context_events_cmd(esw->dev, vport->vport, 0); + if (MLX5_CAP_GEN(esw->dev, log_max_l2_table)) + arm_vport_context_events_cmd(esw->dev, vport->vport, 0); if (!mlx5_esw_is_manager_vport(esw, vport->vport) && MLX5_CAP_GEN(esw->dev, vhca_resource_manager)) @@ -1045,6 +1052,18 @@ static void mlx5_eswitch_clear_vf_vports_info(struct mlx5_eswitch *esw) } } +static void mlx5_eswitch_clear_ec_vf_vports_info(struct mlx5_eswitch *esw) +{ + struct mlx5_vport *vport; + unsigned long i; + + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { + memset(&vport->qos, 0, sizeof(vport->qos)); + memset(&vport->info, 0, sizeof(vport->info)); + vport->info.link_state = MLX5_VPORT_ADMIN_STATE_AUTO; + } +} + /* Public E-Switch API */ int mlx5_eswitch_load_vport(struct mlx5_eswitch *esw, u16 vport_num, enum mlx5_eswitch_vport_event enabled_events) @@ -1084,6 +1103,19 @@ void mlx5_eswitch_unload_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs) } } +static void mlx5_eswitch_unload_ec_vf_vports(struct mlx5_eswitch *esw, + u16 num_ec_vfs) +{ + struct mlx5_vport *vport; + unsigned long i; + + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { + if (!vport->enabled) + continue; + mlx5_eswitch_unload_vport(esw, vport->vport); + } +} + int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, enum mlx5_eswitch_vport_event enabled_events) { @@ -1104,6 +1136,26 @@ int mlx5_eswitch_load_vf_vports(struct mlx5_eswitch *esw, u16 num_vfs, return err; } +static int mlx5_eswitch_load_ec_vf_vports(struct mlx5_eswitch *esw, u16 num_ec_vfs, + enum mlx5_eswitch_vport_event enabled_events) +{ + struct mlx5_vport *vport; + unsigned long i; + int err; + + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, num_ec_vfs) { + err = mlx5_eswitch_load_vport(esw, vport->vport, enabled_events); + if (err) + goto vf_err; + } + + return 0; + +vf_err: + mlx5_eswitch_unload_ec_vf_vports(esw, num_ec_vfs); + return err; +} + static int host_pf_enable_hca(struct mlx5_core_dev *dev) { if (!mlx5_core_is_ecpf(dev)) @@ -1148,6 +1200,12 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, ret = mlx5_eswitch_load_vport(esw, MLX5_VPORT_ECPF, enabled_events); if (ret) goto ecpf_err; + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + ret = mlx5_eswitch_load_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs, + enabled_events); + if (ret) + goto ec_vf_err; + } } /* Enable VF vports */ @@ -1158,6 +1216,9 @@ mlx5_eswitch_enable_pf_vf_vports(struct mlx5_eswitch *esw, return 0; vf_err: + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); +ec_vf_err: if (mlx5_ecpf_vport_exists(esw->dev)) mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); ecpf_err: @@ -1174,8 +1235,11 @@ void mlx5_eswitch_disable_pf_vf_vports(struct mlx5_eswitch *esw) { mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); - if (mlx5_ecpf_vport_exists(esw->dev)) + if (mlx5_ecpf_vport_exists(esw->dev)) { + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_vfs); mlx5_eswitch_unload_vport(esw, MLX5_VPORT_ECPF); + } host_pf_disable_hca(esw->dev); mlx5_eswitch_unload_vport(esw, MLX5_VPORT_PF); @@ -1219,6 +1283,9 @@ mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, int num_vfs) esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out, host_params_context.host_num_of_vfs); + if (mlx5_core_ec_sriov_enabled(esw->dev)) + esw->esw_funcs.num_ec_vfs = num_vfs; + kvfree(out); } @@ -1326,9 +1393,9 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) mlx5_eswitch_event_handlers_register(esw); - esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n", + esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", - esw->esw_funcs.num_vfs, esw->enabled_vports); + esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); mlx5_esw_mode_change_notify(esw, esw->mode); @@ -1350,7 +1417,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs) int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { bool toggle_lag; - int ret; + int ret = 0; if (!mlx5_esw_allowed(esw)) return 0; @@ -1370,10 +1437,21 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) vport_events = (esw->mode == MLX5_ESWITCH_LEGACY) ? MLX5_LEGACY_SRIOV_VPORT_EVENTS : MLX5_VPORT_UC_ADDR_CHANGE; - ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); - if (!ret) - esw->esw_funcs.num_vfs = num_vfs; + /* If this is the ECPF the number of host VFs is managed via the + * eswitch function change event handler, and any num_vfs provided + * here are intended to be EC VFs. + */ + if (!mlx5_core_is_ecpf(esw->dev)) { + ret = mlx5_eswitch_load_vf_vports(esw, num_vfs, vport_events); + if (!ret) + esw->esw_funcs.num_vfs = num_vfs; + } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { + ret = mlx5_eswitch_load_ec_vf_vports(esw, num_vfs, vport_events); + if (!ret) + esw->esw_funcs.num_ec_vfs = num_vfs; + } } + up_write(&esw->mode_lock); if (toggle_lag) @@ -1393,16 +1471,22 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) /* If driver is unloaded, this function is called twice by remove_one() * and mlx5_unload(). Prevent the second call. */ - if (!esw->esw_funcs.num_vfs && !clear_vf) + if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf) goto unlock; - esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), active vports(%d)\n", + esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", - esw->esw_funcs.num_vfs, esw->enabled_vports); - - mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); - if (clear_vf) - mlx5_eswitch_clear_vf_vports_info(esw); + esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); + + if (!mlx5_core_is_ecpf(esw->dev)) { + mlx5_eswitch_unload_vf_vports(esw, esw->esw_funcs.num_vfs); + if (clear_vf) + mlx5_eswitch_clear_vf_vports_info(esw); + } else if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_eswitch_unload_ec_vf_vports(esw, esw->esw_funcs.num_ec_vfs); + if (clear_vf) + mlx5_eswitch_clear_ec_vf_vports_info(esw); + } if (esw->mode == MLX5_ESWITCH_OFFLOADS) { struct devlink *devlink = priv_to_devlink(esw->dev); @@ -1413,7 +1497,10 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) if (esw->mode == MLX5_ESWITCH_LEGACY) mlx5_eswitch_disable_locked(esw); - esw->esw_funcs.num_vfs = 0; + if (!mlx5_core_is_ecpf(esw->dev)) + esw->esw_funcs.num_vfs = 0; + else + esw->esw_funcs.num_ec_vfs = 0; unlock: up_write(&esw->mode_lock); @@ -1433,9 +1520,9 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw) mlx5_eswitch_event_handlers_unregister(esw); - esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), active vports(%d)\n", + esw_info(esw->dev, "Disable: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n", esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS", - esw->esw_funcs.num_vfs, esw->enabled_vports); + esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports); if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) { esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED; @@ -1595,7 +1682,19 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) idx++; } - if (mlx5_ecpf_vport_exists(dev)) { + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + int ec_vf_base_num = mlx5_core_ec_vf_vport_base(dev); + + for (i = 0; i < mlx5_core_max_ec_vfs(esw->dev); i++) { + err = mlx5_esw_vport_alloc(esw, idx, ec_vf_base_num + i); + if (err) + goto err; + idx++; + } + } + + if (mlx5_ecpf_vport_exists(dev) || + mlx5_core_is_ecpf_esw_manager(dev)) { err = mlx5_esw_vport_alloc(esw, idx, MLX5_VPORT_ECPF); if (err) goto err; @@ -1611,17 +1710,56 @@ static int mlx5_esw_vports_init(struct mlx5_eswitch *esw) return err; } +static int mlx5_devlink_esw_multiport_set(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct mlx5_core_dev *dev = devlink_priv(devlink); + + if (!MLX5_ESWITCH_MANAGER(dev)) + return -EOPNOTSUPP; + + if (ctx->val.vbool) + return mlx5_lag_mpesw_enable(dev); + + mlx5_lag_mpesw_disable(dev); + return 0; +} + +static int mlx5_devlink_esw_multiport_get(struct devlink *devlink, u32 id, + struct devlink_param_gset_ctx *ctx) +{ + struct mlx5_core_dev *dev = devlink_priv(devlink); + + ctx->val.vbool = mlx5_lag_is_mpesw(dev); + return 0; +} + +static const struct devlink_param mlx5_eswitch_params[] = { + DEVLINK_PARAM_DRIVER(MLX5_DEVLINK_PARAM_ID_ESW_MULTIPORT, + "esw_multiport", DEVLINK_PARAM_TYPE_BOOL, + BIT(DEVLINK_PARAM_CMODE_RUNTIME), + mlx5_devlink_esw_multiport_get, + mlx5_devlink_esw_multiport_set, NULL), +}; + int mlx5_eswitch_init(struct mlx5_core_dev *dev) { struct mlx5_eswitch *esw; int err; - if (!MLX5_VPORT_MANAGER(dev)) + if (!MLX5_VPORT_MANAGER(dev) && !MLX5_ESWITCH_MANAGER(dev)) return 0; + err = devl_params_register(priv_to_devlink(dev), mlx5_eswitch_params, + ARRAY_SIZE(mlx5_eswitch_params)); + if (err) + return err; + esw = kzalloc(sizeof(*esw), GFP_KERNEL); - if (!esw) - return -ENOMEM; + if (!esw) { + err = -ENOMEM; + goto unregister_param; + } esw->dev = dev; esw->manager_vport = mlx5_eswitch_manager_vport(dev); @@ -1681,12 +1819,15 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) if (esw->work_queue) destroy_workqueue(esw->work_queue); kfree(esw); +unregister_param: + devl_params_unregister(priv_to_devlink(dev), mlx5_eswitch_params, + ARRAY_SIZE(mlx5_eswitch_params)); return err; } void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) { - if (!esw || !MLX5_VPORT_MANAGER(esw->dev)) + if (!esw) return; esw_info(esw->dev, "cleanup\n"); @@ -1704,6 +1845,8 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) esw_offloads_cleanup(esw); mlx5_esw_vports_cleanup(esw); kfree(esw); + devl_params_unregister(priv_to_devlink(esw->dev), mlx5_eswitch_params, + ARRAY_SIZE(mlx5_eswitch_params)); } /* Vport Administration */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 1a042c9817131e..266b60fefe257d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -123,8 +123,14 @@ struct vport_ingress { } offloads; }; +enum vport_egress_acl_type { + VPORT_EGRESS_ACL_TYPE_DEFAULT, + VPORT_EGRESS_ACL_TYPE_SHARED_FDB, +}; + struct vport_egress { struct mlx5_flow_table *acl; + enum vport_egress_acl_type type; struct mlx5_flow_handle *allowed_vlan; struct mlx5_flow_group *vlan_grp; union { @@ -136,7 +142,7 @@ struct vport_egress { struct { struct mlx5_flow_group *fwd_grp; struct mlx5_flow_handle *fwd_rule; - struct mlx5_flow_handle *bounce_rule; + struct xarray bounce_rules; struct mlx5_flow_group *bounce_grp; } offloads; }; @@ -218,7 +224,7 @@ struct mlx5_eswitch_fdb { struct mlx5_flow_group *send_to_vport_grp; struct mlx5_flow_group *send_to_vport_meta_grp; struct mlx5_flow_group *peer_miss_grp; - struct mlx5_flow_handle **peer_miss_rules; + struct mlx5_flow_handle **peer_miss_rules[MLX5_MAX_PORTS]; struct mlx5_flow_group *miss_grp; struct mlx5_flow_handle **send_to_vport_meta_rules; struct mlx5_flow_handle *miss_rule_uni; @@ -249,7 +255,7 @@ struct mlx5_esw_offload { struct mlx5_flow_group *vport_rx_drop_group; struct mlx5_flow_handle *vport_rx_drop_rule; struct xarray vport_reps; - struct list_head peer_flows; + struct list_head peer_flows[MLX5_MAX_PORTS]; struct mutex peer_mutex; struct mutex encap_tbl_lock; /* protects encap_tbl */ DECLARE_HASHTABLE(encap_tbl, 8); @@ -283,6 +289,7 @@ struct mlx5_host_work { struct mlx5_esw_functions { struct mlx5_nb nb; u16 num_vfs; + u16 num_ec_vfs; }; enum { @@ -337,11 +344,13 @@ struct mlx5_eswitch { int mode; u16 manager_vport; u16 first_host_vport; + u8 num_peers; struct mlx5_esw_functions esw_funcs; struct { u32 large_group_num; } params; struct blocking_notifier_head n_head; + bool paired[MLX5_MAX_PORTS]; }; void esw_offloads_disable(struct mlx5_eswitch *esw); @@ -369,6 +378,8 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs); void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf); void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw); void mlx5_eswitch_disable(struct mlx5_eswitch *esw); +void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw); +void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw); int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, u16 vport, const u8 *mac); int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, @@ -503,12 +514,12 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, struct netlink_ext_ack *extack); int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, enum devlink_eswitch_encap_mode *encap); -int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port, - u8 *hw_addr, int *hw_addr_len, - struct netlink_ext_ack *extack); -int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port, - const u8 *hw_addr, int hw_addr_len, - struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack); +int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, + const u8 *hw_addr, int hw_addr_len, + struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_roce_get(struct devlink_port *port, bool *is_enabled, struct netlink_ext_ack *extack); int mlx5_devlink_port_fn_roce_set(struct devlink_port *port, bool enable, @@ -575,6 +586,13 @@ mlx5_esw_is_manager_vport(const struct mlx5_eswitch *esw, u16 vport_num) return esw->manager_vport == vport_num; } +static inline bool mlx5_esw_is_owner(struct mlx5_eswitch *esw, u16 vport_num, + u16 esw_owner_vhca_id) +{ + return esw_owner_vhca_id == MLX5_CAP_GEN(esw->dev, vhca_id) || + (vport_num == MLX5_VPORT_UPLINK && mlx5_lag_is_master(esw->dev)); +} + static inline u16 mlx5_eswitch_first_host_vport_num(struct mlx5_core_dev *dev) { return mlx5_core_is_ecpf_esw_manager(dev) ? @@ -637,6 +655,18 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw); #define mlx5_esw_for_each_host_func_vport(esw, index, vport, last) \ mlx5_esw_for_each_vport_marked(esw, index, vport, last, MLX5_ESW_VPT_HOST_FN) +/* This macro should only be used if EC SRIOV is enabled. + * + * Because there were no more marks available on the xarray this uses a + * for_each_range approach. The range is only valid when EC SRIOV is enabled + */ +#define mlx5_esw_for_each_ec_vf_vport(esw, index, vport, last) \ + xa_for_each_range(&((esw)->vports), \ + index, \ + vport, \ + MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base), \ + (last) - 1) + struct mlx5_eswitch *mlx5_devlink_eswitch_get(struct devlink *devlink); struct mlx5_vport *__must_check mlx5_eswitch_get_vport(struct mlx5_eswitch *esw, u16 vport_num); @@ -683,6 +713,14 @@ mlx5_esw_vporttbl_put(struct mlx5_eswitch *esw, struct mlx5_vport_tbl_attr *attr struct mlx5_flow_handle * esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag); +void mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw, + u32 *flow_group_in, + int match_params); + +void mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, + u16 vport, + struct mlx5_flow_spec *spec); + int esw_offloads_load_rep(struct mlx5_eswitch *esw, u16 vport_num); void esw_offloads_unload_rep(struct mlx5_eswitch *esw, u16 vport_num); @@ -737,9 +775,9 @@ void esw_vport_change_handle_locked(struct mlx5_vport *vport); bool mlx5_esw_offloads_controller_valid(const struct mlx5_eswitch *esw, u32 controller); -int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, - struct mlx5_eswitch *slave_esw); -void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, +int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves); +void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, struct mlx5_eswitch *slave_esw); int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw); @@ -754,6 +792,13 @@ static inline int mlx5_eswitch_num_vfs(struct mlx5_eswitch *esw) return 0; } +static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) +{ + if (mlx5_esw_allowed(esw)) + return esw->num_peers; + return 0; +} + static inline struct mlx5_flow_table * mlx5_eswitch_get_slow_fdb(struct mlx5_eswitch *esw) { @@ -767,6 +812,8 @@ static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {} static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; } static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) {} static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {} +static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) {} +static inline void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) {} static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; } static inline int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; } @@ -789,16 +836,18 @@ mlx5_esw_vport_to_devlink_port_index(const struct mlx5_core_dev *dev, } static inline int -mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, - struct mlx5_eswitch *slave_esw) +mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves) { return 0; } static inline void -mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, +mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, struct mlx5_eswitch *slave_esw) {} +static inline int mlx5_eswitch_get_npeers(struct mlx5_eswitch *esw) { return 0; } + static inline int mlx5_eswitch_reload_reps(struct mlx5_eswitch *esw) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 69215ffb999953..fdf482f6fb34c3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -55,13 +55,6 @@ #define mlx5_esw_for_each_rep(esw, i, rep) \ xa_for_each(&((esw)->offloads.vport_reps), i, rep) -#define mlx5_esw_for_each_sf_rep(esw, i, rep) \ - xa_for_each_marked(&((esw)->offloads.vport_reps), i, rep, MLX5_ESW_VPT_SF) - -#define mlx5_esw_for_each_vf_rep(esw, index, rep) \ - mlx5_esw_for_each_entry_marked(&((esw)->offloads.vport_reps), index, \ - rep, (esw)->esw_funcs.num_vfs, MLX5_ESW_VPT_VF) - /* There are two match-all miss flows, one for unicast dst mac and * one for multicast. */ @@ -838,6 +831,7 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw, struct mlx5_flow_handle *flow_rule; struct mlx5_flow_spec *spec; void *misc; + u16 vport; spec = kvzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) { @@ -847,20 +841,43 @@ mlx5_eswitch_add_send_to_vport_rule(struct mlx5_eswitch *on_esw, misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); MLX5_SET(fte_match_set_misc, misc, source_sqn, sqn); - /* source vport is the esw manager */ - MLX5_SET(fte_match_set_misc, misc, source_port, from_esw->manager_vport); - if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) - MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, - MLX5_CAP_GEN(from_esw->dev, vhca_id)); misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_sqn); - MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); - if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) - MLX5_SET_TO_ONES(fte_match_set_misc, misc, - source_eswitch_owner_vhca_id); spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; + + /* source vport is the esw manager */ + vport = from_esw->manager_vport; + + if (mlx5_eswitch_vport_match_metadata_enabled(on_esw)) { + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2); + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_for_match(from_esw, vport)); + + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters_2); + MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_mask()); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_2; + } else { + misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); + MLX5_SET(fte_match_set_misc, misc, source_port, vport); + + if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) + MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, + MLX5_CAP_GEN(from_esw->dev, vhca_id)); + + misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); + MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); + + if (MLX5_CAP_ESW(on_esw->dev, merged_eswitch)) + MLX5_SET_TO_ONES(fte_match_set_misc, misc, + source_eswitch_owner_vhca_id); + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS; + } + dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT; dest.vport.num = rep->vport; dest.vport.vhca_id = MLX5_CAP_GEN(rep->esw->dev, vhca_id); @@ -1108,11 +1125,32 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, flows[vport->index] = flow; } - esw->fdb_table.offloads.peer_miss_rules = flows; + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { + if (i >= mlx5_core_max_ec_vfs(peer_dev)) + break; + esw_set_peer_miss_rule_source_port(esw, peer_dev->priv.eswitch, + spec, vport->vport); + flow = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb, + spec, &flow_act, &dest, 1); + if (IS_ERR(flow)) { + err = PTR_ERR(flow); + goto add_ec_vf_flow_err; + } + flows[vport->index] = flow; + } + } + esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)] = flows; kvfree(spec); return 0; +add_ec_vf_flow_err: + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { + if (!flows[vport->index]) + continue; + mlx5_del_flow_rules(flows[vport->index]); + } add_vf_flow_err: mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) { if (!flows[vport->index]) @@ -1136,13 +1174,25 @@ static int esw_add_fdb_peer_miss_rules(struct mlx5_eswitch *esw, return err; } -static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw) +static void esw_del_fdb_peer_miss_rules(struct mlx5_eswitch *esw, + struct mlx5_core_dev *peer_dev) { struct mlx5_flow_handle **flows; struct mlx5_vport *vport; unsigned long i; - flows = esw->fdb_table.offloads.peer_miss_rules; + flows = esw->fdb_table.offloads.peer_miss_rules[mlx5_get_dev_index(peer_dev)]; + + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, mlx5_core_max_ec_vfs(esw->dev)) { + /* The flow for a particular vport could be NULL if the other ECPF + * has fewer or no VFs enabled + */ + if (!flows[vport->index]) + continue; + mlx5_del_flow_rules(flows[vport->index]); + } + } mlx5_esw_for_each_vf_vport(esw, i, vport, mlx5_core_max_vfs(esw->dev)) mlx5_del_flow_rules(flows[vport->index]); @@ -1269,8 +1319,10 @@ esw_add_restore_rule(struct mlx5_eswitch *esw, u32 tag) #define MAX_PF_SQ 256 #define MAX_SQ_NVPORTS 32 -static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw, - u32 *flow_group_in) +void +mlx5_esw_set_flow_group_source_port(struct mlx5_eswitch *esw, + u32 *flow_group_in, + int match_params) { void *match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, @@ -1279,7 +1331,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw, if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS_2); + MLX5_MATCH_MISC_PARAMETERS_2 | match_params); MLX5_SET(fte_match_param, match_criteria, misc_parameters_2.metadata_reg_c_0, @@ -1287,7 +1339,7 @@ static void esw_set_flow_group_source_port(struct mlx5_eswitch *esw, } else { MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS); + MLX5_MATCH_MISC_PARAMETERS | match_params); MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port); @@ -1463,14 +1515,13 @@ esw_create_send_to_vport_group(struct mlx5_eswitch *esw, memset(flow_group_in, 0, inlen); - MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS); + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, MLX5_MATCH_MISC_PARAMETERS); match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria); - MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_sqn); - MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port); - if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) { + + if (!mlx5_eswitch_vport_match_metadata_enabled(esw) && + MLX5_CAP_ESW(esw->dev, merged_eswitch)) { MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_eswitch_owner_vhca_id); MLX5_SET(create_flow_group_in, flow_group_in, @@ -1548,6 +1599,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw, u32 *flow_group_in, int *ix) { + int max_peer_ports = (esw->total_vports - 1) * (MLX5_MAX_PORTS - 1); int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); struct mlx5_flow_group *g; void *match_criteria; @@ -1558,7 +1610,7 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw, memset(flow_group_in, 0, inlen); - esw_set_flow_group_source_port(esw, flow_group_in); + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0); if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) { match_criteria = MLX5_ADDR_OF(create_flow_group_in, @@ -1574,8 +1626,8 @@ esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw, MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, *ix); MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, - *ix + esw->total_vports - 1); - *ix += esw->total_vports; + *ix + max_peer_ports); + *ix += max_peer_ports + 1; g = mlx5_create_flow_group(fdb, flow_group_in); if (IS_ERR(g)) { @@ -1677,7 +1729,7 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw) * total vports of the peer (currently is also uses esw->total_vports). */ table_size = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ) + - esw->total_vports * 2 + MLX5_ESW_MISS_FLOWS; + esw->total_vports * MLX5_MAX_PORTS + MLX5_ESW_MISS_FLOWS; /* create the slow path fdb with encap set, so further table instances * can be created at run time while VFs are probed if the FW allows that. @@ -1845,7 +1897,7 @@ static int esw_create_vport_rx_group(struct mlx5_eswitch *esw) return -ENOMEM; /* create vport rx group */ - esw_set_flow_group_source_port(esw, flow_group_in); + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0); MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, nvports - 1); @@ -1915,21 +1967,13 @@ static void esw_destroy_vport_rx_drop_group(struct mlx5_eswitch *esw) mlx5_destroy_flow_group(esw->offloads.vport_rx_drop_group); } -struct mlx5_flow_handle * -mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, - struct mlx5_flow_destination *dest) +void +mlx5_esw_set_spec_source_port(struct mlx5_eswitch *esw, + u16 vport, + struct mlx5_flow_spec *spec) { - struct mlx5_flow_act flow_act = {0}; - struct mlx5_flow_handle *flow_rule; - struct mlx5_flow_spec *spec; void *misc; - spec = kvzalloc(sizeof(*spec), GFP_KERNEL); - if (!spec) { - flow_rule = ERR_PTR(-ENOMEM); - goto out; - } - if (mlx5_eswitch_vport_match_metadata_enabled(esw)) { misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters_2); MLX5_SET(fte_match_set_misc2, misc, metadata_reg_c_0, @@ -1949,6 +1993,23 @@ mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; } +} + +struct mlx5_flow_handle * +mlx5_eswitch_create_vport_rx_rule(struct mlx5_eswitch *esw, u16 vport, + struct mlx5_flow_destination *dest) +{ + struct mlx5_flow_act flow_act = {0}; + struct mlx5_flow_handle *flow_rule; + struct mlx5_flow_spec *spec; + + spec = kvzalloc(sizeof(*spec), GFP_KERNEL); + if (!spec) { + flow_rule = ERR_PTR(-ENOMEM); + goto out; + } + + mlx5_esw_set_spec_source_port(esw, vport, spec); flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, spec, @@ -2142,6 +2203,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, "Failed setting eswitch to offloads"); esw->mode = MLX5_ESWITCH_LEGACY; mlx5_rescan_drivers(esw->dev); + return err; } if (esw->offloads.inline_mode == MLX5_INLINE_MODE_NONE) { if (mlx5_eswitch_inline_mode_get(esw, @@ -2151,19 +2213,7 @@ static int esw_offloads_start(struct mlx5_eswitch *esw, "Inline mode is different between vports"); } } - return err; -} - -static void mlx5_esw_offloads_rep_mark_set(struct mlx5_eswitch *esw, - struct mlx5_eswitch_rep *rep, - xa_mark_t mark) -{ - bool mark_set; - - /* Copy the mark from vport to its rep */ - mark_set = xa_get_mark(&esw->vports, rep->vport, mark); - if (mark_set) - xa_set_mark(&esw->offloads.vport_reps, rep->vport, mark); + return 0; } static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx5_vport *vport) @@ -2185,9 +2235,6 @@ static int mlx5_esw_offloads_rep_init(struct mlx5_eswitch *esw, const struct mlx if (err) goto insert_err; - mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_HOST_FN); - mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_VF); - mlx5_esw_offloads_rep_mark_set(esw, rep, MLX5_ESW_VPT_SF); return 0; insert_err: @@ -2328,37 +2375,13 @@ static void __esw_offloads_unload_rep(struct mlx5_eswitch *esw, esw->offloads.rep_ops[rep_type]->unload(rep); } -static void __unload_reps_sf_vport(struct mlx5_eswitch *esw, u8 rep_type) -{ - struct mlx5_eswitch_rep *rep; - unsigned long i; - - mlx5_esw_for_each_sf_rep(esw, i, rep) - __esw_offloads_unload_rep(esw, rep, rep_type); -} - static void __unload_reps_all_vport(struct mlx5_eswitch *esw, u8 rep_type) { struct mlx5_eswitch_rep *rep; unsigned long i; - __unload_reps_sf_vport(esw, rep_type); - - mlx5_esw_for_each_vf_rep(esw, i, rep) - __esw_offloads_unload_rep(esw, rep, rep_type); - - if (mlx5_ecpf_vport_exists(esw->dev)) { - rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_ECPF); - __esw_offloads_unload_rep(esw, rep, rep_type); - } - - if (mlx5_core_is_ecpf_esw_manager(esw->dev)) { - rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_PF); + mlx5_esw_for_each_rep(esw, i, rep) __esw_offloads_unload_rep(esw, rep, rep_type); - } - - rep = mlx5_eswitch_get_rep(esw, MLX5_VPORT_UPLINK); - __esw_offloads_unload_rep(esw, rep, rep_type); } int mlx5_esw_offloads_rep_load(struct mlx5_eswitch *esw, u16 vport_num) @@ -2476,6 +2499,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master, struct mlx5_vport *vport, struct mlx5_flow_table *acl) { + u16 slave_index = MLX5_CAP_GEN(slave, vhca_id); struct mlx5_flow_handle *flow_rule = NULL; struct mlx5_flow_destination dest = {}; struct mlx5_flow_act flow_act = {}; @@ -2491,8 +2515,7 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master, misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, misc_parameters); MLX5_SET(fte_match_set_misc, misc, source_port, MLX5_VPORT_UPLINK); - MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, - MLX5_CAP_GEN(slave, vhca_id)); + MLX5_SET(fte_match_set_misc, misc, source_eswitch_owner_vhca_id, slave_index); misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters); MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); @@ -2507,44 +2530,35 @@ static int __esw_set_master_egress_rule(struct mlx5_core_dev *master, flow_rule = mlx5_add_flow_rules(acl, spec, &flow_act, &dest, 1); - if (IS_ERR(flow_rule)) + if (IS_ERR(flow_rule)) { err = PTR_ERR(flow_rule); - else - vport->egress.offloads.bounce_rule = flow_rule; + } else { + err = xa_insert(&vport->egress.offloads.bounce_rules, + slave_index, flow_rule, GFP_KERNEL); + if (err) + mlx5_del_flow_rules(flow_rule); + } kvfree(spec); return err; } -static int esw_set_master_egress_rule(struct mlx5_core_dev *master, - struct mlx5_core_dev *slave) +static int esw_master_egress_create_resources(struct mlx5_flow_namespace *egress_ns, + struct mlx5_vport *vport, size_t count) { int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in); - struct mlx5_eswitch *esw = master->priv.eswitch; struct mlx5_flow_table_attr ft_attr = { - .max_fte = 1, .prio = 0, .level = 0, + .max_fte = count, .prio = 0, .level = 0, .flags = MLX5_FLOW_TABLE_OTHER_VPORT, }; - struct mlx5_flow_namespace *egress_ns; struct mlx5_flow_table *acl; struct mlx5_flow_group *g; - struct mlx5_vport *vport; void *match_criteria; u32 *flow_group_in; int err; - vport = mlx5_eswitch_get_vport(esw, esw->manager_vport); - if (IS_ERR(vport)) - return PTR_ERR(vport); - - egress_ns = mlx5_get_flow_vport_acl_namespace(master, - MLX5_FLOW_NAMESPACE_ESW_EGRESS, - vport->index); - if (!egress_ns) - return -EINVAL; - if (vport->egress.acl) - return -EINVAL; + return 0; flow_group_in = kvzalloc(inlen, GFP_KERNEL); if (!flow_group_in) @@ -2568,7 +2582,7 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, MLX5_SET(create_flow_group_in, flow_group_in, source_eswitch_owner_vhca_id_valid, 1); MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, 0); - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, 0); + MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, count); g = mlx5_create_flow_group(acl, flow_group_in); if (IS_ERR(g)) { @@ -2576,19 +2590,15 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, goto err_group; } - err = __esw_set_master_egress_rule(master, slave, vport, acl); - if (err) - goto err_rule; - vport->egress.acl = acl; vport->egress.offloads.bounce_grp = g; + vport->egress.type = VPORT_EGRESS_ACL_TYPE_SHARED_FDB; + xa_init_flags(&vport->egress.offloads.bounce_rules, XA_FLAGS_ALLOC); kvfree(flow_group_in); return 0; -err_rule: - mlx5_destroy_flow_group(g); err_group: mlx5_destroy_flow_table(acl); out: @@ -2596,18 +2606,70 @@ static int esw_set_master_egress_rule(struct mlx5_core_dev *master, return err; } -static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev) +static void esw_master_egress_destroy_resources(struct mlx5_vport *vport) +{ + mlx5_destroy_flow_group(vport->egress.offloads.bounce_grp); + mlx5_destroy_flow_table(vport->egress.acl); +} + +static int esw_set_master_egress_rule(struct mlx5_core_dev *master, + struct mlx5_core_dev *slave, size_t count) +{ + struct mlx5_eswitch *esw = master->priv.eswitch; + u16 slave_index = MLX5_CAP_GEN(slave, vhca_id); + struct mlx5_flow_namespace *egress_ns; + struct mlx5_vport *vport; + int err; + + vport = mlx5_eswitch_get_vport(esw, esw->manager_vport); + if (IS_ERR(vport)) + return PTR_ERR(vport); + + egress_ns = mlx5_get_flow_vport_acl_namespace(master, + MLX5_FLOW_NAMESPACE_ESW_EGRESS, + vport->index); + if (!egress_ns) + return -EINVAL; + + if (vport->egress.acl && vport->egress.type != VPORT_EGRESS_ACL_TYPE_SHARED_FDB) + return 0; + + err = esw_master_egress_create_resources(egress_ns, vport, count); + if (err) + return err; + + if (xa_load(&vport->egress.offloads.bounce_rules, slave_index)) + return -EINVAL; + + err = __esw_set_master_egress_rule(master, slave, vport, vport->egress.acl); + if (err) + goto err_rule; + + return 0; + +err_rule: + esw_master_egress_destroy_resources(vport); + return err; +} + +static void esw_unset_master_egress_rule(struct mlx5_core_dev *dev, + struct mlx5_core_dev *slave_dev) { struct mlx5_vport *vport; vport = mlx5_eswitch_get_vport(dev->priv.eswitch, dev->priv.eswitch->manager_vport); - esw_acl_egress_ofld_cleanup(vport); + esw_acl_egress_ofld_bounce_rule_destroy(vport, MLX5_CAP_GEN(slave_dev, vhca_id)); + + if (xa_empty(&vport->egress.offloads.bounce_rules)) { + esw_acl_egress_ofld_cleanup(vport); + xa_destroy(&vport->egress.offloads.bounce_rules); + } } -int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, - struct mlx5_eswitch *slave_esw) +int mlx5_eswitch_offloads_single_fdb_add_one(struct mlx5_eswitch *master_esw, + struct mlx5_eswitch *slave_esw, int max_slaves) { int err; @@ -2617,7 +2679,7 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, return err; err = esw_set_master_egress_rule(master_esw->dev, - slave_esw->dev); + slave_esw->dev, max_slaves); if (err) goto err_acl; @@ -2625,21 +2687,21 @@ int mlx5_eswitch_offloads_config_single_fdb(struct mlx5_eswitch *master_esw, err_acl: esw_set_slave_root_fdb(NULL, slave_esw->dev); - return err; } -void mlx5_eswitch_offloads_destroy_single_fdb(struct mlx5_eswitch *master_esw, +void mlx5_eswitch_offloads_single_fdb_del_one(struct mlx5_eswitch *master_esw, struct mlx5_eswitch *slave_esw) { - esw_unset_master_egress_rule(master_esw->dev); esw_set_slave_root_fdb(NULL, slave_esw->dev); + esw_unset_master_egress_rule(master_esw->dev, slave_esw->dev); } #define ESW_OFFLOADS_DEVCOM_PAIR (0) #define ESW_OFFLOADS_DEVCOM_UNPAIR (1) -static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw) +static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw, + struct mlx5_eswitch *peer_esw) { const struct mlx5_eswitch_rep_ops *ops; struct mlx5_eswitch_rep *rep; @@ -2652,18 +2714,19 @@ static void mlx5_esw_offloads_rep_event_unpair(struct mlx5_eswitch *esw) ops = esw->offloads.rep_ops[rep_type]; if (atomic_read(&rep->rep_data[rep_type].state) == REP_LOADED && ops->event) - ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, NULL); + ops->event(esw, rep, MLX5_SWITCHDEV_EVENT_UNPAIR, peer_esw); } } } -static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw) +static void mlx5_esw_offloads_unpair(struct mlx5_eswitch *esw, + struct mlx5_eswitch *peer_esw) { #if IS_ENABLED(CONFIG_MLX5_CLS_ACT) mlx5e_tc_clean_fdb_peer_flows(esw); #endif - mlx5_esw_offloads_rep_event_unpair(esw); - esw_del_fdb_peer_miss_rules(esw); + mlx5_esw_offloads_rep_event_unpair(esw, peer_esw); + esw_del_fdb_peer_miss_rules(esw, peer_esw->dev); } static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw, @@ -2694,7 +2757,7 @@ static int mlx5_esw_offloads_pair(struct mlx5_eswitch *esw, return 0; err_out: - mlx5_esw_offloads_unpair(esw); + mlx5_esw_offloads_unpair(esw, peer_esw); return err; } @@ -2702,7 +2765,9 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw, struct mlx5_eswitch *peer_esw, bool pair) { + u8 peer_idx = mlx5_get_dev_index(peer_esw->dev); struct mlx5_flow_root_namespace *peer_ns; + u8 idx = mlx5_get_dev_index(esw->dev); struct mlx5_flow_root_namespace *ns; int err; @@ -2710,18 +2775,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw, ns = esw->dev->priv.steering->fdb_root_ns; if (pair) { - err = mlx5_flow_namespace_set_peer(ns, peer_ns); + err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_idx); if (err) return err; - err = mlx5_flow_namespace_set_peer(peer_ns, ns); + err = mlx5_flow_namespace_set_peer(peer_ns, ns, idx); if (err) { - mlx5_flow_namespace_set_peer(ns, NULL); + mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); return err; } } else { - mlx5_flow_namespace_set_peer(ns, NULL); - mlx5_flow_namespace_set_peer(peer_ns, NULL); + mlx5_flow_namespace_set_peer(ns, NULL, peer_idx); + mlx5_flow_namespace_set_peer(peer_ns, NULL, idx); } return 0; @@ -2742,6 +2807,9 @@ static int mlx5_esw_offloads_devcom_event(int event, mlx5_eswitch_vport_match_metadata_enabled(peer_esw)) break; + if (esw->paired[mlx5_get_dev_index(peer_esw->dev)]) + break; + err = mlx5_esw_offloads_set_ns_peer(esw, peer_esw, true); if (err) goto err_out; @@ -2753,16 +2821,25 @@ static int mlx5_esw_offloads_devcom_event(int event, if (err) goto err_pair; - mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); + esw->paired[mlx5_get_dev_index(peer_esw->dev)] = true; + peer_esw->paired[mlx5_get_dev_index(esw->dev)] = true; + esw->num_peers++; + peer_esw->num_peers++; + mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, true); break; case ESW_OFFLOADS_DEVCOM_UNPAIR: - if (!mlx5_devcom_is_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS)) + if (!esw->paired[mlx5_get_dev_index(peer_esw->dev)]) break; - mlx5_devcom_set_paired(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); - mlx5_esw_offloads_unpair(peer_esw); - mlx5_esw_offloads_unpair(esw); + peer_esw->num_peers--; + esw->num_peers--; + if (!esw->num_peers && !peer_esw->num_peers) + mlx5_devcom_comp_set_ready(devcom, MLX5_DEVCOM_ESW_OFFLOADS, false); + esw->paired[mlx5_get_dev_index(peer_esw->dev)] = false; + peer_esw->paired[mlx5_get_dev_index(esw->dev)] = false; + mlx5_esw_offloads_unpair(peer_esw, esw); + mlx5_esw_offloads_unpair(esw, peer_esw); mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); break; } @@ -2770,7 +2847,7 @@ static int mlx5_esw_offloads_devcom_event(int event, return 0; err_pair: - mlx5_esw_offloads_unpair(esw); + mlx5_esw_offloads_unpair(esw, peer_esw); err_peer: mlx5_esw_offloads_set_ns_peer(esw, peer_esw, false); err_out: @@ -2779,11 +2856,13 @@ static int mlx5_esw_offloads_devcom_event(int event, return err; } -static void esw_offloads_devcom_init(struct mlx5_eswitch *esw) +void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) { struct mlx5_devcom *devcom = esw->dev->priv.devcom; + int i; - INIT_LIST_HEAD(&esw->offloads.peer_flows); + for (i = 0; i < MLX5_MAX_PORTS; i++) + INIT_LIST_HEAD(&esw->offloads.peer_flows[i]); mutex_init(&esw->offloads.peer_mutex); if (!MLX5_CAP_ESW(esw->dev, merged_eswitch)) @@ -2797,12 +2876,14 @@ static void esw_offloads_devcom_init(struct mlx5_eswitch *esw) mlx5_esw_offloads_devcom_event, esw); + esw->num_peers = 0; mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, - ESW_OFFLOADS_DEVCOM_PAIR, esw); + ESW_OFFLOADS_DEVCOM_PAIR, + ESW_OFFLOADS_DEVCOM_UNPAIR, esw); } -static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) +void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) { struct mlx5_devcom *devcom = esw->dev->priv.devcom; @@ -2813,6 +2894,7 @@ static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) return; mlx5_devcom_send_event(devcom, MLX5_DEVCOM_ESW_OFFLOADS, + ESW_OFFLOADS_DEVCOM_UNPAIR, ESW_OFFLOADS_DEVCOM_UNPAIR, esw); mlx5_devcom_unregister_component(devcom, MLX5_DEVCOM_ESW_OFFLOADS); @@ -2827,9 +2909,6 @@ bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw) MLX5_FDB_TO_VPORT_REG_C_0)) return false; - if (!MLX5_CAP_ESW_FLOWTABLE(esw->dev, flow_source)) - return false; - return true; } @@ -3240,6 +3319,9 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) /* Representor will control the vport link state */ mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs) vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; + if (mlx5_core_ec_sriov_enabled(esw->dev)) + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) + vport->info.link_state = MLX5_VPORT_ADMIN_STATE_DOWN; /* Uplink vport rep must load first. */ err = esw_offloads_load_rep(esw, MLX5_VPORT_UPLINK); @@ -3250,8 +3332,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw) if (err) goto err_vports; - esw_offloads_devcom_init(esw); - return 0; err_vports: @@ -3280,7 +3360,7 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, /* If changing from switchdev to legacy mode without sriov enabled, * no need to create legacy fdb. */ - if (!mlx5_sriov_is_enabled(esw->dev)) + if (!mlx5_core_is_pf(esw->dev) || !mlx5_sriov_is_enabled(esw->dev)) return 0; err = mlx5_eswitch_enable_locked(esw, MLX5_ESWITCH_IGNORE_NUM_VFS); @@ -3292,7 +3372,6 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw, void esw_offloads_disable(struct mlx5_eswitch *esw) { - esw_offloads_devcom_cleanup(esw); mlx5_eswitch_disable_pf_vf_vports(esw); esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK); esw_set_passing_vport_metadata(esw, false); @@ -3480,8 +3559,27 @@ static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode, goto revert_inline_mode; } } + if (mlx5_core_ec_sriov_enabled(esw->dev)) { + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { + err = mlx5_modify_nic_vport_min_inline(dev, vport->vport, mlx5_mode); + if (err) { + err_vport_num = vport->vport; + NL_SET_ERR_MSG_MOD(extack, + "Failed to set min inline on vport"); + goto revert_ec_vf_inline_mode; + } + } + } return 0; +revert_ec_vf_inline_mode: + mlx5_esw_for_each_ec_vf_vport(esw, i, vport, esw->esw_funcs.num_ec_vfs) { + if (vport->vport == err_vport_num) + break; + mlx5_modify_nic_vport_min_inline(dev, + vport->vport, + esw->offloads.inline_mode); + } revert_inline_mode: mlx5_esw_for_each_host_func_vport(esw, i, vport, esw->esw_funcs.num_vfs) { if (vport->vport == err_vport_num) @@ -3922,9 +4020,9 @@ is_port_function_supported(struct mlx5_eswitch *esw, u16 vport_num) mlx5_esw_is_sf_vport(esw, vport_num); } -int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port, - u8 *hw_addr, int *hw_addr_len, - struct netlink_ext_ack *extack) +int mlx5_devlink_port_fn_hw_addr_get(struct devlink_port *port, + u8 *hw_addr, int *hw_addr_len, + struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw; struct mlx5_vport *vport; @@ -3951,9 +4049,9 @@ int mlx5_devlink_port_function_hw_addr_get(struct devlink_port *port, return 0; } -int mlx5_devlink_port_function_hw_addr_set(struct devlink_port *port, - const u8 *hw_addr, int hw_addr_len, - struct netlink_ext_ack *extack) +int mlx5_devlink_port_fn_hw_addr_set(struct devlink_port *port, + const u8 *hw_addr, int hw_addr_len, + struct netlink_ext_ack *extack) { struct mlx5_eswitch *esw; u16 vport_num; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index 144e5948068644..8a10ed4d8cbbbb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -139,7 +139,8 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace } static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns) + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx) { return 0; } @@ -243,16 +244,22 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns, ft->type == FS_FT_FDB && mlx5_lag_is_shared_fdb(dev) && mlx5_lag_is_master(dev)) { - err = mlx5_cmd_set_slave_root_fdb(dev, - mlx5_lag_get_peer_mdev(dev), - !disconnect, (!disconnect) ? - ft->id : 0); - if (err && !disconnect) { - MLX5_SET(set_flow_table_root_in, in, op_mod, 0); - MLX5_SET(set_flow_table_root_in, in, table_id, - ns->root_ft->id); - mlx5_cmd_exec_in(dev, set_flow_table_root, in); + struct mlx5_core_dev *peer_dev; + int i; + + mlx5_lag_for_each_peer_mdev(dev, peer_dev, i) { + err = mlx5_cmd_set_slave_root_fdb(dev, peer_dev, !disconnect, + (!disconnect) ? ft->id : 0); + if (err && !disconnect) { + MLX5_SET(set_flow_table_root_in, in, op_mod, 0); + MLX5_SET(set_flow_table_root_in, in, table_id, + ns->root_ft->id); + mlx5_cmd_exec_in(dev, set_flow_table_root, in); + } + if (err) + break; } + } return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 8ef4254b9ea126..b6b9a5a20591df 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -93,7 +93,8 @@ struct mlx5_flow_cmds { struct mlx5_modify_hdr *modify_hdr); int (*set_peer)(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns); + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx); int (*create_ns)(struct mlx5_flow_root_namespace *ns); int (*destroy_ns)(struct mlx5_flow_root_namespace *ns); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c index 19da02c4161618..4ef04aa287719e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c @@ -3620,7 +3620,8 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev, } int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns) + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx) { if (peer_ns && ns->mode != peer_ns->mode) { mlx5_core_err(ns->dev, @@ -3628,7 +3629,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, return -EINVAL; } - return ns->cmds->set_peer(ns, peer_ns); + return ns->cmds->set_peer(ns, peer_ns, peer_idx); } /* This function should be called only at init stage of the namespace. diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index f137a0611b77b4..200ec946409c25 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -295,7 +295,8 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev, const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void); int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns); + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx); int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns, enum mlx5_flow_steering_mode mode); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fw.c b/drivers/net/ethernet/mellanox/mlx5/core/fw.c index 7bb7be01225a8a..fb2035a5ec9992 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fw.c @@ -196,14 +196,11 @@ int mlx5_query_hca_caps(struct mlx5_core_dev *dev) return err; } - if (MLX5_CAP_GEN(dev, vport_group_manager) && - MLX5_ESWITCH_MANAGER(dev)) { + if (MLX5_ESWITCH_MANAGER(dev)) { err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH_FLOW_TABLE); if (err) return err; - } - if (MLX5_ESWITCH_MANAGER(dev)) { err = mlx5_core_get_caps(dev, MLX5_CAP_ESWITCH); if (err) return err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 871c32dda66ec5..210100a4064a72 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -719,7 +719,7 @@ static const struct devlink_health_reporter_ops mlx5_fw_fatal_reporter_ops = { #define MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD 30000 #define MLX5_FW_REPORTER_DEFAULT_GRACEFUL_PERIOD MLX5_FW_REPORTER_VF_GRACEFUL_PERIOD -static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev) +void mlx5_fw_reporters_create(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; struct devlink *devlink = priv_to_devlink(dev); @@ -735,17 +735,17 @@ static void mlx5_fw_reporters_create(struct mlx5_core_dev *dev) } health->fw_reporter = - devlink_health_reporter_create(devlink, &mlx5_fw_reporter_ops, - 0, dev); + devl_health_reporter_create(devlink, &mlx5_fw_reporter_ops, + 0, dev); if (IS_ERR(health->fw_reporter)) mlx5_core_warn(dev, "Failed to create fw reporter, err = %ld\n", PTR_ERR(health->fw_reporter)); health->fw_fatal_reporter = - devlink_health_reporter_create(devlink, - &mlx5_fw_fatal_reporter_ops, - grace_period, - dev); + devl_health_reporter_create(devlink, + &mlx5_fw_fatal_reporter_ops, + grace_period, + dev); if (IS_ERR(health->fw_fatal_reporter)) mlx5_core_warn(dev, "Failed to create fw fatal reporter, err = %ld\n", PTR_ERR(health->fw_fatal_reporter)); @@ -777,7 +777,8 @@ void mlx5_trigger_health_work(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; - queue_work(health->wq, &health->fatal_report_work); + if (!mlx5_dev_is_lightweight(dev)) + queue_work(health->wq, &health->fatal_report_work); } #define MLX5_MSEC_PER_HOUR (MSEC_PER_SEC * 60 * 60) @@ -905,10 +906,15 @@ void mlx5_health_cleanup(struct mlx5_core_dev *dev) int mlx5_health_init(struct mlx5_core_dev *dev) { + struct devlink *devlink = priv_to_devlink(dev); struct mlx5_core_health *health; char *name; - mlx5_fw_reporters_create(dev); + if (!mlx5_dev_is_lightweight(dev)) { + devl_lock(devlink); + mlx5_fw_reporters_create(dev); + devl_unlock(devlink); + } mlx5_reporter_vnic_create(dev); health = &dev->priv.health; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c index 5d331b940f4d43..ffd7e17b8ebe3e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c @@ -512,8 +512,11 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev, return; if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) && - tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) + tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) { + if (ldev->ports > 2) + ldev->buckets = MLX5_LAG_MAX_HASH_BUCKETS; set_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, flags); + } } static int mlx5_lag_set_flags(struct mlx5_lag *ldev, enum mlx5_lag_mode mode, @@ -550,6 +553,29 @@ char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags) } } +static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev) +{ + struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; + struct mlx5_eswitch *master_esw = dev0->priv.eswitch; + int err; + int i; + + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) { + struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch; + + err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw, + slave_esw, ldev->ports); + if (err) + goto err; + } + return 0; +err: + for (; i > MLX5_LAG_P1; i--) + mlx5_eswitch_offloads_single_fdb_del_one(master_esw, + ldev->pf[i].dev->priv.eswitch); + return err; +} + static int mlx5_create_lag(struct mlx5_lag *ldev, struct lag_tracker *tracker, enum mlx5_lag_mode mode, @@ -557,7 +583,6 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, { bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; int err; @@ -575,8 +600,7 @@ static int mlx5_create_lag(struct mlx5_lag *ldev, } if (shared_fdb) { - err = mlx5_eswitch_offloads_config_single_fdb(dev0->priv.eswitch, - dev1->priv.eswitch); + err = mlx5_lag_create_single_fdb(ldev); if (err) mlx5_core_err(dev0, "Can't enable single FDB mode\n"); else @@ -647,19 +671,21 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, int mlx5_deactivate_lag(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; + struct mlx5_eswitch *master_esw = dev0->priv.eswitch; u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {}; bool roce_lag = __mlx5_lag_is_roce(ldev); unsigned long flags = ldev->mode_flags; int err; + int i; ldev->mode = MLX5_LAG_MODE_NONE; ldev->mode_flags = 0; mlx5_lag_mp_reset(ldev); if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) { - mlx5_eswitch_offloads_destroy_single_fdb(dev0->priv.eswitch, - dev1->priv.eswitch); + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) + mlx5_eswitch_offloads_single_fdb_del_one(master_esw, + ldev->pf[i].dev->priv.eswitch); clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags); } @@ -685,7 +711,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev) return 0; } -#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 2 +#define MLX5_LAG_OFFLOADS_SUPPORTED_PORTS 4 bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) { #ifdef CONFIG_MLX5_ESWITCH @@ -711,7 +737,7 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev) if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode) return false; - if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports != MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) + if (mode == MLX5_ESWITCH_OFFLOADS && ldev->ports > MLX5_LAG_OFFLOADS_SUPPORTED_PORTS) return false; #else for (i = 0; i < ldev->ports; i++) @@ -759,7 +785,6 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) { bool shared_fdb = test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags); struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; bool roce_lag; int err; int i; @@ -784,28 +809,35 @@ void mlx5_disable_lag(struct mlx5_lag *ldev) if (shared_fdb || roce_lag) mlx5_lag_add_devices(ldev); - if (shared_fdb) { - if (!(dev0->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) - mlx5_eswitch_reload_reps(dev0->priv.eswitch); - if (!(dev1->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) - mlx5_eswitch_reload_reps(dev1->priv.eswitch); - } + if (shared_fdb) + for (i = 0; i < ldev->ports; i++) + if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)) + mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); } -bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) +static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev) { - struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; - - if (is_mdev_switchdev_mode(dev0) && - is_mdev_switchdev_mode(dev1) && - mlx5_eswitch_vport_match_metadata_enabled(dev0->priv.eswitch) && - mlx5_eswitch_vport_match_metadata_enabled(dev1->priv.eswitch) && - mlx5_devcom_is_paired(dev0->priv.devcom, - MLX5_DEVCOM_ESW_OFFLOADS) && - MLX5_CAP_GEN(dev1, lag_native_fdb_selection) && - MLX5_CAP_ESW(dev1, root_ft_on_other_esw) && - MLX5_CAP_ESW(dev0, esw_shared_ingress_acl)) + struct mlx5_core_dev *dev; + int i; + + for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) { + dev = ldev->pf[i].dev; + if (is_mdev_switchdev_mode(dev) && + mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && + MLX5_CAP_GEN(dev, lag_native_fdb_selection) && + MLX5_CAP_ESW(dev, root_ft_on_other_esw) && + mlx5_eswitch_get_npeers(dev->priv.eswitch) == + MLX5_CAP_GEN(dev, num_lag_ports) - 1) + continue; + return false; + } + + dev = ldev->pf[MLX5_LAG_P1].dev; + if (is_mdev_switchdev_mode(dev) && + mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) && + mlx5_devcom_comp_is_ready(dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS) && + MLX5_CAP_ESW(dev, esw_shared_ingress_acl) && + mlx5_eswitch_get_npeers(dev->priv.eswitch) == MLX5_CAP_GEN(dev, num_lag_ports) - 1) return true; return false; @@ -842,7 +874,6 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond) static void mlx5_do_bond(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; - struct mlx5_core_dev *dev1 = ldev->pf[MLX5_LAG_P2].dev; struct lag_tracker tracker = { }; bool do_bond, roce_lag; int err; @@ -883,20 +914,24 @@ static void mlx5_do_bond(struct mlx5_lag *ldev) for (i = 1; i < ldev->ports; i++) mlx5_nic_vport_enable_roce(ldev->pf[i].dev); } else if (shared_fdb) { + int i; + dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; mlx5_rescan_drivers_locked(dev0); - err = mlx5_eswitch_reload_reps(dev0->priv.eswitch); - if (!err) - err = mlx5_eswitch_reload_reps(dev1->priv.eswitch); + for (i = 0; i < ldev->ports; i++) { + err = mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); + if (err) + break; + } if (err) { dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV; mlx5_rescan_drivers_locked(dev0); mlx5_deactivate_lag(ldev); mlx5_lag_add_devices(ldev); - mlx5_eswitch_reload_reps(dev0->priv.eswitch); - mlx5_eswitch_reload_reps(dev1->priv.eswitch); + for (i = 0; i < ldev->ports; i++) + mlx5_eswitch_reload_reps(ldev->pf[i].dev->priv.eswitch); mlx5_core_err(dev0, "Failed to enable lag\n"); return; } @@ -1496,26 +1531,37 @@ u8 mlx5_lag_get_num_ports(struct mlx5_core_dev *dev) } EXPORT_SYMBOL(mlx5_lag_get_num_ports); -struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev) +struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int *i) { struct mlx5_core_dev *peer_dev = NULL; struct mlx5_lag *ldev; unsigned long flags; + int idx; spin_lock_irqsave(&lag_lock, flags); ldev = mlx5_lag_dev(dev); if (!ldev) goto unlock; - peer_dev = ldev->pf[MLX5_LAG_P1].dev == dev ? - ldev->pf[MLX5_LAG_P2].dev : - ldev->pf[MLX5_LAG_P1].dev; + if (*i == ldev->ports) + goto unlock; + for (idx = *i; idx < ldev->ports; idx++) + if (ldev->pf[idx].dev != dev) + break; + + if (idx == ldev->ports) { + *i = idx; + goto unlock; + } + *i = idx + 1; + + peer_dev = ldev->pf[idx].dev; unlock: spin_unlock_irqrestore(&lag_lock, flags); return peer_dev; } -EXPORT_SYMBOL(mlx5_lag_get_peer_mdev); +EXPORT_SYMBOL(mlx5_lag_get_next_peer_mdev); int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev, u64 *values, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h index bc1f1dd3e2834a..d7e7fa2348a5f1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h @@ -111,7 +111,6 @@ int mlx5_activate_lag(struct mlx5_lag *ldev, bool shared_fdb); int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev, struct net_device *ndev); -bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev); char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags); void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c index d85a8dfc153d6a..976caa8e692290 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c @@ -14,6 +14,7 @@ static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev) return ldev->mode == MLX5_LAG_MODE_MULTIPATH; } +#define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2 static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) { if (!mlx5_lag_is_ready(ldev)) @@ -22,6 +23,9 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev) if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev)) return false; + if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS) + return false; + return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev, ldev->pf[MLX5_LAG_P2].dev); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c index 0c0ef600f6437d..0e869a76dfe4e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c @@ -65,6 +65,7 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev) return err; } +#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 2 static int enable_mpesw(struct mlx5_lag *ldev) { struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev; @@ -74,6 +75,9 @@ static int enable_mpesw(struct mlx5_lag *ldev) if (ldev->mode != MLX5_LAG_MODE_NONE) return -EINVAL; + if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS) + return -EOPNOTSUPP; + if (mlx5_eswitch_mode(dev0) != MLX5_ESWITCH_OFFLOADS || !MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table) || !MLX5_CAP_GEN(dev0, create_lag_when_not_master_up) || diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c index adefde3ea94101..78c94b22bdc09a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.c @@ -3,6 +3,7 @@ #include #include "lib/devcom.h" +#include "mlx5_core.h" static LIST_HEAD(devcom_list); @@ -13,12 +14,12 @@ static LIST_HEAD(devcom_list); struct mlx5_devcom_component { struct { - void *data; + void __rcu *data; } device[MLX5_DEVCOM_PORTS_SUPPORTED]; mlx5_devcom_event_handler_t handler; struct rw_semaphore sem; - bool paired; + bool ready; }; struct mlx5_devcom_list { @@ -74,12 +75,14 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) if (!mlx5_core_is_pf(dev)) return NULL; - if (MLX5_CAP_GEN(dev, num_lag_ports) != MLX5_DEVCOM_PORTS_SUPPORTED) + if (MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_DEVCOM_PORTS_SUPPORTED) return NULL; + mlx5_dev_list_lock(); sguid0 = mlx5_query_nic_system_image_guid(dev); list_for_each_entry(iter, &devcom_list, list) { - struct mlx5_core_dev *tmp_dev = NULL; + /* There is at least one device in iter */ + struct mlx5_core_dev *tmp_dev; idx = -1; for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) { @@ -102,8 +105,10 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) if (!priv) { priv = mlx5_devcom_list_alloc(); - if (!priv) - return ERR_PTR(-ENOMEM); + if (!priv) { + devcom = ERR_PTR(-ENOMEM); + goto out; + } idx = 0; new_priv = true; @@ -112,13 +117,16 @@ struct mlx5_devcom *mlx5_devcom_register_device(struct mlx5_core_dev *dev) priv->devs[idx] = dev; devcom = mlx5_devcom_alloc(priv, idx); if (!devcom) { - kfree(priv); - return ERR_PTR(-ENOMEM); + if (new_priv) + kfree(priv); + devcom = ERR_PTR(-ENOMEM); + goto out; } if (new_priv) list_add(&priv->list, &devcom_list); - +out: + mlx5_dev_list_unlock(); return devcom; } @@ -131,6 +139,7 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom) if (IS_ERR_OR_NULL(devcom)) return; + mlx5_dev_list_lock(); priv = devcom->priv; priv->devs[devcom->idx] = NULL; @@ -141,10 +150,12 @@ void mlx5_devcom_unregister_device(struct mlx5_devcom *devcom) break; if (i != MLX5_DEVCOM_PORTS_SUPPORTED) - return; + goto out; list_del(&priv->list); kfree(priv); +out: + mlx5_dev_list_unlock(); } void mlx5_devcom_register_component(struct mlx5_devcom *devcom, @@ -162,7 +173,7 @@ void mlx5_devcom_register_component(struct mlx5_devcom *devcom, comp = &devcom->priv->components[id]; down_write(&comp->sem); comp->handler = handler; - comp->device[devcom->idx].data = data; + rcu_assign_pointer(comp->device[devcom->idx].data, data); up_write(&comp->sem); } @@ -176,13 +187,14 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom, comp = &devcom->priv->components[id]; down_write(&comp->sem); - comp->device[devcom->idx].data = NULL; + RCU_INIT_POINTER(comp->device[devcom->idx].data, NULL); up_write(&comp->sem); + synchronize_rcu(); } int mlx5_devcom_send_event(struct mlx5_devcom *devcom, enum mlx5_devcom_components id, - int event, + int event, int rollback_event, void *event_data) { struct mlx5_devcom_component *comp; @@ -193,65 +205,140 @@ int mlx5_devcom_send_event(struct mlx5_devcom *devcom, comp = &devcom->priv->components[id]; down_write(&comp->sem); - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) - if (i != devcom->idx && comp->device[i].data) { - err = comp->handler(event, comp->device[i].data, - event_data); - break; + for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) { + void *data = rcu_dereference_protected(comp->device[i].data, + lockdep_is_held(&comp->sem)); + + if (i != devcom->idx && data) { + err = comp->handler(event, data, event_data); + if (err) + goto rollback; } + } + + up_write(&comp->sem); + return 0; + +rollback: + while (i--) { + void *data = rcu_dereference_protected(comp->device[i].data, + lockdep_is_held(&comp->sem)); + + if (i != devcom->idx && data) + comp->handler(rollback_event, data, event_data); + } up_write(&comp->sem); return err; } -void mlx5_devcom_set_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - bool paired) +void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + bool ready) { struct mlx5_devcom_component *comp; comp = &devcom->priv->components[id]; WARN_ON(!rwsem_is_locked(&comp->sem)); - comp->paired = paired; + WRITE_ONCE(comp->ready, ready); } -bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id) { if (IS_ERR_OR_NULL(devcom)) return false; - return devcom->priv->components[id].paired; + return READ_ONCE(devcom->priv->components[id].ready); } -void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id) +bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id) { struct mlx5_devcom_component *comp; - int i; if (IS_ERR_OR_NULL(devcom)) - return NULL; + return false; comp = &devcom->priv->components[id]; down_read(&comp->sem); - if (!comp->paired) { + if (!READ_ONCE(comp->ready)) { up_read(&comp->sem); - return NULL; + return false; } - for (i = 0; i < MLX5_DEVCOM_PORTS_SUPPORTED; i++) - if (i != devcom->idx) - break; - - return comp->device[i].data; + return true; } -void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom, +void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, enum mlx5_devcom_components id) { struct mlx5_devcom_component *comp = &devcom->priv->components[id]; up_read(&comp->sem); } + +void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + int *i) +{ + struct mlx5_devcom_component *comp; + void *ret; + int idx; + + comp = &devcom->priv->components[id]; + + if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) + return NULL; + for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { + if (idx != devcom->idx) { + ret = rcu_dereference_protected(comp->device[idx].data, + lockdep_is_held(&comp->sem)); + if (ret) + break; + } + } + + if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { + *i = idx; + return NULL; + } + *i = idx + 1; + + return ret; +} + +void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + int *i) +{ + struct mlx5_devcom_component *comp; + void *ret; + int idx; + + comp = &devcom->priv->components[id]; + + if (*i == MLX5_DEVCOM_PORTS_SUPPORTED) + return NULL; + for (idx = *i; idx < MLX5_DEVCOM_PORTS_SUPPORTED; idx++) { + if (idx != devcom->idx) { + /* This can change concurrently, however 'data' pointer will remain + * valid for the duration of RCU read section. + */ + if (!READ_ONCE(comp->ready)) + return NULL; + ret = rcu_dereference(comp->device[idx].data); + if (ret) + break; + } + } + + if (idx == MLX5_DEVCOM_PORTS_SUPPORTED) { + *i = idx; + return NULL; + } + *i = idx + 1; + + return ret; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h index 94313c18bb6470..d953a01b8eaac1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/devcom.h @@ -6,7 +6,7 @@ #include -#define MLX5_DEVCOM_PORTS_SUPPORTED 2 +#define MLX5_DEVCOM_PORTS_SUPPORTED 4 enum mlx5_devcom_components { MLX5_DEVCOM_ESW_OFFLOADS, @@ -30,19 +30,33 @@ void mlx5_devcom_unregister_component(struct mlx5_devcom *devcom, int mlx5_devcom_send_event(struct mlx5_devcom *devcom, enum mlx5_devcom_components id, - int event, + int event, int rollback_event, void *event_data); -void mlx5_devcom_set_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id, - bool paired); -bool mlx5_devcom_is_paired(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); +void mlx5_devcom_comp_set_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, + bool ready); +bool mlx5_devcom_comp_is_ready(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id); -void *mlx5_devcom_get_peer_data(struct mlx5_devcom *devcom, - enum mlx5_devcom_components id); -void mlx5_devcom_release_peer_data(struct mlx5_devcom *devcom, +bool mlx5_devcom_for_each_peer_begin(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id); +void mlx5_devcom_for_each_peer_end(struct mlx5_devcom *devcom, enum mlx5_devcom_components id); +void *mlx5_devcom_get_next_peer_data(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, int *i); -#endif +#define mlx5_devcom_for_each_peer_entry(devcom, id, data, i) \ + for (i = 0, data = mlx5_devcom_get_next_peer_data(devcom, id, &i); \ + data; \ + data = mlx5_devcom_get_next_peer_data(devcom, id, &i)) + +void *mlx5_devcom_get_next_peer_data_rcu(struct mlx5_devcom *devcom, + enum mlx5_devcom_components id, int *i); +#define mlx5_devcom_for_each_peer_entry_rcu(devcom, id, data, i) \ + for (i = 0, data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i); \ + data; \ + data = mlx5_devcom_get_next_peer_data_rcu(devcom, id, &i)) + +#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c index 8ff16318e32dc9..4450091e181a10 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c @@ -99,7 +99,7 @@ int mlx5_mpfs_init(struct mlx5_core_dev *dev) int l2table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table); struct mlx5_mpfs *mpfs; - if (!MLX5_ESWITCH_MANAGER(dev)) + if (!MLX5_ESWITCH_MANAGER(dev) || l2table_size == 1) return 0; mpfs = kzalloc(sizeof(*mpfs), GFP_KERNEL); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 995eb2d5ace0b2..6fa314f8e5ee59 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -923,7 +923,6 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct pci_dev *pdev, } mlx5_pci_vsc_init(dev); - dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev); return 0; err_clr_master: @@ -1049,7 +1048,7 @@ static int mlx5_init_once(struct mlx5_core_dev *dev) dev->dm = mlx5_dm_create(dev); if (IS_ERR(dev->dm)) - mlx5_core_warn(dev, "Failed to init device memory%d\n", err); + mlx5_core_warn(dev, "Failed to init device memory %ld\n", PTR_ERR(dev->dm)); dev->tracer = mlx5_fw_tracer_create(dev); dev->hv_vhca = mlx5_hv_vhca_create(dev); @@ -1119,7 +1118,7 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev) mlx5_devcom_unregister_device(dev->priv.devcom); } -static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout) +static int mlx5_function_enable(struct mlx5_core_dev *dev, bool boot, u64 timeout) { int err; @@ -1155,6 +1154,7 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout goto err_cmd_cleanup; } + dev->caps.embedded_cpu = mlx5_read_embedded_cpu(dev); mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_UP); mlx5_start_health_poll(dev); @@ -1183,28 +1183,56 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout goto reclaim_boot_pages; } + return 0; + +reclaim_boot_pages: + mlx5_reclaim_startup_pages(dev); +err_disable_hca: + mlx5_core_disable_hca(dev, 0); +stop_health_poll: + mlx5_stop_health_poll(dev, boot); +err_cmd_cleanup: + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_cleanup(dev); + + return err; +} + +static void mlx5_function_disable(struct mlx5_core_dev *dev, bool boot) +{ + mlx5_reclaim_startup_pages(dev); + mlx5_core_disable_hca(dev, 0); + mlx5_stop_health_poll(dev, boot); + mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); + mlx5_cmd_cleanup(dev); +} + +static int mlx5_function_open(struct mlx5_core_dev *dev) +{ + int err; + err = set_hca_ctrl(dev); if (err) { mlx5_core_err(dev, "set_hca_ctrl failed\n"); - goto reclaim_boot_pages; + return err; } err = set_hca_cap(dev); if (err) { mlx5_core_err(dev, "set_hca_cap failed\n"); - goto reclaim_boot_pages; + return err; } err = mlx5_satisfy_startup_pages(dev, 0); if (err) { mlx5_core_err(dev, "failed to allocate init pages\n"); - goto reclaim_boot_pages; + return err; } err = mlx5_cmd_init_hca(dev, sw_owner_id); if (err) { mlx5_core_err(dev, "init hca failed\n"); - goto reclaim_boot_pages; + return err; } mlx5_set_driver_version(dev); @@ -1212,26 +1240,13 @@ static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout err = mlx5_query_hca_caps(dev); if (err) { mlx5_core_err(dev, "query hca failed\n"); - goto reclaim_boot_pages; + return err; } mlx5_start_health_fw_log_up(dev); - return 0; - -reclaim_boot_pages: - mlx5_reclaim_startup_pages(dev); -err_disable_hca: - mlx5_core_disable_hca(dev, 0); -stop_health_poll: - mlx5_stop_health_poll(dev, boot); -err_cmd_cleanup: - mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); - mlx5_cmd_cleanup(dev); - - return err; } -static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) +static int mlx5_function_close(struct mlx5_core_dev *dev) { int err; @@ -1240,15 +1255,33 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) mlx5_core_err(dev, "tear_down_hca failed, skip cleanup\n"); return err; } - mlx5_reclaim_startup_pages(dev); - mlx5_core_disable_hca(dev, 0); - mlx5_stop_health_poll(dev, boot); - mlx5_cmd_set_state(dev, MLX5_CMDIF_STATE_DOWN); - mlx5_cmd_cleanup(dev); return 0; } +static int mlx5_function_setup(struct mlx5_core_dev *dev, bool boot, u64 timeout) +{ + int err; + + err = mlx5_function_enable(dev, boot, timeout); + if (err) + return err; + + err = mlx5_function_open(dev); + if (err) + mlx5_function_disable(dev, boot); + return err; +} + +static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot) +{ + int err = mlx5_function_close(dev); + + if (!err) + mlx5_function_disable(dev, boot); + return err; +} + static int mlx5_load(struct mlx5_core_dev *dev) { int err; @@ -1391,12 +1424,11 @@ static void mlx5_unload(struct mlx5_core_dev *dev) mlx5_put_uars_page(dev, dev->priv.uar); } -int mlx5_init_one(struct mlx5_core_dev *dev) +int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev) { - struct devlink *devlink = priv_to_devlink(dev); + bool light_probe = mlx5_dev_is_lightweight(dev); int err = 0; - devl_lock(devlink); mutex_lock(&dev->intf_state_mutex); dev->state = MLX5_DEVICE_STATE_UP; @@ -1410,9 +1442,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev) goto function_teardown; } - err = mlx5_devlink_params_register(priv_to_devlink(dev)); - if (err) - goto err_devlink_params_reg; + /* In case of light_probe, mlx5_devlink is already registered. + * Hence, don't register devlink again. + */ + if (!light_probe) { + err = mlx5_devlink_params_register(priv_to_devlink(dev)); + if (err) + goto err_devlink_params_reg; + } err = mlx5_load(dev); if (err) @@ -1425,14 +1462,14 @@ int mlx5_init_one(struct mlx5_core_dev *dev) goto err_register; mutex_unlock(&dev->intf_state_mutex); - devl_unlock(devlink); return 0; err_register: clear_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state); mlx5_unload(dev); err_load: - mlx5_devlink_params_unregister(priv_to_devlink(dev)); + if (!light_probe) + mlx5_devlink_params_unregister(priv_to_devlink(dev)); err_devlink_params_reg: mlx5_cleanup_once(dev); function_teardown: @@ -1440,6 +1477,16 @@ int mlx5_init_one(struct mlx5_core_dev *dev) err_function: dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; mutex_unlock(&dev->intf_state_mutex); + return err; +} + +int mlx5_init_one(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + int err; + + devl_lock(devlink); + err = mlx5_init_one_devl_locked(dev); devl_unlock(devlink); return err; } @@ -1557,6 +1604,100 @@ void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend) devl_unlock(devlink); } +/* In case of light probe, we don't need a full query of hca_caps, but only the bellow caps. + * A full query of hca_caps will be done when the device will reload. + */ +static int mlx5_query_hca_caps_light(struct mlx5_core_dev *dev) +{ + int err; + + err = mlx5_core_get_caps(dev, MLX5_CAP_GENERAL); + if (err) + return err; + + if (MLX5_CAP_GEN(dev, eth_net_offloads)) { + err = mlx5_core_get_caps(dev, MLX5_CAP_ETHERNET_OFFLOADS); + if (err) + return err; + } + + if (MLX5_CAP_GEN(dev, nic_flow_table) || + MLX5_CAP_GEN(dev, ipoib_enhanced_offloads)) { + err = mlx5_core_get_caps(dev, MLX5_CAP_FLOW_TABLE); + if (err) + return err; + } + + if (MLX5_CAP_GEN_64(dev, general_obj_types) & + MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) { + err = mlx5_core_get_caps(dev, MLX5_CAP_VDPA_EMULATION); + if (err) + return err; + } + + return 0; +} + +int mlx5_init_one_light(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + int err; + + dev->state = MLX5_DEVICE_STATE_UP; + err = mlx5_function_enable(dev, true, mlx5_tout_ms(dev, FW_PRE_INIT_TIMEOUT)); + if (err) { + mlx5_core_warn(dev, "mlx5_function_enable err=%d\n", err); + goto out; + } + + err = mlx5_query_hca_caps_light(dev); + if (err) { + mlx5_core_warn(dev, "mlx5_query_hca_caps_light err=%d\n", err); + goto query_hca_caps_err; + } + + devl_lock(devlink); + err = mlx5_devlink_params_register(priv_to_devlink(dev)); + devl_unlock(devlink); + if (err) { + mlx5_core_warn(dev, "mlx5_devlink_param_reg err = %d\n", err); + goto query_hca_caps_err; + } + + return 0; + +query_hca_caps_err: + mlx5_function_disable(dev, true); +out: + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; + return err; +} + +void mlx5_uninit_one_light(struct mlx5_core_dev *dev) +{ + struct devlink *devlink = priv_to_devlink(dev); + + devl_lock(devlink); + mlx5_devlink_params_unregister(priv_to_devlink(dev)); + devl_unlock(devlink); + if (dev->state != MLX5_DEVICE_STATE_UP) + return; + mlx5_function_disable(dev, true); +} + +/* xxx_light() function are used in order to configure the device without full + * init (light init). e.g.: There isn't a point in reload a device to light state. + * Hence, mlx5_load_one_light() isn't needed. + */ + +void mlx5_unload_one_light(struct mlx5_core_dev *dev) +{ + if (dev->state != MLX5_DEVICE_STATE_UP) + return; + mlx5_function_disable(dev, false); + dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR; +} + static const int types[] = { MLX5_CAP_GENERAL, MLX5_CAP_GENERAL_2, @@ -1802,15 +1943,16 @@ static void remove_one(struct pci_dev *pdev) struct devlink *devlink = priv_to_devlink(dev); set_bit(MLX5_BREAK_FW_WAIT, &dev->intf_state); - /* mlx5_drain_fw_reset() is using devlink APIs. Hence, we must drain - * fw_reset before unregistering the devlink. + /* mlx5_drain_fw_reset() and mlx5_drain_health_wq() are using + * devlink notify APIs. + * Hence, we must drain them before unregistering the devlink. */ mlx5_drain_fw_reset(dev); + mlx5_drain_health_wq(dev); devlink_unregister(devlink); - mlx5_sriov_disable(pdev); + mlx5_sriov_disable(pdev, false); mlx5_thermal_uninit(dev); mlx5_crdump_disable(dev); - mlx5_drain_health_wq(dev); mlx5_uninit_one(dev); mlx5_pci_close(dev); mlx5_mdev_uninit(dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 1d879374acaa4e..464c6885a01c6f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -195,7 +195,7 @@ void mlx5_sriov_cleanup(struct mlx5_core_dev *dev); int mlx5_sriov_attach(struct mlx5_core_dev *dev); void mlx5_sriov_detach(struct mlx5_core_dev *dev); int mlx5_core_sriov_configure(struct pci_dev *dev, int num_vfs); -void mlx5_sriov_disable(struct pci_dev *pdev); +void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change); int mlx5_core_sriov_set_msix_vec_count(struct pci_dev *vf, int msix_vec_count); int mlx5_core_enable_hca(struct mlx5_core_dev *dev, u16 func_id); int mlx5_core_disable_hca(struct mlx5_core_dev *dev, u16 func_id); @@ -240,11 +240,14 @@ int mlx5_attach_device(struct mlx5_core_dev *dev); void mlx5_detach_device(struct mlx5_core_dev *dev, bool suspend); int mlx5_register_device(struct mlx5_core_dev *dev); void mlx5_unregister_device(struct mlx5_core_dev *dev); +void mlx5_dev_set_lightweight(struct mlx5_core_dev *dev); +bool mlx5_dev_is_lightweight(struct mlx5_core_dev *dev); struct mlx5_core_dev *mlx5_get_next_phys_dev_lag(struct mlx5_core_dev *dev); void mlx5_dev_list_lock(void); void mlx5_dev_list_unlock(void); int mlx5_dev_list_trylock(void); +void mlx5_fw_reporters_create(struct mlx5_core_dev *dev); int mlx5_query_mtpps(struct mlx5_core_dev *dev, u32 *mtpps, u32 mtpps_size); int mlx5_set_mtpps(struct mlx5_core_dev *mdev, u32 *mtpps, u32 mtpps_size); int mlx5_query_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 *arm, u8 *mode); @@ -319,16 +322,20 @@ static inline bool mlx5_core_is_sf(const struct mlx5_core_dev *dev) int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx); void mlx5_mdev_uninit(struct mlx5_core_dev *dev); int mlx5_init_one(struct mlx5_core_dev *dev); +int mlx5_init_one_devl_locked(struct mlx5_core_dev *dev); void mlx5_uninit_one(struct mlx5_core_dev *dev); void mlx5_unload_one(struct mlx5_core_dev *dev, bool suspend); void mlx5_unload_one_devl_locked(struct mlx5_core_dev *dev, bool suspend); int mlx5_load_one(struct mlx5_core_dev *dev, bool recovery); int mlx5_load_one_devl_locked(struct mlx5_core_dev *dev, bool recovery); +int mlx5_init_one_light(struct mlx5_core_dev *dev); +void mlx5_uninit_one_light(struct mlx5_core_dev *dev); +void mlx5_unload_one_light(struct mlx5_core_dev *dev); -int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 function_id, +int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, u16 vport, u16 opmod); -#define mlx5_vport_get_other_func_general_cap(dev, fid, out) \ - mlx5_vport_get_other_func_cap(dev, fid, out, MLX5_CAP_GENERAL) +#define mlx5_vport_get_other_func_general_cap(dev, vport, out) \ + mlx5_vport_get_other_func_cap(dev, vport, out, MLX5_CAP_GENERAL) void mlx5_events_work_enqueue(struct mlx5_core_dev *dev, struct work_struct *work); static inline u32 mlx5_sriov_get_vf_total_msix(struct pci_dev *pdev) @@ -343,4 +350,24 @@ bool mlx5_rdma_supported(struct mlx5_core_dev *dev); bool mlx5_vnet_supported(struct mlx5_core_dev *dev); bool mlx5_same_hw_devs(struct mlx5_core_dev *dev, struct mlx5_core_dev *peer_dev); +static inline u16 mlx5_core_ec_vf_vport_base(const struct mlx5_core_dev *dev) +{ + return MLX5_CAP_GEN_2(dev, ec_vf_vport_base); +} + +static inline u16 mlx5_core_ec_sriov_enabled(const struct mlx5_core_dev *dev) +{ + return mlx5_core_is_ecpf(dev) && mlx5_core_ec_vf_vport_base(dev); +} + +static inline bool mlx5_core_is_ec_vf_vport(const struct mlx5_core_dev *dev, u16 vport_num) +{ + int base_vport = mlx5_core_ec_vf_vport_base(dev); + int max_vport = base_vport + mlx5_core_max_ec_vfs(dev); + + if (!mlx5_core_ec_sriov_enabled(dev)) + return false; + + return (vport_num >= base_vport && vport_num < max_vport); +} #endif /* __MLX5_CORE_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h index efd0c299c5c73f..aa403a5ea34ed2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_irq.h @@ -15,6 +15,7 @@ int mlx5_irq_table_init(struct mlx5_core_dev *dev); void mlx5_irq_table_cleanup(struct mlx5_core_dev *dev); int mlx5_irq_table_create(struct mlx5_core_dev *dev); void mlx5_irq_table_destroy(struct mlx5_core_dev *dev); +void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev); int mlx5_irq_table_get_num_comp(struct mlx5_irq_table *table); int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table); struct mlx5_irq_table *mlx5_irq_table_get(struct mlx5_core_dev *dev); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mr.c b/drivers/net/ethernet/mellanox/mlx5/core/mr.c index 9d735c343a3b8c..678f0be8137520 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/mr.c @@ -32,6 +32,7 @@ #include #include +#include #include "mlx5_core.h" int mlx5_core_create_mkey(struct mlx5_core_dev *dev, u32 *mkey, u32 *in, @@ -122,3 +123,23 @@ int mlx5_core_destroy_psv(struct mlx5_core_dev *dev, int psv_num) return mlx5_cmd_exec_in(dev, destroy_psv, in); } EXPORT_SYMBOL(mlx5_core_destroy_psv); + +__be32 mlx5_core_get_terminate_scatter_list_mkey(struct mlx5_core_dev *dev) +{ + u32 out[MLX5_ST_SZ_DW(query_special_contexts_out)] = {}; + u32 in[MLX5_ST_SZ_DW(query_special_contexts_in)] = {}; + u32 mkey; + + if (!MLX5_CAP_GEN(dev, terminate_scatter_list_mkey)) + return MLX5_TERMINATE_SCATTER_LIST_LKEY; + + MLX5_SET(query_special_contexts_in, in, opcode, + MLX5_CMD_OP_QUERY_SPECIAL_CONTEXTS); + if (mlx5_cmd_exec_inout(dev, query_special_contexts, in, out)) + return MLX5_TERMINATE_SCATTER_LIST_LKEY; + + mkey = MLX5_GET(query_special_contexts_out, out, + terminate_scatter_list_mkey); + return cpu_to_be32(mkey); +} +EXPORT_SYMBOL(mlx5_core_get_terminate_scatter_list_mkey); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c index 95dc67fb300157..dcf58efac159cf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c @@ -79,7 +79,13 @@ static u16 func_id_to_type(struct mlx5_core_dev *dev, u16 func_id, bool ec_funct if (!func_id) return mlx5_core_is_ecpf(dev) && !ec_function ? MLX5_HOST_PF : MLX5_PF; - return func_id <= mlx5_core_max_vfs(dev) ? MLX5_VF : MLX5_SF; + if (func_id <= max(mlx5_core_max_vfs(dev), mlx5_core_max_ec_vfs(dev))) { + if (ec_function) + return MLX5_EC_VF; + else + return MLX5_VF; + } + return MLX5_SF; } static u32 mlx5_get_ec_function(u32 function) @@ -730,6 +736,9 @@ int mlx5_reclaim_startup_pages(struct mlx5_core_dev *dev) WARN(dev->priv.page_counters[MLX5_HOST_PF], "External host PF FW pages counter is %d after reclaiming all pages\n", dev->priv.page_counters[MLX5_HOST_PF]); + WARN(dev->priv.page_counters[MLX5_EC_VF], + "EC VFs FW pages counter is %d after reclaiming all pages\n", + dev->priv.page_counters[MLX5_EC_VF]); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c index 2245d3b2f393bc..b2dbae763ca6e7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c @@ -32,6 +32,7 @@ struct mlx5_irq { struct mlx5_irq_pool *pool; int refcount; struct msi_map map; + u32 pool_index; }; struct mlx5_irq_table { @@ -40,6 +41,15 @@ struct mlx5_irq_table { struct mlx5_irq_pool *sf_comp_pool; }; +static int mlx5_core_func_to_vport(const struct mlx5_core_dev *dev, + int func, + bool ec_vf_func) +{ + if (!ec_vf_func) + return func; + return mlx5_core_ec_vf_vport_base(dev) + func - 1; +} + /** * mlx5_get_default_msix_vec_count - Get the default number of MSI-X vectors * to be ssigned to each VF. @@ -78,6 +88,8 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); void *hca_cap = NULL, *query_cap = NULL, *cap; int num_vf_msix, min_msix, max_msix; + bool ec_vf_function; + int vport; int ret; num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix); @@ -103,7 +115,9 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, goto out; } - ret = mlx5_vport_get_other_func_general_cap(dev, function_id, query_cap); + ec_vf_function = mlx5_core_ec_sriov_enabled(dev); + vport = mlx5_core_func_to_vport(dev, function_id, ec_vf_function); + ret = mlx5_vport_get_other_func_general_cap(dev, vport, query_cap); if (ret) goto out; @@ -114,6 +128,7 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id, MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP); MLX5_SET(set_hca_cap_in, hca_cap, other_function, 1); + MLX5_SET(set_hca_cap_in, hca_cap, ec_vf_function, ec_vf_function); MLX5_SET(set_hca_cap_in, hca_cap, function_id, function_id); MLX5_SET(set_hca_cap_in, hca_cap, op_mod, @@ -132,7 +147,7 @@ static void irq_release(struct mlx5_irq *irq) struct cpu_rmap *rmap; #endif - xa_erase(&pool->irqs, irq->map.index); + xa_erase(&pool->irqs, irq->pool_index); /* free_irq requires that affinity_hint and rmap will be cleared before * calling it. To satisfy this requirement, we call * irq_cpu_rmap_remove() to remove the notifier @@ -140,7 +155,7 @@ static void irq_release(struct mlx5_irq *irq) irq_update_affinity_hint(irq->map.virq, NULL); #ifdef CONFIG_RFS_ACCEL rmap = mlx5_eq_table_get_rmap(pool->dev); - if (rmap && irq->map.index) + if (rmap) irq_cpu_rmap_remove(rmap, irq->map.virq); #endif @@ -231,12 +246,13 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i, if (!irq) return ERR_PTR(-ENOMEM); if (!i || !pci_msix_can_alloc_dyn(dev->pdev)) { - /* The vector at index 0 was already allocated. - * Just get the irq number. If dynamic irq is not supported - * vectors have also been allocated. + /* The vector at index 0 is always statically allocated. If + * dynamic irq is not supported all vectors are statically + * allocated. In both cases just get the irq number and set + * the index. */ irq->map.virq = pci_irq_vector(dev->pdev, i); - irq->map.index = 0; + irq->map.index = i; } else { irq->map = pci_msix_alloc_irq_at(dev->pdev, MSI_ANY_INDEX, af_desc); if (!irq->map.virq) { @@ -276,11 +292,11 @@ struct mlx5_irq *mlx5_irq_alloc(struct mlx5_irq_pool *pool, int i, } irq->pool = pool; irq->refcount = 1; - irq->map.index = i; - err = xa_err(xa_store(&pool->irqs, irq->map.index, irq, GFP_KERNEL)); + irq->pool_index = i; + err = xa_err(xa_store(&pool->irqs, irq->pool_index, irq, GFP_KERNEL)); if (err) { mlx5_core_err(dev, "Failed to alloc xa entry for irq(%u). err = %d\n", - irq->map.index, err); + irq->pool_index, err); goto err_xa; } return irq; @@ -567,13 +583,13 @@ int mlx5_irqs_request_vectors(struct mlx5_core_dev *dev, u16 *cpus, int nirqs, struct mlx5_irq *irq; int i; - af_desc.is_managed = 1; + af_desc.is_managed = false; for (i = 0; i < nirqs; i++) { + cpumask_clear(&af_desc.mask); cpumask_set_cpu(cpus[i], &af_desc.mask); irq = mlx5_irq_request(dev, i + 1, &af_desc, rmap); if (IS_ERR(irq)) break; - cpumask_clear(&af_desc.mask); irqs[i] = irq; } @@ -691,6 +707,24 @@ static void irq_pools_destroy(struct mlx5_irq_table *table) irq_pool_free(table->pcif_pool); } +static void mlx5_irq_pool_free_irqs(struct mlx5_irq_pool *pool) +{ + struct mlx5_irq *irq; + unsigned long index; + + xa_for_each(&pool->irqs, index, irq) + free_irq(irq->map.virq, &irq->nh); +} + +static void mlx5_irq_pools_free_irqs(struct mlx5_irq_table *table) +{ + if (table->sf_ctrl_pool) { + mlx5_irq_pool_free_irqs(table->sf_comp_pool); + mlx5_irq_pool_free_irqs(table->sf_ctrl_pool); + } + mlx5_irq_pool_free_irqs(table->pcif_pool); +} + /* irq_table API */ int mlx5_irq_table_init(struct mlx5_core_dev *dev) @@ -774,6 +808,17 @@ void mlx5_irq_table_destroy(struct mlx5_core_dev *dev) pci_free_irq_vectors(dev->pdev); } +void mlx5_irq_table_free_irqs(struct mlx5_core_dev *dev) +{ + struct mlx5_irq_table *table = dev->priv.irq_table; + + if (mlx5_core_is_sf(dev)) + return; + + mlx5_irq_pools_free_irqs(table); + pci_free_irq_vectors(dev->pdev); +} + int mlx5_irq_table_get_sfs_vec(struct mlx5_irq_table *table) { if (table->sf_comp_pool) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c index 540cf05f637399..a42f6cd99b7448 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/rdma.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/rdma.c @@ -30,9 +30,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) struct mlx5_flow_spec *spec; struct mlx5_flow_table *ft; struct mlx5_flow_group *fg; - void *match_criteria; + struct mlx5_eswitch *esw; u32 *flow_group_in; - void *misc; int err; if (!(MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support) && @@ -63,12 +62,8 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) goto free; } - MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS); - match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, - match_criteria); - MLX5_SET_TO_ONES(fte_match_param, match_criteria, - misc_parameters.source_port); + esw = dev->priv.eswitch; + mlx5_esw_set_flow_group_source_port(esw, flow_group_in, 0); fg = mlx5_create_flow_group(ft, flow_group_in); if (IS_ERR(fg)) { @@ -77,14 +72,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) goto destroy_flow_table; } - spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS; - misc = MLX5_ADDR_OF(fte_match_param, spec->match_value, - misc_parameters); - MLX5_SET(fte_match_set_misc, misc, source_port, - dev->priv.eswitch->manager_vport); - misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, - misc_parameters); - MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port); + mlx5_esw_set_spec_source_port(esw, esw->manager_vport, spec); flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; flow_rule = mlx5_add_flow_rules(ft, spec, &flow_act, NULL, 0); @@ -115,7 +103,7 @@ static int mlx5_rdma_enable_roce_steering(struct mlx5_core_dev *dev) static void mlx5_rdma_del_roce_addr(struct mlx5_core_dev *dev) { - mlx5_core_roce_gid_set(dev, 0, 0, 0, + mlx5_core_roce_gid_set(dev, 0, MLX5_ROCE_VERSION_2, 0, NULL, NULL, false, 0, 1); } @@ -135,7 +123,7 @@ static int mlx5_rdma_add_roce_addr(struct mlx5_core_dev *dev) mlx5_rdma_make_default_gid(dev, &gid); return mlx5_core_roce_gid_set(dev, 0, - MLX5_ROCE_VERSION_1, + MLX5_ROCE_VERSION_2, 0, gid.raw, mac, false, 0, 1); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c index e2f26d0bc61541..8fe82f1191bb92 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/dev/driver.c @@ -3,6 +3,7 @@ #include #include +#include #include "mlx5_core.h" #include "dev.h" #include "devlink.h" @@ -28,6 +29,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia mdev->priv.adev_idx = adev->id; sf_dev->mdev = mdev; + /* Only local SFs do light probe */ + if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) + mlx5_dev_set_lightweight(mdev); + err = mlx5_mdev_init(mdev, MLX5_SF_PROF); if (err) { mlx5_core_warn(mdev, "mlx5_mdev_init on err=%d\n", err); @@ -41,7 +46,10 @@ static int mlx5_sf_dev_probe(struct auxiliary_device *adev, const struct auxilia goto remap_err; } - err = mlx5_init_one(mdev); + if (MLX5_ESWITCH_MANAGER(sf_dev->parent_mdev)) + err = mlx5_init_one_light(mdev); + else + err = mlx5_init_one(mdev); if (err) { mlx5_core_warn(mdev, "mlx5_init_one err=%d\n", err); goto init_one_err; @@ -63,8 +71,12 @@ static void mlx5_sf_dev_remove(struct auxiliary_device *adev) struct mlx5_sf_dev *sf_dev = container_of(adev, struct mlx5_sf_dev, adev); struct devlink *devlink = priv_to_devlink(sf_dev->mdev); + mlx5_drain_health_wq(sf_dev->mdev); devlink_unregister(devlink); - mlx5_uninit_one(sf_dev->mdev); + if (mlx5_dev_is_lightweight(sf_dev->mdev)) + mlx5_uninit_one_light(sf_dev->mdev); + else + mlx5_uninit_one(sf_dev->mdev); iounmap(sf_dev->mdev->iseg); mlx5_mdev_uninit(sf_dev->mdev); mlx5_devlink_free(devlink); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c index 7d955a4d9f1452..9c02e5ea797c5c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c @@ -283,7 +283,7 @@ int mlx5_devlink_sf_port_fn_state_set(struct devlink_port *dl_port, static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, const struct devlink_port_new_attrs *new_attr, struct netlink_ext_ack *extack, - unsigned int *new_port_index) + struct devlink_port **dl_port) { struct mlx5_eswitch *esw = dev->priv.eswitch; struct mlx5_sf *sf; @@ -297,7 +297,7 @@ static int mlx5_sf_add(struct mlx5_core_dev *dev, struct mlx5_sf_table *table, new_attr->controller, new_attr->sfnum); if (err) goto esw_err; - *new_port_index = sf->port_index; + *dl_port = &sf->dl_port; trace_mlx5_sf_add(dev, sf->port_index, sf->controller, sf->hw_fn_id, new_attr->sfnum); return 0; @@ -339,7 +339,7 @@ mlx5_sf_new_check_attr(struct mlx5_core_dev *dev, const struct devlink_port_new_ int mlx5_devlink_sf_port_new(struct devlink *devlink, const struct devlink_port_new_attrs *new_attr, struct netlink_ext_ack *extack, - unsigned int *new_port_index) + struct devlink_port **dl_port) { struct mlx5_core_dev *dev = devlink_priv(devlink); struct mlx5_sf_table *table; @@ -355,7 +355,7 @@ int mlx5_devlink_sf_port_new(struct devlink *devlink, "Port add is only supported in eswitch switchdev mode or SF ports are disabled."); return -EOPNOTSUPP; } - err = mlx5_sf_add(dev, table, new_attr, extack, new_port_index); + err = mlx5_sf_add(dev, table, new_attr, extack, dl_port); mlx5_sf_table_put(table); return err; } @@ -379,7 +379,8 @@ static void mlx5_sf_dealloc(struct mlx5_sf_table *table, struct mlx5_sf *sf) } } -int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index, +int mlx5_devlink_sf_port_del(struct devlink *devlink, + struct devlink_port *dl_port, struct netlink_ext_ack *extack) { struct mlx5_core_dev *dev = devlink_priv(devlink); @@ -394,7 +395,7 @@ int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index, "Port del is only supported in eswitch switchdev mode or SF ports are disabled."); return -EOPNOTSUPP; } - sf = mlx5_sf_lookup_by_index(table, port_index); + sf = mlx5_sf_lookup_by_index(table, dl_port->index); if (!sf) { err = -ENODEV; goto sf_err; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h index 3a480e06ecc017..860f9ddb7107b8 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/sf/sf.h @@ -21,8 +21,9 @@ void mlx5_sf_table_cleanup(struct mlx5_core_dev *dev); int mlx5_devlink_sf_port_new(struct devlink *devlink, const struct devlink_port_new_attrs *add_attr, struct netlink_ext_ack *extack, - unsigned int *new_port_index); -int mlx5_devlink_sf_port_del(struct devlink *devlink, unsigned int port_index, + struct devlink_port **dl_port); +int mlx5_devlink_sf_port_del(struct devlink *devlink, + struct devlink_port *dl_port, struct netlink_ext_ack *extack); int mlx5_devlink_sf_port_fn_state_get(struct devlink_port *dl_port, enum devlink_port_fn_state *state, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c index 20d7662c10fb6b..4e42a3b9b8eecb 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -37,7 +37,7 @@ #include "mlx5_irq.h" #include "eswitch.h" -static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf) +static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf, u16 func_id) { struct mlx5_core_sriov *sriov = &dev->priv.sriov; struct mlx5_hca_vport_context *in; @@ -59,7 +59,7 @@ static int sriov_restore_guids(struct mlx5_core_dev *dev, int vf) !!(in->node_guid) * MLX5_HCA_VPORT_SEL_NODE_GUID | !!(in->policy) * MLX5_HCA_VPORT_SEL_STATE_POLICY; - err = mlx5_core_modify_hca_vport_context(dev, 1, 1, vf + 1, in); + err = mlx5_core_modify_hca_vport_context(dev, 1, 1, func_id, in); if (err) mlx5_core_warn(dev, "modify vport context failed, unable to restore VF %d settings\n", vf); @@ -73,9 +73,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) { struct mlx5_core_sriov *sriov = &dev->priv.sriov; int err, vf, num_msix_count; - - if (!MLX5_ESWITCH_MANAGER(dev)) - goto enable_vfs_hca; + int vport_num; err = mlx5_eswitch_enable(dev->priv.eswitch, num_vfs); if (err) { @@ -84,7 +82,6 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) return err; } -enable_vfs_hca: num_msix_count = mlx5_get_default_msix_vec_count(dev, num_vfs); for (vf = 0; vf < num_vfs; vf++) { /* Notify the VF before its enablement to let it set @@ -108,7 +105,10 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) sriov->vfs_ctx[vf].enabled = 1; if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) { - err = sriov_restore_guids(dev, vf); + vport_num = mlx5_core_ec_sriov_enabled(dev) ? + mlx5_core_ec_vf_vport_base(dev) + vf + : vf + 1; + err = sriov_restore_guids(dev, vf, vport_num); if (err) { mlx5_core_warn(dev, "failed to restore VF %d settings, err %d\n", @@ -123,9 +123,11 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) } static void -mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf) +mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf, bool num_vf_change) { struct mlx5_core_sriov *sriov = &dev->priv.sriov; + bool wait_for_ec_vf_pages = true; + bool wait_for_vf_pages = true; int err; int vf; @@ -147,11 +149,30 @@ mlx5_device_disable_sriov(struct mlx5_core_dev *dev, int num_vfs, bool clear_vf) mlx5_eswitch_disable_sriov(dev->priv.eswitch, clear_vf); + /* There are a number of scenarios when SRIOV is being disabled: + * 1. VFs or ECVFs had been created, and now set back to 0 (num_vf_change == true). + * - If EC SRIOV is enabled then this flow is happening on the + * embedded platform, wait for only EC VF pages. + * - If EC SRIOV is not enabled this flow is happening on non-embedded + * platform, wait for the VF pages. + * + * 2. The driver is being unloaded. In this case wait for all pages. + */ + if (num_vf_change) { + if (mlx5_core_ec_sriov_enabled(dev)) + wait_for_vf_pages = false; + else + wait_for_ec_vf_pages = false; + } + + if (wait_for_ec_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_EC_VF])) + mlx5_core_warn(dev, "timeout reclaiming EC VFs pages\n"); + /* For ECPFs, skip waiting for host VF pages until ECPF is destroyed */ if (mlx5_core_is_ecpf(dev)) return; - if (mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF])) + if (wait_for_vf_pages && mlx5_wait_for_pages(dev, &dev->priv.page_counters[MLX5_VF])) mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); } @@ -172,12 +193,12 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs) err = pci_enable_sriov(pdev, num_vfs); if (err) { mlx5_core_warn(dev, "pci_enable_sriov failed : %d\n", err); - mlx5_device_disable_sriov(dev, num_vfs, true); + mlx5_device_disable_sriov(dev, num_vfs, true, true); } return err; } -void mlx5_sriov_disable(struct pci_dev *pdev) +void mlx5_sriov_disable(struct pci_dev *pdev, bool num_vf_change) { struct mlx5_core_dev *dev = pci_get_drvdata(pdev); struct devlink *devlink = priv_to_devlink(dev); @@ -185,7 +206,7 @@ void mlx5_sriov_disable(struct pci_dev *pdev) pci_disable_sriov(pdev); devl_lock(devlink); - mlx5_device_disable_sriov(dev, num_vfs, true); + mlx5_device_disable_sriov(dev, num_vfs, true, num_vf_change); devl_unlock(devlink); } @@ -200,7 +221,7 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs) if (num_vfs) err = mlx5_sriov_enable(pdev, num_vfs); else - mlx5_sriov_disable(pdev); + mlx5_sriov_disable(pdev, true); if (!err) sriov->num_vfs = num_vfs; @@ -245,7 +266,7 @@ void mlx5_sriov_detach(struct mlx5_core_dev *dev) if (!mlx5_core_is_pf(dev)) return; - mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false); + mlx5_device_disable_sriov(dev, pci_num_vf(dev->pdev), false, false); } static u16 mlx5_get_max_vfs(struct mlx5_core_dev *dev) @@ -284,6 +305,7 @@ int mlx5_sriov_init(struct mlx5_core_dev *dev) total_vfs = pci_sriov_get_totalvfs(pdev); sriov->max_vfs = mlx5_get_max_vfs(dev); sriov->num_vfs = pci_num_vf(pdev); + sriov->max_ec_vfs = mlx5_core_ec_sriov_enabled(dev) ? pci_sriov_get_totalvfs(dev->pdev) : 0; sriov->vfs_ctx = kcalloc(total_vfs, sizeof(*sriov->vfs_ctx), GFP_KERNEL); if (!sriov->vfs_ctx) return -ENOMEM; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c index 0eb9a8d7f282fc..4e9bc1897a8856 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c @@ -2071,8 +2071,9 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn, struct mlx5dr_action *action; u8 peer_vport; - peer_vport = vhca_id_valid && (vhca_id != dmn->info.caps.gvmi); - vport_dmn = peer_vport ? dmn->peer_dmn : dmn; + peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) && + (vhca_id != dmn->info.caps.gvmi); + vport_dmn = peer_vport ? dmn->peer_dmn[vhca_id] : dmn; if (!vport_dmn) { mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n"); return NULL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c index 3835ba3f4ddac6..1aa525e509f109 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c @@ -117,6 +117,8 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev, caps->gvmi = MLX5_CAP_GEN(mdev, vhca_id); caps->flex_protocols = MLX5_CAP_GEN(mdev, flex_parser_protocols); caps->sw_format_ver = MLX5_CAP_GEN(mdev, steering_format_version); + caps->roce_caps.fl_rc_qp_when_roce_disabled = + MLX5_CAP_GEN(mdev, fl_rc_qp_when_roce_disabled); if (MLX5_CAP_GEN(mdev, roce)) { err = dr_cmd_query_nic_vport_roce_en(mdev, 0, &roce_en); @@ -124,7 +126,7 @@ int mlx5dr_cmd_query_device(struct mlx5_core_dev *mdev, return err; caps->roce_caps.roce_en = roce_en; - caps->roce_caps.fl_rc_qp_when_roce_disabled = + caps->roce_caps.fl_rc_qp_when_roce_disabled |= MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_disabled); caps->roce_caps.fl_rc_qp_when_roce_enabled = MLX5_CAP_ROCE(mdev, fl_rc_qp_when_roce_enabled); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c index 9a2dfe6ebe3188..75dc85dc24ef21 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c @@ -555,17 +555,18 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn) } void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, - struct mlx5dr_domain *peer_dmn) + struct mlx5dr_domain *peer_dmn, + u8 peer_idx) { mlx5dr_domain_lock(dmn); - if (dmn->peer_dmn) - refcount_dec(&dmn->peer_dmn->refcount); + if (dmn->peer_dmn[peer_idx]) + refcount_dec(&dmn->peer_dmn[peer_idx]->refcount); - dmn->peer_dmn = peer_dmn; + dmn->peer_dmn[peer_idx] = peer_dmn; - if (dmn->peer_dmn) - refcount_inc(&dmn->peer_dmn->refcount); + if (dmn->peer_dmn[peer_idx]) + refcount_inc(&dmn->peer_dmn[peer_idx]->refcount); mlx5dr_domain_unlock(dmn); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c index 13e06a6a6b22af..d6947fe13d560d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ptrn.c @@ -213,6 +213,8 @@ struct mlx5dr_ptrn_mgr *mlx5dr_ptrn_mgr_create(struct mlx5dr_domain *dmn) } INIT_LIST_HEAD(&mgr->ptrn_list); + mutex_init(&mgr->modify_hdr_mutex); + return mgr; free_mgr: @@ -237,5 +239,6 @@ void mlx5dr_ptrn_mgr_destroy(struct mlx5dr_ptrn_mgr *mgr) } mlx5dr_icm_pool_destroy(mgr->ptrn_icm_pool); + mutex_destroy(&mgr->modify_hdr_mutex); kfree(mgr); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c index 9413aaf51251b7..e94fbb015efad7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c @@ -15,7 +15,8 @@ static u32 dr_ste_crc32_calc(const void *input_data, size_t length) { u32 crc = crc32(0, input_data, length); - return (__force u32)htonl(crc); + return (__force u32)((crc >> 24) & 0xff) | ((crc << 8) & 0xff0000) | + ((crc >> 8) & 0xff00) | ((crc << 24) & 0xff000000); } bool mlx5dr_ste_supp_ttl_cs_recalc(struct mlx5dr_cmd_caps *caps) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c index 2010d4ac651909..69d7a8f3c402e3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c @@ -1647,6 +1647,7 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, u8 *tag) { struct mlx5dr_match_misc *misc = &value->misc; + int id = misc->source_eswitch_owner_vhca_id; struct mlx5dr_cmd_vport_cap *vport_cap; struct mlx5dr_domain *dmn = sb->dmn; struct mlx5dr_domain *vport_dmn; @@ -1657,11 +1658,11 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, if (sb->vhca_id_valid) { /* Find port GVMI based on the eswitch_owner_vhca_id */ - if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) + if (id == dmn->info.caps.gvmi) vport_dmn = dmn; - else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == - dmn->peer_dmn->info.caps.gvmi)) - vport_dmn = dmn->peer_dmn; + else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && + (id == dmn->peer_dmn[id]->info.caps.gvmi)) + vport_dmn = dmn->peer_dmn[id]; else return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c index 4c0704ad166b35..f4ef0b22b99121 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c @@ -1979,6 +1979,7 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, u8 *tag) { struct mlx5dr_match_misc *misc = &value->misc; + int id = misc->source_eswitch_owner_vhca_id; struct mlx5dr_cmd_vport_cap *vport_cap; struct mlx5dr_domain *dmn = sb->dmn; struct mlx5dr_domain *vport_dmn; @@ -1988,11 +1989,11 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value, if (sb->vhca_id_valid) { /* Find port GVMI based on the eswitch_owner_vhca_id */ - if (misc->source_eswitch_owner_vhca_id == dmn->info.caps.gvmi) + if (id == dmn->info.caps.gvmi) vport_dmn = dmn; - else if (dmn->peer_dmn && (misc->source_eswitch_owner_vhca_id == - dmn->peer_dmn->info.caps.gvmi)) - vport_dmn = dmn->peer_dmn; + else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] && + (id == dmn->peer_dmn[id]->info.caps.gvmi)) + vport_dmn = dmn->peer_dmn[id]; else return -EINVAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h index 678a993ab053d4..1622dbbe6b970d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h @@ -935,7 +935,7 @@ struct mlx5dr_domain_info { }; struct mlx5dr_domain { - struct mlx5dr_domain *peer_dmn; + struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS]; struct mlx5_core_dev *mdev; u32 pdn; struct mlx5_uars_page *uar; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c index 98465375677961..c6fda1cbfcffb1 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c @@ -770,14 +770,15 @@ static int mlx5_cmd_dr_update_fte(struct mlx5_flow_root_namespace *ns, } static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns, - struct mlx5_flow_root_namespace *peer_ns) + struct mlx5_flow_root_namespace *peer_ns, + u8 peer_idx) { struct mlx5dr_domain *peer_domain = NULL; if (peer_ns) peer_domain = peer_ns->fs_dr_domain.dr_domain; mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain, - peer_domain); + peer_domain, peer_idx); return 0; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h index 9afd268a257381..5ba88f2ecb3f4d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h @@ -48,7 +48,8 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *domain); int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags); void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn, - struct mlx5dr_domain *peer_dmn); + struct mlx5dr_domain *peer_dmn, + u8 peer_idx); struct mlx5dr_table * mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/vport.c b/drivers/net/ethernet/mellanox/mlx5/core/vport.c index ba7e3df2241394..6d3984dd5b21e4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/vport.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/vport.c @@ -288,7 +288,8 @@ int mlx5_query_nic_vport_mac_list(struct mlx5_core_dev *dev, MLX5_CMD_OP_QUERY_NIC_VPORT_CONTEXT); MLX5_SET(query_nic_vport_context_in, in, allowed_list_type, list_type); MLX5_SET(query_nic_vport_context_in, in, vport_number, vport); - MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); + if (vport || mlx5_core_is_ecpf(dev)) + MLX5_SET(query_nic_vport_context_in, in, other_vport, 1); err = mlx5_cmd_exec(dev, in, sizeof(in), out, out_sz); if (err) @@ -1160,23 +1161,32 @@ u64 mlx5_query_nic_system_image_guid(struct mlx5_core_dev *mdev) } EXPORT_SYMBOL_GPL(mlx5_query_nic_system_image_guid); -int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 function_id, void *out, +static int mlx5_vport_to_func_id(const struct mlx5_core_dev *dev, u16 vport, bool ec_vf_func) +{ + return ec_vf_func ? vport - mlx5_core_ec_vf_vport_base(dev) + : vport; +} + +int mlx5_vport_get_other_func_cap(struct mlx5_core_dev *dev, u16 vport, void *out, u16 opmod) { + bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); u8 in[MLX5_ST_SZ_BYTES(query_hca_cap_in)] = {}; opmod = (opmod << 1) | (HCA_CAP_OPMOD_GET_MAX & 0x01); MLX5_SET(query_hca_cap_in, in, opcode, MLX5_CMD_OP_QUERY_HCA_CAP); MLX5_SET(query_hca_cap_in, in, op_mod, opmod); - MLX5_SET(query_hca_cap_in, in, function_id, function_id); + MLX5_SET(query_hca_cap_in, in, function_id, mlx5_vport_to_func_id(dev, vport, ec_vf_func)); MLX5_SET(query_hca_cap_in, in, other_function, true); + MLX5_SET(query_hca_cap_in, in, ec_vf_function, ec_vf_func); return mlx5_cmd_exec_inout(dev, query_hca_cap, in, out); } EXPORT_SYMBOL_GPL(mlx5_vport_get_other_func_cap); int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap, - u16 function_id, u16 opmod) + u16 vport, u16 opmod) { + bool ec_vf_func = mlx5_core_is_ec_vf_vport(dev, vport); int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in); void *set_hca_cap; void *set_ctx; @@ -1190,8 +1200,10 @@ int mlx5_vport_set_other_func_cap(struct mlx5_core_dev *dev, const void *hca_cap MLX5_SET(set_hca_cap_in, set_ctx, op_mod, opmod << 1); set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability); memcpy(set_hca_cap, hca_cap, MLX5_ST_SZ_BYTES(cmd_hca_cap)); - MLX5_SET(set_hca_cap_in, set_ctx, function_id, function_id); + MLX5_SET(set_hca_cap_in, set_ctx, function_id, + mlx5_vport_to_func_id(dev, vport, ec_vf_func)); MLX5_SET(set_hca_cap_in, set_ctx, other_function, true); + MLX5_SET(set_hca_cap_in, set_ctx, ec_vf_function, ec_vf_func); ret = mlx5_cmd_exec_in(dev, set_hca_cap, set_ctx); kfree(set_ctx); diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c index afa3b92a6905f6..0d5a41a2ae0109 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c @@ -245,12 +245,6 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts) skb = priv->rx_skb[rx_pi_rem]; - skb_put(skb, datalen); - - skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */ - - skb->protocol = eth_type_trans(skb, netdev); - /* Alloc another RX SKB for this same index */ rx_skb = mlxbf_gige_alloc_skb(priv, MLXBF_GIGE_DEFAULT_BUF_SZ, &rx_buf_dma, DMA_FROM_DEVICE); @@ -259,6 +253,13 @@ static bool mlxbf_gige_rx_packet(struct mlxbf_gige *priv, int *rx_pkts) priv->rx_skb[rx_pi_rem] = rx_skb; dma_unmap_single(priv->dev, *rx_wqe_addr, MLXBF_GIGE_DEFAULT_BUF_SZ, DMA_FROM_DEVICE); + + skb_put(skb, datalen); + + skb->ip_summed = CHECKSUM_NONE; /* device did not checksum packet */ + + skb->protocol = eth_type_trans(skb, netdev); + *rx_wqe_addr = rx_buf_dma; } else if (rx_cqe & MLXBF_GIGE_RX_CQE_PKT_STATUS_MAC_ERR) { priv->stats.rx_mac_errors++; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 22db0bb15c4539..1ccf3b73ed7245 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -1723,8 +1723,6 @@ static const struct devlink_ops mlxsw_devlink_ops = { BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE), .reload_down = mlxsw_devlink_core_bus_device_reload_down, .reload_up = mlxsw_devlink_core_bus_device_reload_up, - .port_split = mlxsw_devlink_port_split, - .port_unsplit = mlxsw_devlink_port_unsplit, .sb_pool_get = mlxsw_devlink_sb_pool_get, .sb_pool_set = mlxsw_devlink_sb_pool_set, .sb_port_pool_get = mlxsw_devlink_sb_port_pool_get, @@ -3116,6 +3114,11 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, } EXPORT_SYMBOL(mlxsw_core_res_get); +static const struct devlink_port_ops mlxsw_devlink_port_ops = { + .port_split = mlxsw_devlink_port_split, + .port_unsplit = mlxsw_devlink_port_unsplit, +}; + static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, enum devlink_port_flavour flavour, u8 slot_index, u32 port_number, bool split, @@ -3150,7 +3153,8 @@ static int __mlxsw_core_port_init(struct mlxsw_core *mlxsw_core, u16 local_port, devlink_port_linecard_set(devlink_port, linecard->devlink_linecard); } - err = devl_port_register(devlink, devlink_port, local_port); + err = devl_port_register_with_ops(devlink, devlink_port, local_port, + &mlxsw_devlink_port_ops); if (err) memset(mlxsw_core_port, 0, sizeof(*mlxsw_core_port)); return err; diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c index bd1a51a0a54085..f0b2963ebac32b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.c @@ -42,6 +42,7 @@ static const struct mlxsw_afk_element_info mlxsw_afk_element_infos[] = { MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_64_95, 0x34, 4), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_32_63, 0x38, 4), MLXSW_AFK_ELEMENT_INFO_BUF(DST_IP_0_31, 0x3C, 4), + MLXSW_AFK_ELEMENT_INFO_U32(FDB_MISS, 0x40, 0, 1), }; struct mlxsw_afk { diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h index 3a037fe47211dd..65a4abadc7dbb6 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_keys.h @@ -35,6 +35,7 @@ enum mlxsw_afk_element { MLXSW_AFK_ELEMENT_IP_DSCP, MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB, MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB, + MLXSW_AFK_ELEMENT_FDB_MISS, MLXSW_AFK_ELEMENT_MAX, }; @@ -69,7 +70,7 @@ struct mlxsw_afk_element_info { MLXSW_AFK_ELEMENT_INFO(MLXSW_AFK_ELEMENT_TYPE_BUF, \ _element, _offset, 0, _size) -#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x40 +#define MLXSW_AFK_ELEMENT_STORAGE_SIZE 0x44 struct mlxsw_afk_element_inst { /* element instance in actual block */ enum mlxsw_afk_element element; diff --git a/drivers/net/ethernet/mellanox/mlxsw/i2c.c b/drivers/net/ethernet/mellanox/mlxsw/i2c.c index 2c586c2308aef1..41298835a11e16 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/i2c.c +++ b/drivers/net/ethernet/mellanox/mlxsw/i2c.c @@ -751,7 +751,7 @@ static void mlxsw_i2c_remove(struct i2c_client *client) int mlxsw_i2c_driver_register(struct i2c_driver *i2c_driver) { - i2c_driver->probe_new = mlxsw_i2c_probe; + i2c_driver->probe = mlxsw_i2c_probe; i2c_driver->remove = mlxsw_i2c_remove; return i2c_add_driver(i2c_driver); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 02a327744a61b6..4609b13bda02b9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -5139,14 +5139,6 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb, return notifier_from_errno(err); } -static struct notifier_block mlxsw_sp_inetaddr_valid_nb __read_mostly = { - .notifier_call = mlxsw_sp_inetaddr_valid_event, -}; - -static struct notifier_block mlxsw_sp_inet6addr_valid_nb __read_mostly = { - .notifier_call = mlxsw_sp_inet6addr_valid_event, -}; - static const struct pci_device_id mlxsw_sp1_pci_id_table[] = { {PCI_VDEVICE(MELLANOX, PCI_DEVICE_ID_MELLANOX_SPECTRUM), 0}, {0, }, @@ -5191,12 +5183,9 @@ static int __init mlxsw_sp_module_init(void) { int err; - register_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); - register_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); - err = mlxsw_core_driver_register(&mlxsw_sp1_driver); if (err) - goto err_sp1_core_driver_register; + return err; err = mlxsw_core_driver_register(&mlxsw_sp2_driver); if (err) @@ -5242,9 +5231,6 @@ static int __init mlxsw_sp_module_init(void) mlxsw_core_driver_unregister(&mlxsw_sp2_driver); err_sp2_core_driver_register: mlxsw_core_driver_unregister(&mlxsw_sp1_driver); -err_sp1_core_driver_register: - unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); - unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); return err; } @@ -5258,8 +5244,6 @@ static void __exit mlxsw_sp_module_exit(void) mlxsw_core_driver_unregister(&mlxsw_sp3_driver); mlxsw_core_driver_unregister(&mlxsw_sp2_driver); mlxsw_core_driver_unregister(&mlxsw_sp1_driver); - unregister_inet6addr_validator_notifier(&mlxsw_sp_inet6addr_valid_nb); - unregister_inetaddr_validator_notifier(&mlxsw_sp_inetaddr_valid_nb); } module_init(mlxsw_sp_module_init); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index 4c22f800451434..0b57c8d0cce0a0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -755,10 +755,6 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp); void mlxsw_sp_rif_macvlan_del(struct mlxsw_sp *mlxsw_sp, const struct net_device *macvlan_dev); -int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr); -int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr); int mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, struct net_device *l3_dev, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c index 00c32320f89155..4dea39f2b304b9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c @@ -123,10 +123,12 @@ const struct mlxsw_afk_ops mlxsw_sp1_afk_ops = { }; static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_0[] = { + MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1), MLXSW_AFK_ELEMENT_INST_BUF(DMAC_0_31, 0x04, 4), }; static struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_1[] = { + MLXSW_AFK_ELEMENT_INST_U32(FDB_MISS, 0x00, 3, 1), MLXSW_AFK_ELEMENT_INST_BUF(SMAC_0_31, 0x04, 4), }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c index 5416093c0e3580..c8a356accdf8ef 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c @@ -221,7 +221,7 @@ mlxsw_sp_dpipe_table_erif_entries_dump(void *priv, bool counters_enabled, for (; i < rif_count; i++) { struct mlxsw_sp_rif *rif = mlxsw_sp_rif_by_index(mlxsw_sp, i); - if (!rif || !mlxsw_sp_rif_dev(rif)) + if (!rif || !mlxsw_sp_rif_has_dev(rif)) continue; err = mlxsw_sp_erif_entry_get(mlxsw_sp, &entry, rif, counters_enabled); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c index 594cdcb90b3d03..72917f09e806e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c @@ -281,39 +281,38 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp, return 0; } -static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, - struct flow_cls_offload *f, - struct mlxsw_sp_flow_block *block) +static int +mlxsw_sp_flower_parse_meta_iif(struct mlxsw_sp_acl_rule_info *rulei, + const struct mlxsw_sp_flow_block *block, + const struct flow_match_meta *match, + struct netlink_ext_ack *extack) { - struct flow_rule *rule = flow_cls_offload_flow_rule(f); struct mlxsw_sp_port *mlxsw_sp_port; struct net_device *ingress_dev; - struct flow_match_meta match; - if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) + if (!match->mask->ingress_ifindex) return 0; - flow_rule_match_meta(rule, &match); - if (match.mask->ingress_ifindex != 0xFFFFFFFF) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Unsupported ingress ifindex mask"); + if (match->mask->ingress_ifindex != 0xFFFFFFFF) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask"); return -EINVAL; } ingress_dev = __dev_get_by_index(block->net, - match.key->ingress_ifindex); + match->key->ingress_ifindex); if (!ingress_dev) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Can't find specified ingress port to match on"); + NL_SET_ERR_MSG_MOD(extack, "Can't find specified ingress port to match on"); return -EINVAL; } if (!mlxsw_sp_port_dev_check(ingress_dev)) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on non-mlxsw ingress port"); + NL_SET_ERR_MSG_MOD(extack, "Can't match on non-mlxsw ingress port"); return -EINVAL; } mlxsw_sp_port = netdev_priv(ingress_dev); if (mlxsw_sp_port->mlxsw_sp != block->mlxsw_sp) { - NL_SET_ERR_MSG_MOD(f->common.extack, "Can't match on a port from different device"); + NL_SET_ERR_MSG_MOD(extack, "Can't match on a port from different device"); return -EINVAL; } @@ -321,9 +320,29 @@ static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, MLXSW_AFK_ELEMENT_SRC_SYS_PORT, mlxsw_sp_port->local_port, 0xFFFFFFFF); + return 0; } +static int mlxsw_sp_flower_parse_meta(struct mlxsw_sp_acl_rule_info *rulei, + struct flow_cls_offload *f, + struct mlxsw_sp_flow_block *block) +{ + struct flow_rule *rule = flow_cls_offload_flow_rule(f); + struct flow_match_meta match; + + if (!flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) + return 0; + + flow_rule_match_meta(rule, &match); + + mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_FDB_MISS, + match.key->l2_miss, match.mask->l2_miss); + + return mlxsw_sp_flower_parse_meta_iif(rulei, block, &match, + f->common.extack); +} + static void mlxsw_sp_flower_parse_ipv4(struct mlxsw_sp_acl_rule_info *rulei, struct flow_cls_offload *f) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c index 1f6bc0c7e91dda..69cd689dbc83e9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_mr.c @@ -704,12 +704,12 @@ void mlxsw_sp_mr_vif_del(struct mlxsw_sp_mr_table *mr_table, vifi_t vif_index) static struct mlxsw_sp_mr_vif * mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table, - const struct net_device *dev) + const struct mlxsw_sp_rif *rif) { vifi_t vif_index; for (vif_index = 0; vif_index < MAXVIFS; vif_index++) - if (mr_table->vifs[vif_index].dev == dev) + if (mlxsw_sp_rif_dev_is(rif, mr_table->vifs[vif_index].dev)) return &mr_table->vifs[vif_index]; return NULL; } @@ -717,13 +717,12 @@ mlxsw_sp_mr_dev_vif_lookup(struct mlxsw_sp_mr_table *mr_table, int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table, const struct mlxsw_sp_rif *rif) { - const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_mr_vif *mr_vif; - if (!rif_dev) + if (!mlxsw_sp_rif_has_dev(rif)) return 0; - mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev); + mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif); if (!mr_vif) return 0; return mlxsw_sp_mr_vif_resolve(mr_table, mr_vif->dev, mr_vif, @@ -733,13 +732,12 @@ int mlxsw_sp_mr_rif_add(struct mlxsw_sp_mr_table *mr_table, void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table, const struct mlxsw_sp_rif *rif) { - const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp_mr_vif *mr_vif; - if (!rif_dev) + if (!mlxsw_sp_rif_has_dev(rif)) return; - mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev); + mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif); if (!mr_vif) return; mlxsw_sp_mr_vif_unresolve(mr_table, mr_vif->dev, mr_vif); @@ -748,17 +746,16 @@ void mlxsw_sp_mr_rif_del(struct mlxsw_sp_mr_table *mr_table, void mlxsw_sp_mr_rif_mtu_update(struct mlxsw_sp_mr_table *mr_table, const struct mlxsw_sp_rif *rif, int mtu) { - const struct net_device *rif_dev = mlxsw_sp_rif_dev(rif); struct mlxsw_sp *mlxsw_sp = mr_table->mlxsw_sp; struct mlxsw_sp_mr_route_vif_entry *rve; struct mlxsw_sp_mr *mr = mlxsw_sp->mr; struct mlxsw_sp_mr_vif *mr_vif; - if (!rif_dev) + if (!mlxsw_sp_rif_has_dev(rif)) return; /* Search for a VIF that use that RIF */ - mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif_dev); + mr_vif = mlxsw_sp_mr_dev_vif_lookup(mr_table, rif); if (!mr_vif) return; diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c index d309b77a01944c..bb8eeb86edf751 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve_vxlan.c @@ -11,10 +11,12 @@ #include "spectrum_nve.h" #define MLXSW_SP_NVE_VXLAN_IPV4_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \ - VXLAN_F_LEARN) + VXLAN_F_LEARN | \ + VXLAN_F_LOCALBYPASS) #define MLXSW_SP_NVE_VXLAN_IPV6_SUPPORTED_FLAGS (VXLAN_F_IPV6 | \ VXLAN_F_UDP_ZERO_CSUM6_TX | \ - VXLAN_F_UDP_ZERO_CSUM6_RX) + VXLAN_F_UDP_ZERO_CSUM6_RX | \ + VXLAN_F_LOCALBYPASS) static bool mlxsw_sp_nve_vxlan_ipv4_flags_check(const struct vxlan_config *cfg, struct netlink_ext_ack *extack) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 4a73e2fe95ef90..f9328e8410f521 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -96,8 +96,8 @@ struct mlxsw_sp_rif_subport { struct mlxsw_sp_rif_ipip_lb { struct mlxsw_sp_rif common; struct mlxsw_sp_rif_ipip_lb_config lb_config; - u16 ul_vr_id; /* Reserved for Spectrum-2. */ - u16 ul_rif_id; /* Reserved for Spectrum. */ + u16 ul_vr_id; /* Spectrum-1. */ + u16 ul_rif_id; /* Spectrum-2+. */ }; struct mlxsw_sp_rif_params_ipip_lb { @@ -748,10 +748,11 @@ static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr) static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); struct mlxsw_sp_vr *vr; int i; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router->vrs[i]; if (!mlxsw_sp_vr_is_used(vr)) return vr; @@ -792,12 +793,13 @@ static u32 mlxsw_sp_fix_tb_id(u32 tb_id) static struct mlxsw_sp_vr *mlxsw_sp_vr_find(struct mlxsw_sp *mlxsw_sp, u32 tb_id) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); struct mlxsw_sp_vr *vr; int i; tb_id = mlxsw_sp_fix_tb_id(tb_id); - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router->vrs[i]; if (mlxsw_sp_vr_is_used(vr) && vr->tb_id == tb_id) return vr; @@ -959,6 +961,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib *fib, struct mlxsw_sp_lpm_tree *new_tree) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); enum mlxsw_sp_l3proto proto = fib->proto; struct mlxsw_sp_lpm_tree *old_tree; u8 old_id, new_id = new_tree->id; @@ -968,7 +971,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, old_tree = mlxsw_sp->router->lpm.proto_trees[proto]; old_id = old_tree->id; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { vr = &mlxsw_sp->router->vrs[i]; if (!mlxsw_sp_vr_lpm_tree_should_replace(vr, proto, old_id)) continue; @@ -2745,13 +2748,12 @@ static void mlxsw_sp_router_update_priority_work(struct work_struct *work) } static int mlxsw_sp_router_schedule_work(struct net *net, - struct notifier_block *nb, + struct mlxsw_sp_router *router, + struct neighbour *n, void (*cb)(struct work_struct *)) { struct mlxsw_sp_netevent_work *net_work; - struct mlxsw_sp_router *router; - router = container_of(nb, struct mlxsw_sp_router, netevent_nb); if (!net_eq(net, mlxsw_sp_net(router->mlxsw_sp))) return NOTIFY_DONE; @@ -2761,19 +2763,31 @@ static int mlxsw_sp_router_schedule_work(struct net *net, INIT_WORK(&net_work->work, cb); net_work->mlxsw_sp = router->mlxsw_sp; + net_work->n = n; mlxsw_core_schedule_work(&net_work->work); return NOTIFY_DONE; } +static bool mlxsw_sp_dev_lower_is_port(struct net_device *dev) +{ + struct mlxsw_sp_port *mlxsw_sp_port; + + rcu_read_lock(); + mlxsw_sp_port = mlxsw_sp_port_dev_lower_find_rcu(dev); + rcu_read_unlock(); + return !!mlxsw_sp_port; +} + static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, unsigned long event, void *ptr) { - struct mlxsw_sp_netevent_work *net_work; - struct mlxsw_sp_port *mlxsw_sp_port; - struct mlxsw_sp *mlxsw_sp; + struct mlxsw_sp_router *router; unsigned long interval; struct neigh_parms *p; struct neighbour *n; + struct net *net; + + router = container_of(nb, struct mlxsw_sp_router, netevent_nb); switch (event) { case NETEVENT_DELAY_PROBE_TIME_UPDATE: @@ -2787,51 +2801,37 @@ static int mlxsw_sp_router_netevent_event(struct notifier_block *nb, /* We are in atomic context and can't take RTNL mutex, * so use RCU variant to walk the device chain. */ - mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(p->dev); - if (!mlxsw_sp_port) + if (!mlxsw_sp_dev_lower_is_port(p->dev)) return NOTIFY_DONE; - mlxsw_sp = mlxsw_sp_port->mlxsw_sp; interval = jiffies_to_msecs(NEIGH_VAR(p, DELAY_PROBE_TIME)); - mlxsw_sp->router->neighs_update.interval = interval; - - mlxsw_sp_port_dev_put(mlxsw_sp_port); + router->neighs_update.interval = interval; break; case NETEVENT_NEIGH_UPDATE: n = ptr; + net = neigh_parms_net(n->parms); if (n->tbl->family != AF_INET && n->tbl->family != AF_INET6) return NOTIFY_DONE; - mlxsw_sp_port = mlxsw_sp_port_lower_dev_hold(n->dev); - if (!mlxsw_sp_port) + if (!mlxsw_sp_dev_lower_is_port(n->dev)) return NOTIFY_DONE; - net_work = kzalloc(sizeof(*net_work), GFP_ATOMIC); - if (!net_work) { - mlxsw_sp_port_dev_put(mlxsw_sp_port); - return NOTIFY_BAD; - } - - INIT_WORK(&net_work->work, mlxsw_sp_router_neigh_event_work); - net_work->mlxsw_sp = mlxsw_sp_port->mlxsw_sp; - net_work->n = n; - /* Take a reference to ensure the neighbour won't be * destructed until we drop the reference in delayed * work. */ neigh_clone(n); - mlxsw_core_schedule_work(&net_work->work); - mlxsw_sp_port_dev_put(mlxsw_sp_port); - break; + return mlxsw_sp_router_schedule_work(net, router, n, + mlxsw_sp_router_neigh_event_work); + case NETEVENT_IPV4_MPATH_HASH_UPDATE: case NETEVENT_IPV6_MPATH_HASH_UPDATE: - return mlxsw_sp_router_schedule_work(ptr, nb, + return mlxsw_sp_router_schedule_work(ptr, router, NULL, mlxsw_sp_router_mp_hash_event_work); case NETEVENT_IPV4_FWD_UPDATE_PRIORITY_UPDATE: - return mlxsw_sp_router_schedule_work(ptr, nb, + return mlxsw_sp_router_schedule_work(ptr, router, NULL, mlxsw_sp_router_update_priority_work); } @@ -7298,9 +7298,10 @@ static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp) { + int max_vrs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); int i, j; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { + for (i = 0; i < max_vrs; i++) { struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i]; if (!mlxsw_sp_vr_is_used(vr)) @@ -7699,11 +7700,12 @@ static struct mlxsw_sp_rif * mlxsw_sp_rif_find_by_dev(const struct mlxsw_sp *mlxsw_sp, const struct net_device *dev) { + int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); int i; - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) + for (i = 0; i < max_rifs; i++) if (mlxsw_sp->router->rifs[i] && - mlxsw_sp->router->rifs[i]->dev == dev) + mlxsw_sp_rif_dev_is(mlxsw_sp->router->rifs[i], dev)) return mlxsw_sp->router->rifs[i]; return NULL; @@ -8073,11 +8075,22 @@ int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif) return rif->dev->ifindex; } -const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) +static const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif) { return rif->dev; } +bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif) +{ + return !!mlxsw_sp_rif_dev(rif); +} + +bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif, + const struct net_device *dev) +{ + return mlxsw_sp_rif_dev(rif) == dev; +} + static void mlxsw_sp_rif_push_l3_stats(struct mlxsw_sp_rif *rif) { struct rtnl_hw_stats64 stats = {}; @@ -8874,8 +8887,8 @@ static int mlxsw_sp_inetaddr_event(struct notifier_block *nb, return notifier_from_errno(err); } -int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr) +static int mlxsw_sp_inetaddr_valid_event(struct notifier_block *unused, + unsigned long event, void *ptr) { struct in_validator_info *ivi = (struct in_validator_info *) ptr; struct net_device *dev = ivi->ivi_dev->dev; @@ -8957,8 +8970,8 @@ static int mlxsw_sp_inet6addr_event(struct notifier_block *nb, return NOTIFY_DONE; } -int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, - unsigned long event, void *ptr) +static int mlxsw_sp_inet6addr_valid_event(struct notifier_block *unused, + unsigned long event, void *ptr) { struct in6_validator_info *i6vi = (struct in6_validator_info *) ptr; struct net_device *dev = i6vi->i6vi_dev->dev; @@ -9724,7 +9737,7 @@ mlxsw_sp1_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, struct mlxsw_sp_vr *ul_vr; int err; - ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, NULL); + ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id, extack); if (IS_ERR(ul_vr)) return PTR_ERR(ul_vr); @@ -9923,7 +9936,7 @@ mlxsw_sp2_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif, struct mlxsw_sp_rif *ul_rif; int err; - ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, NULL); + ul_rif = mlxsw_sp_ul_rif_get(mlxsw_sp, ul_tb_id, extack); if (IS_ERR(ul_rif)) return PTR_ERR(ul_rif); @@ -10041,11 +10054,12 @@ static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp) { + int max_rifs = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); struct devlink *devlink = priv_to_devlink(mlxsw_sp->core); int i; WARN_ON_ONCE(atomic_read(&mlxsw_sp->router->rifs_count)); - for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) + for (i = 0; i < max_rifs; i++) WARN_ON_ONCE(mlxsw_sp->router->rifs[i]); devl_resource_occ_get_unregister(devlink, MLXSW_SP_RESOURCE_RIFS); @@ -10504,6 +10518,7 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, struct netlink_ext_ack *extack) { struct mlxsw_sp_router *router; + struct notifier_block *nb; int err; router = kzalloc(sizeof(*mlxsw_sp->router), GFP_KERNEL); @@ -10582,6 +10597,17 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, if (err) goto err_register_inet6addr_notifier; + router->inetaddr_valid_nb.notifier_call = mlxsw_sp_inetaddr_valid_event; + err = register_inetaddr_validator_notifier(&router->inetaddr_valid_nb); + if (err) + goto err_register_inetaddr_valid_notifier; + + nb = &router->inet6addr_valid_nb; + nb->notifier_call = mlxsw_sp_inet6addr_valid_event; + err = register_inet6addr_validator_notifier(nb); + if (err) + goto err_register_inet6addr_valid_notifier; + mlxsw_sp->router->netevent_nb.notifier_call = mlxsw_sp_router_netevent_event; err = register_netevent_notifier(&mlxsw_sp->router->netevent_nb); @@ -10621,6 +10647,10 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, err_register_nexthop_notifier: unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb); err_register_netevent_notifier: + unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb); +err_register_inet6addr_valid_notifier: + unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb); +err_register_inetaddr_valid_notifier: unregister_inet6addr_notifier(&router->inet6addr_nb); err_register_inet6addr_notifier: unregister_inetaddr_notifier(&router->inetaddr_nb); @@ -10658,15 +10688,18 @@ int mlxsw_sp_router_init(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) { + struct mlxsw_sp_router *router = mlxsw_sp->router; + unregister_netdevice_notifier_net(mlxsw_sp_net(mlxsw_sp), - &mlxsw_sp->router->netdevice_nb); - unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), - &mlxsw_sp->router->fib_nb); + &router->netdevice_nb); + unregister_fib_notifier(mlxsw_sp_net(mlxsw_sp), &router->fib_nb); unregister_nexthop_notifier(mlxsw_sp_net(mlxsw_sp), - &mlxsw_sp->router->nexthop_nb); - unregister_netevent_notifier(&mlxsw_sp->router->netevent_nb); - unregister_inet6addr_notifier(&mlxsw_sp->router->inet6addr_nb); - unregister_inetaddr_notifier(&mlxsw_sp->router->inetaddr_nb); + &router->nexthop_nb); + unregister_netevent_notifier(&router->netevent_nb); + unregister_inet6addr_validator_notifier(&router->inet6addr_valid_nb); + unregister_inetaddr_validator_notifier(&router->inetaddr_valid_nb); + unregister_inet6addr_notifier(&router->inet6addr_nb); + unregister_inetaddr_notifier(&router->inetaddr_nb); mlxsw_core_flush_owq(); mlxsw_sp_mp_hash_fini(mlxsw_sp); mlxsw_sp_neigh_fini(mlxsw_sp); @@ -10674,12 +10707,12 @@ void mlxsw_sp_router_fini(struct mlxsw_sp *mlxsw_sp) mlxsw_sp_vrs_fini(mlxsw_sp); mlxsw_sp_mr_fini(mlxsw_sp); mlxsw_sp_lpm_fini(mlxsw_sp); - rhashtable_destroy(&mlxsw_sp->router->nexthop_group_ht); - rhashtable_destroy(&mlxsw_sp->router->nexthop_ht); + rhashtable_destroy(&router->nexthop_group_ht); + rhashtable_destroy(&router->nexthop_ht); mlxsw_sp_ipips_fini(mlxsw_sp); mlxsw_sp_rifs_fini(mlxsw_sp); __mlxsw_sp_router_fini(mlxsw_sp); - cancel_delayed_work_sync(&mlxsw_sp->router->nh_grp_activity_dw); - mutex_destroy(&mlxsw_sp->router->lock); - kfree(mlxsw_sp->router); + cancel_delayed_work_sync(&router->nh_grp_activity_dw); + mutex_destroy(&router->lock); + kfree(router); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h index 37d6e4c80e6a66..5ff443f27136eb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h @@ -52,6 +52,8 @@ struct mlxsw_sp_router { struct notifier_block inetaddr_nb; struct notifier_block inet6addr_nb; struct notifier_block netdevice_nb; + struct notifier_block inetaddr_valid_nb; + struct notifier_block inet6addr_valid_nb; const struct mlxsw_sp_rif_ops **rif_ops_arr; const struct mlxsw_sp_ipip_ops **ipip_ops_arr; struct mlxsw_sp_router_nve_decap nve_decap_config; @@ -91,7 +93,9 @@ u16 mlxsw_sp_ipip_lb_ul_vr_id(const struct mlxsw_sp_rif_ipip_lb *rif); u16 mlxsw_sp_ipip_lb_ul_rif_id(const struct mlxsw_sp_rif_ipip_lb *lb_rif); u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev); int mlxsw_sp_rif_dev_ifindex(const struct mlxsw_sp_rif *rif); -const struct net_device *mlxsw_sp_rif_dev(const struct mlxsw_sp_rif *rif); +bool mlxsw_sp_rif_has_dev(const struct mlxsw_sp_rif *rif); +bool mlxsw_sp_rif_dev_is(const struct mlxsw_sp_rif *rif, + const struct net_device *dev); int mlxsw_sp_rif_counter_value_get(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_rif *rif, enum mlxsw_sp_rif_counter_dir dir, diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 957d96a91a8af7..f1bded993edceb 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -160,16 +160,13 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter) { struct lan743x_csr *csr = &adapter->csr; resource_size_t bar_start, bar_length; - int result; bar_start = pci_resource_start(adapter->pdev, 0); bar_length = pci_resource_len(adapter->pdev, 0); csr->csr_address = devm_ioremap(&adapter->pdev->dev, bar_start, bar_length); - if (!csr->csr_address) { - result = -ENOMEM; - goto clean_up; - } + if (!csr->csr_address) + return -ENOMEM; csr->id_rev = lan743x_csr_read(adapter, ID_REV); csr->fpga_rev = lan743x_csr_read(adapter, FPGA_REV); @@ -177,10 +174,8 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter) "ID_REV = 0x%08X, FPGA_REV = %d.%d\n", csr->id_rev, FPGA_REV_GET_MAJOR_(csr->fpga_rev), FPGA_REV_GET_MINOR_(csr->fpga_rev)); - if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev)) { - result = -ENODEV; - goto clean_up; - } + if (!ID_REV_IS_VALID_CHIP_ID_(csr->id_rev)) + return -ENODEV; csr->flags = LAN743X_CSR_FLAG_SUPPORTS_INTR_AUTO_SET_CLR; switch (csr->id_rev & ID_REV_CHIP_REV_MASK_) { @@ -193,12 +188,7 @@ static int lan743x_csr_init(struct lan743x_adapter *adapter) break; } - result = lan743x_csr_light_reset(adapter); - if (result) - goto clean_up; - return 0; -clean_up: - return result; + return lan743x_csr_light_reset(adapter); } static void lan743x_intr_software_isr(struct lan743x_adapter *adapter) diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c index 5f01b21acdd1ba..f6931dfb3e68e6 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_main.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_main.c @@ -1039,6 +1039,16 @@ static int lan966x_reset_switch(struct lan966x *lan966x) reset_control_reset(switch_reset); + /* Don't reinitialize the switch core, if it is already initialized. In + * case it is initialized twice, some pointers inside the queue system + * in HW will get corrupted and then after a while the queue system gets + * full and no traffic is passing through the switch. The issue is seen + * when loading and unloading the driver and sending traffic through the + * switch. + */ + if (lan_rd(lan966x, SYS_RESET_CFG) & SYS_RESET_CFG_CORE_ENA) + return 0; + lan_wr(SYS_RESET_CFG_CORE_ENA_SET(0), lan966x, SYS_RESET_CFG); lan_wr(SYS_RAM_INIT_RAM_INIT_SET(1), lan966x, SYS_RAM_INIT); ret = readx_poll_timeout(lan966x_ram_init, lan966x, diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c index cf0cc7562d0423..ee652f2d235956 100644 --- a/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c +++ b/drivers/net/ethernet/microchip/lan966x/lan966x_tc.c @@ -21,8 +21,14 @@ static int lan966x_tc_setup_qdisc_mqprio(struct lan966x_port *port, static int lan966x_tc_setup_qdisc_taprio(struct lan966x_port *port, struct tc_taprio_qopt_offload *taprio) { - return taprio->enable ? lan966x_taprio_add(port, taprio) : - lan966x_taprio_del(port); + switch (taprio->cmd) { + case TAPRIO_CMD_REPLACE: + return lan966x_taprio_add(port, taprio); + case TAPRIO_CMD_DESTROY: + return lan966x_taprio_del(port); + default: + return -EOPNOTSUPP; + } } static int lan966x_tc_setup_qdisc_tbf(struct lan966x_port *port, diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 06d6292e09b332..cd4d5ceb9f2db1 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -179,6 +179,14 @@ netdev_tx_t mana_start_xmit(struct sk_buff *skb, struct net_device *ndev) pkg.tx_oob.s_oob.short_vp_offset = txq->vp_offset; } + if (skb_vlan_tag_present(skb)) { + pkt_fmt = MANA_LONG_PKT_FMT; + pkg.tx_oob.l_oob.inject_vlan_pri_tag = 1; + pkg.tx_oob.l_oob.pcp = skb_vlan_tag_get_prio(skb); + pkg.tx_oob.l_oob.dei = skb_vlan_tag_get_cfi(skb); + pkg.tx_oob.l_oob.vlan_id = skb_vlan_tag_get_id(skb); + } + pkg.tx_oob.s_oob.pkt_fmt = pkt_fmt; if (pkt_fmt == MANA_SHORT_PKT_FMT) { @@ -1279,8 +1287,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq) if (comp_read < 1) return; - apc->eth_stats.tx_cqes = comp_read; - for (i = 0; i < comp_read; i++) { struct mana_tx_comp_oob *cqe_oob; @@ -1363,8 +1369,6 @@ static void mana_poll_tx_cq(struct mana_cq *cq) WARN_ON_ONCE(1); cq->work_done = pkt_transmitted; - - apc->eth_stats.tx_cqes -= pkt_transmitted; } static void mana_post_pkt_rxq(struct mana_rxq *rxq) @@ -1461,6 +1465,12 @@ static void mana_rx_skb(void *buf_va, struct mana_rxcomp_oob *cqe, skb_set_hash(skb, hash_value, PKT_HASH_TYPE_L3); } + if (cqe->rx_vlantag_present) { + u16 vlan_tci = cqe->rx_vlan_id; + + __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tci); + } + u64_stats_update_begin(&rx_stats->syncp); rx_stats->packets++; rx_stats->bytes += pkt_len; @@ -1626,15 +1636,11 @@ static void mana_poll_rx_cq(struct mana_cq *cq) { struct gdma_comp *comp = cq->gdma_comp_buf; struct mana_rxq *rxq = cq->rxq; - struct mana_port_context *apc; int comp_read, i; - apc = netdev_priv(rxq->ndev); - comp_read = mana_gd_poll_cq(cq->gdma_cq, comp, CQE_POLLING_BUFFER); WARN_ON_ONCE(comp_read > CQE_POLLING_BUFFER); - apc->eth_stats.rx_cqes = comp_read; rxq->xdp_flush = false; for (i = 0; i < comp_read; i++) { @@ -1646,8 +1652,6 @@ static void mana_poll_rx_cq(struct mana_cq *cq) return; mana_process_rx_cqe(rxq, cq, &comp[i]); - - apc->eth_stats.rx_cqes--; } if (rxq->xdp_flush) @@ -2461,8 +2465,9 @@ static int mana_probe_port(struct mana_context *ac, int port_idx, ndev->hw_features |= NETIF_F_RXCSUM; ndev->hw_features |= NETIF_F_TSO | NETIF_F_TSO6; ndev->hw_features |= NETIF_F_RXHASH; - ndev->features = ndev->hw_features; - ndev->vlan_features = 0; + ndev->features = ndev->hw_features | NETIF_F_HW_VLAN_CTAG_TX | + NETIF_F_HW_VLAN_CTAG_RX; + ndev->vlan_features = ndev->features; ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_NDO_XMIT; diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c index a64c81410dc14c..0dc78679f62096 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c @@ -13,11 +13,9 @@ static const struct { } mana_eth_stats[] = { {"stop_queue", offsetof(struct mana_ethtool_stats, stop_queue)}, {"wake_queue", offsetof(struct mana_ethtool_stats, wake_queue)}, - {"tx_cqes", offsetof(struct mana_ethtool_stats, tx_cqes)}, {"tx_cq_err", offsetof(struct mana_ethtool_stats, tx_cqe_err)}, {"tx_cqe_unknown_type", offsetof(struct mana_ethtool_stats, tx_cqe_unknown_type)}, - {"rx_cqes", offsetof(struct mana_ethtool_stats, rx_cqes)}, {"rx_coalesced_err", offsetof(struct mana_ethtool_stats, rx_coalesced_err)}, {"rx_cqe_unknown_type", offsetof(struct mana_ethtool_stats, diff --git a/drivers/net/ethernet/mscc/ocelot_flower.c b/drivers/net/ethernet/mscc/ocelot_flower.c index ee052404eb55ae..e0916afcddfb96 100644 --- a/drivers/net/ethernet/mscc/ocelot_flower.c +++ b/drivers/net/ethernet/mscc/ocelot_flower.c @@ -592,6 +592,16 @@ ocelot_flower_parse_key(struct ocelot *ocelot, int port, bool ingress, return -EOPNOTSUPP; } + if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_META)) { + struct flow_match_meta match; + + flow_rule_match_meta(rule, &match); + if (match.mask->l2_miss) { + NL_SET_ERR_MSG_MOD(extack, "Can't match on \"l2_miss\""); + return -EOPNOTSUPP; + } + } + /* For VCAP ES0 (egress rewriter) we can match on the ingress port */ if (!ingress) { ret = ocelot_flower_parse_indev(ocelot, port, f, filter); diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index c5687d94ea8850..7b7e1c5b00f472 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -66,6 +66,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c index bf6bae5571585c..8c6954c58a8863 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_devlink.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_devlink.c @@ -311,8 +311,6 @@ nfp_devlink_flash_update(struct devlink *devlink, } const struct devlink_ops nfp_devlink_ops = { - .port_split = nfp_devlink_port_split, - .port_unsplit = nfp_devlink_port_unsplit, .sb_pool_get = nfp_devlink_sb_pool_get, .sb_pool_set = nfp_devlink_sb_pool_set, .eswitch_mode_get = nfp_devlink_eswitch_mode_get, @@ -321,6 +319,11 @@ const struct devlink_ops nfp_devlink_ops = { .flash_update = nfp_devlink_flash_update, }; +static const struct devlink_port_ops nfp_devlink_port_ops = { + .port_split = nfp_devlink_port_split, + .port_unsplit = nfp_devlink_port_unsplit, +}; + int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) { struct devlink_port_attrs attrs = {}; @@ -351,7 +354,8 @@ int nfp_devlink_port_register(struct nfp_app *app, struct nfp_port *port) devlink = priv_to_devlink(app->pf); - return devl_port_register(devlink, &port->dl_port, port->eth_id); + return devl_port_register_with_ops(devlink, &port->dl_port, + port->eth_id, &nfp_devlink_port_ops); } void nfp_devlink_port_unregister(struct nfp_port *port) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 62f0bf91d1e1e5..b7cce746b5c0ad 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -2418,6 +2418,8 @@ static void nfp_net_rss_init(struct nfp_net *nn) /* Enable IPv4/IPv6 TCP by default */ nn->rss_cfg = NFP_NET_CFG_RSS_IPV4_TCP | NFP_NET_CFG_RSS_IPV6_TCP | + NFP_NET_CFG_RSS_IPV4_UDP | + NFP_NET_CFG_RSS_IPV6_UDP | FIELD_PREP(NFP_NET_CFG_RSS_HFUNC, nn->rss_hfunc) | NFP_NET_CFG_RSS_MASK; } diff --git a/drivers/net/ethernet/nvidia/forcedeth.c b/drivers/net/ethernet/nvidia/forcedeth.c index 0605d1ee490dd0..7a549b834e970a 100644 --- a/drivers/net/ethernet/nvidia/forcedeth.c +++ b/drivers/net/ethernet/nvidia/forcedeth.c @@ -6138,6 +6138,7 @@ static int nv_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) return 0; out_error: + nv_mgmt_release_sema(dev); if (phystate_orig) writel(phystate|NVREG_ADAPTCTL_RUNNING, base + NvRegAdapterControl); out_freering: diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index 4e18b64dceb9a5..9651cc714ef267 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -5,7 +5,7 @@ config PCH_GBE tristate "OKI SEMICONDUCTOR IOH(ML7223/ML7831) GbE" - depends on PCI && (X86_32 || COMPILE_TEST) + depends on PCI && (MIPS_GENERIC || X86_32 || COMPILE_TEST) depends on PTP_1588_CLOCK select MII select PTP_1588_CLOCK_PCH diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index 9b2b96fa36af83..3a6b0a9bc24147 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -104,6 +104,15 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs, memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size); } +static void ionic_get_link_ext_stats(struct net_device *netdev, + struct ethtool_link_ext_stats *stats) +{ + struct ionic_lif *lif = netdev_priv(netdev); + + if (lif->ionic->pdev->is_physfn) + stats->link_down_events = lif->link_down_count; +} + static int ionic_get_link_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *ks) { @@ -1074,6 +1083,7 @@ static const struct ethtool_ops ionic_ethtool_ops = { .get_regs_len = ionic_get_regs_len, .get_regs = ionic_get_regs, .get_link = ethtool_op_get_link, + .get_link_ext_stats = ionic_get_link_ext_stats, .get_link_ksettings = ionic_get_link_ksettings, .set_link_ksettings = ionic_set_link_ksettings, .get_coalesce = ionic_get_coalesce, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index 957027e546b306..6ccc1ea91992f1 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -168,6 +168,7 @@ static void ionic_link_status_check(struct ionic_lif *lif) } } else { if (netif_carrier_ok(netdev)) { + lif->link_down_count++; netdev_info(netdev, "Link down\n"); netif_carrier_off(netdev); } diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index c9c4c46d5a166f..fd2ea670e7d84c 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -201,6 +201,7 @@ struct ionic_lif { u64 hw_features; bool registered; u16 lif_type; + unsigned int link_down_count; unsigned int nmcast; unsigned int nucast; unsigned int nvlans; diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 2edd6bf64a3cc2..7776d3bdd459a5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -1903,7 +1903,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats) { u32 i; - if (!cdev) { + if (!cdev || cdev->recov_in_prog) { memset(stats, 0, sizeof(*stats)); return; } diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h index f9931ecb7baa25..4d83ceebdc498d 100644 --- a/drivers/net/ethernet/qlogic/qede/qede.h +++ b/drivers/net/ethernet/qlogic/qede/qede.h @@ -269,6 +269,10 @@ struct qede_dev { #define QEDE_ERR_WARN 3 struct qede_dump_info dump_info; + struct delayed_work periodic_task; + unsigned long stats_coal_ticks; + u32 stats_coal_usecs; + spinlock_t stats_lock; /* lock for vport stats access */ }; enum QEDE_STATE { diff --git a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c index 374a86b875a3e5..95820cf1cd6cc7 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_ethtool.c +++ b/drivers/net/ethernet/qlogic/qede/qede_ethtool.c @@ -429,6 +429,8 @@ static void qede_get_ethtool_stats(struct net_device *dev, } } + spin_lock(&edev->stats_lock); + for (i = 0; i < QEDE_NUM_STATS; i++) { if (qede_is_irrelevant_stat(edev, i)) continue; @@ -438,6 +440,8 @@ static void qede_get_ethtool_stats(struct net_device *dev, buf++; } + spin_unlock(&edev->stats_lock); + __qede_unlock(edev); } @@ -829,6 +833,7 @@ static int qede_get_coalesce(struct net_device *dev, coal->rx_coalesce_usecs = rx_coal; coal->tx_coalesce_usecs = tx_coal; + coal->stats_block_coalesce_usecs = edev->stats_coal_usecs; return rc; } @@ -842,6 +847,19 @@ int qede_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal, int i, rc = 0; u16 rxc, txc; + if (edev->stats_coal_usecs != coal->stats_block_coalesce_usecs) { + edev->stats_coal_usecs = coal->stats_block_coalesce_usecs; + if (edev->stats_coal_usecs) { + edev->stats_coal_ticks = usecs_to_jiffies(edev->stats_coal_usecs); + schedule_delayed_work(&edev->periodic_task, 0); + + DP_INFO(edev, "Configured stats coal ticks=%lu jiffies\n", + edev->stats_coal_ticks); + } else { + cancel_delayed_work_sync(&edev->periodic_task); + } + } + if (!netif_running(dev)) { DP_INFO(edev, "Interface is down\n"); return -EINVAL; @@ -2252,7 +2270,8 @@ static int qede_get_per_coalesce(struct net_device *dev, } static const struct ethtool_ops qede_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS, + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_STATS_BLOCK_USECS, .get_link_ksettings = qede_get_link_ksettings, .set_link_ksettings = qede_set_link_ksettings, .get_drvinfo = qede_get_drvinfo, @@ -2303,7 +2322,8 @@ static const struct ethtool_ops qede_ethtool_ops = { }; static const struct ethtool_ops qede_vf_ethtool_ops = { - .supported_coalesce_params = ETHTOOL_COALESCE_USECS, + .supported_coalesce_params = ETHTOOL_COALESCE_USECS | + ETHTOOL_COALESCE_STATS_BLOCK_USECS, .get_link_ksettings = qede_get_link_ksettings, .get_drvinfo = qede_get_drvinfo, .get_msglevel = qede_get_msglevel, diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c index 4c6c685820e3f0..4b004a7281903f 100644 --- a/drivers/net/ethernet/qlogic/qede/qede_main.c +++ b/drivers/net/ethernet/qlogic/qede/qede_main.c @@ -307,6 +307,8 @@ void qede_fill_by_demand_stats(struct qede_dev *edev) edev->ops->get_vport_stats(edev->cdev, &stats); + spin_lock(&edev->stats_lock); + p_common->no_buff_discards = stats.common.no_buff_discards; p_common->packet_too_big_discard = stats.common.packet_too_big_discard; p_common->ttl0_discard = stats.common.ttl0_discard; @@ -404,6 +406,8 @@ void qede_fill_by_demand_stats(struct qede_dev *edev) p_ah->tx_1519_to_max_byte_packets = stats.ah.tx_1519_to_max_byte_packets; } + + spin_unlock(&edev->stats_lock); } static void qede_get_stats64(struct net_device *dev, @@ -412,9 +416,10 @@ static void qede_get_stats64(struct net_device *dev, struct qede_dev *edev = netdev_priv(dev); struct qede_stats_common *p_common; - qede_fill_by_demand_stats(edev); p_common = &edev->stats.common; + spin_lock(&edev->stats_lock); + stats->rx_packets = p_common->rx_ucast_pkts + p_common->rx_mcast_pkts + p_common->rx_bcast_pkts; stats->tx_packets = p_common->tx_ucast_pkts + p_common->tx_mcast_pkts + @@ -434,6 +439,8 @@ static void qede_get_stats64(struct net_device *dev, stats->collisions = edev->stats.bb.tx_total_collisions; stats->rx_crc_errors = p_common->rx_crc_errors; stats->rx_frame_errors = p_common->rx_align_errors; + + spin_unlock(&edev->stats_lock); } #ifdef CONFIG_QED_SRIOV @@ -1063,6 +1070,23 @@ static void qede_unlock(struct qede_dev *edev) rtnl_unlock(); } +static void qede_periodic_task(struct work_struct *work) +{ + struct qede_dev *edev = container_of(work, struct qede_dev, + periodic_task.work); + + qede_fill_by_demand_stats(edev); + schedule_delayed_work(&edev->periodic_task, edev->stats_coal_ticks); +} + +static void qede_init_periodic_task(struct qede_dev *edev) +{ + INIT_DELAYED_WORK(&edev->periodic_task, qede_periodic_task); + spin_lock_init(&edev->stats_lock); + edev->stats_coal_usecs = USEC_PER_SEC; + edev->stats_coal_ticks = usecs_to_jiffies(USEC_PER_SEC); +} + static void qede_sp_task(struct work_struct *work) { struct qede_dev *edev = container_of(work, struct qede_dev, @@ -1082,6 +1106,7 @@ static void qede_sp_task(struct work_struct *work) */ if (test_and_clear_bit(QEDE_SP_RECOVERY, &edev->sp_flags)) { + cancel_delayed_work_sync(&edev->periodic_task); #ifdef CONFIG_QED_SRIOV /* SRIOV must be disabled outside the lock to avoid a deadlock. * The recovery of the active VFs is currently not supported. @@ -1272,6 +1297,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, */ INIT_DELAYED_WORK(&edev->sp_task, qede_sp_task); mutex_init(&edev->qede_lock); + qede_init_periodic_task(edev); rc = register_netdev(edev->ndev); if (rc) { @@ -1296,6 +1322,11 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level, edev->rx_copybreak = QEDE_RX_HDR_SIZE; qede_log_probe(edev); + + /* retain user config (for example - after recovery) */ + if (edev->stats_coal_usecs) + schedule_delayed_work(&edev->periodic_task, 0); + return 0; err4: @@ -1364,6 +1395,7 @@ static void __qede_remove(struct pci_dev *pdev, enum qede_remove_mode mode) unregister_netdev(ndev); cancel_delayed_work_sync(&edev->sp_task); + cancel_delayed_work_sync(&edev->periodic_task); edev->ops->common->set_power_state(cdev, PCI_D0); diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index a7e376e7e689c0..9445f04f8d48c1 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -616,10 +616,10 @@ struct rtl8169_private { struct work_struct work; } wk; - spinlock_t config25_lock; - spinlock_t mac_ocp_lock; + raw_spinlock_t config25_lock; + raw_spinlock_t mac_ocp_lock; - spinlock_t cfg9346_usage_lock; + raw_spinlock_t cfg9346_usage_lock; int cfg9346_usage_count; unsigned supports_gmii:1; @@ -671,20 +671,20 @@ static void rtl_lock_config_regs(struct rtl8169_private *tp) { unsigned long flags; - spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); + raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); if (!--tp->cfg9346_usage_count) RTL_W8(tp, Cfg9346, Cfg9346_Lock); - spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags); + raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags); } static void rtl_unlock_config_regs(struct rtl8169_private *tp) { unsigned long flags; - spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); + raw_spin_lock_irqsave(&tp->cfg9346_usage_lock, flags); if (!tp->cfg9346_usage_count++) RTL_W8(tp, Cfg9346, Cfg9346_Unlock); - spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags); + raw_spin_unlock_irqrestore(&tp->cfg9346_usage_lock, flags); } static void rtl_pci_commit(struct rtl8169_private *tp) @@ -698,10 +698,10 @@ static void rtl_mod_config2(struct rtl8169_private *tp, u8 clear, u8 set) unsigned long flags; u8 val; - spin_lock_irqsave(&tp->config25_lock, flags); + raw_spin_lock_irqsave(&tp->config25_lock, flags); val = RTL_R8(tp, Config2); RTL_W8(tp, Config2, (val & ~clear) | set); - spin_unlock_irqrestore(&tp->config25_lock, flags); + raw_spin_unlock_irqrestore(&tp->config25_lock, flags); } static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set) @@ -709,10 +709,10 @@ static void rtl_mod_config5(struct rtl8169_private *tp, u8 clear, u8 set) unsigned long flags; u8 val; - spin_lock_irqsave(&tp->config25_lock, flags); + raw_spin_lock_irqsave(&tp->config25_lock, flags); val = RTL_R8(tp, Config5); RTL_W8(tp, Config5, (val & ~clear) | set); - spin_unlock_irqrestore(&tp->config25_lock, flags); + raw_spin_unlock_irqrestore(&tp->config25_lock, flags); } static bool rtl_is_8125(struct rtl8169_private *tp) @@ -899,9 +899,9 @@ static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) { unsigned long flags; - spin_lock_irqsave(&tp->mac_ocp_lock, flags); + raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags); __r8168_mac_ocp_write(tp, reg, data); - spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); + raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); } static u16 __r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) @@ -919,9 +919,9 @@ static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) unsigned long flags; u16 val; - spin_lock_irqsave(&tp->mac_ocp_lock, flags); + raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags); val = __r8168_mac_ocp_read(tp, reg); - spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); + raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); return val; } @@ -932,10 +932,10 @@ static void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask, unsigned long flags; u16 data; - spin_lock_irqsave(&tp->mac_ocp_lock, flags); + raw_spin_lock_irqsave(&tp->mac_ocp_lock, flags); data = __r8168_mac_ocp_read(tp, reg); __r8168_mac_ocp_write(tp, reg, (data & ~mask) | set); - spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); + raw_spin_unlock_irqrestore(&tp->mac_ocp_lock, flags); } /* Work around a hw issue with RTL8168g PHY, the quirk disables @@ -1420,14 +1420,14 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0); } - spin_lock_irqsave(&tp->config25_lock, flags); + raw_spin_lock_irqsave(&tp->config25_lock, flags); for (i = 0; i < tmp; i++) { options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; if (wolopts & cfg[i].opt) options |= cfg[i].mask; RTL_W8(tp, cfg[i].reg, options); } - spin_unlock_irqrestore(&tp->config25_lock, flags); + raw_spin_unlock_irqrestore(&tp->config25_lock, flags); switch (tp->mac_version) { case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06: @@ -5164,6 +5164,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) int jumbo_max, region, rc; enum mac_version chipset; struct net_device *dev; + u32 txconfig; u16 xid; dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp)); @@ -5179,9 +5180,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->eee_adv = -1; tp->ocp_base = OCP_STD_PHY_BASE; - spin_lock_init(&tp->cfg9346_usage_lock); - spin_lock_init(&tp->config25_lock); - spin_lock_init(&tp->mac_ocp_lock); + raw_spin_lock_init(&tp->cfg9346_usage_lock); + raw_spin_lock_init(&tp->config25_lock); + raw_spin_lock_init(&tp->mac_ocp_lock); dev->tstats = devm_netdev_alloc_pcpu_stats(&pdev->dev, struct pcpu_sw_netstats); @@ -5195,38 +5196,35 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* enable device (incl. PCI PM wakeup and hotplug setup) */ rc = pcim_enable_device(pdev); - if (rc < 0) { - dev_err(&pdev->dev, "enable failure\n"); - return rc; - } + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "enable failure\n"); if (pcim_set_mwi(pdev) < 0) dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n"); /* use first MMIO region */ region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1; - if (region < 0) { - dev_err(&pdev->dev, "no MMIO resource found\n"); - return -ENODEV; - } + if (region < 0) + return dev_err_probe(&pdev->dev, -ENODEV, "no MMIO resource found\n"); rc = pcim_iomap_regions(pdev, BIT(region), KBUILD_MODNAME); - if (rc < 0) { - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); - return rc; - } + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "cannot remap MMIO, aborting\n"); tp->mmio_addr = pcim_iomap_table(pdev)[region]; - xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf; + txconfig = RTL_R32(tp, TxConfig); + if (txconfig == ~0U) + return dev_err_probe(&pdev->dev, -EIO, "PCI read failed\n"); + + xid = (txconfig >> 20) & 0xfcf; /* Identify chip attached to board */ chipset = rtl8169_get_mac_version(xid, tp->supports_gmii); - if (chipset == RTL_GIGA_MAC_NONE) { - dev_err(&pdev->dev, "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", xid); - return -ENODEV; - } - + if (chipset == RTL_GIGA_MAC_NONE) + return dev_err_probe(&pdev->dev, -ENODEV, + "unknown chip XID %03x, contact r8169 maintainers (see MAINTAINERS file)\n", + xid); tp->mac_version = chipset; tp->dash_type = rtl_check_dash(tp); @@ -5246,10 +5244,9 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl_hw_reset(tp); rc = rtl_alloc_irq(tp); - if (rc < 0) { - dev_err(&pdev->dev, "Can't allocate interrupt\n"); - return rc; - } + if (rc < 0) + return dev_err_probe(&pdev->dev, rc, "Can't allocate interrupt\n"); + tp->irq = pci_irq_vector(pdev, 0); INIT_WORK(&tp->wk.work, rtl_task); diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c index 29afaddb598db4..84f62c77eb8f8a 100644 --- a/drivers/net/ethernet/renesas/rswitch.c +++ b/drivers/net/ethernet/renesas/rswitch.c @@ -90,6 +90,11 @@ static int rswitch_bpool_config(struct rswitch_private *priv) return rswitch_reg_wait(priv->addr, CABPIRM, CABPIRM_BPR, CABPIRM_BPR); } +static void rswitch_coma_init(struct rswitch_private *priv) +{ + iowrite32(CABPPFLC_INIT_VALUE, priv->addr + CABPPFLC0); +} + /* R-Switch-2 block (TOP) */ static void rswitch_top_init(struct rswitch_private *priv) { @@ -156,24 +161,6 @@ static int rswitch_gwca_axi_ram_reset(struct rswitch_private *priv) return rswitch_reg_wait(priv->addr, GWARIRM, GWARIRM_ARR, GWARIRM_ARR); } -static void rswitch_gwca_set_rate_limit(struct rswitch_private *priv, int rate) -{ - u32 gwgrlulc, gwgrlc; - - switch (rate) { - case 1000: - gwgrlulc = 0x0000005f; - gwgrlc = 0x00010260; - break; - default: - dev_err(&priv->pdev->dev, "%s: This rate is not supported (%d)\n", __func__, rate); - return; - } - - iowrite32(gwgrlulc, priv->addr + GWGRLULC); - iowrite32(gwgrlc, priv->addr + GWGRLC); -} - static bool rswitch_is_any_data_irq(struct rswitch_private *priv, u32 *dis, bool tx) { u32 *mask = tx ? priv->gwca.tx_irq_bits : priv->gwca.rx_irq_bits; @@ -402,7 +389,7 @@ static int rswitch_gwca_queue_format(struct net_device *ndev, linkfix->die_dt = DT_LINKFIX; rswitch_desc_set_dptr(linkfix, gq->ring_dma); - iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_EDE, + iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) | GWDCC_EDE, priv->addr + GWDCC_OFFS(gq->index)); return 0; @@ -500,7 +487,8 @@ static int rswitch_gwca_queue_ext_ts_format(struct net_device *ndev, linkfix->die_dt = DT_LINKFIX; rswitch_desc_set_dptr(linkfix, gq->ring_dma); - iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DQT : 0) | GWDCC_ETS | GWDCC_EDE, + iowrite32(GWDCC_BALR | (gq->dir_tx ? GWDCC_DCP(GWCA_IPV_NUM) | GWDCC_DQT : 0) | + GWDCC_ETS | GWDCC_EDE, priv->addr + GWDCC_OFFS(gq->index)); return 0; @@ -649,7 +637,8 @@ static int rswitch_gwca_hw_init(struct rswitch_private *priv) iowrite32(lower_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC10); iowrite32(upper_32_bits(priv->gwca.ts_queue.ring_dma), priv->addr + GWTDCAC00); iowrite32(GWCA_TS_IRQ_BIT, priv->addr + GWTSDCC0); - rswitch_gwca_set_rate_limit(priv, priv->gwca.speed); + + iowrite32(GWTPC_PPPL(GWCA_IPV_NUM), priv->addr + GWTPC0); for (i = 0; i < RSWITCH_NUM_PORTS; i++) { err = rswitch_rxdmac_init(priv, i); @@ -729,7 +718,7 @@ static bool rswitch_rx(struct net_device *ndev, int *quota) } skb_put(skb, pkt_len); skb->protocol = eth_type_trans(skb, ndev); - netif_receive_skb(skb); + napi_gro_receive(&rdev->napi, skb); rdev->ndev->stats.rx_packets++; rdev->ndev->stats.rx_bytes += pkt_len; @@ -1485,7 +1474,7 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd if (rswitch_get_num_cur_queues(gq) >= gq->ring_size - 1) { netif_stop_subqueue(ndev, 0); - return ret; + return NETDEV_TX_BUSY; } if (skb_put_padto(skb, ETH_ZLEN)) @@ -1502,7 +1491,8 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd rswitch_desc_set_dptr(&desc->desc, dma_addr); desc->desc.info_ds = cpu_to_le16(skb->len); - desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | INFO1_FMT); + desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) | + INFO1_IPV(GWCA_IPV_NUM) | INFO1_FMT); if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { struct rswitch_gwca_ts_info *ts_info; @@ -1772,6 +1762,8 @@ static int rswitch_init(struct rswitch_private *priv) if (err < 0) return err; + rswitch_coma_init(priv); + err = rswitch_gwca_linkfix_alloc(priv); if (err < 0) return -ENOMEM; diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h index b3e0411b408ef8..bb9ed971a97cac 100644 --- a/drivers/net/ethernet/renesas/rswitch.h +++ b/drivers/net/ethernet/renesas/rswitch.h @@ -48,6 +48,7 @@ #define GWCA_NUM_IRQS 8 #define GWCA_INDEX 0 #define AGENT_INDEX_GWCA 3 +#define GWCA_IPV_NUM 0 #define GWRO RSWITCH_GWCA0_OFFSET #define GWCA_TS_IRQ_RESOURCE_NAME "gwca0_rxts0" @@ -768,11 +769,14 @@ enum rswitch_gwca_mode { #define GWARIRM_ARR BIT(1) #define GWDCC_BALR BIT(24) +#define GWDCC_DCP_MASK GENMASK(18, 16) +#define GWDCC_DCP(prio) FIELD_PREP(GWDCC_DCP_MASK, (prio)) #define GWDCC_DQT BIT(11) #define GWDCC_ETS BIT(9) #define GWDCC_EDE BIT(8) #define GWTRC(queue) (GWTRC0 + (queue) / 32 * 4) +#define GWTPC_PPPL(ipv) BIT(ipv) #define GWDCC_OFFS(queue) (GWDCC0 + (queue) * 4) #define GWDIS(i) (GWDIS0 + (i) * 0x10) @@ -789,6 +793,8 @@ enum rswitch_gwca_mode { #define CABPIRM_BPIOG BIT(0) #define CABPIRM_BPR BIT(1) +#define CABPPFLC_INIT_VALUE 0x00800080 + /* MFWD */ #define FWPC0_LTHTA BIT(0) #define FWPC0_IP4UE BIT(3) @@ -863,6 +869,7 @@ enum DIE_DT { /* For transmission */ #define INFO1_TSUN(val) ((u64)(val) << 8ULL) +#define INFO1_IPV(prio) ((u64)(prio) << 28ULL) #define INFO1_CSD0(index) ((u64)(index) << 32ULL) #define INFO1_CSD1(index) ((u64)(index) << 40ULL) #define INFO1_DV(port_vector) ((u64)(port_vector) << 48ULL) diff --git a/drivers/net/ethernet/sfc/Makefile b/drivers/net/ethernet/sfc/Makefile index 55b9c73cd8ef40..16293b58e0a89a 100644 --- a/drivers/net/ethernet/sfc/Makefile +++ b/drivers/net/ethernet/sfc/Makefile @@ -10,7 +10,8 @@ sfc-y += efx.o efx_common.o efx_channels.o nic.o \ efx_devlink.o sfc-$(CONFIG_SFC_MTD) += mtd.o sfc-$(CONFIG_SFC_SRIOV) += sriov.o ef10_sriov.o ef100_sriov.o ef100_rep.o \ - mae.o tc.o tc_bindings.o tc_counters.o + mae.o tc.o tc_bindings.o tc_counters.o \ + tc_encap_actions.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/ethernet/sfc/ef100_netdev.c b/drivers/net/ethernet/sfc/ef100_netdev.c index be395cd8770bc7..7f7d560cb2b4c9 100644 --- a/drivers/net/ethernet/sfc/ef100_netdev.c +++ b/drivers/net/ethernet/sfc/ef100_netdev.c @@ -24,6 +24,7 @@ #include "rx_common.h" #include "ef100_sriov.h" #include "tc_bindings.h" +#include "tc_encap_actions.h" #include "efx_devlink.h" static void ef100_update_name(struct efx_nic *efx) @@ -40,19 +41,26 @@ static int ef100_alloc_vis(struct efx_nic *efx, unsigned int *allocated_vis) unsigned int tx_vis = efx->n_tx_channels + efx->n_extra_tx_channels; unsigned int rx_vis = efx->n_rx_channels; unsigned int min_vis, max_vis; + int rc; EFX_WARN_ON_PARANOID(efx->tx_queues_per_channel != 1); tx_vis += efx->n_xdp_channels * efx->xdp_tx_per_channel; max_vis = max(rx_vis, tx_vis); - /* Currently don't handle resource starvation and only accept - * our maximum needs and no less. + /* We require at least a single complete TX channel worth of queues. */ + min_vis = efx->tx_queues_per_channel; + + rc = efx_mcdi_alloc_vis(efx, min_vis, max_vis, + NULL, allocated_vis); + + /* We retry allocating VIs by reallocating channels when we have not + * been able to allocate the maximum VIs. */ - min_vis = max_vis; + if (!rc && *allocated_vis < max_vis) + rc = -EAGAIN; - return efx_mcdi_alloc_vis(efx, min_vis, max_vis, - NULL, allocated_vis); + return rc; } static int ef100_remap_bar(struct efx_nic *efx, int max_vis) @@ -133,9 +141,41 @@ static int ef100_net_open(struct net_device *net_dev) goto fail; rc = ef100_alloc_vis(efx, &allocated_vis); - if (rc) + if (rc && rc != -EAGAIN) goto fail; + /* Try one more time but with the maximum number of channels + * equal to the allocated VIs, which would more likely succeed. + */ + if (rc == -EAGAIN) { + rc = efx_mcdi_free_vis(efx); + if (rc) + goto fail; + + efx_remove_interrupts(efx); + efx->max_channels = allocated_vis; + + rc = efx_probe_interrupts(efx); + if (rc) + goto fail; + + rc = efx_set_channels(efx); + if (rc) + goto fail; + + rc = ef100_alloc_vis(efx, &allocated_vis); + if (rc && rc != -EAGAIN) + goto fail; + + /* It should be very unlikely that we failed here again, but in + * such a case we return ENOSPC. + */ + if (rc == -EAGAIN) { + rc = -ENOSPC; + goto fail; + } + } + rc = efx_probe_channels(efx); if (rc) return rc; @@ -261,14 +301,38 @@ int ef100_netdev_event(struct notifier_block *this, { struct efx_nic *efx = container_of(this, struct efx_nic, netdev_notifier); struct net_device *net_dev = netdev_notifier_info_to_dev(ptr); + struct ef100_nic_data *nic_data = efx->nic_data; + int err; if (efx->net_dev == net_dev && (event == NETDEV_CHANGENAME || event == NETDEV_REGISTER)) ef100_update_name(efx); + if (!nic_data->grp_mae) + return NOTIFY_DONE; + err = efx_tc_netdev_event(efx, event, net_dev); + if (err & NOTIFY_STOP_MASK) + return err; + return NOTIFY_DONE; } +static int ef100_netevent_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + struct efx_nic *efx = container_of(this, struct efx_nic, netevent_notifier); + struct ef100_nic_data *nic_data = efx->nic_data; + int err; + + if (!nic_data->grp_mae) + return NOTIFY_DONE; + err = efx_tc_netevent_event(efx, event, ptr); + if (err & NOTIFY_STOP_MASK) + return err; + + return NOTIFY_DONE; +}; + static int ef100_register_netdev(struct efx_nic *efx) { struct net_device *net_dev = efx->net_dev; @@ -328,6 +392,7 @@ void ef100_remove_netdev(struct efx_probe_data *probe_data) rtnl_unlock(); unregister_netdevice_notifier(&efx->netdev_notifier); + unregister_netevent_notifier(&efx->netevent_notifier); #if defined(CONFIG_SFC_SRIOV) if (!efx->type->is_vf) efx_ef100_pci_sriov_disable(efx, true); @@ -448,6 +513,14 @@ int ef100_probe_netdev(struct efx_probe_data *probe_data) goto fail; } + efx->netevent_notifier.notifier_call = ef100_netevent_event; + rc = register_netevent_notifier(&efx->netevent_notifier); + if (rc) { + netif_err(efx, probe, efx->net_dev, + "Failed to register netevent notifier, rc=%d\n", rc); + goto fail; + } + efx_probe_devlink_unlock(efx); return rc; fail: diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index a4f22d8e6ac7e7..d670a319b37995 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -32,6 +32,7 @@ #include "io.h" #include "selftest.h" #include "sriov.h" +#include "efx_devlink.h" #include "mcdi_port_common.h" #include "mcdi_pcol.h" @@ -877,6 +878,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) if (efx->type->sriov_fini) efx->type->sriov_fini(efx); + efx_fini_devlink_lock(efx); efx_unregister_netdev(efx); efx_mtd_remove(efx); @@ -886,6 +888,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev) efx_fini_io(efx); pci_dbg(efx->pci_dev, "shutdown successful\n"); + efx_fini_devlink_and_unlock(efx); efx_fini_struct(efx); free_netdev(efx->net_dev); probe_data = container_of(efx, struct efx_probe_data, efx); @@ -1025,7 +1028,13 @@ static int efx_pci_probe_post_io(struct efx_nic *efx) NETDEV_XDP_ACT_REDIRECT | NETDEV_XDP_ACT_NDO_XMIT; + /* devlink creation, registration and lock */ + rc = efx_probe_devlink_and_lock(efx); + if (rc) + pci_err(efx->pci_dev, "devlink registration failed"); + rc = efx_register_netdev(efx); + efx_probe_devlink_unlock(efx); if (!rc) return 0; diff --git a/drivers/net/ethernet/sfc/efx_devlink.c b/drivers/net/ethernet/sfc/efx_devlink.c index 381b805659d39a..b82dad50a5b130 100644 --- a/drivers/net/ethernet/sfc/efx_devlink.c +++ b/drivers/net/ethernet/sfc/efx_devlink.c @@ -25,40 +25,6 @@ struct efx_devlink { }; #ifdef CONFIG_SFC_SRIOV -static void efx_devlink_del_port(struct devlink_port *dl_port) -{ - if (!dl_port) - return; - devl_port_unregister(dl_port); -} - -static int efx_devlink_add_port(struct efx_nic *efx, - struct mae_mport_desc *mport) -{ - bool external = false; - - if (!ef100_mport_on_local_intf(efx, mport)) - external = true; - - switch (mport->mport_type) { - case MAE_MPORT_DESC_MPORT_TYPE_VNIC: - if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL) - devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx, - mport->vf_idx, - external); - else - devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx, - external); - break; - default: - /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */ - return 0; - } - - mport->dl_port.index = mport->mport_id; - - return devl_port_register(efx->devlink, &mport->dl_port, mport->mport_id); -} static int efx_devlink_port_addr_get(struct devlink_port *port, u8 *hw_addr, int *hw_addr_len, @@ -158,6 +124,48 @@ static int efx_devlink_port_addr_set(struct devlink_port *port, return rc; } +static const struct devlink_port_ops sfc_devlink_port_ops = { + .port_fn_hw_addr_get = efx_devlink_port_addr_get, + .port_fn_hw_addr_set = efx_devlink_port_addr_set, +}; + +static void efx_devlink_del_port(struct devlink_port *dl_port) +{ + if (!dl_port) + return; + devl_port_unregister(dl_port); +} + +static int efx_devlink_add_port(struct efx_nic *efx, + struct mae_mport_desc *mport) +{ + bool external = false; + + if (!ef100_mport_on_local_intf(efx, mport)) + external = true; + + switch (mport->mport_type) { + case MAE_MPORT_DESC_MPORT_TYPE_VNIC: + if (mport->vf_idx != MAE_MPORT_DESC_VF_IDX_NULL) + devlink_port_attrs_pci_vf_set(&mport->dl_port, 0, mport->pf_idx, + mport->vf_idx, + external); + else + devlink_port_attrs_pci_pf_set(&mport->dl_port, 0, mport->pf_idx, + external); + break; + default: + /* MAE_MPORT_DESC_MPORT_ALIAS and UNDEFINED */ + return 0; + } + + mport->dl_port.index = mport->mport_id; + + return devl_port_register_with_ops(efx->devlink, &mport->dl_port, + mport->mport_id, + &sfc_devlink_port_ops); +} + #endif static int efx_devlink_info_nvram_partition(struct efx_nic *efx, @@ -171,9 +179,14 @@ static int efx_devlink_info_nvram_partition(struct efx_nic *efx, rc = efx_mcdi_nvram_metadata(efx, partition_type, NULL, version, NULL, 0); + + /* If the partition does not exist, that is not an error. */ + if (rc == -ENOENT) + return 0; + if (rc) { - netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed\n", - version_name); + netif_err(efx, drv, efx->net_dev, "mcdi nvram %s: failed (rc=%d)\n", + version_name, rc); return rc; } @@ -187,36 +200,33 @@ static int efx_devlink_info_nvram_partition(struct efx_nic *efx, static int efx_devlink_info_stored_versions(struct efx_nic *efx, struct devlink_info_req *req) { - int rc; - - rc = efx_devlink_info_nvram_partition(efx, req, - NVRAM_PARTITION_TYPE_BUNDLE, - DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID); - if (rc) - return rc; + int err; - rc = efx_devlink_info_nvram_partition(efx, req, - NVRAM_PARTITION_TYPE_MC_FIRMWARE, - DEVLINK_INFO_VERSION_GENERIC_FW_MGMT); - if (rc) - return rc; - - rc = efx_devlink_info_nvram_partition(efx, req, - NVRAM_PARTITION_TYPE_SUC_FIRMWARE, - EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC); - if (rc) - return rc; - - rc = efx_devlink_info_nvram_partition(efx, req, - NVRAM_PARTITION_TYPE_EXPANSION_ROM, - EFX_DEVLINK_INFO_VERSION_FW_EXPROM); - if (rc) - return rc; - - rc = efx_devlink_info_nvram_partition(efx, req, - NVRAM_PARTITION_TYPE_EXPANSION_UEFI, - EFX_DEVLINK_INFO_VERSION_FW_UEFI); - return rc; + /* We do not care here about the specific error but just if an error + * happened. The specific error will be reported inside the call + * through system messages, and if any error happened in any call + * below, we report it through extack. + */ + err = efx_devlink_info_nvram_partition(efx, req, + NVRAM_PARTITION_TYPE_BUNDLE, + DEVLINK_INFO_VERSION_GENERIC_FW_BUNDLE_ID); + + err |= efx_devlink_info_nvram_partition(efx, req, + NVRAM_PARTITION_TYPE_MC_FIRMWARE, + DEVLINK_INFO_VERSION_GENERIC_FW_MGMT); + + err |= efx_devlink_info_nvram_partition(efx, req, + NVRAM_PARTITION_TYPE_SUC_FIRMWARE, + EFX_DEVLINK_INFO_VERSION_FW_MGMT_SUC); + + err |= efx_devlink_info_nvram_partition(efx, req, + NVRAM_PARTITION_TYPE_EXPANSION_ROM, + EFX_DEVLINK_INFO_VERSION_FW_EXPROM); + + err |= efx_devlink_info_nvram_partition(efx, req, + NVRAM_PARTITION_TYPE_EXPANSION_UEFI, + EFX_DEVLINK_INFO_VERSION_FW_UEFI); + return err; } #define EFX_VER_FLAG(_f) \ @@ -587,37 +597,26 @@ static int efx_devlink_info_get(struct devlink *devlink, { struct efx_devlink *devlink_private = devlink_priv(devlink); struct efx_nic *efx = devlink_private->efx; - int rc; + int err; - /* Several different MCDI commands are used. We report first error - * through extack returning at that point. Specific error - * information via system messages. + /* Several different MCDI commands are used. We report if errors + * happened through extack. Specific error information via system + * messages inside the calls. */ - rc = efx_devlink_info_board_cfg(efx, req); - if (rc) { - NL_SET_ERR_MSG_MOD(extack, "Getting board info failed"); - return rc; - } - rc = efx_devlink_info_stored_versions(efx, req); - if (rc) { - NL_SET_ERR_MSG_MOD(extack, "Getting stored versions failed"); - return rc; - } - rc = efx_devlink_info_running_versions(efx, req); - if (rc) { - NL_SET_ERR_MSG_MOD(extack, "Getting running versions failed"); - return rc; - } + err = efx_devlink_info_board_cfg(efx, req); + + err |= efx_devlink_info_stored_versions(efx, req); + + err |= efx_devlink_info_running_versions(efx, req); + + if (err) + NL_SET_ERR_MSG_MOD(extack, "Errors when getting device info. Check system messages"); return 0; } static const struct devlink_ops sfc_devlink_ops = { .info_get = efx_devlink_info_get, -#ifdef CONFIG_SFC_SRIOV - .port_function_hw_addr_get = efx_devlink_port_addr_get, - .port_function_hw_addr_set = efx_devlink_port_addr_set, -#endif }; #ifdef CONFIG_SFC_SRIOV diff --git a/drivers/net/ethernet/sfc/mae.c b/drivers/net/ethernet/sfc/mae.c index 37a4c6925ad44f..0cab508f2f9d18 100644 --- a/drivers/net/ethernet/sfc/mae.c +++ b/drivers/net/ethernet/sfc/mae.c @@ -15,6 +15,7 @@ #include "mcdi.h" #include "mcdi_pcol.h" #include "mcdi_pcol_mae.h" +#include "tc_encap_actions.h" int efx_mae_allocate_mport(struct efx_nic *efx, u32 *id, u32 *label) { @@ -610,6 +611,87 @@ static int efx_mae_encap_type_to_mae_type(enum efx_encap_type type) } } +int efx_mae_allocate_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(EFX_TC_MAX_ENCAP_HDR)); + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_LEN); + size_t inlen, outlen; + int rc; + + rc = efx_mae_encap_type_to_mae_type(encap->type); + if (rc < 0) + return rc; + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_ENCAP_TYPE, rc); + inlen = MC_CMD_MAE_ENCAP_HEADER_ALLOC_IN_LEN(encap->encap_hdr_len); + if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */ + return -EINVAL; + memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_ALLOC_IN_HDR_DATA), + encap->encap_hdr, + encap->encap_hdr_len); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_ALLOC, inbuf, + inlen, outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + encap->fw_id = MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID); + return 0; +} + +int efx_mae_update_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(EFX_TC_MAX_ENCAP_HDR)); + size_t inlen; + int rc; + + rc = efx_mae_encap_type_to_mae_type(encap->type); + if (rc < 0) + return rc; + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_ENCAP_TYPE, rc); + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_EH_ID, + encap->fw_id); + inlen = MC_CMD_MAE_ENCAP_HEADER_UPDATE_IN_LEN(encap->encap_hdr_len); + if (WARN_ON(inlen > sizeof(inbuf))) /* can't happen */ + return -EINVAL; + memcpy(MCDI_PTR(inbuf, MAE_ENCAP_HEADER_UPDATE_IN_HDR_DATA), + encap->encap_hdr, + encap->encap_hdr_len); + + BUILD_BUG_ON(MC_CMD_MAE_ENCAP_HEADER_UPDATE_OUT_LEN != 0); + return efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_UPDATE, inbuf, + inlen, NULL, 0, NULL); +} + +int efx_mae_free_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_OUT_LEN(1)); + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ENCAP_HEADER_FREE_IN_LEN(1)); + size_t outlen; + int rc; + + MCDI_SET_DWORD(inbuf, MAE_ENCAP_HEADER_FREE_IN_EH_ID, encap->fw_id); + rc = efx_mcdi_rpc(efx, MC_CMD_MAE_ENCAP_HEADER_FREE, inbuf, + sizeof(inbuf), outbuf, sizeof(outbuf), &outlen); + if (rc) + return rc; + if (outlen < sizeof(outbuf)) + return -EIO; + /* FW freed a different ID than we asked for, should also never happen. + * Warn because it means we've now got a different idea to the FW of + * what encap_mds exist, which could cause mayhem later. + */ + if (WARN_ON(MCDI_DWORD(outbuf, MAE_ENCAP_HEADER_FREE_OUT_FREED_EH_ID) != encap->fw_id)) + return -EIO; + /* We're probably about to free @encap, but let's just make sure its + * fw_id is blatted so that it won't look valid if it leaks out. + */ + encap->fw_id = MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL; + return 0; +} + int efx_mae_lookup_mport(struct efx_nic *efx, u32 vf_idx, u32 *id) { struct ef100_nic_data *nic_data = efx->nic_data; @@ -833,8 +915,12 @@ int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act) MCDI_SET_WORD_BE(inbuf, MAE_ACTION_SET_ALLOC_IN_VLAN1_PROTO_BE, act->vlan_proto[1]); } - MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, - MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); + if (act->encap_md) + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, + act->encap_md->fw_id); + else + MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_ENCAP_HEADER_ID, + MC_CMD_MAE_ENCAP_HEADER_ALLOC_OUT_ENCAP_HEADER_ID_NULL); if (act->deliver) MCDI_SET_DWORD(inbuf, MAE_ACTION_SET_ALLOC_IN_DELIVER, act->dest_mport); @@ -1229,6 +1315,29 @@ int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, return 0; } +int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id) +{ + MCDI_DECLARE_BUF(inbuf, MC_CMD_MAE_ACTION_RULE_UPDATE_IN_LEN); + MCDI_DECLARE_STRUCT_PTR(response); + + BUILD_BUG_ON(MC_CMD_MAE_ACTION_RULE_UPDATE_OUT_LEN); + response = _MCDI_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_RESPONSE); + + MCDI_SET_DWORD(inbuf, MAE_ACTION_RULE_UPDATE_IN_AR_ID, id); + if (efx_mae_asl_id(acts_id)) { + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, acts_id); + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, + MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL); + } else { + /* We only had one AS, so we didn't wrap it in an ASL */ + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_ASL_ID, + MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); + MCDI_STRUCT_SET_DWORD(response, MAE_ACTION_RULE_RESPONSE_AS_ID, acts_id); + } + return efx_mcdi_rpc(efx, MC_CMD_MAE_ACTION_RULE_UPDATE, inbuf, sizeof(inbuf), + NULL, 0, NULL); +} + int efx_mae_delete_rule(struct efx_nic *efx, u32 id) { MCDI_DECLARE_BUF(outbuf, MC_CMD_MAE_ACTION_RULE_DELETE_OUT_LEN(1)); diff --git a/drivers/net/ethernet/sfc/mae.h b/drivers/net/ethernet/sfc/mae.h index 1cf8dfeb0c286a..24abfe50969091 100644 --- a/drivers/net/ethernet/sfc/mae.h +++ b/drivers/net/ethernet/sfc/mae.h @@ -90,6 +90,13 @@ int efx_mae_check_encap_type_supported(struct efx_nic *efx, int efx_mae_allocate_counter(struct efx_nic *efx, struct efx_tc_counter *cnt); int efx_mae_free_counter(struct efx_nic *efx, struct efx_tc_counter *cnt); +int efx_mae_allocate_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); +int efx_mae_update_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); +int efx_mae_free_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); + int efx_mae_alloc_action_set(struct efx_nic *efx, struct efx_tc_action_set *act); int efx_mae_free_action_set(struct efx_nic *efx, u32 fw_id); @@ -105,6 +112,7 @@ int efx_mae_unregister_encap_match(struct efx_nic *efx, int efx_mae_insert_rule(struct efx_nic *efx, const struct efx_tc_match *match, u32 prio, u32 acts_id, u32 *id); +int efx_mae_update_rule(struct efx_nic *efx, u32 acts_id, u32 id); int efx_mae_delete_rule(struct efx_nic *efx, u32 id); int efx_init_mae(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index fcd51d3992fa68..a7a22b01979479 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -27,6 +27,7 @@ #include #include #include +#include #include "enum.h" #include "bitfield.h" @@ -996,6 +997,7 @@ struct efx_mae; * @xdp_rxq_info_failed: Have any of the rx queues failed to initialise their * xdp_rxq_info structures? * @netdev_notifier: Netdevice notifier. + * @netevent_notifier: Netevent notifier (for neighbour updates). * @tc: state for TC offload (EF100). * @devlink: reference to devlink structure owned by this device * @dl_port: devlink port associated with the PF @@ -1183,6 +1185,7 @@ struct efx_nic { bool xdp_rxq_info_failed; struct notifier_block netdev_notifier; + struct notifier_block netevent_notifier; struct efx_tc_state *tc; struct devlink *devlink; diff --git a/drivers/net/ethernet/sfc/siena/tx_common.c b/drivers/net/ethernet/sfc/siena/tx_common.c index 93a32d61944f08..a7a9ab304e1368 100644 --- a/drivers/net/ethernet/sfc/siena/tx_common.c +++ b/drivers/net/ethernet/sfc/siena/tx_common.c @@ -12,6 +12,7 @@ #include "efx.h" #include "nic_common.h" #include "tx_common.h" +#include static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue) { diff --git a/drivers/net/ethernet/sfc/tc.c b/drivers/net/ethernet/sfc/tc.c index 6dfbdb39f2fe29..77acdb60381e3e 100644 --- a/drivers/net/ethernet/sfc/tc.c +++ b/drivers/net/ethernet/sfc/tc.c @@ -14,11 +14,12 @@ #include #include "tc.h" #include "tc_bindings.h" +#include "tc_encap_actions.h" #include "mae.h" #include "ef100_rep.h" #include "efx.h" -static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) +enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) { if (netif_is_vxlan(net_dev)) return EFX_ENCAP_TYPE_VXLAN; @@ -33,8 +34,8 @@ static enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev) * May return NULL for the PF (us), or an error pointer for a device that * isn't supported as a TC offload endpoint */ -static struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, - struct net_device *dev) +struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, + struct net_device *dev) { struct efx_rep *efv; @@ -70,7 +71,7 @@ static s64 efx_tc_flower_internal_mport(struct efx_nic *efx, struct efx_rep *efv } /* Convert a driver-internal vport ID into an external device (wire or VF) */ -static s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv) +s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv) { u32 mport; @@ -111,6 +112,10 @@ static void efx_tc_free_action_set(struct efx_nic *efx, } if (act->count) efx_tc_flower_put_counter_index(efx, act->count); + if (act->encap_md) { + list_del(&act->encap_user); + efx_tc_flower_release_encap_md(efx, act->encap_md); + } kfree(act); } @@ -594,6 +599,7 @@ enum efx_tc_action_order { EFX_TC_AO_VLAN_POP, EFX_TC_AO_VLAN_PUSH, EFX_TC_AO_COUNT, + EFX_TC_AO_ENCAP, EFX_TC_AO_DELIVER }; /* Determine whether we can add @new action without violating order */ @@ -623,6 +629,10 @@ static bool efx_tc_flower_action_order_ok(const struct efx_tc_action_set *act, if (act->count) return false; fallthrough; + case EFX_TC_AO_ENCAP: + if (act->encap_md) + return false; + fallthrough; case EFX_TC_AO_DELIVER: return !act->deliver; default: @@ -687,13 +697,12 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, if (!found) { /* We don't care. */ netif_dbg(efx, drv, efx->net_dev, "Ignoring foreign filter that doesn't egdev us\n"); - rc = -EOPNOTSUPP; - goto release; + return -EOPNOTSUPP; } rc = efx_mae_match_check_caps(efx, &match.mask, NULL); if (rc) - goto release; + return rc; if (efx_tc_match_is_encap(&match.mask)) { enum efx_encap_type type; @@ -702,8 +711,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, if (type == EFX_ENCAP_TYPE_NONE) { NL_SET_ERR_MSG_MOD(extack, "Egress encap match on unsupported tunnel device"); - rc = -EOPNOTSUPP; - goto release; + return -EOPNOTSUPP; } rc = efx_mae_check_encap_type_supported(efx, type); @@ -711,26 +719,25 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, NL_SET_ERR_MSG_FMT_MOD(extack, "Firmware reports no support for %s encap match", efx_tc_encap_type_name(type)); - goto release; + return rc; } rc = efx_tc_flower_record_encap_match(efx, &match, type, EFX_TC_EM_DIRECT, 0, 0, extack); if (rc) - goto release; + return rc; } else { /* This is not a tunnel decap rule, ignore it */ netif_dbg(efx, drv, efx->net_dev, "Ignoring foreign filter without encap match\n"); - rc = -EOPNOTSUPP; - goto release; + return -EOPNOTSUPP; } rule = kzalloc(sizeof(*rule), GFP_USER); if (!rule) { rc = -ENOMEM; - goto release; + goto out_free; } INIT_LIST_HEAD(&rule->acts.list); rule->cookie = tc->cookie; @@ -742,7 +749,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, "Ignoring already-offloaded rule (cookie %lx)\n", tc->cookie); rc = -EEXIST; - goto release; + goto out_free; } act = kzalloc(sizeof(*act), GFP_USER); @@ -907,6 +914,7 @@ static int efx_tc_flower_replace_foreign(struct efx_nic *efx, efx_tc_match_action_ht_params); efx_tc_free_action_set_list(efx, &rule->acts, false); } +out_free: kfree(rule); if (match.encap) efx_tc_flower_release_encap_match(efx, match.encap); @@ -920,11 +928,13 @@ static int efx_tc_flower_replace(struct efx_nic *efx, { struct flow_rule *fr = flow_cls_offload_flow_rule(tc); struct netlink_ext_ack *extack = tc->common.extack; + const struct ip_tunnel_info *encap_info = NULL; struct efx_tc_flow_rule *rule = NULL, *old; struct efx_tc_action_set *act = NULL; const struct flow_action_entry *fa; struct efx_rep *from_efv, *to_efv; struct efx_tc_match match; + u32 acts_id; s64 rc; int i; @@ -963,8 +973,7 @@ static int efx_tc_flower_replace(struct efx_nic *efx, return rc; if (efx_tc_match_is_encap(&match.mask)) { NL_SET_ERR_MSG_MOD(extack, "Ingress enc_key matches not supported"); - rc = -EOPNOTSUPP; - goto release; + return -EOPNOTSUPP; } if (tc->common.chain_index) { @@ -988,9 +997,9 @@ static int efx_tc_flower_replace(struct efx_nic *efx, if (old) { netif_dbg(efx, drv, efx->net_dev, "Already offloaded rule (cookie %lx)\n", tc->cookie); - rc = -EEXIST; NL_SET_ERR_MSG_MOD(extack, "Rule already offloaded"); - goto release; + kfree(rule); + return -EEXIST; } /* Parse actions */ @@ -1090,6 +1099,48 @@ static int efx_tc_flower_replace(struct efx_nic *efx, case FLOW_ACTION_MIRRED: save = *act; + if (encap_info) { + struct efx_tc_encap_action *encap; + + if (!efx_tc_flower_action_order_ok(act, + EFX_TC_AO_ENCAP)) { + rc = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "Encap action violates action order"); + goto release; + } + encap = efx_tc_flower_create_encap_md( + efx, encap_info, fa->dev, extack); + if (IS_ERR_OR_NULL(encap)) { + rc = PTR_ERR(encap); + if (!rc) + rc = -EIO; /* arbitrary */ + goto release; + } + act->encap_md = encap; + list_add_tail(&act->encap_user, &encap->users); + act->dest_mport = encap->dest_mport; + act->deliver = 1; + rc = efx_mae_alloc_action_set(efx, act); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to write action set to hw (encap)"); + goto release; + } + list_add_tail(&act->list, &rule->acts.list); + act->user = &rule->acts; + act = NULL; + if (fa->id == FLOW_ACTION_REDIRECT) + break; /* end of the line */ + /* Mirror, so continue on with saved act */ + save.count = NULL; + act = kzalloc(sizeof(*act), GFP_USER); + if (!act) { + rc = -ENOMEM; + goto release; + } + *act = save; + break; + } + if (!efx_tc_flower_action_order_ok(act, EFX_TC_AO_DELIVER)) { /* can't happen */ rc = -EOPNOTSUPP; @@ -1153,6 +1204,37 @@ static int efx_tc_flower_replace(struct efx_nic *efx, act->vlan_proto[act->vlan_push] = fa->vlan.proto; act->vlan_push++; break; + case FLOW_ACTION_TUNNEL_ENCAP: + if (encap_info) { + /* Can't specify encap multiple times. + * If you want to overwrite an existing + * encap_info, use an intervening + * FLOW_ACTION_TUNNEL_DECAP to clear it. + */ + NL_SET_ERR_MSG_MOD(extack, "Tunnel key set when already set"); + rc = -EINVAL; + goto release; + } + if (!fa->tunnel) { + NL_SET_ERR_MSG_MOD(extack, "Tunnel key set is missing key"); + rc = -EOPNOTSUPP; + goto release; + } + encap_info = fa->tunnel; + break; + case FLOW_ACTION_TUNNEL_DECAP: + if (encap_info) { + encap_info = NULL; + break; + } + /* Since we don't support enc_key matches on ingress + * (and if we did there'd be no tunnel-device to give + * us a type), we can't offload a decap that's not + * just undoing a previous encap action. + */ + NL_SET_ERR_MSG_MOD(extack, "Cannot offload tunnel decap action without tunnel device"); + rc = -EOPNOTSUPP; + goto release; default: NL_SET_ERR_MSG_FMT_MOD(extack, "Unhandled action %u", fa->id); @@ -1196,8 +1278,21 @@ static int efx_tc_flower_replace(struct efx_nic *efx, NL_SET_ERR_MSG_MOD(extack, "Failed to write action set list to hw"); goto release; } + if (from_efv == EFX_EFV_PF) + /* PF netdev, so rule applies to traffic from wire */ + rule->fallback = &efx->tc->facts.pf; + else + /* repdev, so rule applies to traffic from representee */ + rule->fallback = &efx->tc->facts.reps; + if (!efx_tc_check_ready(efx, rule)) { + netif_dbg(efx, drv, efx->net_dev, "action not ready for hw\n"); + acts_id = rule->fallback->fw_id; + } else { + netif_dbg(efx, drv, efx->net_dev, "ready for hw\n"); + acts_id = rule->acts.fw_id; + } rc = efx_mae_insert_rule(efx, &rule->match, EFX_TC_PRIO_TC, - rule->acts.fw_id, &rule->fw_id); + acts_id, &rule->fw_id); if (rc) { NL_SET_ERR_MSG_MOD(extack, "Failed to insert rule in hw"); goto release_acts; @@ -1394,6 +1489,58 @@ void efx_tc_deconfigure_default_rule(struct efx_nic *efx, rule->fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; } +static int efx_tc_configure_fallback_acts(struct efx_nic *efx, u32 eg_port, + struct efx_tc_action_set_list *acts) +{ + struct efx_tc_action_set *act; + int rc; + + act = kzalloc(sizeof(*act), GFP_KERNEL); + if (!act) + return -ENOMEM; + act->deliver = 1; + act->dest_mport = eg_port; + rc = efx_mae_alloc_action_set(efx, act); + if (rc) + goto fail1; + EFX_WARN_ON_PARANOID(!list_empty(&acts->list)); + list_add_tail(&act->list, &acts->list); + rc = efx_mae_alloc_action_set_list(efx, acts); + if (rc) + goto fail2; + return 0; +fail2: + list_del(&act->list); + efx_mae_free_action_set(efx, act->fw_id); +fail1: + kfree(act); + return rc; +} + +static int efx_tc_configure_fallback_acts_pf(struct efx_nic *efx) +{ + struct efx_tc_action_set_list *acts = &efx->tc->facts.pf; + u32 eg_port; + + efx_mae_mport_uplink(efx, &eg_port); + return efx_tc_configure_fallback_acts(efx, eg_port, acts); +} + +static int efx_tc_configure_fallback_acts_reps(struct efx_nic *efx) +{ + struct efx_tc_action_set_list *acts = &efx->tc->facts.reps; + u32 eg_port; + + efx_mae_mport_mport(efx, efx->tc->reps_mport_id, &eg_port); + return efx_tc_configure_fallback_acts(efx, eg_port, acts); +} + +static void efx_tc_deconfigure_fallback_acts(struct efx_nic *efx, + struct efx_tc_action_set_list *acts) +{ + efx_tc_free_action_set_list(efx, acts, true); +} + static int efx_tc_configure_rep_mport(struct efx_nic *efx) { u32 rep_mport_label; @@ -1484,6 +1631,12 @@ int efx_init_tc(struct efx_nic *efx) if (rc) return rc; rc = efx_tc_configure_rep_mport(efx); + if (rc) + return rc; + rc = efx_tc_configure_fallback_acts_pf(efx); + if (rc) + return rc; + rc = efx_tc_configure_fallback_acts_reps(efx); if (rc) return rc; efx->tc->up = true; @@ -1503,6 +1656,8 @@ void efx_fini_tc(struct efx_nic *efx) efx_tc_deconfigure_rep_mport(efx); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.pf); efx_tc_deconfigure_default_rule(efx, &efx->tc->dflt.wire); + efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.pf); + efx_tc_deconfigure_fallback_acts(efx, &efx->tc->facts.reps); efx->tc->up = false; } @@ -1552,6 +1707,9 @@ int efx_init_struct_tc(struct efx_nic *efx) mutex_init(&efx->tc->mutex); init_waitqueue_head(&efx->tc->flush_wq); + rc = efx_tc_init_encap_actions(efx); + if (rc < 0) + goto fail_encap_actions; rc = efx_tc_init_counters(efx); if (rc < 0) goto fail_counters; @@ -1567,6 +1725,10 @@ int efx_init_struct_tc(struct efx_nic *efx) efx->tc->dflt.pf.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; INIT_LIST_HEAD(&efx->tc->dflt.wire.acts.list); efx->tc->dflt.wire.fw_id = MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL; + INIT_LIST_HEAD(&efx->tc->facts.pf.list); + efx->tc->facts.pf.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; + INIT_LIST_HEAD(&efx->tc->facts.reps.list); + efx->tc->facts.reps.fw_id = MC_CMD_MAE_ACTION_SET_ALLOC_OUT_ACTION_SET_ID_NULL; efx->extra_channel_type[EFX_EXTRA_CHANNEL_TC] = &efx_tc_channel_type; return 0; fail_match_action_ht: @@ -1574,6 +1736,8 @@ int efx_init_struct_tc(struct efx_nic *efx) fail_encap_match_ht: efx_tc_destroy_counters(efx); fail_counters: + efx_tc_destroy_encap_actions(efx); +fail_encap_actions: mutex_destroy(&efx->tc->mutex); kfree(efx->tc->caps); fail_alloc_caps: @@ -1592,11 +1756,16 @@ void efx_fini_struct_tc(struct efx_nic *efx) MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL); EFX_WARN_ON_PARANOID(efx->tc->dflt.wire.fw_id != MC_CMD_MAE_ACTION_RULE_INSERT_OUT_ACTION_RULE_ID_NULL); + EFX_WARN_ON_PARANOID(efx->tc->facts.pf.fw_id != + MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); + EFX_WARN_ON_PARANOID(efx->tc->facts.reps.fw_id != + MC_CMD_MAE_ACTION_SET_LIST_ALLOC_OUT_ACTION_SET_LIST_ID_NULL); rhashtable_free_and_destroy(&efx->tc->match_action_ht, efx_tc_flow_free, efx); rhashtable_free_and_destroy(&efx->tc->encap_match_ht, efx_tc_encap_match_free, NULL); efx_tc_fini_counters(efx); + efx_tc_fini_encap_actions(efx); mutex_unlock(&efx->tc->mutex); mutex_destroy(&efx->tc->mutex); kfree(efx->tc->caps); diff --git a/drivers/net/ethernet/sfc/tc.h b/drivers/net/ethernet/sfc/tc.h index 24e9640c74e906..607429f8bb289a 100644 --- a/drivers/net/ethernet/sfc/tc.h +++ b/drivers/net/ethernet/sfc/tc.h @@ -25,6 +25,8 @@ static inline bool efx_ipv6_addr_all_ones(struct in6_addr *addr) } #endif +struct efx_tc_encap_action; /* see tc_encap_actions.h */ + struct efx_tc_action_set { u16 vlan_push:2; u16 vlan_pop:2; @@ -33,6 +35,9 @@ struct efx_tc_action_set { __be16 vlan_tci[2]; /* TCIs for vlan_push */ __be16 vlan_proto[2]; /* Ethertypes for vlan_push */ struct efx_tc_counter_index *count; + struct efx_tc_encap_action *encap_md; /* entry in tc_encap_ht table */ + struct list_head encap_user; /* entry on encap_md->users list */ + struct efx_tc_action_set_list *user; /* Only populated if encap_md */ u32 dest_mport; u32 fw_id; /* index of this entry in firmware actions table */ struct list_head list; @@ -127,6 +132,7 @@ struct efx_tc_flow_rule { struct rhash_head linkage; struct efx_tc_match match; struct efx_tc_action_set_list acts; + struct efx_tc_action_set_list *fallback; /* what to use when unready? */ u32 fw_id; }; @@ -144,8 +150,10 @@ enum efx_tc_rule_prios { * @mutex: Used to serialise operations on TC hashtables * @counter_ht: Hashtable of TC counters (FW IDs and counter values) * @counter_id_ht: Hashtable mapping TC counter cookies to counters + * @encap_ht: Hashtable of TC encap actions * @encap_match_ht: Hashtable of TC encap matches * @match_action_ht: Hashtable of TC match-action rules + * @neigh_ht: Hashtable of neighbour watches (&struct efx_neigh_binder) * @reps_mport_id: MAE port allocated for representor RX * @reps_filter_uc: VNIC filter for representor unicast RX (promisc) * @reps_filter_mc: VNIC filter for representor multicast RX (allmulti) @@ -160,6 +168,11 @@ enum efx_tc_rule_prios { * %EFX_TC_PRIO_DFLT. Named by *ingress* port * @dflt.pf: rule for traffic ingressing from PF (egresses to wire) * @dflt.wire: rule for traffic ingressing from wire (egresses to PF) + * @facts: Fallback action-set-lists for unready rules. Named by *egress* port + * @facts.pf: action-set-list for unready rules on PF netdev, hence applying to + * traffic from wire, and egressing to PF + * @facts.reps: action-set-list for unready rules on representors, hence + * applying to traffic from representees, and egressing to the reps mport * @up: have TC datastructures been set up? */ struct efx_tc_state { @@ -168,8 +181,10 @@ struct efx_tc_state { struct mutex mutex; struct rhashtable counter_ht; struct rhashtable counter_id_ht; + struct rhashtable encap_ht; struct rhashtable encap_match_ht; struct rhashtable match_action_ht; + struct rhashtable neigh_ht; u32 reps_mport_id, reps_mport_vport_id; s32 reps_filter_uc, reps_filter_mc; bool flush_counters; @@ -180,11 +195,19 @@ struct efx_tc_state { struct efx_tc_flow_rule pf; struct efx_tc_flow_rule wire; } dflt; + struct { + struct efx_tc_action_set_list pf; + struct efx_tc_action_set_list reps; + } facts; bool up; }; struct efx_rep; +enum efx_encap_type efx_tc_indr_netdev_type(struct net_device *net_dev); +struct efx_rep *efx_tc_flower_lookup_efv(struct efx_nic *efx, + struct net_device *dev); +s64 efx_tc_flower_external_mport(struct efx_nic *efx, struct efx_rep *efv); int efx_tc_configure_default_rule_rep(struct efx_rep *efv); void efx_tc_deconfigure_default_rule(struct efx_nic *efx, struct efx_tc_flow_rule *rule); diff --git a/drivers/net/ethernet/sfc/tc_bindings.c b/drivers/net/ethernet/sfc/tc_bindings.c index c18d64519c2db9..1b79c535c54ed5 100644 --- a/drivers/net/ethernet/sfc/tc_bindings.c +++ b/drivers/net/ethernet/sfc/tc_bindings.c @@ -10,6 +10,7 @@ #include "tc_bindings.h" #include "tc.h" +#include "tc_encap_actions.h" struct efx_tc_block_binding { struct list_head list; @@ -226,3 +227,15 @@ int efx_tc_setup(struct net_device *net_dev, enum tc_setup_type type, return -EOPNOTSUPP; } + +int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event, + struct net_device *net_dev) +{ + if (efx->type->is_vf) + return NOTIFY_DONE; + + if (event == NETDEV_UNREGISTER) + efx_tc_unregister_egdev(efx, net_dev); + + return NOTIFY_OK; +} diff --git a/drivers/net/ethernet/sfc/tc_bindings.h b/drivers/net/ethernet/sfc/tc_bindings.h index c210bb09150ee6..095ddeb59eb3c8 100644 --- a/drivers/net/ethernet/sfc/tc_bindings.h +++ b/drivers/net/ethernet/sfc/tc_bindings.h @@ -26,4 +26,6 @@ int efx_tc_indr_setup_cb(struct net_device *net_dev, struct Qdisc *sch, void *cb_priv, enum tc_setup_type type, void *type_data, void *data, void (*cleanup)(struct flow_block_cb *block_cb)); +int efx_tc_netdev_event(struct efx_nic *efx, unsigned long event, + struct net_device *net_dev); #endif /* EFX_TC_BINDINGS_H */ diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.c b/drivers/net/ethernet/sfc/tc_encap_actions.c new file mode 100644 index 00000000000000..aac259528e73e2 --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_encap_actions.c @@ -0,0 +1,746 @@ +// SPDX-License-Identifier: GPL-2.0-only +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include "tc_encap_actions.h" +#include "tc.h" +#include "mae.h" +#include +#include +#include +#include + +static const struct rhashtable_params efx_neigh_ht_params = { + .key_len = offsetof(struct efx_neigh_binder, ha), + .key_offset = 0, + .head_offset = offsetof(struct efx_neigh_binder, linkage), +}; + +static const struct rhashtable_params efx_tc_encap_ht_params = { + .key_len = offsetofend(struct efx_tc_encap_action, key), + .key_offset = 0, + .head_offset = offsetof(struct efx_tc_encap_action, linkage), +}; + +static void efx_tc_encap_free(void *ptr, void *__unused) +{ + struct efx_tc_encap_action *enc = ptr; + + WARN_ON(refcount_read(&enc->ref)); + kfree(enc); +} + +static void efx_neigh_free(void *ptr, void *__unused) +{ + struct efx_neigh_binder *neigh = ptr; + + WARN_ON(refcount_read(&neigh->ref)); + WARN_ON(!list_empty(&neigh->users)); + put_net_track(neigh->net, &neigh->ns_tracker); + netdev_put(neigh->egdev, &neigh->dev_tracker); + kfree(neigh); +} + +int efx_tc_init_encap_actions(struct efx_nic *efx) +{ + int rc; + + rc = rhashtable_init(&efx->tc->neigh_ht, &efx_neigh_ht_params); + if (rc < 0) + goto fail_neigh_ht; + rc = rhashtable_init(&efx->tc->encap_ht, &efx_tc_encap_ht_params); + if (rc < 0) + goto fail_encap_ht; + return 0; +fail_encap_ht: + rhashtable_destroy(&efx->tc->neigh_ht); +fail_neigh_ht: + return rc; +} + +/* Only call this in init failure teardown. + * Normal exit should fini instead as there may be entries in the table. + */ +void efx_tc_destroy_encap_actions(struct efx_nic *efx) +{ + rhashtable_destroy(&efx->tc->encap_ht); + rhashtable_destroy(&efx->tc->neigh_ht); +} + +void efx_tc_fini_encap_actions(struct efx_nic *efx) +{ + rhashtable_free_and_destroy(&efx->tc->encap_ht, efx_tc_encap_free, NULL); + rhashtable_free_and_destroy(&efx->tc->neigh_ht, efx_neigh_free, NULL); +} + +static void efx_neigh_update(struct work_struct *work); + +static int efx_bind_neigh(struct efx_nic *efx, + struct efx_tc_encap_action *encap, struct net *net, + struct netlink_ext_ack *extack) +{ + struct efx_neigh_binder *neigh, *old; + struct flowi6 flow6 = {}; + struct flowi4 flow4 = {}; + int rc; + + /* GCC stupidly thinks that only values explicitly listed in the enum + * definition can _possibly_ be sensible case values, so without this + * cast it complains about the IPv6 versions. + */ + switch ((int)encap->type) { + case EFX_ENCAP_TYPE_VXLAN: + case EFX_ENCAP_TYPE_GENEVE: + flow4.flowi4_proto = IPPROTO_UDP; + flow4.fl4_dport = encap->key.tp_dst; + flow4.flowi4_tos = encap->key.tos; + flow4.daddr = encap->key.u.ipv4.dst; + flow4.saddr = encap->key.u.ipv4.src; + break; + case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6: + case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6: + flow6.flowi6_proto = IPPROTO_UDP; + flow6.fl6_dport = encap->key.tp_dst; + flow6.flowlabel = ip6_make_flowinfo(encap->key.tos, + encap->key.label); + flow6.daddr = encap->key.u.ipv6.dst; + flow6.saddr = encap->key.u.ipv6.src; + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported encap type %d", + (int)encap->type); + return -EOPNOTSUPP; + } + + neigh = kzalloc(sizeof(*neigh), GFP_KERNEL_ACCOUNT); + if (!neigh) + return -ENOMEM; + neigh->net = get_net_track(net, &neigh->ns_tracker, GFP_KERNEL_ACCOUNT); + neigh->dst_ip = flow4.daddr; + neigh->dst_ip6 = flow6.daddr; + + old = rhashtable_lookup_get_insert_fast(&efx->tc->neigh_ht, + &neigh->linkage, + efx_neigh_ht_params); + if (old) { + /* don't need our new entry */ + put_net_track(neigh->net, &neigh->ns_tracker); + kfree(neigh); + if (!refcount_inc_not_zero(&old->ref)) + return -EAGAIN; + /* existing entry found, ref taken */ + neigh = old; + } else { + /* New entry. We need to initiate a lookup */ + struct neighbour *n; + struct rtable *rt; + + if (encap->type & EFX_ENCAP_FLAG_IPV6) { +#if IS_ENABLED(CONFIG_IPV6) + struct dst_entry *dst; + + dst = ipv6_stub->ipv6_dst_lookup_flow(net, NULL, &flow6, + NULL); + rc = PTR_ERR_OR_ZERO(dst); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for IPv6 encap"); + goto out_free; + } + neigh->egdev = dst->dev; + netdev_hold(neigh->egdev, &neigh->dev_tracker, + GFP_KERNEL_ACCOUNT); + neigh->ttl = ip6_dst_hoplimit(dst); + n = dst_neigh_lookup(dst, &flow6.daddr); + dst_release(dst); +#else + /* We shouldn't ever get here, because if IPv6 isn't + * enabled how did someone create an IPv6 tunnel_key? + */ + rc = -EOPNOTSUPP; + NL_SET_ERR_MSG_MOD(extack, "No IPv6 support (neigh bind)"); +#endif + } else { + rt = ip_route_output_key(net, &flow4); + if (IS_ERR_OR_NULL(rt)) { + rc = PTR_ERR_OR_ZERO(rt); + if (!rc) + rc = -EIO; + NL_SET_ERR_MSG_MOD(extack, "Failed to lookup route for encap"); + goto out_free; + } + neigh->egdev = rt->dst.dev; + netdev_hold(neigh->egdev, &neigh->dev_tracker, + GFP_KERNEL_ACCOUNT); + neigh->ttl = ip4_dst_hoplimit(&rt->dst); + n = dst_neigh_lookup(&rt->dst, &flow4.daddr); + ip_rt_put(rt); + } + if (!n) { + rc = -ENETUNREACH; + NL_SET_ERR_MSG_MOD(extack, "Failed to lookup neighbour for encap"); + netdev_put(neigh->egdev, &neigh->dev_tracker); + goto out_free; + } + refcount_set(&neigh->ref, 1); + INIT_LIST_HEAD(&neigh->users); + read_lock_bh(&n->lock); + ether_addr_copy(neigh->ha, n->ha); + neigh->n_valid = n->nud_state & NUD_VALID; + read_unlock_bh(&n->lock); + rwlock_init(&neigh->lock); + INIT_WORK(&neigh->work, efx_neigh_update); + neigh->efx = efx; + neigh->used = jiffies; + if (!neigh->n_valid) + /* Prod ARP to find us a neighbour */ + neigh_event_send(n, NULL); + neigh_release(n); + } + /* Add us to this neigh */ + encap->neigh = neigh; + list_add_tail(&encap->list, &neigh->users); + return 0; + +out_free: + /* cleanup common to several error paths */ + rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage, + efx_neigh_ht_params); + synchronize_rcu(); + put_net_track(net, &neigh->ns_tracker); + kfree(neigh); + return rc; +} + +static void efx_free_neigh(struct efx_neigh_binder *neigh) +{ + struct efx_nic *efx = neigh->efx; + + rhashtable_remove_fast(&efx->tc->neigh_ht, &neigh->linkage, + efx_neigh_ht_params); + synchronize_rcu(); + netdev_put(neigh->egdev, &neigh->dev_tracker); + put_net_track(neigh->net, &neigh->ns_tracker); + kfree(neigh); +} + +static void efx_release_neigh(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + struct efx_neigh_binder *neigh = encap->neigh; + + if (!neigh) + return; + list_del(&encap->list); + encap->neigh = NULL; + if (!refcount_dec_and_test(&neigh->ref)) + return; /* still in use */ + efx_free_neigh(neigh); +} + +static void efx_gen_tun_header_eth(struct efx_tc_encap_action *encap, u16 proto) +{ + struct efx_neigh_binder *neigh = encap->neigh; + struct ethhdr *eth; + + encap->encap_hdr_len = sizeof(*eth); + eth = (struct ethhdr *)encap->encap_hdr; + + if (encap->neigh->n_valid) + ether_addr_copy(eth->h_dest, neigh->ha); + else + eth_zero_addr(eth->h_dest); + ether_addr_copy(eth->h_source, neigh->egdev->dev_addr); + eth->h_proto = htons(proto); +} + +static void efx_gen_tun_header_ipv4(struct efx_tc_encap_action *encap, u8 ipproto, u8 len) +{ + struct efx_neigh_binder *neigh = encap->neigh; + struct ip_tunnel_key *key = &encap->key; + struct iphdr *ip; + + ip = (struct iphdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*ip); + + ip->daddr = key->u.ipv4.dst; + ip->saddr = key->u.ipv4.src; + ip->ttl = neigh->ttl; + ip->protocol = ipproto; + ip->version = 0x4; + ip->ihl = 0x5; + ip->tot_len = cpu_to_be16(ip->ihl * 4 + len); + ip_send_check(ip); +} + +#ifdef CONFIG_IPV6 +static void efx_gen_tun_header_ipv6(struct efx_tc_encap_action *encap, u8 ipproto, u8 len) +{ + struct efx_neigh_binder *neigh = encap->neigh; + struct ip_tunnel_key *key = &encap->key; + struct ipv6hdr *ip; + + ip = (struct ipv6hdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*ip); + + ip6_flow_hdr(ip, key->tos, key->label); + ip->daddr = key->u.ipv6.dst; + ip->saddr = key->u.ipv6.src; + ip->hop_limit = neigh->ttl; + ip->nexthdr = ipproto; + ip->version = 0x6; + ip->payload_len = cpu_to_be16(len); +} +#endif + +static void efx_gen_tun_header_udp(struct efx_tc_encap_action *encap, u8 len) +{ + struct ip_tunnel_key *key = &encap->key; + struct udphdr *udp; + + udp = (struct udphdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*udp); + + udp->dest = key->tp_dst; + udp->len = cpu_to_be16(sizeof(*udp) + len); +} + +static void efx_gen_tun_header_vxlan(struct efx_tc_encap_action *encap) +{ + struct ip_tunnel_key *key = &encap->key; + struct vxlanhdr *vxlan; + + vxlan = (struct vxlanhdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*vxlan); + + vxlan->vx_flags = VXLAN_HF_VNI; + vxlan->vx_vni = vxlan_vni_field(tunnel_id_to_key32(key->tun_id)); +} + +static void efx_gen_tun_header_geneve(struct efx_tc_encap_action *encap) +{ + struct ip_tunnel_key *key = &encap->key; + struct genevehdr *geneve; + u32 vni; + + geneve = (struct genevehdr *)(encap->encap_hdr + encap->encap_hdr_len); + encap->encap_hdr_len += sizeof(*geneve); + + geneve->proto_type = htons(ETH_P_TEB); + /* convert tun_id to host-endian so we can use host arithmetic to + * extract individual bytes. + */ + vni = ntohl(tunnel_id_to_key32(key->tun_id)); + geneve->vni[0] = vni >> 16; + geneve->vni[1] = vni >> 8; + geneve->vni[2] = vni; +} + +#define vxlan_header_l4_len (sizeof(struct udphdr) + sizeof(struct vxlanhdr)) +#define vxlan4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + vxlan_header_l4_len) +static void efx_gen_vxlan_header_ipv4(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan4_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IP); + efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, vxlan_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr)); + efx_gen_tun_header_vxlan(encap); +} + +#define geneve_header_l4_len (sizeof(struct udphdr) + sizeof(struct genevehdr)) +#define geneve4_header_len (sizeof(struct ethhdr) + sizeof(struct iphdr) + geneve_header_l4_len) +static void efx_gen_geneve_header_ipv4(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve4_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IP); + efx_gen_tun_header_ipv4(encap, IPPROTO_UDP, geneve_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct genevehdr)); + efx_gen_tun_header_geneve(encap); +} + +#ifdef CONFIG_IPV6 +#define vxlan6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + vxlan_header_l4_len) +static void efx_gen_vxlan_header_ipv6(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < vxlan6_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IPV6); + efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, vxlan_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct vxlanhdr)); + efx_gen_tun_header_vxlan(encap); +} + +#define geneve6_header_len (sizeof(struct ethhdr) + sizeof(struct ipv6hdr) + geneve_header_l4_len) +static void efx_gen_geneve_header_ipv6(struct efx_tc_encap_action *encap) +{ + BUILD_BUG_ON(sizeof(encap->encap_hdr) < geneve6_header_len); + efx_gen_tun_header_eth(encap, ETH_P_IPV6); + efx_gen_tun_header_ipv6(encap, IPPROTO_UDP, geneve_header_l4_len); + efx_gen_tun_header_udp(encap, sizeof(struct genevehdr)); + efx_gen_tun_header_geneve(encap); +} +#endif + +static void efx_gen_encap_header(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + encap->n_valid = encap->neigh->n_valid; + + /* GCC stupidly thinks that only values explicitly listed in the enum + * definition can _possibly_ be sensible case values, so without this + * cast it complains about the IPv6 versions. + */ + switch ((int)encap->type) { + case EFX_ENCAP_TYPE_VXLAN: + efx_gen_vxlan_header_ipv4(encap); + break; + case EFX_ENCAP_TYPE_GENEVE: + efx_gen_geneve_header_ipv4(encap); + break; +#ifdef CONFIG_IPV6 + case EFX_ENCAP_TYPE_VXLAN | EFX_ENCAP_FLAG_IPV6: + efx_gen_vxlan_header_ipv6(encap); + break; + case EFX_ENCAP_TYPE_GENEVE | EFX_ENCAP_FLAG_IPV6: + efx_gen_geneve_header_ipv6(encap); + break; +#endif + default: + /* unhandled encap type, can't happen */ + if (net_ratelimit()) + netif_err(efx, drv, efx->net_dev, + "Bogus encap type %d, can't generate\n", + encap->type); + + /* Use fallback action. */ + encap->n_valid = false; + break; + } +} + +static void efx_tc_update_encap(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + struct efx_tc_action_set_list *acts, *fallback; + struct efx_tc_flow_rule *rule; + struct efx_tc_action_set *act; + int rc; + + if (encap->n_valid) { + /* Make sure no rules are using this encap while we change it */ + list_for_each_entry(act, &encap->users, encap_user) { + acts = act->user; + if (WARN_ON(!acts)) /* can't happen */ + continue; + rule = container_of(acts, struct efx_tc_flow_rule, acts); + if (rule->fallback) + fallback = rule->fallback; + else /* fallback fallback: deliver to PF */ + fallback = &efx->tc->facts.pf; + rc = efx_mae_update_rule(efx, fallback->fw_id, + rule->fw_id); + if (rc) + netif_err(efx, drv, efx->net_dev, + "Failed to update (f) rule %08x rc %d\n", + rule->fw_id, rc); + else + netif_dbg(efx, drv, efx->net_dev, "Updated (f) rule %08x\n", + rule->fw_id); + } + } + + /* Make sure we don't leak arbitrary bytes on the wire; + * set an all-0s ethernet header. A successful call to + * efx_gen_encap_header() will overwrite this. + */ + memset(encap->encap_hdr, 0, sizeof(encap->encap_hdr)); + encap->encap_hdr_len = ETH_HLEN; + + if (encap->neigh) { + read_lock_bh(&encap->neigh->lock); + efx_gen_encap_header(efx, encap); + read_unlock_bh(&encap->neigh->lock); + } else { + encap->n_valid = false; + } + + rc = efx_mae_update_encap_md(efx, encap); + if (rc) { + netif_err(efx, drv, efx->net_dev, + "Failed to update encap hdr %08x rc %d\n", + encap->fw_id, rc); + return; + } + netif_dbg(efx, drv, efx->net_dev, "Updated encap hdr %08x\n", + encap->fw_id); + if (!encap->n_valid) + return; + /* Update rule users: use the action if they are now ready */ + list_for_each_entry(act, &encap->users, encap_user) { + acts = act->user; + if (WARN_ON(!acts)) /* can't happen */ + continue; + rule = container_of(acts, struct efx_tc_flow_rule, acts); + if (!efx_tc_check_ready(efx, rule)) + continue; + rc = efx_mae_update_rule(efx, acts->fw_id, rule->fw_id); + if (rc) + netif_err(efx, drv, efx->net_dev, + "Failed to update rule %08x rc %d\n", + rule->fw_id, rc); + else + netif_dbg(efx, drv, efx->net_dev, "Updated rule %08x\n", + rule->fw_id); + } +} + +static void efx_neigh_update(struct work_struct *work) +{ + struct efx_neigh_binder *neigh = container_of(work, struct efx_neigh_binder, work); + struct efx_tc_encap_action *encap; + struct efx_nic *efx = neigh->efx; + + mutex_lock(&efx->tc->mutex); + list_for_each_entry(encap, &neigh->users, list) + efx_tc_update_encap(neigh->efx, encap); + /* release ref taken in efx_neigh_event() */ + if (refcount_dec_and_test(&neigh->ref)) + efx_free_neigh(neigh); + mutex_unlock(&efx->tc->mutex); +} + +static int efx_neigh_event(struct efx_nic *efx, struct neighbour *n) +{ + struct efx_neigh_binder keys = {NULL}, *neigh; + bool n_valid, ipv6 = false; + char ha[ETH_ALEN]; + size_t keysize; + + if (WARN_ON(!efx->tc)) + return NOTIFY_DONE; + + if (n->tbl == &arp_tbl) { + keysize = sizeof(keys.dst_ip); +#if IS_ENABLED(CONFIG_IPV6) + } else if (n->tbl == ipv6_stub->nd_tbl) { + ipv6 = true; + keysize = sizeof(keys.dst_ip6); +#endif + } else { + return NOTIFY_DONE; + } + if (!n->parms) { + netif_warn(efx, drv, efx->net_dev, "neigh_event with no parms!\n"); + return NOTIFY_DONE; + } + keys.net = read_pnet(&n->parms->net); + if (n->tbl->key_len != keysize) { + netif_warn(efx, drv, efx->net_dev, "neigh_event with bad key_len %u\n", + n->tbl->key_len); + return NOTIFY_DONE; + } + read_lock_bh(&n->lock); /* Get a consistent view */ + memcpy(ha, n->ha, ETH_ALEN); + n_valid = (n->nud_state & NUD_VALID) && !n->dead; + read_unlock_bh(&n->lock); + if (ipv6) + memcpy(&keys.dst_ip6, n->primary_key, n->tbl->key_len); + else + memcpy(&keys.dst_ip, n->primary_key, n->tbl->key_len); + rcu_read_lock(); + neigh = rhashtable_lookup_fast(&efx->tc->neigh_ht, &keys, + efx_neigh_ht_params); + if (!neigh || neigh->dying) + /* We're not interested in this neighbour */ + goto done; + write_lock_bh(&neigh->lock); + if (n_valid == neigh->n_valid && !memcmp(ha, neigh->ha, ETH_ALEN)) { + write_unlock_bh(&neigh->lock); + /* Nothing has changed; no work to do */ + goto done; + } + neigh->n_valid = n_valid; + memcpy(neigh->ha, ha, ETH_ALEN); + write_unlock_bh(&neigh->lock); + if (refcount_inc_not_zero(&neigh->ref)) { + rcu_read_unlock(); + if (!schedule_work(&neigh->work)) + /* failed to schedule, release the ref we just took */ + if (refcount_dec_and_test(&neigh->ref)) + efx_free_neigh(neigh); + } else { +done: + rcu_read_unlock(); + } + return NOTIFY_DONE; +} + +bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule) +{ + struct efx_tc_action_set *act; + + /* Encap actions can only be offloaded if they have valid + * neighbour info for the outer Ethernet header. + */ + list_for_each_entry(act, &rule->acts.list, list) + if (act->encap_md && !act->encap_md->n_valid) + return false; + return true; +} + +struct efx_tc_encap_action *efx_tc_flower_create_encap_md( + struct efx_nic *efx, const struct ip_tunnel_info *info, + struct net_device *egdev, struct netlink_ext_ack *extack) +{ + enum efx_encap_type type = efx_tc_indr_netdev_type(egdev); + struct efx_tc_encap_action *encap, *old; + struct efx_rep *to_efv; + s64 rc; + + if (type == EFX_ENCAP_TYPE_NONE) { + /* dest is not an encap device */ + NL_SET_ERR_MSG_MOD(extack, "Not a (supported) tunnel device but tunnel_key is set"); + return ERR_PTR(-EOPNOTSUPP); + } + rc = efx_mae_check_encap_type_supported(efx, type); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Firmware reports no support for this tunnel type"); + return ERR_PTR(rc); + } + /* No support yet for Geneve options */ + if (info->options_len) { + NL_SET_ERR_MSG_MOD(extack, "Unsupported tunnel options"); + return ERR_PTR(-EOPNOTSUPP); + } + switch (info->mode) { + case IP_TUNNEL_INFO_TX: + break; + case IP_TUNNEL_INFO_TX | IP_TUNNEL_INFO_IPV6: + type |= EFX_ENCAP_FLAG_IPV6; + break; + default: + NL_SET_ERR_MSG_FMT_MOD(extack, "Unsupported tunnel mode %u", + info->mode); + return ERR_PTR(-EOPNOTSUPP); + } + encap = kzalloc(sizeof(*encap), GFP_KERNEL_ACCOUNT); + if (!encap) + return ERR_PTR(-ENOMEM); + encap->type = type; + encap->key = info->key; + INIT_LIST_HEAD(&encap->users); + old = rhashtable_lookup_get_insert_fast(&efx->tc->encap_ht, + &encap->linkage, + efx_tc_encap_ht_params); + if (old) { + /* don't need our new entry */ + kfree(encap); + if (!refcount_inc_not_zero(&old->ref)) + return ERR_PTR(-EAGAIN); + /* existing entry found, ref taken */ + return old; + } + + rc = efx_bind_neigh(efx, encap, dev_net(egdev), extack); + if (rc < 0) + goto out_remove; + to_efv = efx_tc_flower_lookup_efv(efx, encap->neigh->egdev); + if (IS_ERR(to_efv)) { + /* neigh->egdev isn't ours */ + NL_SET_ERR_MSG_MOD(extack, "Tunnel egress device not on switch"); + rc = PTR_ERR(to_efv); + goto out_release; + } + rc = efx_tc_flower_external_mport(efx, to_efv); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Failed to identify tunnel egress m-port"); + goto out_release; + } + encap->dest_mport = rc; + read_lock_bh(&encap->neigh->lock); + efx_gen_encap_header(efx, encap); + read_unlock_bh(&encap->neigh->lock); + + rc = efx_mae_allocate_encap_md(efx, encap); + if (rc < 0) { + NL_SET_ERR_MSG_MOD(extack, "Failed to write tunnel header to hw"); + goto out_release; + } + + /* ref and return */ + refcount_set(&encap->ref, 1); + return encap; +out_release: + efx_release_neigh(efx, encap); +out_remove: + rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage, + efx_tc_encap_ht_params); + kfree(encap); + return ERR_PTR(rc); +} + +void efx_tc_flower_release_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap) +{ + if (!refcount_dec_and_test(&encap->ref)) + return; /* still in use */ + efx_release_neigh(efx, encap); + rhashtable_remove_fast(&efx->tc->encap_ht, &encap->linkage, + efx_tc_encap_ht_params); + efx_mae_free_encap_md(efx, encap); + kfree(encap); +} + +static void efx_tc_remove_neigh_users(struct efx_nic *efx, struct efx_neigh_binder *neigh) +{ + struct efx_tc_encap_action *encap, *next; + + list_for_each_entry_safe(encap, next, &neigh->users, list) { + /* Should cause neigh usage count to fall to zero, freeing it */ + efx_release_neigh(efx, encap); + /* The encap has lost its neigh, so it's now unready */ + efx_tc_update_encap(efx, encap); + } +} + +void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev) +{ + struct efx_neigh_binder *neigh; + struct rhashtable_iter walk; + + mutex_lock(&efx->tc->mutex); + rhashtable_walk_enter(&efx->tc->neigh_ht, &walk); + rhashtable_walk_start(&walk); + while ((neigh = rhashtable_walk_next(&walk)) != NULL) { + if (IS_ERR(neigh)) + continue; + if (neigh->egdev != net_dev) + continue; + neigh->dying = true; + rhashtable_walk_stop(&walk); + synchronize_rcu(); /* Make sure any updates see dying flag */ + efx_tc_remove_neigh_users(efx, neigh); /* might sleep */ + rhashtable_walk_start(&walk); + } + rhashtable_walk_stop(&walk); + rhashtable_walk_exit(&walk); + mutex_unlock(&efx->tc->mutex); +} + +int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event, + void *ptr) +{ + if (efx->type->is_vf) + return NOTIFY_DONE; + + switch (event) { + case NETEVENT_NEIGH_UPDATE: + return efx_neigh_event(efx, ptr); + default: + return NOTIFY_DONE; + } +} diff --git a/drivers/net/ethernet/sfc/tc_encap_actions.h b/drivers/net/ethernet/sfc/tc_encap_actions.h new file mode 100644 index 00000000000000..4d755fb92daf1f --- /dev/null +++ b/drivers/net/ethernet/sfc/tc_encap_actions.h @@ -0,0 +1,103 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/**************************************************************************** + * Driver for Solarflare network controllers and boards + * Copyright 2023, Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#ifndef EFX_TC_ENCAP_ACTIONS_H +#define EFX_TC_ENCAP_ACTIONS_H +#include "net_driver.h" + +#include +#include + +/** + * struct efx_neigh_binder - driver state for a neighbour entry + * @net: the network namespace in which this neigh resides + * @dst_ip: the IPv4 destination address resolved by this neigh + * @dst_ip6: the IPv6 destination address resolved by this neigh + * @ha: the hardware (Ethernet) address of the neighbour + * @n_valid: true if the neighbour is in NUD_VALID state + * @lock: protects @ha and @n_valid + * @ttl: Time To Live associated with the route used + * @dying: set when egdev is going away, to skip further updates + * @egdev: egress device from the route lookup. Holds a reference + * @dev_tracker: reference tracker entry for @egdev + * @ns_tracker: reference tracker entry for @ns + * @ref: counts encap actions referencing this entry + * @used: jiffies of last time traffic hit any encap action using this. + * When counter reads update this, a new neighbour event is sent to + * indicate that the neighbour entry is still in use. + * @users: list of &struct efx_tc_encap_action + * @linkage: entry in efx->neigh_ht (keys are @net, @dst_ip, @dst_ip6). + * @work: processes neighbour state changes, updates the encap actions + * @efx: owning NIC instance. + * + * Associates a neighbour entry with the encap actions that are + * interested in it, allowing the latter to be updated when the + * neighbour details change. + * Whichever of @dst_ip and @dst_ip6 is not in use will be all-zeroes, + * this distinguishes IPv4 from IPv6 entries. + */ +struct efx_neigh_binder { + struct net *net; + __be32 dst_ip; + struct in6_addr dst_ip6; + char ha[ETH_ALEN]; + bool n_valid; + rwlock_t lock; + u8 ttl; + bool dying; + struct net_device *egdev; + netdevice_tracker dev_tracker; + netns_tracker ns_tracker; + refcount_t ref; + unsigned long used; + struct list_head users; + struct rhash_head linkage; + struct work_struct work; + struct efx_nic *efx; +}; + +/* This limit is arbitrary; current hardware (SN1022) handles encap headers + * of up to 126 bytes, but that limit is not enshrined in the MCDI protocol. + */ +#define EFX_TC_MAX_ENCAP_HDR 126 +struct efx_tc_encap_action { + enum efx_encap_type type; + struct ip_tunnel_key key; /* 52 bytes */ + u32 dest_mport; /* is copied into struct efx_tc_action_set */ + u8 encap_hdr_len; + bool n_valid; + u8 encap_hdr[EFX_TC_MAX_ENCAP_HDR]; + struct efx_neigh_binder *neigh; + struct list_head list; /* entry on neigh->users list */ + struct list_head users; /* action sets using this encap_md */ + struct rhash_head linkage; /* efx->tc_encap_ht */ + refcount_t ref; + u32 fw_id; /* index of this entry in firmware encap table */ +}; + +/* create/uncreate/teardown hashtables */ +int efx_tc_init_encap_actions(struct efx_nic *efx); +void efx_tc_destroy_encap_actions(struct efx_nic *efx); +void efx_tc_fini_encap_actions(struct efx_nic *efx); + +struct efx_tc_flow_rule; +bool efx_tc_check_ready(struct efx_nic *efx, struct efx_tc_flow_rule *rule); + +struct efx_tc_encap_action *efx_tc_flower_create_encap_md( + struct efx_nic *efx, const struct ip_tunnel_info *info, + struct net_device *egdev, struct netlink_ext_ack *extack); +void efx_tc_flower_release_encap_md(struct efx_nic *efx, + struct efx_tc_encap_action *encap); + +void efx_tc_unregister_egdev(struct efx_nic *efx, struct net_device *net_dev); +int efx_tc_netevent_event(struct efx_nic *efx, unsigned long event, + void *ptr); + +#endif /* EFX_TC_ENCAP_ACTIONS_H */ diff --git a/drivers/net/ethernet/sfc/tx_common.c b/drivers/net/ethernet/sfc/tx_common.c index 67e789b96c437c..4ce7d00e697d00 100644 --- a/drivers/net/ethernet/sfc/tx_common.c +++ b/drivers/net/ethernet/sfc/tx_common.c @@ -12,6 +12,7 @@ #include "efx.h" #include "nic_common.h" #include "tx_common.h" +#include static unsigned int efx_tx_cb_page_count(struct efx_tx_queue *tx_queue) { diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index 5f5a997f21f363..5583f0b055ec72 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -158,6 +158,9 @@ config DWMAC_SOCFPGA default ARCH_INTEL_SOCFPGA depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST) select MFD_SYSCON + select MDIO_REGMAP + select REGMAP_MMIO + select PCS_LYNX help Support for ethernet controller on Altera SOCFPGA diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 8738fdbb4b2dc0..7dd3d388068bda 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -35,7 +35,7 @@ obj-$(CONFIG_DWMAC_IMX8) += dwmac-imx.o obj-$(CONFIG_DWMAC_TEGRA) += dwmac-tegra.o obj-$(CONFIG_DWMAC_VISCONTI) += dwmac-visconti.o stmmac-platform-objs:= stmmac_platform.o -dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o +dwmac-altr-socfpga-objs := dwmac-socfpga.o obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o obj-$(CONFIG_DWMAC_INTEL) += dwmac-intel.o diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c deleted file mode 100644 index 00f6d347eaf75b..00000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c +++ /dev/null @@ -1,257 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* Copyright Altera Corporation (C) 2016. All rights reserved. - * - * Author: Tien Hock Loh - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "stmmac.h" -#include "stmmac_platform.h" -#include "altr_tse_pcs.h" - -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0 -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII BIT(1) -#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII BIT(2) -#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 -#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK GENMASK(1, 0) - -#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12) -#define TSE_PCS_CONTROL_REG 0x00 -#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9) -#define TSE_PCS_CTRL_AUTONEG_SGMII 0x1140 -#define TSE_PCS_IF_MODE_REG 0x28 -#define TSE_PCS_LINK_TIMER_0_REG 0x24 -#define TSE_PCS_LINK_TIMER_1_REG 0x26 -#define TSE_PCS_SIZE 0x40 -#define TSE_PCS_STATUS_AN_COMPLETED_MASK BIT(5) -#define TSE_PCS_STATUS_LINK_MASK 0x0004 -#define TSE_PCS_STATUS_REG 0x02 -#define TSE_PCS_SGMII_SPEED_1000 BIT(3) -#define TSE_PCS_SGMII_SPEED_100 BIT(2) -#define TSE_PCS_SGMII_SPEED_10 0x0 -#define TSE_PCS_SW_RST_MASK 0x8000 -#define TSE_PCS_PARTNER_ABILITY_REG 0x0A -#define TSE_PCS_PARTNER_DUPLEX_FULL 0x1000 -#define TSE_PCS_PARTNER_DUPLEX_HALF 0x0000 -#define TSE_PCS_PARTNER_DUPLEX_MASK 0x1000 -#define TSE_PCS_PARTNER_SPEED_MASK GENMASK(11, 10) -#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) -#define TSE_PCS_PARTNER_SPEED_100 BIT(10) -#define TSE_PCS_PARTNER_SPEED_10 0x0000 -#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) -#define TSE_PCS_PARTNER_SPEED_100 BIT(10) -#define TSE_PCS_PARTNER_SPEED_10 0x0000 -#define TSE_PCS_SGMII_SPEED_MASK GENMASK(3, 2) -#define TSE_PCS_SGMII_LINK_TIMER_0 0x0D40 -#define TSE_PCS_SGMII_LINK_TIMER_1 0x0003 -#define TSE_PCS_SW_RESET_TIMEOUT 100 -#define TSE_PCS_USE_SGMII_AN_MASK BIT(1) -#define TSE_PCS_USE_SGMII_ENA BIT(0) -#define TSE_PCS_IF_USE_SGMII 0x03 - -#define AUTONEGO_LINK_TIMER 20 - -static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs) -{ - int counter = 0; - u16 val; - - val = readw(base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_SW_RST_MASK; - writew(val, base + TSE_PCS_CONTROL_REG); - - while (counter < TSE_PCS_SW_RESET_TIMEOUT) { - val = readw(base + TSE_PCS_CONTROL_REG); - val &= TSE_PCS_SW_RST_MASK; - if (val == 0) - break; - counter++; - udelay(1); - } - if (counter >= TSE_PCS_SW_RESET_TIMEOUT) { - dev_err(pcs->dev, "PCS could not get out of sw reset\n"); - return -ETIMEDOUT; - } - - return 0; -} - -int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs) -{ - int ret = 0; - - writew(TSE_PCS_IF_USE_SGMII, base + TSE_PCS_IF_MODE_REG); - - writew(TSE_PCS_CTRL_AUTONEG_SGMII, base + TSE_PCS_CONTROL_REG); - - writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG); - writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); - - ret = tse_pcs_reset(base, pcs); - if (ret == 0) - writew(SGMII_ADAPTER_ENABLE, - pcs->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - - return ret; -} - -static void pcs_link_timer_callback(struct tse_pcs *pcs) -{ - u16 val = 0; - void __iomem *tse_pcs_base = pcs->tse_pcs_base; - void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; - - val = readw(tse_pcs_base + TSE_PCS_STATUS_REG); - val &= TSE_PCS_STATUS_LINK_MASK; - - if (val != 0) { - dev_dbg(pcs->dev, "Adapter: Link is established\n"); - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - } else { - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} - -static void auto_nego_timer_callback(struct tse_pcs *pcs) -{ - u16 val = 0; - u16 speed = 0; - u16 duplex = 0; - void __iomem *tse_pcs_base = pcs->tse_pcs_base; - void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; - - val = readw(tse_pcs_base + TSE_PCS_STATUS_REG); - val &= TSE_PCS_STATUS_AN_COMPLETED_MASK; - - if (val != 0) { - dev_dbg(pcs->dev, "Adapter: Auto Negotiation is completed\n"); - val = readw(tse_pcs_base + TSE_PCS_PARTNER_ABILITY_REG); - speed = val & TSE_PCS_PARTNER_SPEED_MASK; - duplex = val & TSE_PCS_PARTNER_DUPLEX_MASK; - - if (speed == TSE_PCS_PARTNER_SPEED_10 && - duplex == TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 10/Full\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_100 && - duplex == TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 100/Full\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_1000 && - duplex == TSE_PCS_PARTNER_DUPLEX_FULL) - dev_dbg(pcs->dev, - "Adapter: Link Partner is Up - 1000/Full\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_10 && - duplex == TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_100 && - duplex == TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else if (speed == TSE_PCS_PARTNER_SPEED_1000 && - duplex == TSE_PCS_PARTNER_DUPLEX_HALF) - dev_err(pcs->dev, - "Adapter does not support Half Duplex\n"); - else - dev_err(pcs->dev, - "Adapter: Invalid Partner Speed and Duplex\n"); - - if (duplex == TSE_PCS_PARTNER_DUPLEX_FULL && - (speed == TSE_PCS_PARTNER_SPEED_10 || - speed == TSE_PCS_PARTNER_SPEED_100 || - speed == TSE_PCS_PARTNER_SPEED_1000)) - writew(SGMII_ADAPTER_ENABLE, - sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - } else { - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_CONTROL_RESTART_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - tse_pcs_reset(tse_pcs_base, pcs); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} - -static void aneg_link_timer_callback(struct timer_list *t) -{ - struct tse_pcs *pcs = from_timer(pcs, t, aneg_link_timer); - - if (pcs->autoneg == AUTONEG_ENABLE) - auto_nego_timer_callback(pcs); - else if (pcs->autoneg == AUTONEG_DISABLE) - pcs_link_timer_callback(pcs); -} - -void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, - unsigned int speed) -{ - void __iomem *tse_pcs_base = pcs->tse_pcs_base; - u32 val; - - pcs->autoneg = phy_dev->autoneg; - - if (phy_dev->autoneg == AUTONEG_ENABLE) { - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_CONTROL_AN_EN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val |= TSE_PCS_USE_SGMII_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val |= TSE_PCS_CONTROL_RESTART_AN_MASK; - - tse_pcs_reset(tse_pcs_base, pcs); - - timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback, - 0); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } else if (phy_dev->autoneg == AUTONEG_DISABLE) { - val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); - val &= ~TSE_PCS_CONTROL_AN_EN_MASK; - writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); - - val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val &= ~TSE_PCS_USE_SGMII_AN_MASK; - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); - val &= ~TSE_PCS_SGMII_SPEED_MASK; - - switch (speed) { - case 1000: - val |= TSE_PCS_SGMII_SPEED_1000; - break; - case 100: - val |= TSE_PCS_SGMII_SPEED_100; - break; - case 10: - val |= TSE_PCS_SGMII_SPEED_10; - break; - default: - return; - } - writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); - - tse_pcs_reset(tse_pcs_base, pcs); - - timer_setup(&pcs->aneg_link_timer, aneg_link_timer_callback, - 0); - mod_timer(&pcs->aneg_link_timer, jiffies + - msecs_to_jiffies(AUTONEGO_LINK_TIMER)); - } -} diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h deleted file mode 100644 index 694ac25ef426ba..00000000000000 --- a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h +++ /dev/null @@ -1,29 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright Altera Corporation (C) 2016. All rights reserved. - * - * Author: Tien Hock Loh - */ - -#ifndef __TSE_PCS_H__ -#define __TSE_PCS_H__ - -#include -#include - -#define SGMII_ADAPTER_CTRL_REG 0x00 -#define SGMII_ADAPTER_ENABLE 0x0000 -#define SGMII_ADAPTER_DISABLE 0x0001 - -struct tse_pcs { - struct device *dev; - void __iomem *tse_pcs_base; - void __iomem *sgmii_adapter_base; - struct timer_list aneg_link_timer; - int autoneg; -}; - -int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs); -void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, - unsigned int speed); - -#endif /* __TSE_PCS_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index 4ad692c4116c8b..16e67c18b6f713 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -519,6 +519,7 @@ struct mac_device_info { const struct stmmac_tc_ops *tc; const struct stmmac_mmc_ops *mmc; struct dw_xpcs *xpcs; + struct phylink_pcs *lynx_pcs; /* Lynx external PCS */ struct mii_regs mii; /* MII register Addresses */ struct mac_link link; void __iomem *pcsr; /* vpointer to device CSRs */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 1db97a5209c4f2..c801838fae2a4f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -644,7 +644,8 @@ static int qcom_ethqos_probe(struct platform_device *pdev) plat_dat->fix_mac_speed = ethqos_fix_mac_speed; plat_dat->dump_debug_regs = rgmii_dump; plat_dat->has_gmac4 = 1; - plat_dat->dwmac4_addrs = &data->dwmac4_addrs; + if (ethqos->has_emac3) + plat_dat->dwmac4_addrs = &data->dwmac4_addrs; plat_dat->pmt = 1; plat_dat->tso_en = of_property_read_bool(np, "snps,tso"); if (of_device_is_compatible(np, "qcom,qcs404-ethqos")) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 6ee050300b316d..6267bcb60206b3 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -10,14 +10,14 @@ #include #include #include +#include +#include #include #include #include "stmmac.h" #include "stmmac_platform.h" -#include "altr_tse_pcs.h" - #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 @@ -37,6 +37,10 @@ #define EMAC_SPLITTER_CTRL_SPEED_100 0x3 #define EMAC_SPLITTER_CTRL_SPEED_1000 0x0 +#define SGMII_ADAPTER_CTRL_REG 0x00 +#define SGMII_ADAPTER_ENABLE 0x0000 +#define SGMII_ADAPTER_DISABLE 0x0001 + struct socfpga_dwmac; struct socfpga_dwmac_ops { int (*set_phy_mode)(struct socfpga_dwmac *dwmac_priv); @@ -50,16 +54,18 @@ struct socfpga_dwmac { struct reset_control *stmmac_rst; struct reset_control *stmmac_ocp_rst; void __iomem *splitter_base; + void __iomem *tse_pcs_base; + void __iomem *sgmii_adapter_base; bool f2h_ptp_ref_clk; - struct tse_pcs pcs; const struct socfpga_dwmac_ops *ops; + struct mdio_device *pcs_mdiodev; }; static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) { struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; void __iomem *splitter_base = dwmac->splitter_base; - void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base; + void __iomem *sgmii_adapter_base = dwmac->sgmii_adapter_base; struct device *dev = dwmac->dev; struct net_device *ndev = dev_get_drvdata(dev); struct phy_device *phy_dev = ndev->phydev; @@ -89,11 +95,9 @@ static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); } - if (phy_dev && sgmii_adapter_base) { + if (phy_dev && sgmii_adapter_base) writew(SGMII_ADAPTER_ENABLE, sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); - tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); - } } static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) @@ -183,11 +187,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * goto err_node_put; } - dwmac->pcs.sgmii_adapter_base = + dwmac->sgmii_adapter_base = devm_ioremap_resource(dev, &res_sgmii_adapter); - if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) { - ret = PTR_ERR(dwmac->pcs.sgmii_adapter_base); + if (IS_ERR(dwmac->sgmii_adapter_base)) { + ret = PTR_ERR(dwmac->sgmii_adapter_base); goto err_node_put; } } @@ -205,11 +209,11 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * goto err_node_put; } - dwmac->pcs.tse_pcs_base = + dwmac->tse_pcs_base = devm_ioremap_resource(dev, &res_tse_pcs); - if (IS_ERR(dwmac->pcs.tse_pcs_base)) { - ret = PTR_ERR(dwmac->pcs.tse_pcs_base); + if (IS_ERR(dwmac->tse_pcs_base)) { + ret = PTR_ERR(dwmac->tse_pcs_base); goto err_node_put; } } @@ -235,6 +239,13 @@ static int socfpga_get_plat_phymode(struct socfpga_dwmac *dwmac) return priv->plat->interface; } +static void socfpga_sgmii_config(struct socfpga_dwmac *dwmac, bool enable) +{ + u16 val = enable ? SGMII_ADAPTER_ENABLE : SGMII_ADAPTER_DISABLE; + + writew(val, dwmac->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); +} + static int socfpga_set_phy_mode_common(int phymode, u32 *val) { switch (phymode) { @@ -310,12 +321,8 @@ static int socfpga_gen5_set_phy_mode(struct socfpga_dwmac *dwmac) */ reset_control_deassert(dwmac->stmmac_ocp_rst); reset_control_deassert(dwmac->stmmac_rst); - if (phymode == PHY_INTERFACE_MODE_SGMII) { - if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { - dev_err(dwmac->dev, "Unable to initialize TSE PCS"); - return -EINVAL; - } - } + if (phymode == PHY_INTERFACE_MODE_SGMII) + socfpga_sgmii_config(dwmac, true); return 0; } @@ -367,12 +374,8 @@ static int socfpga_gen10_set_phy_mode(struct socfpga_dwmac *dwmac) */ reset_control_deassert(dwmac->stmmac_ocp_rst); reset_control_deassert(dwmac->stmmac_rst); - if (phymode == PHY_INTERFACE_MODE_SGMII) { - if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { - dev_err(dwmac->dev, "Unable to initialize TSE PCS"); - return -EINVAL; - } - } + if (phymode == PHY_INTERFACE_MODE_SGMII) + socfpga_sgmii_config(dwmac, true); return 0; } @@ -443,6 +446,48 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) if (ret) goto err_dvr_remove; + /* Create a regmap for the PCS so that it can be used by the PCS driver, + * if we have such a PCS + */ + if (dwmac->tse_pcs_base) { + struct regmap_config pcs_regmap_cfg; + struct mdio_regmap_config mrc; + struct regmap *pcs_regmap; + struct mii_bus *pcs_bus; + + memset(&pcs_regmap_cfg, 0, sizeof(pcs_regmap_cfg)); + memset(&mrc, 0, sizeof(mrc)); + + pcs_regmap_cfg.reg_bits = 16; + pcs_regmap_cfg.val_bits = 16; + pcs_regmap_cfg.reg_shift = REGMAP_UPSHIFT(1); + + pcs_regmap = devm_regmap_init_mmio(&pdev->dev, dwmac->tse_pcs_base, + &pcs_regmap_cfg); + if (IS_ERR(pcs_regmap)) { + ret = PTR_ERR(pcs_regmap); + goto err_dvr_remove; + } + + mrc.regmap = pcs_regmap; + mrc.parent = &pdev->dev; + mrc.valid_addr = 0x0; + mrc.autoscan = false; + + snprintf(mrc.name, MII_BUS_ID_SIZE, "%s-pcs-mii", ndev->name); + pcs_bus = devm_mdio_regmap_register(&pdev->dev, &mrc); + if (IS_ERR(pcs_bus)) { + ret = PTR_ERR(pcs_bus); + goto err_dvr_remove; + } + + stpriv->hw->lynx_pcs = lynx_pcs_create_mdiodev(pcs_bus, 0); + if (IS_ERR(stpriv->hw->lynx_pcs)) { + ret = PTR_ERR(stpriv->hw->lynx_pcs); + goto err_dvr_remove; + } + } + return 0; err_dvr_remove: @@ -453,6 +498,17 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) return ret; } +static void socfpga_dwmac_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + struct phylink_pcs *pcs = priv->hw->lynx_pcs; + + stmmac_pltfr_remove(pdev); + + lynx_pcs_destroy(pcs); +} + #ifdef CONFIG_PM_SLEEP static int socfpga_dwmac_resume(struct device *dev) { @@ -524,7 +580,7 @@ MODULE_DEVICE_TABLE(of, socfpga_dwmac_match); static struct platform_driver socfpga_dwmac_driver = { .probe = socfpga_dwmac_probe, - .remove_new = stmmac_pltfr_remove, + .remove_new = socfpga_dwmac_remove, .driver = { .name = "socfpga-dwmac", .pm = &socfpga_dwmac_pm_ops, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 0fca81507a779a..fa07b0d50b4689 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -937,10 +937,13 @@ static struct phylink_pcs *stmmac_mac_select_pcs(struct phylink_config *config, { struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev)); - if (!priv->hw->xpcs) - return NULL; + if (priv->hw->xpcs) + return &priv->hw->xpcs->pcs; + + if (priv->hw->lynx_pcs) + return priv->hw->lynx_pcs; - return &priv->hw->xpcs->pcs; + return NULL; } static void stmmac_mac_config(struct phylink_config *config, unsigned int mode, @@ -3813,7 +3816,8 @@ static int __stmmac_open(struct net_device *dev, if (priv->hw->pcs != STMMAC_PCS_TBI && priv->hw->pcs != STMMAC_PCS_RTBI && (!priv->hw->xpcs || - xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73)) { + xpcs_get_an_mode(priv->hw->xpcs, mode) != DW_AN_C73) && + !priv->hw->lynx_pcs) { ret = stmmac_init_phy(dev); if (ret) { netdev_err(priv->dev, @@ -7233,8 +7237,7 @@ int stmmac_dvr_probe(struct device *device, ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | - NETDEV_XDP_ACT_XSK_ZEROCOPY | - NETDEV_XDP_ACT_NDO_XMIT; + NETDEV_XDP_ACT_XSK_ZEROCOPY; ret = stmmac_tc_init(priv, priv); if (!ret) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 6807c4c1a0a2f7..3db1cb0fd160ca 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -491,7 +491,6 @@ int stmmac_mdio_reset(struct mii_bus *bus) int stmmac_xpcs_setup(struct mii_bus *bus) { struct net_device *ndev = bus->priv; - struct mdio_device *mdiodev; struct stmmac_priv *priv; struct dw_xpcs *xpcs; int mode, addr; @@ -501,16 +500,10 @@ int stmmac_xpcs_setup(struct mii_bus *bus) /* Try to probe the XPCS by scanning all addresses. */ for (addr = 0; addr < PHY_MAX_ADDR; addr++) { - mdiodev = mdio_device_create(bus, addr); - if (IS_ERR(mdiodev)) + xpcs = xpcs_create_mdiodev(bus, addr, mode); + if (IS_ERR(xpcs)) continue; - xpcs = xpcs_create(mdiodev, mode); - if (IS_ERR_OR_NULL(xpcs)) { - mdio_device_free(mdiodev); - continue; - } - priv->hw->xpcs = xpcs; break; } @@ -669,10 +662,8 @@ int stmmac_mdio_unregister(struct net_device *ndev) if (!priv->mii) return 0; - if (priv->hw->xpcs) { - mdio_device_free(priv->hw->xpcs->mdiodev); + if (priv->hw->xpcs) xpcs_destroy(priv->hw->xpcs); - } mdiobus_unregister(priv->mii); priv->mii->priv = NULL; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c index 9d55226479b4a7..ac41ef4cbd2f02 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c @@ -966,8 +966,11 @@ static int tc_setup_taprio(struct stmmac_priv *priv, return -EOPNOTSUPP; } - if (!qopt->enable) + if (qopt->cmd == TAPRIO_CMD_DESTROY) goto disable; + else if (qopt->cmd != TAPRIO_CMD_REPLACE) + return -EOPNOTSUPP; + if (qopt->num_entries >= dep) return -EINVAL; if (!qopt->cycle_time) @@ -988,7 +991,7 @@ static int tc_setup_taprio(struct stmmac_priv *priv, mutex_lock(&priv->plat->est->lock); priv->plat->est->gcl_size = size; - priv->plat->est->enable = qopt->enable; + priv->plat->est->enable = qopt->cmd == TAPRIO_CMD_REPLACE; mutex_unlock(&priv->plat->est->lock); for (i = 0; i < size; i++) { diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c index 9d4d8c3dad0a3f..aa6f16d3df649e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c @@ -117,6 +117,9 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog, return -EOPNOTSUPP; } + if (!prog) + xdp_features_clear_redirect_target(dev); + need_update = !!priv->xdp_prog != !!prog; if (if_running && need_update) stmmac_xdp_release(dev); @@ -131,5 +134,8 @@ int stmmac_xdp_set_prog(struct stmmac_priv *priv, struct bpf_prog *prog, if (if_running && need_update) stmmac_xdp_open(dev); + if (prog) + xdp_features_set_redirect_target(dev, false); + return 0; } diff --git a/drivers/net/ethernet/ti/am65-cpsw-qos.c b/drivers/net/ethernet/ti/am65-cpsw-qos.c index 3a908db6e5b22e..eced87fa261c9c 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-qos.c +++ b/drivers/net/ethernet/ti/am65-cpsw-qos.c @@ -450,7 +450,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev, am65_cpsw_est_update_state(ndev); - if (!est_new->taprio.enable) { + if (est_new->taprio.cmd == TAPRIO_CMD_DESTROY) { am65_cpsw_stop_est(ndev); return ret; } @@ -476,7 +476,7 @@ static int am65_cpsw_configure_taprio(struct net_device *ndev, am65_cpsw_est_set_sched_list(ndev, est_new); am65_cpsw_port_est_assign_buf_num(ndev, est_new->buf); - am65_cpsw_est_set(ndev, est_new->taprio.enable); + am65_cpsw_est_set(ndev, est_new->taprio.cmd == TAPRIO_CMD_REPLACE); if (tact == TACT_PROG) { ret = am65_cpsw_timer_set(ndev, est_new); @@ -520,7 +520,7 @@ static int am65_cpsw_set_taprio(struct net_device *ndev, void *type_data) am65_cpsw_cp_taprio(taprio, &est_new->taprio); ret = am65_cpsw_configure_taprio(ndev, est_new); if (!ret) { - if (taprio->enable) { + if (taprio->cmd == TAPRIO_CMD_REPLACE) { devm_kfree(&ndev->dev, port->qos.est_admin); port->qos.est_admin = est_new; @@ -564,8 +564,13 @@ static void am65_cpsw_est_link_up(struct net_device *ndev, int link_speed) static int am65_cpsw_setup_taprio(struct net_device *ndev, void *type_data) { struct am65_cpsw_port *port = am65_ndev_to_port(ndev); + struct tc_taprio_qopt_offload *taprio = type_data; struct am65_cpsw_common *common = port->common; + if (taprio->cmd != TAPRIO_CMD_REPLACE && + taprio->cmd != TAPRIO_CMD_DESTROY) + return -EOPNOTSUPP; + if (!IS_ENABLED(CONFIG_TI_AM65_CPSW_TAS)) return -ENODEV; diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig index c9d88673d30628..39596cd1353948 100644 --- a/drivers/net/ethernet/wangxun/Kconfig +++ b/drivers/net/ethernet/wangxun/Kconfig @@ -40,6 +40,16 @@ config NGBE config TXGBE tristate "Wangxun(R) 10GbE PCI Express adapters support" depends on PCI + depends on COMMON_CLK + select REGMAP + select I2C + select I2C_DESIGNWARE_PLATFORM + select PHYLINK + select HWMON if TXGBE=y + select SFP + select GPIOLIB + select GPIOLIB_IRQCHIP + select PCS_XPCS select LIBWX help This driver supports Wangxun(R) 10GbE PCI Express family of diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c index ca409b4054d060..39a9aeee7aab22 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c @@ -1182,12 +1182,28 @@ static void wx_enable_sec_rx_path(struct wx *wx) WX_WRITE_FLUSH(wx); } +static void wx_vlan_strip_control(struct wx *wx, bool enable) +{ + int i, j; + + for (i = 0; i < wx->num_rx_queues; i++) { + struct wx_ring *ring = wx->rx_ring[i]; + + j = ring->reg_idx; + wr32m(wx, WX_PX_RR_CFG(j), WX_PX_RR_CFG_VLAN, + enable ? WX_PX_RR_CFG_VLAN : 0); + } +} + void wx_set_rx_mode(struct net_device *netdev) { struct wx *wx = netdev_priv(netdev); + netdev_features_t features; u32 fctrl, vmolr, vlnctrl; int count; + features = netdev->features; + /* Check for Promiscuous and All Multicast modes */ fctrl = rd32(wx, WX_PSR_CTL); fctrl &= ~(WX_PSR_CTL_UPE | WX_PSR_CTL_MPE); @@ -1254,6 +1270,13 @@ void wx_set_rx_mode(struct net_device *netdev) wr32(wx, WX_PSR_VLAN_CTL, vlnctrl); wr32(wx, WX_PSR_CTL, fctrl); wr32(wx, WX_PSR_VM_L2CTL(0), vmolr); + + if ((features & NETIF_F_HW_VLAN_CTAG_RX) && + (features & NETIF_F_HW_VLAN_STAG_RX)) + wx_vlan_strip_control(wx, true); + else + wx_vlan_strip_control(wx, false); + } EXPORT_SYMBOL(wx_set_rx_mode); @@ -1462,6 +1485,16 @@ static void wx_configure_tx(struct wx *wx) WX_MAC_TX_CFG_TE, WX_MAC_TX_CFG_TE); } +static void wx_restore_vlan(struct wx *wx) +{ + u16 vid = 1; + + wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), 0); + + for_each_set_bit_from(vid, wx->active_vlans, VLAN_N_VID) + wx_vlan_rx_add_vid(wx->netdev, htons(ETH_P_8021Q), vid); +} + /** * wx_configure_rx - Configure Receive Unit after Reset * @wx: pointer to private structure @@ -1527,7 +1560,7 @@ void wx_configure(struct wx *wx) wx_configure_port(wx); wx_set_rx_mode(wx->netdev); - + wx_restore_vlan(wx); wx_enable_sec_rx_path(wx); wx_configure_tx(wx); @@ -1727,4 +1760,241 @@ int wx_sw_init(struct wx *wx) } EXPORT_SYMBOL(wx_sw_init); +/** + * wx_find_vlvf_slot - find the vlanid or the first empty slot + * @wx: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * + * return the VLVF index where this VLAN id should be placed + * + **/ +static int wx_find_vlvf_slot(struct wx *wx, u32 vlan) +{ + u32 bits = 0, first_empty_slot = 0; + int regindex; + + /* short cut the special case */ + if (vlan == 0) + return 0; + + /* Search for the vlan id in the VLVF entries. Save off the first empty + * slot found along the way + */ + for (regindex = 1; regindex < WX_PSR_VLAN_SWC_ENTRIES; regindex++) { + wr32(wx, WX_PSR_VLAN_SWC_IDX, regindex); + bits = rd32(wx, WX_PSR_VLAN_SWC); + if (!bits && !(first_empty_slot)) + first_empty_slot = regindex; + else if ((bits & 0x0FFF) == vlan) + break; + } + + if (regindex >= WX_PSR_VLAN_SWC_ENTRIES) { + if (first_empty_slot) + regindex = first_empty_slot; + else + regindex = -ENOMEM; + } + + return regindex; +} + +/** + * wx_set_vlvf - Set VLAN Pool Filter + * @wx: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFVFB + * @vlan_on: boolean flag to turn on/off VLAN in VFVF + * @vfta_changed: pointer to boolean flag which indicates whether VFTA + * should be changed + * + * Turn on/off specified bit in VLVF table. + **/ +static int wx_set_vlvf(struct wx *wx, u32 vlan, u32 vind, bool vlan_on, + bool *vfta_changed) +{ + int vlvf_index; + u32 vt, bits; + + /* If VT Mode is set + * Either vlan_on + * make sure the vlan is in VLVF + * set the vind bit in the matching VLVFB + * Or !vlan_on + * clear the pool bit and possibly the vind + */ + vt = rd32(wx, WX_CFG_PORT_CTL); + if (!(vt & WX_CFG_PORT_CTL_NUM_VT_MASK)) + return 0; + + vlvf_index = wx_find_vlvf_slot(wx, vlan); + if (vlvf_index < 0) + return vlvf_index; + + wr32(wx, WX_PSR_VLAN_SWC_IDX, vlvf_index); + if (vlan_on) { + /* set the pool bit */ + if (vind < 32) { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L); + bits |= (1 << vind); + wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits); + } else { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H); + bits |= (1 << (vind - 32)); + wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits); + } + } else { + /* clear the pool bit */ + if (vind < 32) { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_L); + bits &= ~(1 << vind); + wr32(wx, WX_PSR_VLAN_SWC_VM_L, bits); + bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_H); + } else { + bits = rd32(wx, WX_PSR_VLAN_SWC_VM_H); + bits &= ~(1 << (vind - 32)); + wr32(wx, WX_PSR_VLAN_SWC_VM_H, bits); + bits |= rd32(wx, WX_PSR_VLAN_SWC_VM_L); + } + } + + if (bits) { + wr32(wx, WX_PSR_VLAN_SWC, (WX_PSR_VLAN_SWC_VIEN | vlan)); + if (!vlan_on && vfta_changed) + *vfta_changed = false; + } else { + wr32(wx, WX_PSR_VLAN_SWC, 0); + } + + return 0; +} + +/** + * wx_set_vfta - Set VLAN filter table + * @wx: pointer to hardware structure + * @vlan: VLAN id to write to VLAN filter + * @vind: VMDq output index that maps queue to VLAN id in VFVFB + * @vlan_on: boolean flag to turn on/off VLAN in VFVF + * + * Turn on/off specified VLAN in the VLAN filter table. + **/ +static int wx_set_vfta(struct wx *wx, u32 vlan, u32 vind, bool vlan_on) +{ + u32 bitindex, vfta, targetbit; + bool vfta_changed = false; + int regindex, ret; + + /* this is a 2 part operation - first the VFTA, then the + * VLVF and VLVFB if VT Mode is set + * We don't write the VFTA until we know the VLVF part succeeded. + */ + + /* Part 1 + * The VFTA is a bitstring made up of 128 32-bit registers + * that enable the particular VLAN id, much like the MTA: + * bits[11-5]: which register + * bits[4-0]: which bit in the register + */ + regindex = (vlan >> 5) & 0x7F; + bitindex = vlan & 0x1F; + targetbit = (1 << bitindex); + /* errata 5 */ + vfta = wx->mac.vft_shadow[regindex]; + if (vlan_on) { + if (!(vfta & targetbit)) { + vfta |= targetbit; + vfta_changed = true; + } + } else { + if ((vfta & targetbit)) { + vfta &= ~targetbit; + vfta_changed = true; + } + } + /* Part 2 + * Call wx_set_vlvf to set VLVFB and VLVF + */ + ret = wx_set_vlvf(wx, vlan, vind, vlan_on, &vfta_changed); + if (ret != 0) + return ret; + + if (vfta_changed) + wr32(wx, WX_PSR_VLAN_TBL(regindex), vfta); + wx->mac.vft_shadow[regindex] = vfta; + + return 0; +} + +/** + * wx_clear_vfta - Clear VLAN filter table + * @wx: pointer to hardware structure + * + * Clears the VLAN filer table, and the VMDq index associated with the filter + **/ +static void wx_clear_vfta(struct wx *wx) +{ + u32 offset; + + for (offset = 0; offset < wx->mac.vft_size; offset++) { + wr32(wx, WX_PSR_VLAN_TBL(offset), 0); + wx->mac.vft_shadow[offset] = 0; + } + + for (offset = 0; offset < WX_PSR_VLAN_SWC_ENTRIES; offset++) { + wr32(wx, WX_PSR_VLAN_SWC_IDX, offset); + wr32(wx, WX_PSR_VLAN_SWC, 0); + wr32(wx, WX_PSR_VLAN_SWC_VM_L, 0); + wr32(wx, WX_PSR_VLAN_SWC_VM_H, 0); + } +} + +int wx_vlan_rx_add_vid(struct net_device *netdev, + __be16 proto, u16 vid) +{ + struct wx *wx = netdev_priv(netdev); + + /* add VID to filter table */ + wx_set_vfta(wx, vid, VMDQ_P(0), true); + set_bit(vid, wx->active_vlans); + + return 0; +} +EXPORT_SYMBOL(wx_vlan_rx_add_vid); + +int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid) +{ + struct wx *wx = netdev_priv(netdev); + + /* remove VID from filter table */ + if (vid) + wx_set_vfta(wx, vid, VMDQ_P(0), false); + clear_bit(vid, wx->active_vlans); + + return 0; +} +EXPORT_SYMBOL(wx_vlan_rx_kill_vid); + +/** + * wx_start_hw - Prepare hardware for Tx/Rx + * @wx: pointer to hardware structure + * + * Starts the hardware using the generic start_hw function + * and the generation start_hw function. + * Then performs revision-specific operations, if any. + **/ +void wx_start_hw(struct wx *wx) +{ + int i; + + /* Clear the VLAN filter table */ + wx_clear_vfta(wx); + WX_WRITE_FLUSH(wx); + /* Clear the rate limiters */ + for (i = 0; i < wx->mac.max_tx_queues; i++) { + wr32(wx, WX_TDM_RP_IDX, i); + wr32(wx, WX_TDM_RP_RATE, 0); + } +} +EXPORT_SYMBOL(wx_start_hw); + MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.h b/drivers/net/ethernet/wangxun/libwx/wx_hw.h index c173c56f0ab5d2..1f93ca32c92125 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_hw.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.h @@ -26,10 +26,13 @@ void wx_set_rx_mode(struct net_device *netdev); int wx_change_mtu(struct net_device *netdev, int new_mtu); void wx_disable_rx_queue(struct wx *wx, struct wx_ring *ring); void wx_configure(struct wx *wx); +void wx_start_hw(struct wx *wx); int wx_disable_pcie_master(struct wx *wx); int wx_stop_adapter(struct wx *wx); void wx_reset_misc(struct wx *wx); int wx_get_pcie_msix_counts(struct wx *wx, u16 *msix_count, u16 max_msix_count); int wx_sw_init(struct wx *wx); +int wx_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, u16 vid); +int wx_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, u16 vid); #endif /* _WX_HW_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.c b/drivers/net/ethernet/wangxun/libwx/wx_lib.c index 1e8d8b7b0c62e2..2c3f08be8c3743 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.c +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.c @@ -2,14 +2,157 @@ /* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */ #include +#include #include +#include #include +#include #include +#include +#include #include "wx_type.h" #include "wx_lib.h" #include "wx_hw.h" +/* Lookup table mapping the HW PTYPE to the bit field for decoding */ +static struct wx_dec_ptype wx_ptype_lookup[256] = { + /* L2: mac */ + [0x11] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x12] = WX_PTT(L2, NONE, NONE, NONE, TS, PAY2), + [0x13] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x14] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x15] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE), + [0x16] = WX_PTT(L2, NONE, NONE, NONE, NONE, PAY2), + [0x17] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE), + + /* L2: ethertype filter */ + [0x18 ... 0x1F] = WX_PTT(L2, NONE, NONE, NONE, NONE, NONE), + + /* L3: ip non-tunnel */ + [0x21] = WX_PTT(IP, FGV4, NONE, NONE, NONE, PAY3), + [0x22] = WX_PTT(IP, IPV4, NONE, NONE, NONE, PAY3), + [0x23] = WX_PTT(IP, IPV4, NONE, NONE, UDP, PAY4), + [0x24] = WX_PTT(IP, IPV4, NONE, NONE, TCP, PAY4), + [0x25] = WX_PTT(IP, IPV4, NONE, NONE, SCTP, PAY4), + [0x29] = WX_PTT(IP, FGV6, NONE, NONE, NONE, PAY3), + [0x2A] = WX_PTT(IP, IPV6, NONE, NONE, NONE, PAY3), + [0x2B] = WX_PTT(IP, IPV6, NONE, NONE, UDP, PAY3), + [0x2C] = WX_PTT(IP, IPV6, NONE, NONE, TCP, PAY4), + [0x2D] = WX_PTT(IP, IPV6, NONE, NONE, SCTP, PAY4), + + /* L2: fcoe */ + [0x30 ... 0x34] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3), + [0x38 ... 0x3C] = WX_PTT(FCOE, NONE, NONE, NONE, NONE, PAY3), + + /* IPv4 --> IPv4/IPv6 */ + [0x81] = WX_PTT(IP, IPV4, IPIP, FGV4, NONE, PAY3), + [0x82] = WX_PTT(IP, IPV4, IPIP, IPV4, NONE, PAY3), + [0x83] = WX_PTT(IP, IPV4, IPIP, IPV4, UDP, PAY4), + [0x84] = WX_PTT(IP, IPV4, IPIP, IPV4, TCP, PAY4), + [0x85] = WX_PTT(IP, IPV4, IPIP, IPV4, SCTP, PAY4), + [0x89] = WX_PTT(IP, IPV4, IPIP, FGV6, NONE, PAY3), + [0x8A] = WX_PTT(IP, IPV4, IPIP, IPV6, NONE, PAY3), + [0x8B] = WX_PTT(IP, IPV4, IPIP, IPV6, UDP, PAY4), + [0x8C] = WX_PTT(IP, IPV4, IPIP, IPV6, TCP, PAY4), + [0x8D] = WX_PTT(IP, IPV4, IPIP, IPV6, SCTP, PAY4), + + /* IPv4 --> GRE/NAT --> NONE/IPv4/IPv6 */ + [0x90] = WX_PTT(IP, IPV4, IG, NONE, NONE, PAY3), + [0x91] = WX_PTT(IP, IPV4, IG, FGV4, NONE, PAY3), + [0x92] = WX_PTT(IP, IPV4, IG, IPV4, NONE, PAY3), + [0x93] = WX_PTT(IP, IPV4, IG, IPV4, UDP, PAY4), + [0x94] = WX_PTT(IP, IPV4, IG, IPV4, TCP, PAY4), + [0x95] = WX_PTT(IP, IPV4, IG, IPV4, SCTP, PAY4), + [0x99] = WX_PTT(IP, IPV4, IG, FGV6, NONE, PAY3), + [0x9A] = WX_PTT(IP, IPV4, IG, IPV6, NONE, PAY3), + [0x9B] = WX_PTT(IP, IPV4, IG, IPV6, UDP, PAY4), + [0x9C] = WX_PTT(IP, IPV4, IG, IPV6, TCP, PAY4), + [0x9D] = WX_PTT(IP, IPV4, IG, IPV6, SCTP, PAY4), + + /* IPv4 --> GRE/NAT --> MAC --> NONE/IPv4/IPv6 */ + [0xA0] = WX_PTT(IP, IPV4, IGM, NONE, NONE, PAY3), + [0xA1] = WX_PTT(IP, IPV4, IGM, FGV4, NONE, PAY3), + [0xA2] = WX_PTT(IP, IPV4, IGM, IPV4, NONE, PAY3), + [0xA3] = WX_PTT(IP, IPV4, IGM, IPV4, UDP, PAY4), + [0xA4] = WX_PTT(IP, IPV4, IGM, IPV4, TCP, PAY4), + [0xA5] = WX_PTT(IP, IPV4, IGM, IPV4, SCTP, PAY4), + [0xA9] = WX_PTT(IP, IPV4, IGM, FGV6, NONE, PAY3), + [0xAA] = WX_PTT(IP, IPV4, IGM, IPV6, NONE, PAY3), + [0xAB] = WX_PTT(IP, IPV4, IGM, IPV6, UDP, PAY4), + [0xAC] = WX_PTT(IP, IPV4, IGM, IPV6, TCP, PAY4), + [0xAD] = WX_PTT(IP, IPV4, IGM, IPV6, SCTP, PAY4), + + /* IPv4 --> GRE/NAT --> MAC+VLAN --> NONE/IPv4/IPv6 */ + [0xB0] = WX_PTT(IP, IPV4, IGMV, NONE, NONE, PAY3), + [0xB1] = WX_PTT(IP, IPV4, IGMV, FGV4, NONE, PAY3), + [0xB2] = WX_PTT(IP, IPV4, IGMV, IPV4, NONE, PAY3), + [0xB3] = WX_PTT(IP, IPV4, IGMV, IPV4, UDP, PAY4), + [0xB4] = WX_PTT(IP, IPV4, IGMV, IPV4, TCP, PAY4), + [0xB5] = WX_PTT(IP, IPV4, IGMV, IPV4, SCTP, PAY4), + [0xB9] = WX_PTT(IP, IPV4, IGMV, FGV6, NONE, PAY3), + [0xBA] = WX_PTT(IP, IPV4, IGMV, IPV6, NONE, PAY3), + [0xBB] = WX_PTT(IP, IPV4, IGMV, IPV6, UDP, PAY4), + [0xBC] = WX_PTT(IP, IPV4, IGMV, IPV6, TCP, PAY4), + [0xBD] = WX_PTT(IP, IPV4, IGMV, IPV6, SCTP, PAY4), + + /* IPv6 --> IPv4/IPv6 */ + [0xC1] = WX_PTT(IP, IPV6, IPIP, FGV4, NONE, PAY3), + [0xC2] = WX_PTT(IP, IPV6, IPIP, IPV4, NONE, PAY3), + [0xC3] = WX_PTT(IP, IPV6, IPIP, IPV4, UDP, PAY4), + [0xC4] = WX_PTT(IP, IPV6, IPIP, IPV4, TCP, PAY4), + [0xC5] = WX_PTT(IP, IPV6, IPIP, IPV4, SCTP, PAY4), + [0xC9] = WX_PTT(IP, IPV6, IPIP, FGV6, NONE, PAY3), + [0xCA] = WX_PTT(IP, IPV6, IPIP, IPV6, NONE, PAY3), + [0xCB] = WX_PTT(IP, IPV6, IPIP, IPV6, UDP, PAY4), + [0xCC] = WX_PTT(IP, IPV6, IPIP, IPV6, TCP, PAY4), + [0xCD] = WX_PTT(IP, IPV6, IPIP, IPV6, SCTP, PAY4), + + /* IPv6 --> GRE/NAT -> NONE/IPv4/IPv6 */ + [0xD0] = WX_PTT(IP, IPV6, IG, NONE, NONE, PAY3), + [0xD1] = WX_PTT(IP, IPV6, IG, FGV4, NONE, PAY3), + [0xD2] = WX_PTT(IP, IPV6, IG, IPV4, NONE, PAY3), + [0xD3] = WX_PTT(IP, IPV6, IG, IPV4, UDP, PAY4), + [0xD4] = WX_PTT(IP, IPV6, IG, IPV4, TCP, PAY4), + [0xD5] = WX_PTT(IP, IPV6, IG, IPV4, SCTP, PAY4), + [0xD9] = WX_PTT(IP, IPV6, IG, FGV6, NONE, PAY3), + [0xDA] = WX_PTT(IP, IPV6, IG, IPV6, NONE, PAY3), + [0xDB] = WX_PTT(IP, IPV6, IG, IPV6, UDP, PAY4), + [0xDC] = WX_PTT(IP, IPV6, IG, IPV6, TCP, PAY4), + [0xDD] = WX_PTT(IP, IPV6, IG, IPV6, SCTP, PAY4), + + /* IPv6 --> GRE/NAT -> MAC -> NONE/IPv4/IPv6 */ + [0xE0] = WX_PTT(IP, IPV6, IGM, NONE, NONE, PAY3), + [0xE1] = WX_PTT(IP, IPV6, IGM, FGV4, NONE, PAY3), + [0xE2] = WX_PTT(IP, IPV6, IGM, IPV4, NONE, PAY3), + [0xE3] = WX_PTT(IP, IPV6, IGM, IPV4, UDP, PAY4), + [0xE4] = WX_PTT(IP, IPV6, IGM, IPV4, TCP, PAY4), + [0xE5] = WX_PTT(IP, IPV6, IGM, IPV4, SCTP, PAY4), + [0xE9] = WX_PTT(IP, IPV6, IGM, FGV6, NONE, PAY3), + [0xEA] = WX_PTT(IP, IPV6, IGM, IPV6, NONE, PAY3), + [0xEB] = WX_PTT(IP, IPV6, IGM, IPV6, UDP, PAY4), + [0xEC] = WX_PTT(IP, IPV6, IGM, IPV6, TCP, PAY4), + [0xED] = WX_PTT(IP, IPV6, IGM, IPV6, SCTP, PAY4), + + /* IPv6 --> GRE/NAT -> MAC--> NONE/IPv */ + [0xF0] = WX_PTT(IP, IPV6, IGMV, NONE, NONE, PAY3), + [0xF1] = WX_PTT(IP, IPV6, IGMV, FGV4, NONE, PAY3), + [0xF2] = WX_PTT(IP, IPV6, IGMV, IPV4, NONE, PAY3), + [0xF3] = WX_PTT(IP, IPV6, IGMV, IPV4, UDP, PAY4), + [0xF4] = WX_PTT(IP, IPV6, IGMV, IPV4, TCP, PAY4), + [0xF5] = WX_PTT(IP, IPV6, IGMV, IPV4, SCTP, PAY4), + [0xF9] = WX_PTT(IP, IPV6, IGMV, FGV6, NONE, PAY3), + [0xFA] = WX_PTT(IP, IPV6, IGMV, IPV6, NONE, PAY3), + [0xFB] = WX_PTT(IP, IPV6, IGMV, IPV6, UDP, PAY4), + [0xFC] = WX_PTT(IP, IPV6, IGMV, IPV6, TCP, PAY4), + [0xFD] = WX_PTT(IP, IPV6, IGMV, IPV6, SCTP, PAY4), +}; + +static struct wx_dec_ptype wx_decode_ptype(const u8 ptype) +{ + return wx_ptype_lookup[ptype]; +} + /* wx_test_staterr - tests bits in Rx descriptor status and error fields */ static __le32 wx_test_staterr(union wx_rx_desc *rx_desc, const u32 stat_err_bits) @@ -419,6 +562,116 @@ static bool wx_cleanup_headers(struct wx_ring *rx_ring, return false; } +static void wx_rx_hash(struct wx_ring *ring, + union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u16 rss_type; + + if (!(ring->netdev->features & NETIF_F_RXHASH)) + return; + + rss_type = le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) & + WX_RXD_RSSTYPE_MASK; + + if (!rss_type) + return; + + skb_set_hash(skb, le32_to_cpu(rx_desc->wb.lower.hi_dword.rss), + (WX_RSS_L4_TYPES_MASK & (1ul << rss_type)) ? + PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); +} + +/** + * wx_rx_checksum - indicate in skb if hw indicated a good cksum + * @ring: structure containing ring specific data + * @rx_desc: current Rx descriptor being processed + * @skb: skb currently being received and modified + **/ +static void wx_rx_checksum(struct wx_ring *ring, + union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + struct wx_dec_ptype dptype = wx_decode_ptype(WX_RXD_PKTTYPE(rx_desc)); + + skb_checksum_none_assert(skb); + /* Rx csum disabled */ + if (!(ring->netdev->features & NETIF_F_RXCSUM)) + return; + + /* if IPv4 header checksum error */ + if ((wx_test_staterr(rx_desc, WX_RXD_STAT_IPCS) && + wx_test_staterr(rx_desc, WX_RXD_ERR_IPE)) || + (wx_test_staterr(rx_desc, WX_RXD_STAT_OUTERIPCS) && + wx_test_staterr(rx_desc, WX_RXD_ERR_OUTERIPER))) { + ring->rx_stats.csum_err++; + return; + } + + /* L4 checksum offload flag must set for the below code to work */ + if (!wx_test_staterr(rx_desc, WX_RXD_STAT_L4CS)) + return; + + /* Hardware can't guarantee csum if IPv6 Dest Header found */ + if (dptype.prot != WX_DEC_PTYPE_PROT_SCTP && WX_RXD_IPV6EX(rx_desc)) + return; + + /* if L4 checksum error */ + if (wx_test_staterr(rx_desc, WX_RXD_ERR_TCPE)) { + ring->rx_stats.csum_err++; + return; + } + + /* It must be a TCP or UDP or SCTP packet with a valid checksum */ + skb->ip_summed = CHECKSUM_UNNECESSARY; + + /* If there is an outer header present that might contain a checksum + * we need to bump the checksum level by 1 to reflect the fact that + * we are indicating we validated the inner checksum. + */ + if (dptype.etype >= WX_DEC_PTYPE_ETYPE_IG) + __skb_incr_checksum_unnecessary(skb); + ring->rx_stats.csum_good_cnt++; +} + +static void wx_rx_vlan(struct wx_ring *ring, union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + u16 ethertype; + u8 idx = 0; + + if ((ring->netdev->features & + (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_STAG_RX)) && + wx_test_staterr(rx_desc, WX_RXD_STAT_VP)) { + idx = (le16_to_cpu(rx_desc->wb.lower.lo_dword.hs_rss.pkt_info) & + 0x1c0) >> 6; + ethertype = ring->q_vector->wx->tpid[idx]; + __vlan_hwaccel_put_tag(skb, htons(ethertype), + le16_to_cpu(rx_desc->wb.upper.vlan)); + } +} + +/** + * wx_process_skb_fields - Populate skb header fields from Rx descriptor + * @rx_ring: rx descriptor ring packet is being transacted on + * @rx_desc: pointer to the EOP Rx descriptor + * @skb: pointer to current skb being populated + * + * This function checks the ring, descriptor, and packet information in + * order to populate the hash, checksum, protocol, and + * other fields within the skb. + **/ +static void wx_process_skb_fields(struct wx_ring *rx_ring, + union wx_rx_desc *rx_desc, + struct sk_buff *skb) +{ + wx_rx_hash(rx_ring, rx_desc, skb); + wx_rx_checksum(rx_ring, rx_desc, skb); + wx_rx_vlan(rx_ring, rx_desc, skb); + skb_record_rx_queue(skb, rx_ring->queue_index); + skb->protocol = eth_type_trans(skb, rx_ring->netdev); +} + /** * wx_clean_rx_irq - Clean completed descriptors from Rx ring - bounce buf * @q_vector: structure containing interrupt and ring information @@ -486,8 +739,8 @@ static int wx_clean_rx_irq(struct wx_q_vector *q_vector, /* probably a little skewed due to removing CRC */ total_rx_bytes += skb->len; - skb_record_rx_queue(skb, rx_ring->queue_index); - skb->protocol = eth_type_trans(skb, rx_ring->netdev); + /* populate checksum, timestamp, VLAN, and protocol */ + wx_process_skb_fields(rx_ring, rx_desc, skb); napi_gro_receive(&q_vector->napi, skb); /* update budget accounting */ @@ -707,11 +960,50 @@ static int wx_maybe_stop_tx(struct wx_ring *tx_ring, u16 size) return 0; } +static u32 wx_tx_cmd_type(u32 tx_flags) +{ + /* set type for advanced descriptor with frame checksum insertion */ + u32 cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS; + + /* set HW vlan bit if vlan is present */ + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_HW_VLAN, WX_TXD_VLE); + /* set segmentation enable bits for TSO/FSO */ + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSO, WX_TXD_TSE); + /* set timestamp bit if present */ + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_TSTAMP, WX_TXD_MAC_TSTAMP); + cmd_type |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_LINKSEC, WX_TXD_LINKSEC); + + return cmd_type; +} + +static void wx_tx_olinfo_status(union wx_tx_desc *tx_desc, + u32 tx_flags, unsigned int paylen) +{ + u32 olinfo_status = paylen << WX_TXD_PAYLEN_SHIFT; + + /* enable L4 checksum for TSO and TX checksum offload */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CSUM, WX_TXD_L4CS); + /* enable IPv4 checksum for TSO */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPV4, WX_TXD_IIPCS); + /* enable outer IPv4 checksum for TSO */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_OUTER_IPV4, + WX_TXD_EIPCS); + /* Check Context must be set if Tx switch is enabled, which it + * always is for case where virtual functions are running + */ + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_CC, WX_TXD_CC); + olinfo_status |= WX_SET_FLAG(tx_flags, WX_TX_FLAGS_IPSEC, + WX_TXD_IPSEC); + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); +} + static void wx_tx_map(struct wx_ring *tx_ring, - struct wx_tx_buffer *first) + struct wx_tx_buffer *first, + const u8 hdr_len) { struct sk_buff *skb = first->skb; struct wx_tx_buffer *tx_buffer; + u32 tx_flags = first->tx_flags; u16 i = tx_ring->next_to_use; unsigned int data_len, size; union wx_tx_desc *tx_desc; @@ -719,10 +1011,9 @@ static void wx_tx_map(struct wx_ring *tx_ring, dma_addr_t dma; u32 cmd_type; - cmd_type = WX_TXD_DTYP_DATA | WX_TXD_IFCS; + cmd_type = wx_tx_cmd_type(tx_flags); tx_desc = WX_TX_DESC(tx_ring, i); - - tx_desc->read.olinfo_status = cpu_to_le32(skb->len << WX_TXD_PAYLEN_SHIFT); + wx_tx_olinfo_status(tx_desc, tx_flags, skb->len - hdr_len); size = skb_headlen(skb); data_len = skb->data_len; @@ -838,12 +1129,399 @@ static void wx_tx_map(struct wx_ring *tx_ring, tx_ring->next_to_use = i; } +static void wx_tx_ctxtdesc(struct wx_ring *tx_ring, u32 vlan_macip_lens, + u32 fcoe_sof_eof, u32 type_tucmd, u32 mss_l4len_idx) +{ + struct wx_tx_context_desc *context_desc; + u16 i = tx_ring->next_to_use; + + context_desc = WX_TX_CTXTDESC(tx_ring, i); + i++; + tx_ring->next_to_use = (i < tx_ring->count) ? i : 0; + + /* set bits to identify this as an advanced context descriptor */ + type_tucmd |= WX_TXD_DTYP_CTXT; + context_desc->vlan_macip_lens = cpu_to_le32(vlan_macip_lens); + context_desc->seqnum_seed = cpu_to_le32(fcoe_sof_eof); + context_desc->type_tucmd_mlhl = cpu_to_le32(type_tucmd); + context_desc->mss_l4len_idx = cpu_to_le32(mss_l4len_idx); +} + +static void wx_get_ipv6_proto(struct sk_buff *skb, int offset, u8 *nexthdr) +{ + struct ipv6hdr *hdr = (struct ipv6hdr *)(skb->data + offset); + + *nexthdr = hdr->nexthdr; + offset += sizeof(struct ipv6hdr); + while (ipv6_ext_hdr(*nexthdr)) { + struct ipv6_opt_hdr _hdr, *hp; + + if (*nexthdr == NEXTHDR_NONE) + return; + hp = skb_header_pointer(skb, offset, sizeof(_hdr), &_hdr); + if (!hp) + return; + if (*nexthdr == NEXTHDR_FRAGMENT) + break; + *nexthdr = hp->nexthdr; + } +} + +union network_header { + struct iphdr *ipv4; + struct ipv6hdr *ipv6; + void *raw; +}; + +static u8 wx_encode_tx_desc_ptype(const struct wx_tx_buffer *first) +{ + u8 tun_prot = 0, l4_prot = 0, ptype = 0; + struct sk_buff *skb = first->skb; + + if (skb->encapsulation) { + union network_header hdr; + + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + ptype = WX_PTYPE_TUN_IPV4; + break; + case htons(ETH_P_IPV6): + wx_get_ipv6_proto(skb, skb_network_offset(skb), &tun_prot); + ptype = WX_PTYPE_TUN_IPV6; + break; + default: + return ptype; + } + + if (tun_prot == IPPROTO_IPIP) { + hdr.raw = (void *)inner_ip_hdr(skb); + ptype |= WX_PTYPE_PKT_IPIP; + } else if (tun_prot == IPPROTO_UDP) { + hdr.raw = (void *)inner_ip_hdr(skb); + if (skb->inner_protocol_type != ENCAP_TYPE_ETHER || + skb->inner_protocol != htons(ETH_P_TEB)) { + ptype |= WX_PTYPE_PKT_IG; + } else { + if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto + == htons(ETH_P_8021Q)) + ptype |= WX_PTYPE_PKT_IGMV; + else + ptype |= WX_PTYPE_PKT_IGM; + } + + } else if (tun_prot == IPPROTO_GRE) { + hdr.raw = (void *)inner_ip_hdr(skb); + if (skb->inner_protocol == htons(ETH_P_IP) || + skb->inner_protocol == htons(ETH_P_IPV6)) { + ptype |= WX_PTYPE_PKT_IG; + } else { + if (((struct ethhdr *)skb_inner_mac_header(skb))->h_proto + == htons(ETH_P_8021Q)) + ptype |= WX_PTYPE_PKT_IGMV; + else + ptype |= WX_PTYPE_PKT_IGM; + } + } else { + return ptype; + } + + switch (hdr.ipv4->version) { + case IPVERSION: + l4_prot = hdr.ipv4->protocol; + break; + case 6: + wx_get_ipv6_proto(skb, skb_inner_network_offset(skb), &l4_prot); + ptype |= WX_PTYPE_PKT_IPV6; + break; + default: + return ptype; + } + } else { + switch (first->protocol) { + case htons(ETH_P_IP): + l4_prot = ip_hdr(skb)->protocol; + ptype = WX_PTYPE_PKT_IP; + break; + case htons(ETH_P_IPV6): + wx_get_ipv6_proto(skb, skb_network_offset(skb), &l4_prot); + ptype = WX_PTYPE_PKT_IP | WX_PTYPE_PKT_IPV6; + break; + default: + return WX_PTYPE_PKT_MAC | WX_PTYPE_TYP_MAC; + } + } + switch (l4_prot) { + case IPPROTO_TCP: + ptype |= WX_PTYPE_TYP_TCP; + break; + case IPPROTO_UDP: + ptype |= WX_PTYPE_TYP_UDP; + break; + case IPPROTO_SCTP: + ptype |= WX_PTYPE_TYP_SCTP; + break; + default: + ptype |= WX_PTYPE_TYP_IP; + break; + } + + return ptype; +} + +static int wx_tso(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + u8 *hdr_len, u8 ptype) +{ + u32 vlan_macip_lens, type_tucmd, mss_l4len_idx; + struct net_device *netdev = tx_ring->netdev; + u32 l4len, tunhdr_eiplen_tunlen = 0; + struct sk_buff *skb = first->skb; + bool enc = skb->encapsulation; + struct ipv6hdr *ipv6h; + struct tcphdr *tcph; + struct iphdr *iph; + u8 tun_prot = 0; + int err; + + if (skb->ip_summed != CHECKSUM_PARTIAL) + return 0; + + if (!skb_is_gso(skb)) + return 0; + + err = skb_cow_head(skb, 0); + if (err < 0) + return err; + + /* indicates the inner headers in the skbuff are valid. */ + iph = enc ? inner_ip_hdr(skb) : ip_hdr(skb); + if (iph->version == 4) { + tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb); + iph->tot_len = 0; + iph->check = 0; + tcph->check = ~csum_tcpudp_magic(iph->saddr, + iph->daddr, 0, + IPPROTO_TCP, 0); + first->tx_flags |= WX_TX_FLAGS_TSO | + WX_TX_FLAGS_CSUM | + WX_TX_FLAGS_IPV4 | + WX_TX_FLAGS_CC; + } else if (iph->version == 6 && skb_is_gso_v6(skb)) { + ipv6h = enc ? inner_ipv6_hdr(skb) : ipv6_hdr(skb); + tcph = enc ? inner_tcp_hdr(skb) : tcp_hdr(skb); + ipv6h->payload_len = 0; + tcph->check = ~csum_ipv6_magic(&ipv6h->saddr, + &ipv6h->daddr, 0, + IPPROTO_TCP, 0); + first->tx_flags |= WX_TX_FLAGS_TSO | + WX_TX_FLAGS_CSUM | + WX_TX_FLAGS_CC; + } + + /* compute header lengths */ + l4len = enc ? inner_tcp_hdrlen(skb) : tcp_hdrlen(skb); + *hdr_len = enc ? (skb_inner_transport_header(skb) - skb->data) : + skb_transport_offset(skb); + *hdr_len += l4len; + + /* update gso size and bytecount with header size */ + first->gso_segs = skb_shinfo(skb)->gso_segs; + first->bytecount += (first->gso_segs - 1) * *hdr_len; + + /* mss_l4len_id: use 0 as index for TSO */ + mss_l4len_idx = l4len << WX_TXD_L4LEN_SHIFT; + mss_l4len_idx |= skb_shinfo(skb)->gso_size << WX_TXD_MSS_SHIFT; + + /* vlan_macip_lens: HEADLEN, MACLEN, VLAN tag */ + if (enc) { + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + first->tx_flags |= WX_TX_FLAGS_OUTER_IPV4; + break; + case htons(ETH_P_IPV6): + tun_prot = ipv6_hdr(skb)->nexthdr; + break; + default: + break; + } + switch (tun_prot) { + case IPPROTO_UDP: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP; + tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_GRE: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE; + tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_IPIP: + tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - + (char *)ip_hdr(skb)) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT; + break; + default: + break; + } + vlan_macip_lens = skb_inner_network_header_len(skb) >> 1; + } else { + vlan_macip_lens = skb_network_header_len(skb) >> 1; + } + + vlan_macip_lens |= skb_network_offset(skb) << WX_TXD_MACLEN_SHIFT; + vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK; + + type_tucmd = ptype << 24; + if (skb->vlan_proto == htons(ETH_P_8021AD) && + netdev->features & NETIF_F_HW_VLAN_STAG_TX) + type_tucmd |= WX_SET_FLAG(first->tx_flags, + WX_TX_FLAGS_HW_VLAN, + 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT); + wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen, + type_tucmd, mss_l4len_idx); + + return 1; +} + +static void wx_tx_csum(struct wx_ring *tx_ring, struct wx_tx_buffer *first, + u8 ptype) +{ + u32 tunhdr_eiplen_tunlen = 0, vlan_macip_lens = 0; + struct net_device *netdev = tx_ring->netdev; + u32 mss_l4len_idx = 0, type_tucmd; + struct sk_buff *skb = first->skb; + u8 tun_prot = 0; + + if (skb->ip_summed != CHECKSUM_PARTIAL) { + if (!(first->tx_flags & WX_TX_FLAGS_HW_VLAN) && + !(first->tx_flags & WX_TX_FLAGS_CC)) + return; + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + } else { + u8 l4_prot = 0; + union { + struct iphdr *ipv4; + struct ipv6hdr *ipv6; + u8 *raw; + } network_hdr; + union { + struct tcphdr *tcphdr; + u8 *raw; + } transport_hdr; + + if (skb->encapsulation) { + network_hdr.raw = skb_inner_network_header(skb); + transport_hdr.raw = skb_inner_transport_header(skb); + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + switch (first->protocol) { + case htons(ETH_P_IP): + tun_prot = ip_hdr(skb)->protocol; + break; + case htons(ETH_P_IPV6): + tun_prot = ipv6_hdr(skb)->nexthdr; + break; + default: + return; + } + switch (tun_prot) { + case IPPROTO_UDP: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_UDP; + tunhdr_eiplen_tunlen |= + ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_GRE: + tunhdr_eiplen_tunlen = WX_TXD_TUNNEL_GRE; + tunhdr_eiplen_tunlen |= ((skb_network_header_len(skb) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT) | + (((skb_inner_mac_header(skb) - + skb_transport_header(skb)) >> 1) << + WX_TXD_TUNNEL_LEN_SHIFT); + break; + case IPPROTO_IPIP: + tunhdr_eiplen_tunlen = (((char *)inner_ip_hdr(skb) - + (char *)ip_hdr(skb)) >> 2) << + WX_TXD_OUTER_IPLEN_SHIFT; + break; + default: + break; + } + + } else { + network_hdr.raw = skb_network_header(skb); + transport_hdr.raw = skb_transport_header(skb); + vlan_macip_lens = skb_network_offset(skb) << + WX_TXD_MACLEN_SHIFT; + } + + switch (network_hdr.ipv4->version) { + case IPVERSION: + vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; + l4_prot = network_hdr.ipv4->protocol; + break; + case 6: + vlan_macip_lens |= (transport_hdr.raw - network_hdr.raw) >> 1; + l4_prot = network_hdr.ipv6->nexthdr; + break; + default: + break; + } + + switch (l4_prot) { + case IPPROTO_TCP: + mss_l4len_idx = (transport_hdr.tcphdr->doff * 4) << + WX_TXD_L4LEN_SHIFT; + break; + case IPPROTO_SCTP: + mss_l4len_idx = sizeof(struct sctphdr) << + WX_TXD_L4LEN_SHIFT; + break; + case IPPROTO_UDP: + mss_l4len_idx = sizeof(struct udphdr) << + WX_TXD_L4LEN_SHIFT; + break; + default: + break; + } + + /* update TX checksum flag */ + first->tx_flags |= WX_TX_FLAGS_CSUM; + } + first->tx_flags |= WX_TX_FLAGS_CC; + /* vlan_macip_lens: MACLEN, VLAN tag */ + vlan_macip_lens |= first->tx_flags & WX_TX_FLAGS_VLAN_MASK; + + type_tucmd = ptype << 24; + if (skb->vlan_proto == htons(ETH_P_8021AD) && + netdev->features & NETIF_F_HW_VLAN_STAG_TX) + type_tucmd |= WX_SET_FLAG(first->tx_flags, + WX_TX_FLAGS_HW_VLAN, + 0x1 << WX_TXD_TAG_TPID_SEL_SHIFT); + wx_tx_ctxtdesc(tx_ring, vlan_macip_lens, tunhdr_eiplen_tunlen, + type_tucmd, mss_l4len_idx); +} + static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb, struct wx_ring *tx_ring) { u16 count = TXD_USE_COUNT(skb_headlen(skb)); struct wx_tx_buffer *first; + u8 hdr_len = 0, ptype; unsigned short f; + u32 tx_flags = 0; + int tso; /* need: 1 descriptor per page * PAGE_SIZE/WX_MAX_DATA_PER_TXD, * + 1 desc for skb_headlen/WX_MAX_DATA_PER_TXD, @@ -864,7 +1542,29 @@ static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb, first->bytecount = skb->len; first->gso_segs = 1; - wx_tx_map(tx_ring, first); + /* if we have a HW VLAN tag being added default to the HW one */ + if (skb_vlan_tag_present(skb)) { + tx_flags |= skb_vlan_tag_get(skb) << WX_TX_FLAGS_VLAN_SHIFT; + tx_flags |= WX_TX_FLAGS_HW_VLAN; + } + + /* record initial flags and protocol */ + first->tx_flags = tx_flags; + first->protocol = vlan_get_protocol(skb); + + ptype = wx_encode_tx_desc_ptype(first); + + tso = wx_tso(tx_ring, first, &hdr_len, ptype); + if (tso < 0) + goto out_drop; + else if (!tso) + wx_tx_csum(tx_ring, first, ptype); + wx_tx_map(tx_ring, first, hdr_len); + + return NETDEV_TX_OK; +out_drop: + dev_kfree_skb_any(first->skb); + first->skb = NULL; return NETDEV_TX_OK; } @@ -1348,7 +2048,8 @@ void wx_free_irq(struct wx *wx) free_irq(entry->vector, q_vector); } - free_irq(wx->msix_entries[vector].vector, wx); + if (wx->mac.type == wx_mac_em) + free_irq(wx->msix_entries[vector].vector, wx); } EXPORT_SYMBOL(wx_free_irq); @@ -2004,4 +2705,24 @@ void wx_get_stats64(struct net_device *netdev, } EXPORT_SYMBOL(wx_get_stats64); +int wx_set_features(struct net_device *netdev, netdev_features_t features) +{ + netdev_features_t changed = netdev->features ^ features; + struct wx *wx = netdev_priv(netdev); + + if (changed & NETIF_F_RXHASH) + wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, + WX_RDB_RA_CTL_RSS_EN); + else + wr32m(wx, WX_RDB_RA_CTL, WX_RDB_RA_CTL_RSS_EN, 0); + + if (changed & + (NETIF_F_HW_VLAN_CTAG_RX | + NETIF_F_HW_VLAN_STAG_RX)) + wx_set_rx_mode(netdev); + + return 1; +} +EXPORT_SYMBOL(wx_set_features); + MODULE_LICENSE("GPL"); diff --git a/drivers/net/ethernet/wangxun/libwx/wx_lib.h b/drivers/net/ethernet/wangxun/libwx/wx_lib.h index 50ee41f1fa10d2..df1f4a5951f06c 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_lib.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_lib.h @@ -28,5 +28,6 @@ void wx_free_resources(struct wx *wx); int wx_setup_resources(struct wx *wx); void wx_get_stats64(struct net_device *netdev, struct rtnl_link_stats64 *stats); +int wx_set_features(struct net_device *netdev, netdev_features_t features); #endif /* _NGBE_LIB_H_ */ diff --git a/drivers/net/ethernet/wangxun/libwx/wx_type.h b/drivers/net/ethernet/wangxun/libwx/wx_type.h index cbe7f184b50edd..29dfb561887d30 100644 --- a/drivers/net/ethernet/wangxun/libwx/wx_type.h +++ b/drivers/net/ethernet/wangxun/libwx/wx_type.h @@ -6,6 +6,8 @@ #include #include +#include +#include #define WX_NCSI_SUP 0x8000 #define WX_NCSI_MASK 0x8000 @@ -64,6 +66,8 @@ #define WX_CFG_PORT_CTL_QINQ BIT(2) #define WX_CFG_PORT_CTL_D_VLAN BIT(0) /* double vlan*/ #define WX_CFG_TAG_TPID(_i) (0x14430 + ((_i) * 4)) +#define WX_CFG_PORT_CTL_NUM_VT_MASK GENMASK(13, 12) /* number of TVs */ + /* GPIO Registers */ #define WX_GPIO_DR 0x14800 @@ -79,7 +83,9 @@ #define WX_GPIO_INTMASK 0x14834 #define WX_GPIO_INTTYPE_LEVEL 0x14838 #define WX_GPIO_POLARITY 0x1483C +#define WX_GPIO_INTSTATUS 0x14844 #define WX_GPIO_EOI 0x1484C +#define WX_GPIO_EXT 0x14850 /*********************** Transmit DMA registers **************************/ /* transmit global control */ @@ -87,6 +93,8 @@ /* TDM CTL BIT */ #define WX_TDM_CTL_TE BIT(0) /* Transmit Enable */ #define WX_TDM_PB_THRE(_i) (0x18020 + ((_i) * 4)) +#define WX_TDM_RP_IDX 0x1820C +#define WX_TDM_RP_RATE 0x18404 /***************************** RDB registers *********************************/ /* receive packet buffer */ @@ -105,6 +113,8 @@ #define WX_RDB_PL_CFG_L2HDR BIT(3) #define WX_RDB_PL_CFG_TUN_TUNHDR BIT(4) #define WX_RDB_PL_CFG_TUN_OUTL2HDR BIT(5) +#define WX_RDB_RA_CTL 0x194F4 +#define WX_RDB_RA_CTL_RSS_EN BIT(2) /* RSS Enable */ /******************************* PSR Registers *******************************/ /* psr control */ @@ -150,6 +160,9 @@ #define WX_PSR_LAN_FLEX_DW_H(_i) (0x15C04 + ((_i) * 16)) #define WX_PSR_LAN_FLEX_MSK(_i) (0x15C08 + ((_i) * 16)) +/* vlan tbl */ +#define WX_PSR_VLAN_TBL(_i) (0x16000 + ((_i) * 4)) + /* mac switcher */ #define WX_PSR_MAC_SWC_AD_L 0x16200 #define WX_PSR_MAC_SWC_AD_H 0x16204 @@ -161,6 +174,15 @@ #define WX_PSR_MAC_SWC_IDX 0x16210 #define WX_CLEAR_VMDQ_ALL 0xFFFFFFFFU +/* vlan switch */ +#define WX_PSR_VLAN_SWC 0x16220 +#define WX_PSR_VLAN_SWC_VM_L 0x16224 +#define WX_PSR_VLAN_SWC_VM_H 0x16228 +#define WX_PSR_VLAN_SWC_IDX 0x16230 /* 64 vlan entries */ +/* VLAN pool filtering masks */ +#define WX_PSR_VLAN_SWC_VIEN BIT(31) /* filter is valid */ +#define WX_PSR_VLAN_SWC_ENTRIES 64 + /********************************* RSEC **************************************/ /* general rsec */ #define WX_RSC_CTL 0x17000 @@ -255,6 +277,7 @@ #define WX_PX_RR_RP(_i) (0x0100C + ((_i) * 0x40)) #define WX_PX_RR_CFG(_i) (0x01010 + ((_i) * 0x40)) /* PX_RR_CFG bit definitions */ +#define WX_PX_RR_CFG_VLAN BIT(31) #define WX_PX_RR_CFG_SPLIT_MODE BIT(26) #define WX_PX_RR_CFG_RR_THER_SHIFT 16 #define WX_PX_RR_CFG_RR_HDR_SZ GENMASK(15, 12) @@ -296,6 +319,7 @@ #define WX_MAX_TXD 8192 #define WX_MAX_JUMBO_FRAME_SIZE 9432 /* max payload 9414 */ +#define VMDQ_P(p) p /* Supported Rx Buffer Sizes */ #define WX_RXBUFFER_256 256 /* Used for skb receive header */ @@ -315,17 +339,64 @@ #define TXD_USE_COUNT(S) DIV_ROUND_UP((S), WX_MAX_DATA_PER_TXD) #define DESC_NEEDED (MAX_SKB_FRAGS + 4) -/* Ether Types */ -#define WX_ETH_P_CNM 0x22E7 - #define WX_CFG_PORT_ST 0x14404 /******************* Receive Descriptor bit definitions **********************/ #define WX_RXD_STAT_DD BIT(0) /* Done */ #define WX_RXD_STAT_EOP BIT(1) /* End of Packet */ +#define WX_RXD_STAT_VP BIT(5) /* IEEE VLAN Pkt */ +#define WX_RXD_STAT_L4CS BIT(7) /* L4 xsum calculated */ +#define WX_RXD_STAT_IPCS BIT(8) /* IP xsum calculated */ +#define WX_RXD_STAT_OUTERIPCS BIT(10) /* Cloud IP xsum calculated*/ +#define WX_RXD_ERR_OUTERIPER BIT(26) /* CRC IP Header error */ #define WX_RXD_ERR_RXE BIT(29) /* Any MAC Error */ - +#define WX_RXD_ERR_TCPE BIT(30) /* TCP/UDP Checksum Error */ +#define WX_RXD_ERR_IPE BIT(31) /* IP Checksum Error */ + +/* RSS Hash results */ +#define WX_RXD_RSSTYPE_MASK GENMASK(3, 0) +#define WX_RXD_RSSTYPE_IPV4_TCP 0x00000001U +#define WX_RXD_RSSTYPE_IPV6_TCP 0x00000003U +#define WX_RXD_RSSTYPE_IPV4_SCTP 0x00000004U +#define WX_RXD_RSSTYPE_IPV6_SCTP 0x00000006U +#define WX_RXD_RSSTYPE_IPV4_UDP 0x00000007U +#define WX_RXD_RSSTYPE_IPV6_UDP 0x00000008U + +#define WX_RSS_L4_TYPES_MASK \ + ((1ul << WX_RXD_RSSTYPE_IPV4_TCP) | \ + (1ul << WX_RXD_RSSTYPE_IPV4_UDP) | \ + (1ul << WX_RXD_RSSTYPE_IPV4_SCTP) | \ + (1ul << WX_RXD_RSSTYPE_IPV6_TCP) | \ + (1ul << WX_RXD_RSSTYPE_IPV6_UDP) | \ + (1ul << WX_RXD_RSSTYPE_IPV6_SCTP)) +/* TUN */ +#define WX_PTYPE_TUN_IPV4 0x80 +#define WX_PTYPE_TUN_IPV6 0xC0 + +/* PKT for TUN */ +#define WX_PTYPE_PKT_IPIP 0x00 /* IP+IP */ +#define WX_PTYPE_PKT_IG 0x10 /* IP+GRE */ +#define WX_PTYPE_PKT_IGM 0x20 /* IP+GRE+MAC */ +#define WX_PTYPE_PKT_IGMV 0x30 /* IP+GRE+MAC+VLAN */ +/* PKT for !TUN */ +#define WX_PTYPE_PKT_MAC 0x10 +#define WX_PTYPE_PKT_IP 0x20 + +/* TYP for PKT=mac */ +#define WX_PTYPE_TYP_MAC 0x01 +/* TYP for PKT=ip */ +#define WX_PTYPE_PKT_IPV6 0x08 +#define WX_PTYPE_TYP_IPFRAG 0x01 +#define WX_PTYPE_TYP_IP 0x02 +#define WX_PTYPE_TYP_UDP 0x03 +#define WX_PTYPE_TYP_TCP 0x04 +#define WX_PTYPE_TYP_SCTP 0x05 + +#define WX_RXD_PKTTYPE(_rxd) \ + ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 9) & 0xFF) +#define WX_RXD_IPV6EX(_rxd) \ + ((le32_to_cpu((_rxd)->wb.lower.lo_dword.data) >> 6) & 0x1) /*********************** Transmit Descriptor Config Masks ****************/ #define WX_TXD_STAT_DD BIT(0) /* Descriptor Done */ #define WX_TXD_DTYP_DATA 0 /* Adv Data Descriptor */ @@ -334,6 +405,113 @@ #define WX_TXD_IFCS BIT(25) /* Insert FCS */ #define WX_TXD_RS BIT(27) /* Report Status */ +/*********************** Adv Transmit Descriptor Config Masks ****************/ +#define WX_TXD_MAC_TSTAMP BIT(19) /* IEEE1588 time stamp */ +#define WX_TXD_DTYP_CTXT BIT(20) /* Adv Context Desc */ +#define WX_TXD_LINKSEC BIT(26) /* enable linksec */ +#define WX_TXD_VLE BIT(30) /* VLAN pkt enable */ +#define WX_TXD_TSE BIT(31) /* TCP Seg enable */ +#define WX_TXD_CC BIT(7) /* Check Context */ +#define WX_TXD_IPSEC BIT(8) /* enable ipsec esp */ +#define WX_TXD_L4CS BIT(9) +#define WX_TXD_IIPCS BIT(10) +#define WX_TXD_EIPCS BIT(11) +#define WX_TXD_PAYLEN_SHIFT 13 /* Adv desc PAYLEN shift */ +#define WX_TXD_MACLEN_SHIFT 9 /* Adv ctxt desc mac len shift */ +#define WX_TXD_TAG_TPID_SEL_SHIFT 11 + +#define WX_TXD_L4LEN_SHIFT 8 /* Adv ctxt L4LEN shift */ +#define WX_TXD_MSS_SHIFT 16 /* Adv ctxt MSS shift */ + +#define WX_TXD_OUTER_IPLEN_SHIFT 12 /* Adv ctxt OUTERIPLEN shift */ +#define WX_TXD_TUNNEL_LEN_SHIFT 21 /* Adv ctxt TUNNELLEN shift */ +#define WX_TXD_TUNNEL_TYPE_SHIFT 11 /* Adv Tx Desc Tunnel Type shift */ +#define WX_TXD_TUNNEL_UDP FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 0) +#define WX_TXD_TUNNEL_GRE FIELD_PREP(BIT(WX_TXD_TUNNEL_TYPE_SHIFT), 1) + +enum wx_tx_flags { + /* cmd_type flags */ + WX_TX_FLAGS_HW_VLAN = 0x01, + WX_TX_FLAGS_TSO = 0x02, + WX_TX_FLAGS_TSTAMP = 0x04, + + /* olinfo flags */ + WX_TX_FLAGS_CC = 0x08, + WX_TX_FLAGS_IPV4 = 0x10, + WX_TX_FLAGS_CSUM = 0x20, + WX_TX_FLAGS_OUTER_IPV4 = 0x100, + WX_TX_FLAGS_LINKSEC = 0x200, + WX_TX_FLAGS_IPSEC = 0x400, +}; + +/* VLAN info */ +#define WX_TX_FLAGS_VLAN_MASK GENMASK(31, 16) +#define WX_TX_FLAGS_VLAN_SHIFT 16 + +/* wx_dec_ptype.mac: outer mac */ +enum wx_dec_ptype_mac { + WX_DEC_PTYPE_MAC_IP = 0, + WX_DEC_PTYPE_MAC_L2 = 2, + WX_DEC_PTYPE_MAC_FCOE = 3, +}; + +/* wx_dec_ptype.[e]ip: outer&encaped ip */ +#define WX_DEC_PTYPE_IP_FRAG 0x4 +enum wx_dec_ptype_ip { + WX_DEC_PTYPE_IP_NONE = 0, + WX_DEC_PTYPE_IP_IPV4 = 1, + WX_DEC_PTYPE_IP_IPV6 = 2, + WX_DEC_PTYPE_IP_FGV4 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV4, + WX_DEC_PTYPE_IP_FGV6 = WX_DEC_PTYPE_IP_FRAG | WX_DEC_PTYPE_IP_IPV6, +}; + +/* wx_dec_ptype.etype: encaped type */ +enum wx_dec_ptype_etype { + WX_DEC_PTYPE_ETYPE_NONE = 0, + WX_DEC_PTYPE_ETYPE_IPIP = 1, /* IP+IP */ + WX_DEC_PTYPE_ETYPE_IG = 2, /* IP+GRE */ + WX_DEC_PTYPE_ETYPE_IGM = 3, /* IP+GRE+MAC */ + WX_DEC_PTYPE_ETYPE_IGMV = 4, /* IP+GRE+MAC+VLAN */ +}; + +/* wx_dec_ptype.proto: payload proto */ +enum wx_dec_ptype_prot { + WX_DEC_PTYPE_PROT_NONE = 0, + WX_DEC_PTYPE_PROT_UDP = 1, + WX_DEC_PTYPE_PROT_TCP = 2, + WX_DEC_PTYPE_PROT_SCTP = 3, + WX_DEC_PTYPE_PROT_ICMP = 4, + WX_DEC_PTYPE_PROT_TS = 5, /* time sync */ +}; + +/* wx_dec_ptype.layer: payload layer */ +enum wx_dec_ptype_layer { + WX_DEC_PTYPE_LAYER_NONE = 0, + WX_DEC_PTYPE_LAYER_PAY2 = 1, + WX_DEC_PTYPE_LAYER_PAY3 = 2, + WX_DEC_PTYPE_LAYER_PAY4 = 3, +}; + +struct wx_dec_ptype { + u32 known:1; + u32 mac:2; /* outer mac */ + u32 ip:3; /* outer ip*/ + u32 etype:3; /* encaped type */ + u32 eip:3; /* encaped ip */ + u32 prot:4; /* payload proto */ + u32 layer:3; /* payload layer */ +}; + +/* macro to make the table lines short */ +#define WX_PTT(mac, ip, etype, eip, proto, layer)\ + {1, \ + WX_DEC_PTYPE_MAC_##mac, /* mac */\ + WX_DEC_PTYPE_IP_##ip, /* ip */ \ + WX_DEC_PTYPE_ETYPE_##etype, /* etype */\ + WX_DEC_PTYPE_IP_##eip, /* eip */\ + WX_DEC_PTYPE_PROT_##proto, /* proto */\ + WX_DEC_PTYPE_LAYER_##layer /* layer */} + /* Host Interface Command Structures */ struct wx_hic_hdr { u8 cmd; @@ -412,6 +590,8 @@ struct wx_mac_info { u32 mta_shadow[128]; s32 mc_filter_type; u32 mcft_size; + u32 vft_shadow[128]; + u32 vft_size; u32 num_rar_entries; u32 rx_pb_size; u32 tx_pb_size; @@ -508,10 +688,25 @@ union wx_rx_desc { } wb; /* writeback */ }; +struct wx_tx_context_desc { + __le32 vlan_macip_lens; + __le32 seqnum_seed; + __le32 type_tucmd_mlhl; + __le32 mss_l4len_idx; +}; + +/* if _flag is in _input, return _result */ +#define WX_SET_FLAG(_input, _flag, _result) \ + (((_flag) <= (_result)) ? \ + ((u32)((_input) & (_flag)) * ((_result) / (_flag))) : \ + ((u32)((_input) & (_flag)) / ((_flag) / (_result)))) + #define WX_RX_DESC(R, i) \ (&(((union wx_rx_desc *)((R)->desc))[i])) #define WX_TX_DESC(R, i) \ (&(((union wx_tx_desc *)((R)->desc))[i])) +#define WX_TX_CTXTDESC(R, i) \ + (&(((struct wx_tx_context_desc *)((R)->desc))[i])) /* wrapper around a pointer to a socket buffer, * so a DMA handle can be stored along with the buffer @@ -523,6 +718,8 @@ struct wx_tx_buffer { unsigned short gso_segs; DEFINE_DMA_UNMAP_ADDR(dma); DEFINE_DMA_UNMAP_LEN(len); + __be16 protocol; + u32 tx_flags; }; struct wx_rx_buffer { @@ -539,6 +736,11 @@ struct wx_queue_stats { u64 bytes; }; +struct wx_rx_queue_stats { + u64 csum_good_cnt; + u64 csum_err; +}; + /* iterator for handling rings in ring container */ #define wx_for_each_ring(posm, headm) \ for (posm = (headm).ring; posm; posm = posm->next) @@ -550,7 +752,6 @@ struct wx_ring_container { u8 count; /* total number of rings in vector */ u8 itr; /* current ITR setting for ring */ }; - struct wx_ring { struct wx_ring *next; /* pointer to next ring in q_vector */ struct wx_q_vector *q_vector; /* backpointer to host q_vector */ @@ -580,6 +781,9 @@ struct wx_ring { struct wx_queue_stats stats; struct u64_stats_sync syncp; + union { + struct wx_rx_queue_stats rx_stats; + }; } ____cacheline_internodealigned_in_smp; struct wx_q_vector { @@ -610,6 +814,9 @@ enum wx_isb_idx { }; struct wx { + unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; + + void *priv; u8 __iomem *hw_addr; struct pci_dev *pdev; struct net_device *netdev; @@ -642,6 +849,7 @@ struct wx { bool wol_enabled; bool ncsi_enabled; bool gpio_ctrl; + raw_spinlock_t gpio_lock; /* Tx fast path data */ int num_tx_queues; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c index df6b870aa87116..c99a5d3de72e60 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c @@ -115,6 +115,7 @@ static int ngbe_sw_init(struct wx *wx) wx->mac.max_rx_queues = NGBE_MAX_RX_QUEUES; wx->mac.max_tx_queues = NGBE_MAX_TX_QUEUES; wx->mac.mcft_size = NGBE_MC_TBL_SIZE; + wx->mac.vft_size = NGBE_SP_VFT_TBL_SIZE; wx->mac.rx_pb_size = NGBE_RX_PB_SIZE; wx->mac.tx_pb_size = NGBE_TDB_PB_SZ; @@ -473,9 +474,12 @@ static const struct net_device_ops ngbe_netdev_ops = { .ndo_change_mtu = wx_change_mtu, .ndo_start_xmit = wx_xmit_frame, .ndo_set_rx_mode = wx_set_rx_mode, + .ndo_set_features = wx_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = wx_set_mac, .ndo_get_stats64 = wx_get_stats64, + .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid, }; /** @@ -551,12 +555,18 @@ static int ngbe_probe(struct pci_dev *pdev, ngbe_set_ethtool_ops(netdev); netdev->netdev_ops = &ngbe_netdev_ops; - netdev->features |= NETIF_F_HIGHDMA; - netdev->features = NETIF_F_SG; - + netdev->features = NETIF_F_SG | NETIF_F_IP_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_RXHASH | NETIF_F_RXCSUM; + netdev->features |= NETIF_F_SCTP_CRC | NETIF_F_TSO_MANGLEID; + netdev->vlan_features |= netdev->features; + netdev->features |= NETIF_F_IPV6_CSUM | NETIF_F_VLAN_FEATURES; /* copy netdev features into list of user selectable features */ - netdev->hw_features |= netdev->features | - NETIF_F_RXALL; + netdev->hw_features |= netdev->features | NETIF_F_RXALL; + netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; + netdev->features |= NETIF_F_HIGHDMA; + netdev->hw_features |= NETIF_F_GRO; + netdev->features |= NETIF_F_GRO; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h index 373d5af628cd52..b70eca397b6722 100644 --- a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h +++ b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h @@ -136,6 +136,7 @@ enum NGBE_MSCA_CMD_value { #define NGBE_RAR_ENTRIES 32 #define NGBE_RX_PB_SIZE 42 #define NGBE_MC_TBL_SIZE 128 +#define NGBE_SP_VFT_TBL_SIZE 128 #define NGBE_TDB_PB_SZ (20 * 1024) /* 160KB Packet Buffer */ /* TX/RX descriptor defines */ diff --git a/drivers/net/ethernet/wangxun/txgbe/Makefile b/drivers/net/ethernet/wangxun/txgbe/Makefile index 6db14a2cb2d04a..7507f762edfe54 100644 --- a/drivers/net/ethernet/wangxun/txgbe/Makefile +++ b/drivers/net/ethernet/wangxun/txgbe/Makefile @@ -8,4 +8,5 @@ obj-$(CONFIG_TXGBE) += txgbe.o txgbe-objs := txgbe_main.o \ txgbe_hw.o \ + txgbe_phy.o \ txgbe_ethtool.o diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c index d914e9a0540404..859da112586a42 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_ethtool.c @@ -6,11 +6,39 @@ #include #include "../libwx/wx_ethtool.h" +#include "../libwx/wx_type.h" +#include "txgbe_type.h" #include "txgbe_ethtool.h" +static int txgbe_nway_reset(struct net_device *netdev) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_nway_reset(txgbe->phylink); +} + +static int txgbe_get_link_ksettings(struct net_device *netdev, + struct ethtool_link_ksettings *cmd) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_ksettings_get(txgbe->phylink, cmd); +} + +static int txgbe_set_link_ksettings(struct net_device *netdev, + const struct ethtool_link_ksettings *cmd) +{ + struct txgbe *txgbe = netdev_to_txgbe(netdev); + + return phylink_ethtool_ksettings_set(txgbe->phylink, cmd); +} + static const struct ethtool_ops txgbe_ethtool_ops = { .get_drvinfo = wx_get_drvinfo, + .nway_reset = txgbe_nway_reset, .get_link = ethtool_op_get_link, + .get_link_ksettings = txgbe_get_link_ksettings, + .set_link_ksettings = txgbe_set_link_ksettings, }; void txgbe_set_ethtool_ops(struct net_device *netdev) diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c index 5b8a121fb496b3..46eba6d6188b2f 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_main.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -15,6 +16,7 @@ #include "../libwx/wx_hw.h" #include "txgbe_type.h" #include "txgbe_hw.h" +#include "txgbe_phy.h" #include "txgbe_ethtool.h" char txgbe_driver_name[] = "txgbe"; @@ -81,6 +83,8 @@ static int txgbe_enumerate_functions(struct wx *wx) **/ static void txgbe_irq_enable(struct wx *wx, bool queues) { + wr32(wx, WX_PX_MISC_IEN, TXGBE_PX_MISC_IEN_MASK); + /* unmask interrupt */ wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); if (queues) @@ -128,17 +132,6 @@ static irqreturn_t txgbe_intr(int __always_unused irq, void *data) return IRQ_HANDLED; } -static irqreturn_t txgbe_msix_other(int __always_unused irq, void *data) -{ - struct wx *wx = data; - - /* re-enable the original interrupt state */ - if (netif_running(wx->netdev)) - txgbe_irq_enable(wx, false); - - return IRQ_HANDLED; -} - /** * txgbe_request_msix_irqs - Initialize MSI-X interrupts * @wx: board private structure @@ -170,13 +163,6 @@ static int txgbe_request_msix_irqs(struct wx *wx) } } - err = request_irq(wx->msix_entries[vector].vector, - txgbe_msix_other, 0, netdev->name, wx); - if (err) { - wx_err(wx, "request_irq for msix_other failed: %d\n", err); - goto free_queue_irqs; - } - return 0; free_queue_irqs: @@ -219,7 +205,8 @@ static int txgbe_request_irq(struct wx *wx) static void txgbe_up_complete(struct wx *wx) { - u32 reg; + struct net_device *netdev = wx->netdev; + struct txgbe *txgbe; wx_control_hw(wx, true); wx_configure_vectors(wx); @@ -228,24 +215,17 @@ static void txgbe_up_complete(struct wx *wx) smp_mb__before_atomic(); wx_napi_enable_all(wx); + txgbe = netdev_to_txgbe(netdev); + phylink_start(txgbe->phylink); + /* clear any pending interrupts, may auto mask */ rd32(wx, WX_PX_IC(0)); rd32(wx, WX_PX_IC(1)); rd32(wx, WX_PX_MISC_IC); txgbe_irq_enable(wx, true); - /* Configure MAC Rx and Tx when link is up */ - reg = rd32(wx, WX_MAC_RX_CFG); - wr32(wx, WX_MAC_RX_CFG, reg); - wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); - reg = rd32(wx, WX_MAC_WDG_TIMEOUT); - wr32(wx, WX_MAC_WDG_TIMEOUT, reg); - reg = rd32(wx, WX_MAC_TX_CFG); - wr32(wx, WX_MAC_TX_CFG, (reg & ~WX_MAC_TX_CFG_SPEED_MASK) | WX_MAC_TX_CFG_SPEED_10G); - /* enable transmits */ - netif_tx_start_all_queues(wx->netdev); - netif_carrier_on(wx->netdev); + netif_tx_start_all_queues(netdev); } static void txgbe_reset(struct wx *wx) @@ -258,6 +238,7 @@ static void txgbe_reset(struct wx *wx) if (err != 0) wx_err(wx, "Hardware Error: %d\n", err); + wx_start_hw(wx); /* do not flush user set addresses */ memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len); wx_flush_sw_mac_table(wx); @@ -279,7 +260,6 @@ static void txgbe_disable_device(struct wx *wx) wx_disable_rx_queue(wx, wx->rx_ring[i]); netif_tx_stop_all_queues(netdev); - netif_carrier_off(netdev); netif_tx_disable(netdev); wx_irq_disable(wx); @@ -310,8 +290,11 @@ static void txgbe_disable_device(struct wx *wx) static void txgbe_down(struct wx *wx) { + struct txgbe *txgbe = netdev_to_txgbe(wx->netdev); + txgbe_disable_device(wx); txgbe_reset(wx); + phylink_stop(txgbe->phylink); wx_clean_all_tx_rings(wx); wx_clean_all_rx_rings(wx); @@ -330,6 +313,7 @@ static int txgbe_sw_init(struct wx *wx) wx->mac.max_tx_queues = TXGBE_SP_MAX_TX_QUEUES; wx->mac.max_rx_queues = TXGBE_SP_MAX_RX_QUEUES; wx->mac.mcft_size = TXGBE_SP_MC_TBL_SIZE; + wx->mac.vft_size = TXGBE_SP_VFT_TBL_SIZE; wx->mac.rx_pb_size = TXGBE_SP_RX_PB_SIZE; wx->mac.tx_pb_size = TXGBE_SP_TDB_PB_SZ; @@ -455,7 +439,7 @@ static int txgbe_close(struct net_device *netdev) return 0; } -static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) +static void txgbe_dev_shutdown(struct pci_dev *pdev) { struct wx *wx = pci_get_drvdata(pdev); struct net_device *netdev; @@ -475,12 +459,10 @@ static void txgbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake) static void txgbe_shutdown(struct pci_dev *pdev) { - bool wake; - - txgbe_dev_shutdown(pdev, &wake); + txgbe_dev_shutdown(pdev); if (system_state == SYSTEM_POWER_OFF) { - pci_wake_from_d3(pdev, wake); + pci_wake_from_d3(pdev, false); pci_set_power_state(pdev, PCI_D3hot); } } @@ -491,9 +473,12 @@ static const struct net_device_ops txgbe_netdev_ops = { .ndo_change_mtu = wx_change_mtu, .ndo_start_xmit = wx_xmit_frame, .ndo_set_rx_mode = wx_set_rx_mode, + .ndo_set_features = wx_set_features, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = wx_set_mac, .ndo_get_stats64 = wx_get_stats64, + .ndo_vlan_rx_add_vid = wx_vlan_rx_add_vid, + .ndo_vlan_rx_kill_vid = wx_vlan_rx_kill_vid, }; /** @@ -513,6 +498,7 @@ static int txgbe_probe(struct pci_dev *pdev, struct net_device *netdev; int err, expected_gts; struct wx *wx = NULL; + struct txgbe *txgbe; u16 eeprom_verh = 0, eeprom_verl = 0, offset = 0; u16 eeprom_cfg_blkh = 0, eeprom_cfg_blkl = 0; @@ -596,11 +582,25 @@ static int txgbe_probe(struct pci_dev *pdev, goto err_free_mac_table; } - netdev->features |= NETIF_F_HIGHDMA; - netdev->features = NETIF_F_SG; - + netdev->features = NETIF_F_SG | + NETIF_F_TSO | + NETIF_F_TSO6 | + NETIF_F_RXHASH | + NETIF_F_RXCSUM | + NETIF_F_HW_CSUM; + + netdev->gso_partial_features = NETIF_F_GSO_ENCAP_ALL; + netdev->features |= netdev->gso_partial_features; + netdev->features |= NETIF_F_SCTP_CRC; + netdev->vlan_features |= netdev->features | NETIF_F_TSO_MANGLEID; + netdev->hw_enc_features |= netdev->vlan_features; + netdev->features |= NETIF_F_VLAN_FEATURES; /* copy netdev features into list of user selectable features */ netdev->hw_features |= netdev->features | NETIF_F_RXALL; + netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; + netdev->features |= NETIF_F_HIGHDMA; + netdev->hw_features |= NETIF_F_GRO; + netdev->features |= NETIF_F_GRO; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; @@ -663,10 +663,23 @@ static int txgbe_probe(struct pci_dev *pdev, "0x%08x", etrack_id); } - err = register_netdev(netdev); + txgbe = devm_kzalloc(&pdev->dev, sizeof(*txgbe), GFP_KERNEL); + if (!txgbe) { + err = -ENOMEM; + goto err_release_hw; + } + + txgbe->wx = wx; + wx->priv = txgbe; + + err = txgbe_init_phy(txgbe); if (err) goto err_release_hw; + err = register_netdev(netdev); + if (err) + goto err_remove_phy; + pci_set_drvdata(pdev, wx); netif_tx_stop_all_queues(netdev); @@ -694,6 +707,8 @@ static int txgbe_probe(struct pci_dev *pdev, return 0; +err_remove_phy: + txgbe_remove_phy(txgbe); err_release_hw: wx_clear_interrupt_scheme(wx); wx_control_hw(wx, false); @@ -719,11 +734,14 @@ static int txgbe_probe(struct pci_dev *pdev, static void txgbe_remove(struct pci_dev *pdev) { struct wx *wx = pci_get_drvdata(pdev); + struct txgbe *txgbe = wx->priv; struct net_device *netdev; netdev = wx->netdev; unregister_netdev(netdev); + txgbe_remove_phy(txgbe); + pci_release_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM)); diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c new file mode 100644 index 00000000000000..8779645a54be47 --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c @@ -0,0 +1,673 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libwx/wx_type.h" +#include "../libwx/wx_lib.h" +#include "../libwx/wx_hw.h" +#include "txgbe_type.h" +#include "txgbe_phy.h" + +static int txgbe_swnodes_register(struct txgbe *txgbe) +{ + struct txgbe_nodes *nodes = &txgbe->nodes; + struct pci_dev *pdev = txgbe->wx->pdev; + struct software_node *swnodes; + u32 id; + + id = (pdev->bus->number << 8) | pdev->devfn; + + snprintf(nodes->gpio_name, sizeof(nodes->gpio_name), "txgbe_gpio-%x", id); + snprintf(nodes->i2c_name, sizeof(nodes->i2c_name), "txgbe_i2c-%x", id); + snprintf(nodes->sfp_name, sizeof(nodes->sfp_name), "txgbe_sfp-%x", id); + snprintf(nodes->phylink_name, sizeof(nodes->phylink_name), "txgbe_phylink-%x", id); + + swnodes = nodes->swnodes; + + /* GPIO 0: tx fault + * GPIO 1: tx disable + * GPIO 2: sfp module absent + * GPIO 3: rx signal lost + * GPIO 4: rate select, 1G(0) 10G(1) + * GPIO 5: rate select, 1G(0) 10G(1) + */ + nodes->gpio_props[0] = PROPERTY_ENTRY_STRING("pinctrl-names", "default"); + swnodes[SWNODE_GPIO] = NODE_PROP(nodes->gpio_name, nodes->gpio_props); + nodes->gpio0_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 0, GPIO_ACTIVE_HIGH); + nodes->gpio1_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 1, GPIO_ACTIVE_HIGH); + nodes->gpio2_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 2, GPIO_ACTIVE_LOW); + nodes->gpio3_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 3, GPIO_ACTIVE_HIGH); + nodes->gpio4_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 4, GPIO_ACTIVE_HIGH); + nodes->gpio5_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_GPIO], 5, GPIO_ACTIVE_HIGH); + + nodes->i2c_props[0] = PROPERTY_ENTRY_STRING("compatible", "snps,designware-i2c"); + nodes->i2c_props[1] = PROPERTY_ENTRY_BOOL("wx,i2c-snps-model"); + nodes->i2c_props[2] = PROPERTY_ENTRY_U32("clock-frequency", I2C_MAX_STANDARD_MODE_FREQ); + swnodes[SWNODE_I2C] = NODE_PROP(nodes->i2c_name, nodes->i2c_props); + nodes->i2c_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_I2C]); + + nodes->sfp_props[0] = PROPERTY_ENTRY_STRING("compatible", "sff,sfp"); + nodes->sfp_props[1] = PROPERTY_ENTRY_REF_ARRAY("i2c-bus", nodes->i2c_ref); + nodes->sfp_props[2] = PROPERTY_ENTRY_REF_ARRAY("tx-fault-gpios", nodes->gpio0_ref); + nodes->sfp_props[3] = PROPERTY_ENTRY_REF_ARRAY("tx-disable-gpios", nodes->gpio1_ref); + nodes->sfp_props[4] = PROPERTY_ENTRY_REF_ARRAY("mod-def0-gpios", nodes->gpio2_ref); + nodes->sfp_props[5] = PROPERTY_ENTRY_REF_ARRAY("los-gpios", nodes->gpio3_ref); + nodes->sfp_props[6] = PROPERTY_ENTRY_REF_ARRAY("rate-select1-gpios", nodes->gpio4_ref); + nodes->sfp_props[7] = PROPERTY_ENTRY_REF_ARRAY("rate-select0-gpios", nodes->gpio5_ref); + swnodes[SWNODE_SFP] = NODE_PROP(nodes->sfp_name, nodes->sfp_props); + nodes->sfp_ref[0] = SOFTWARE_NODE_REFERENCE(&swnodes[SWNODE_SFP]); + + nodes->phylink_props[0] = PROPERTY_ENTRY_STRING("managed", "in-band-status"); + nodes->phylink_props[1] = PROPERTY_ENTRY_REF_ARRAY("sfp", nodes->sfp_ref); + swnodes[SWNODE_PHYLINK] = NODE_PROP(nodes->phylink_name, nodes->phylink_props); + + nodes->group[SWNODE_GPIO] = &swnodes[SWNODE_GPIO]; + nodes->group[SWNODE_I2C] = &swnodes[SWNODE_I2C]; + nodes->group[SWNODE_SFP] = &swnodes[SWNODE_SFP]; + nodes->group[SWNODE_PHYLINK] = &swnodes[SWNODE_PHYLINK]; + + return software_node_register_node_group(nodes->group); +} + +static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum) +{ + struct wx *wx = bus->priv; + u32 offset, val; + + if (addr) + return -EOPNOTSUPP; + + offset = devnum << 16 | regnum; + + /* Set the LAN port indicator to IDA_ADDR */ + wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); + + /* Read the data from IDA_DATA register */ + val = rd32(wx, TXGBE_XPCS_IDA_DATA); + + return (u16)val; +} + +static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val) +{ + struct wx *wx = bus->priv; + u32 offset; + + if (addr) + return -EOPNOTSUPP; + + offset = devnum << 16 | regnum; + + /* Set the LAN port indicator to IDA_ADDR */ + wr32(wx, TXGBE_XPCS_IDA_ADDR, offset); + + /* Write the data to IDA_DATA register */ + wr32(wx, TXGBE_XPCS_IDA_DATA, val); + + return 0; +} + +static int txgbe_mdio_pcs_init(struct txgbe *txgbe) +{ + struct mii_bus *mii_bus; + struct dw_xpcs *xpcs; + struct pci_dev *pdev; + struct wx *wx; + int ret = 0; + + wx = txgbe->wx; + pdev = wx->pdev; + + mii_bus = devm_mdiobus_alloc(&pdev->dev); + if (!mii_bus) + return -ENOMEM; + + mii_bus->name = "txgbe_pcs_mdio_bus"; + mii_bus->read_c45 = &txgbe_pcs_read; + mii_bus->write_c45 = &txgbe_pcs_write; + mii_bus->parent = &pdev->dev; + mii_bus->phy_mask = ~0; + mii_bus->priv = wx; + snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x", + (pdev->bus->number << 8) | pdev->devfn); + + ret = devm_mdiobus_register(&pdev->dev, mii_bus); + if (ret) + return ret; + + xpcs = xpcs_create_mdiodev(mii_bus, 0, PHY_INTERFACE_MODE_10GBASER); + if (IS_ERR(xpcs)) + return PTR_ERR(xpcs); + + txgbe->xpcs = xpcs; + + return 0; +} + +static struct phylink_pcs *txgbe_phylink_mac_select(struct phylink_config *config, + phy_interface_t interface) +{ + struct txgbe *txgbe = netdev_to_txgbe(to_net_dev(config->dev)); + + return &txgbe->xpcs->pcs; +} + +static void txgbe_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ +} + +static void txgbe_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + + wr32m(wx, WX_MAC_TX_CFG, WX_MAC_TX_CFG_TE, 0); +} + +static void txgbe_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct wx *wx = netdev_priv(to_net_dev(config->dev)); + u32 txcfg, wdg; + + txcfg = rd32(wx, WX_MAC_TX_CFG); + txcfg &= ~WX_MAC_TX_CFG_SPEED_MASK; + + switch (speed) { + case SPEED_10000: + txcfg |= WX_MAC_TX_CFG_SPEED_10G; + break; + case SPEED_1000: + case SPEED_100: + case SPEED_10: + txcfg |= WX_MAC_TX_CFG_SPEED_1G; + break; + default: + break; + } + + wr32(wx, WX_MAC_TX_CFG, txcfg | WX_MAC_TX_CFG_TE); + + /* Re configure MAC Rx */ + wr32m(wx, WX_MAC_RX_CFG, WX_MAC_RX_CFG_RE, WX_MAC_RX_CFG_RE); + wr32(wx, WX_MAC_PKT_FLT, WX_MAC_PKT_FLT_PR); + wdg = rd32(wx, WX_MAC_WDG_TIMEOUT); + wr32(wx, WX_MAC_WDG_TIMEOUT, wdg); +} + +static const struct phylink_mac_ops txgbe_mac_ops = { + .mac_select_pcs = txgbe_phylink_mac_select, + .mac_config = txgbe_mac_config, + .mac_link_down = txgbe_mac_link_down, + .mac_link_up = txgbe_mac_link_up, +}; + +static int txgbe_phylink_init(struct txgbe *txgbe) +{ + struct phylink_config *config; + struct fwnode_handle *fwnode; + struct wx *wx = txgbe->wx; + phy_interface_t phy_mode; + struct phylink *phylink; + + config = devm_kzalloc(&wx->pdev->dev, sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; + + config->dev = &wx->netdev->dev; + config->type = PHYLINK_NETDEV; + config->mac_capabilities = MAC_10000FD | MAC_1000FD | MAC_SYM_PAUSE | MAC_ASYM_PAUSE; + phy_mode = PHY_INTERFACE_MODE_10GBASER; + __set_bit(PHY_INTERFACE_MODE_10GBASER, config->supported_interfaces); + fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_PHYLINK]); + phylink = phylink_create(config, fwnode, phy_mode, &txgbe_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + txgbe->phylink = phylink; + + return 0; +} + +static int txgbe_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + int val; + + val = rd32m(wx, WX_GPIO_EXT, BIT(offset)); + + return !!(val & BIT(offset)); +} + +static int txgbe_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + u32 val; + + val = rd32(wx, WX_GPIO_DDR); + if (BIT(offset) & val) + return GPIO_LINE_DIRECTION_OUT; + + return GPIO_LINE_DIRECTION_IN; +} + +static int txgbe_gpio_direction_in(struct gpio_chip *chip, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(chip); + unsigned long flags; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_DDR, BIT(offset), 0); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static int txgbe_gpio_direction_out(struct gpio_chip *chip, unsigned int offset, + int val) +{ + struct wx *wx = gpiochip_get_data(chip); + unsigned long flags; + u32 set; + + set = val ? BIT(offset) : 0; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_DR, BIT(offset), set); + wr32m(wx, WX_GPIO_DDR, BIT(offset), BIT(offset)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static void txgbe_gpio_irq_ack(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32(wx, WX_GPIO_EOI, BIT(hwirq)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_gpio_irq_mask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + gpiochip_disable_irq(gc, hwirq); + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), BIT(hwirq)); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_gpio_irq_unmask(struct irq_data *d) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + unsigned long flags; + + gpiochip_enable_irq(gc, hwirq); + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + wr32m(wx, WX_GPIO_INTMASK, BIT(hwirq), 0); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); +} + +static void txgbe_toggle_trigger(struct gpio_chip *gc, unsigned int offset) +{ + struct wx *wx = gpiochip_get_data(gc); + u32 pol, val; + + pol = rd32(wx, WX_GPIO_POLARITY); + val = rd32(wx, WX_GPIO_EXT); + + if (val & BIT(offset)) + pol &= ~BIT(offset); + else + pol |= BIT(offset); + + wr32(wx, WX_GPIO_POLARITY, pol); +} + +static int txgbe_gpio_set_type(struct irq_data *d, unsigned int type) +{ + struct gpio_chip *gc = irq_data_get_irq_chip_data(d); + irq_hw_number_t hwirq = irqd_to_hwirq(d); + struct wx *wx = gpiochip_get_data(gc); + u32 level, polarity, mask; + unsigned long flags; + + mask = BIT(hwirq); + + if (type & IRQ_TYPE_LEVEL_MASK) { + level = 0; + irq_set_handler_locked(d, handle_level_irq); + } else { + level = mask; + irq_set_handler_locked(d, handle_edge_irq); + } + + if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) + polarity = mask; + else + polarity = 0; + + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + + wr32m(wx, WX_GPIO_INTEN, mask, mask); + wr32m(wx, WX_GPIO_INTTYPE_LEVEL, mask, level); + if (type == IRQ_TYPE_EDGE_BOTH) + txgbe_toggle_trigger(gc, hwirq); + else + wr32m(wx, WX_GPIO_POLARITY, mask, polarity); + + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + + return 0; +} + +static const struct irq_chip txgbe_gpio_irq_chip = { + .name = "txgbe_gpio_irq", + .irq_ack = txgbe_gpio_irq_ack, + .irq_mask = txgbe_gpio_irq_mask, + .irq_unmask = txgbe_gpio_irq_unmask, + .irq_set_type = txgbe_gpio_set_type, + .flags = IRQCHIP_IMMUTABLE, + GPIOCHIP_IRQ_RESOURCE_HELPERS, +}; + +static void txgbe_irq_handler(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct wx *wx = irq_desc_get_handler_data(desc); + struct txgbe *txgbe = wx->priv; + irq_hw_number_t hwirq; + unsigned long gpioirq; + struct gpio_chip *gc; + unsigned long flags; + u32 eicr; + + eicr = wx_misc_isb(wx, WX_ISB_MISC); + + chained_irq_enter(chip, desc); + + gpioirq = rd32(wx, WX_GPIO_INTSTATUS); + + gc = txgbe->gpio; + for_each_set_bit(hwirq, &gpioirq, gc->ngpio) { + int gpio = irq_find_mapping(gc->irq.domain, hwirq); + u32 irq_type = irq_get_trigger_type(gpio); + + generic_handle_domain_irq(gc->irq.domain, hwirq); + + if ((irq_type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) { + raw_spin_lock_irqsave(&wx->gpio_lock, flags); + txgbe_toggle_trigger(gc, hwirq); + raw_spin_unlock_irqrestore(&wx->gpio_lock, flags); + } + } + + chained_irq_exit(chip, desc); + + if (eicr & (TXGBE_PX_MISC_ETH_LK | TXGBE_PX_MISC_ETH_LKDN)) { + u32 reg = rd32(wx, TXGBE_CFG_PORT_ST); + + phylink_mac_change(txgbe->phylink, !!(reg & TXGBE_CFG_PORT_ST_LINK_UP)); + } + + /* unmask interrupt */ + wx_intr_enable(wx, TXGBE_INTR_MISC(wx)); +} + +static int txgbe_gpio_init(struct txgbe *txgbe) +{ + struct gpio_irq_chip *girq; + struct gpio_chip *gc; + struct device *dev; + struct wx *wx; + int ret; + + wx = txgbe->wx; + dev = &wx->pdev->dev; + + raw_spin_lock_init(&wx->gpio_lock); + + gc = devm_kzalloc(dev, sizeof(*gc), GFP_KERNEL); + if (!gc) + return -ENOMEM; + + gc->label = devm_kasprintf(dev, GFP_KERNEL, "txgbe_gpio-%x", + (wx->pdev->bus->number << 8) | wx->pdev->devfn); + if (!gc->label) + return -ENOMEM; + + gc->base = -1; + gc->ngpio = 6; + gc->owner = THIS_MODULE; + gc->parent = dev; + gc->fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_GPIO]); + gc->get = txgbe_gpio_get; + gc->get_direction = txgbe_gpio_get_direction; + gc->direction_input = txgbe_gpio_direction_in; + gc->direction_output = txgbe_gpio_direction_out; + + girq = &gc->irq; + gpio_irq_chip_set_chip(girq, &txgbe_gpio_irq_chip); + girq->parent_handler = txgbe_irq_handler; + girq->parent_handler_data = wx; + girq->num_parents = 1; + girq->parents = devm_kcalloc(dev, girq->num_parents, + sizeof(*girq->parents), GFP_KERNEL); + if (!girq->parents) + return -ENOMEM; + girq->parents[0] = wx->msix_entries[wx->num_q_vectors].vector; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_bad_irq; + + ret = devm_gpiochip_add_data(dev, gc, wx); + if (ret) + return ret; + + txgbe->gpio = gc; + + return 0; +} + +static int txgbe_clock_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct clk_lookup *clock; + char clk_name[32]; + struct clk *clk; + + snprintf(clk_name, sizeof(clk_name), "i2c_designware.%d", + (pdev->bus->number << 8) | pdev->devfn); + + clk = clk_register_fixed_rate(NULL, clk_name, NULL, 0, 156250000); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + clock = clkdev_create(clk, NULL, clk_name); + if (!clock) { + clk_unregister(clk); + return -ENOMEM; + } + + txgbe->clk = clk; + txgbe->clock = clock; + + return 0; +} + +static int txgbe_i2c_read(void *context, unsigned int reg, unsigned int *val) +{ + struct wx *wx = context; + + *val = rd32(wx, reg + TXGBE_I2C_BASE); + + return 0; +} + +static int txgbe_i2c_write(void *context, unsigned int reg, unsigned int val) +{ + struct wx *wx = context; + + wr32(wx, reg + TXGBE_I2C_BASE, val); + + return 0; +} + +static const struct regmap_config i2c_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_read = txgbe_i2c_read, + .reg_write = txgbe_i2c_write, + .fast_io = true, +}; + +static int txgbe_i2c_register(struct txgbe *txgbe) +{ + struct platform_device_info info = {}; + struct platform_device *i2c_dev; + struct regmap *i2c_regmap; + struct pci_dev *pdev; + struct wx *wx; + + wx = txgbe->wx; + pdev = wx->pdev; + i2c_regmap = devm_regmap_init(&pdev->dev, NULL, wx, &i2c_regmap_config); + if (IS_ERR(i2c_regmap)) { + wx_err(wx, "failed to init I2C regmap\n"); + return PTR_ERR(i2c_regmap); + } + + info.parent = &pdev->dev; + info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_I2C]); + info.name = "i2c_designware"; + info.id = (pdev->bus->number << 8) | pdev->devfn; + + info.res = &DEFINE_RES_IRQ(pdev->irq); + info.num_res = 1; + i2c_dev = platform_device_register_full(&info); + if (IS_ERR(i2c_dev)) + return PTR_ERR(i2c_dev); + + txgbe->i2c_dev = i2c_dev; + + return 0; +} + +static int txgbe_sfp_register(struct txgbe *txgbe) +{ + struct pci_dev *pdev = txgbe->wx->pdev; + struct platform_device_info info = {}; + struct platform_device *sfp_dev; + + info.parent = &pdev->dev; + info.fwnode = software_node_fwnode(txgbe->nodes.group[SWNODE_SFP]); + info.name = "sfp"; + info.id = (pdev->bus->number << 8) | pdev->devfn; + sfp_dev = platform_device_register_full(&info); + if (IS_ERR(sfp_dev)) + return PTR_ERR(sfp_dev); + + txgbe->sfp_dev = sfp_dev; + + return 0; +} + +int txgbe_init_phy(struct txgbe *txgbe) +{ + int ret; + + ret = txgbe_swnodes_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register software nodes\n"); + return ret; + } + + ret = txgbe_mdio_pcs_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret); + goto err_unregister_swnode; + } + + ret = txgbe_phylink_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init phylink\n"); + goto err_destroy_xpcs; + } + + ret = txgbe_gpio_init(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init gpio\n"); + goto err_destroy_phylink; + } + + ret = txgbe_clock_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register clock: %d\n", ret); + goto err_destroy_phylink; + } + + ret = txgbe_i2c_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret); + goto err_unregister_clk; + } + + ret = txgbe_sfp_register(txgbe); + if (ret) { + wx_err(txgbe->wx, "failed to register sfp\n"); + goto err_unregister_i2c; + } + + return 0; + +err_unregister_i2c: + platform_device_unregister(txgbe->i2c_dev); +err_unregister_clk: + clkdev_drop(txgbe->clock); + clk_unregister(txgbe->clk); +err_destroy_phylink: + phylink_destroy(txgbe->phylink); +err_destroy_xpcs: + xpcs_destroy(txgbe->xpcs); +err_unregister_swnode: + software_node_unregister_node_group(txgbe->nodes.group); + + return ret; +} + +void txgbe_remove_phy(struct txgbe *txgbe) +{ + platform_device_unregister(txgbe->sfp_dev); + platform_device_unregister(txgbe->i2c_dev); + clkdev_drop(txgbe->clock); + clk_unregister(txgbe->clk); + phylink_destroy(txgbe->phylink); + xpcs_destroy(txgbe->xpcs); + software_node_unregister_node_group(txgbe->nodes.group); +} diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h new file mode 100644 index 00000000000000..1ab592124986ae --- /dev/null +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2015 - 2023 Beijing WangXun Technology Co., Ltd. */ + +#ifndef _TXGBE_PHY_H_ +#define _TXGBE_PHY_H_ + +int txgbe_init_phy(struct txgbe *txgbe); +void txgbe_remove_phy(struct txgbe *txgbe); + +#endif /* _TXGBE_NODE_H_ */ diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h index 63a1c733718d3f..51199c355f95ce 100644 --- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h @@ -4,6 +4,8 @@ #ifndef _TXGBE_TYPE_H_ #define _TXGBE_TYPE_H_ +#include + /* Device IDs */ #define TXGBE_DEV_ID_SP1000 0x1001 #define TXGBE_DEV_ID_WX1820 0x2001 @@ -53,6 +55,39 @@ #define TXGBE_TS_CTL 0x10300 #define TXGBE_TS_CTL_EVAL_MD BIT(31) +/* GPIO register bit */ +#define TXGBE_GPIOBIT_0 BIT(0) /* I:tx fault */ +#define TXGBE_GPIOBIT_1 BIT(1) /* O:tx disabled */ +#define TXGBE_GPIOBIT_2 BIT(2) /* I:sfp module absent */ +#define TXGBE_GPIOBIT_3 BIT(3) /* I:rx signal lost */ +#define TXGBE_GPIOBIT_4 BIT(4) /* O:rate select, 1G(0) 10G(1) */ +#define TXGBE_GPIOBIT_5 BIT(5) /* O:rate select, 1G(0) 10G(1) */ + +/* Extended Interrupt Enable Set */ +#define TXGBE_PX_MISC_ETH_LKDN BIT(8) +#define TXGBE_PX_MISC_DEV_RST BIT(10) +#define TXGBE_PX_MISC_ETH_EVENT BIT(17) +#define TXGBE_PX_MISC_ETH_LK BIT(18) +#define TXGBE_PX_MISC_ETH_AN BIT(19) +#define TXGBE_PX_MISC_INT_ERR BIT(20) +#define TXGBE_PX_MISC_GPIO BIT(26) +#define TXGBE_PX_MISC_IEN_MASK \ + (TXGBE_PX_MISC_ETH_LKDN | TXGBE_PX_MISC_DEV_RST | \ + TXGBE_PX_MISC_ETH_EVENT | TXGBE_PX_MISC_ETH_LK | \ + TXGBE_PX_MISC_ETH_AN | TXGBE_PX_MISC_INT_ERR | \ + TXGBE_PX_MISC_GPIO) + +/* Port cfg registers */ +#define TXGBE_CFG_PORT_ST 0x14404 +#define TXGBE_CFG_PORT_ST_LINK_UP BIT(0) + +/* I2C registers */ +#define TXGBE_I2C_BASE 0x14900 + +/************************************** ETH PHY ******************************/ +#define TXGBE_XPCS_IDA_ADDR 0x13000 +#define TXGBE_XPCS_IDA_DATA 0x13004 + /* Part Number String Length */ #define TXGBE_PBANUM_LENGTH 32 @@ -77,6 +112,7 @@ #define TXGBE_SP_MAX_RX_QUEUES 128 #define TXGBE_SP_RAR_ENTRIES 128 #define TXGBE_SP_MC_TBL_SIZE 128 +#define TXGBE_SP_VFT_TBL_SIZE 128 #define TXGBE_SP_RX_PB_SIZE 512 #define TXGBE_SP_TDB_PB_SZ (160 * 1024) /* 160KB Packet Buffer */ @@ -99,4 +135,58 @@ extern char txgbe_driver_name[]; +static inline struct txgbe *netdev_to_txgbe(struct net_device *netdev) +{ + struct wx *wx = netdev_priv(netdev); + + return wx->priv; +} + +#define NODE_PROP(_NAME, _PROP) \ + (const struct software_node) { \ + .name = _NAME, \ + .properties = _PROP, \ + } + +enum txgbe_swnodes { + SWNODE_GPIO = 0, + SWNODE_I2C, + SWNODE_SFP, + SWNODE_PHYLINK, + SWNODE_MAX +}; + +struct txgbe_nodes { + char gpio_name[32]; + char i2c_name[32]; + char sfp_name[32]; + char phylink_name[32]; + struct property_entry gpio_props[1]; + struct property_entry i2c_props[3]; + struct property_entry sfp_props[8]; + struct property_entry phylink_props[2]; + struct software_node_ref_args i2c_ref[1]; + struct software_node_ref_args gpio0_ref[1]; + struct software_node_ref_args gpio1_ref[1]; + struct software_node_ref_args gpio2_ref[1]; + struct software_node_ref_args gpio3_ref[1]; + struct software_node_ref_args gpio4_ref[1]; + struct software_node_ref_args gpio5_ref[1]; + struct software_node_ref_args sfp_ref[1]; + struct software_node swnodes[SWNODE_MAX]; + const struct software_node *group[SWNODE_MAX + 1]; +}; + +struct txgbe { + struct wx *wx; + struct txgbe_nodes nodes; + struct dw_xpcs *xpcs; + struct phylink *phylink; + struct platform_device *sfp_dev; + struct platform_device *i2c_dev; + struct clk_lookup *clock; + struct clk *clk; + struct gpio_chip *gpio; +}; + #endif /* _TXGBE_TYPE_H_ */ diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 33d51e36391396..c9dd69dbe1b8fb 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h @@ -74,6 +74,7 @@ struct ndis_recv_scale_cap { /* NDIS_RECEIVE_SCALE_CAPABILITIES */ #define NDIS_RSS_HASH_SECRET_KEY_MAX_SIZE_REVISION_2 40 #define ITAB_NUM 128 +#define ITAB_NUM_MAX 256 struct ndis_recv_scale_param { /* NDIS_RECEIVE_SCALE_PARAMETERS */ struct ndis_obj_header hdr; @@ -1034,7 +1035,9 @@ struct net_device_context { u32 tx_table[VRSS_SEND_TAB_SIZE]; - u16 rx_table[ITAB_NUM]; + u16 *rx_table; + + u32 rx_table_sz; /* Ethtool settings */ u8 duplex; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 0103ff91402454..3ba3c8fb28a5d6 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -1747,7 +1747,9 @@ static u32 netvsc_get_rxfh_key_size(struct net_device *dev) static u32 netvsc_rss_indir_size(struct net_device *dev) { - return ITAB_NUM; + struct net_device_context *ndc = netdev_priv(dev); + + return ndc->rx_table_sz; } static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, @@ -1766,7 +1768,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, rndis_dev = ndev->extension; if (indir) { - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) indir[i] = ndc->rx_table[i]; } @@ -1792,11 +1794,11 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir, rndis_dev = ndev->extension; if (indir) { - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) if (indir[i] >= ndev->num_chn) return -EINVAL; - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) ndc->rx_table[i] = indir[i]; } diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index eea777ec2541b7..af95947a87c552 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "hyperv_net.h" #include "netvsc_trace.h" @@ -927,7 +928,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev, struct rndis_set_request *set; struct rndis_set_complete *set_complete; u32 extlen = sizeof(struct ndis_recv_scale_param) + - 4 * ITAB_NUM + NETVSC_HASH_KEYLEN; + 4 * ndc->rx_table_sz + NETVSC_HASH_KEYLEN; struct ndis_recv_scale_param *rssp; u32 *itab; u8 *keyp; @@ -953,7 +954,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev, rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 | NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 | NDIS_HASH_TCP_IPV6; - rssp->indirect_tabsize = 4*ITAB_NUM; + rssp->indirect_tabsize = 4 * ndc->rx_table_sz; rssp->indirect_taboffset = sizeof(struct ndis_recv_scale_param); rssp->hashkey_size = NETVSC_HASH_KEYLEN; rssp->hashkey_offset = rssp->indirect_taboffset + @@ -961,7 +962,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev, /* Set indirection table entries */ itab = (u32 *)(rssp + 1); - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) itab[i] = ndc->rx_table[i]; /* Set hask key values */ @@ -1548,6 +1549,18 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, if (ret || rsscap.num_recv_que < 2) goto out; + if (rsscap.num_indirect_tabent && + rsscap.num_indirect_tabent <= ITAB_NUM_MAX) + ndc->rx_table_sz = rsscap.num_indirect_tabent; + else + ndc->rx_table_sz = ITAB_NUM; + + ndc->rx_table = kcalloc(ndc->rx_table_sz, sizeof(u16), GFP_KERNEL); + if (!ndc->rx_table) { + ret = -ENOMEM; + goto err_dev_remv; + } + /* This guarantees that num_possible_rss_qs <= num_online_cpus */ num_possible_rss_qs = min_t(u32, num_online_cpus(), rsscap.num_recv_que); @@ -1558,7 +1571,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev, net_device->num_chn = min(net_device->max_chn, device_info->num_chn); if (!netif_is_rxfh_configured(net)) { - for (i = 0; i < ITAB_NUM; i++) + for (i = 0; i < ndc->rx_table_sz; i++) ndc->rx_table[i] = ethtool_rxfh_indir_default( i, net_device->num_chn); } @@ -1596,11 +1609,19 @@ void rndis_filter_device_remove(struct hv_device *dev, struct netvsc_device *net_dev) { struct rndis_device *rndis_dev = net_dev->extension; + struct net_device *net = hv_get_drvdata(dev); + struct net_device_context *ndc; + + ndc = netdev_priv(net); /* Halt and release the rndis device */ rndis_filter_halt_device(net_dev, rndis_dev); netvsc_device_remove(dev); + + ndc->rx_table_sz = 0; + kfree(ndc->rx_table); + ndc->rx_table = NULL; } int rndis_filter_open(struct netvsc_device *nvdev) diff --git a/drivers/net/ipa/ipa_endpoint.c b/drivers/net/ipa/ipa_endpoint.c index 2ee80ed140b72b..afa1d56d9095c1 100644 --- a/drivers/net/ipa/ipa_endpoint.c +++ b/drivers/net/ipa/ipa_endpoint.c @@ -119,7 +119,7 @@ enum ipa_status_field_id { }; /* Size in bytes of an IPA packet status structure */ -#define IPA_STATUS_SIZE sizeof(__le32[4]) +#define IPA_STATUS_SIZE sizeof(__le32[8]) /* IPA status structure decoder; looks up field values for a structure */ static u32 ipa_status_extract(struct ipa *ipa, const void *data, diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig index 9ff2e6f22f3f6b..4a7a303be2f744 100644 --- a/drivers/net/mdio/Kconfig +++ b/drivers/net/mdio/Kconfig @@ -185,6 +185,17 @@ config MDIO_IPQ8064 This driver supports the MDIO interface found in the network interface units of the IPQ8064 SoC +config MDIO_REGMAP + tristate + help + This driver allows using MDIO devices that are not sitting on a + regular MDIO bus, but still exposes the standard 802.3 register + layout. It's regmap-based so that it can be used on integrated, + memory-mapped PHYs, SPI PHYs and so on. A new virtual MDIO bus is + created, and its read/write operations are mapped to the underlying + regmap. Users willing to use this driver must explicitly select + REGMAP. + config MDIO_THUNDER tristate "ThunderX SOCs MDIO buses" depends on 64BIT diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile index 7d4cb4c11e4ec1..1015f0db4531db 100644 --- a/drivers/net/mdio/Makefile +++ b/drivers/net/mdio/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxart.o obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o +obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o diff --git a/drivers/net/mdio/mdio-mux-mmioreg.c b/drivers/net/mdio/mdio-mux-mmioreg.c index c02c9c66001696..09af150ed77413 100644 --- a/drivers/net/mdio/mdio-mux-mmioreg.c +++ b/drivers/net/mdio/mdio-mux-mmioreg.c @@ -140,14 +140,15 @@ static int mdio_mux_mmioreg_probe(struct platform_device *pdev) * set any bits outside of the 'mask'. */ for_each_available_child_of_node(np, np2) { - iprop = of_get_property(np2, "reg", &len); - if (!iprop || len != sizeof(uint32_t)) { + u64 reg; + + if (of_property_read_reg(np2, 0, ®, NULL)) { dev_err(&pdev->dev, "mdio-mux child node %pOF is " "missing a 'reg' property\n", np2); of_node_put(np2); return -ENODEV; } - if (be32_to_cpup(iprop) & ~s->mask) { + if ((u32)reg & ~s->mask) { dev_err(&pdev->dev, "mdio-mux child node %pOF has " "a 'reg' value with unmasked bits\n", np2); diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c new file mode 100644 index 00000000000000..8a742a8d6387da --- /dev/null +++ b/drivers/net/mdio/mdio-regmap.c @@ -0,0 +1,93 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Driver for MMIO-Mapped MDIO devices. Some IPs expose internal PHYs or PCS + * within the MMIO-mapped area + * + * Copyright (C) 2023 Maxime Chevallier + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRV_NAME "mdio-regmap" + +struct mdio_regmap_priv { + struct regmap *regmap; + u8 valid_addr; +}; + +static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum) +{ + struct mdio_regmap_priv *ctx = bus->priv; + unsigned int val; + int ret; + + if (ctx->valid_addr != addr) + return -ENODEV; + + ret = regmap_read(ctx->regmap, regnum, &val); + if (ret < 0) + return ret; + + return val; +} + +static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum, + u16 val) +{ + struct mdio_regmap_priv *ctx = bus->priv; + + if (ctx->valid_addr != addr) + return -ENODEV; + + return regmap_write(ctx->regmap, regnum, val); +} + +struct mii_bus *devm_mdio_regmap_register(struct device *dev, + const struct mdio_regmap_config *config) +{ + struct mdio_regmap_priv *mr; + struct mii_bus *mii; + int rc; + + if (!config->parent) + return ERR_PTR(-EINVAL); + + mii = devm_mdiobus_alloc_size(config->parent, sizeof(*mr)); + if (!mii) + return ERR_PTR(-ENOMEM); + + mr = mii->priv; + mr->regmap = config->regmap; + mr->valid_addr = config->valid_addr; + + mii->name = DRV_NAME; + strscpy(mii->id, config->name, MII_BUS_ID_SIZE); + mii->parent = config->parent; + mii->read = mdio_regmap_read_c22; + mii->write = mdio_regmap_write_c22; + + if (config->autoscan) + mii->phy_mask = ~BIT(config->valid_addr); + else + mii->phy_mask = ~0; + + rc = devm_mdiobus_register(dev, mii); + if (rc) { + dev_err(config->parent, "Cannot register MDIO bus![%s] (%d)\n", mii->id, rc); + return ERR_PTR(rc); + } + + return mii; +} +EXPORT_SYMBOL_GPL(devm_mdio_regmap_register); + +MODULE_DESCRIPTION("MDIO API over regmap"); +MODULE_AUTHOR("Maxime Chevallier "); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/pcs/Kconfig b/drivers/net/pcs/Kconfig index 7c34fb7cbf7b43..87cf308fc6d8b6 100644 --- a/drivers/net/pcs/Kconfig +++ b/drivers/net/pcs/Kconfig @@ -33,10 +33,4 @@ config PCS_RZN1_MIIC on RZ/N1 SoCs. This PCS converts MII to RMII/RGMII or can be set in pass-through mode for MII. -config PCS_ALTERA_TSE - tristate - help - This module provides helper functions for the Altera Triple Speed - Ethernet SGMII PCS, that can be found on the Intel Socfpga family. - endmenu diff --git a/drivers/net/pcs/Makefile b/drivers/net/pcs/Makefile index 9b9afd6b1c22d7..ea662a7989b29d 100644 --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile @@ -7,4 +7,3 @@ obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o obj-$(CONFIG_PCS_RZN1_MIIC) += pcs-rzn1-miic.o -obj-$(CONFIG_PCS_ALTERA_TSE) += pcs-altera-tse.o diff --git a/drivers/net/pcs/pcs-altera-tse.c b/drivers/net/pcs/pcs-altera-tse.c deleted file mode 100644 index d616749761f411..00000000000000 --- a/drivers/net/pcs/pcs-altera-tse.c +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (C) 2022 Bootlin - * - * Maxime Chevallier - */ - -#include -#include -#include -#include - -/* SGMII PCS register addresses - */ -#define SGMII_PCS_LINK_TIMER_0 0x12 -#define SGMII_PCS_LINK_TIMER_1 0x13 -#define SGMII_PCS_IF_MODE 0x14 -#define PCS_IF_MODE_SGMII_ENA BIT(0) -#define PCS_IF_MODE_USE_SGMII_AN BIT(1) -#define PCS_IF_MODE_SGMI_HALF_DUPLEX BIT(4) -#define PCS_IF_MODE_SGMI_PHY_AN BIT(5) -#define SGMII_PCS_SW_RESET_TIMEOUT 100 /* usecs */ - -struct altera_tse_pcs { - struct phylink_pcs pcs; - void __iomem *base; - int reg_width; -}; - -static struct altera_tse_pcs *phylink_pcs_to_tse_pcs(struct phylink_pcs *pcs) -{ - return container_of(pcs, struct altera_tse_pcs, pcs); -} - -static u16 tse_pcs_read(struct altera_tse_pcs *tse_pcs, int regnum) -{ - if (tse_pcs->reg_width == 4) - return readl(tse_pcs->base + regnum * 4); - else - return readw(tse_pcs->base + regnum * 2); -} - -static void tse_pcs_write(struct altera_tse_pcs *tse_pcs, int regnum, - u16 value) -{ - if (tse_pcs->reg_width == 4) - writel(value, tse_pcs->base + regnum * 4); - else - writew(value, tse_pcs->base + regnum * 2); -} - -static int tse_pcs_reset(struct altera_tse_pcs *tse_pcs) -{ - u16 bmcr; - - /* Reset PCS block */ - bmcr = tse_pcs_read(tse_pcs, MII_BMCR); - bmcr |= BMCR_RESET; - tse_pcs_write(tse_pcs, MII_BMCR, bmcr); - - return read_poll_timeout(tse_pcs_read, bmcr, (bmcr & BMCR_RESET), - 10, SGMII_PCS_SW_RESET_TIMEOUT, 1, - tse_pcs, MII_BMCR); -} - -static int alt_tse_pcs_validate(struct phylink_pcs *pcs, - unsigned long *supported, - const struct phylink_link_state *state) -{ - if (state->interface == PHY_INTERFACE_MODE_SGMII || - state->interface == PHY_INTERFACE_MODE_1000BASEX) - return 1; - - return -EINVAL; -} - -static int alt_tse_pcs_config(struct phylink_pcs *pcs, unsigned int mode, - phy_interface_t interface, - const unsigned long *advertising, - bool permit_pause_to_mac) -{ - struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs); - u32 ctrl, if_mode; - - ctrl = tse_pcs_read(tse_pcs, MII_BMCR); - if_mode = tse_pcs_read(tse_pcs, SGMII_PCS_IF_MODE); - - /* Set link timer to 1.6ms, as per the MegaCore Function User Guide */ - tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_0, 0x0D40); - tse_pcs_write(tse_pcs, SGMII_PCS_LINK_TIMER_1, 0x03); - - if (interface == PHY_INTERFACE_MODE_SGMII) { - if_mode |= PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA; - } else if (interface == PHY_INTERFACE_MODE_1000BASEX) { - if_mode &= ~(PCS_IF_MODE_USE_SGMII_AN | PCS_IF_MODE_SGMII_ENA); - } - - ctrl |= (BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_ANENABLE); - - tse_pcs_write(tse_pcs, MII_BMCR, ctrl); - tse_pcs_write(tse_pcs, SGMII_PCS_IF_MODE, if_mode); - - return tse_pcs_reset(tse_pcs); -} - -static void alt_tse_pcs_get_state(struct phylink_pcs *pcs, - struct phylink_link_state *state) -{ - struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs); - u16 bmsr, lpa; - - bmsr = tse_pcs_read(tse_pcs, MII_BMSR); - lpa = tse_pcs_read(tse_pcs, MII_LPA); - - phylink_mii_c22_pcs_decode_state(state, bmsr, lpa); -} - -static void alt_tse_pcs_an_restart(struct phylink_pcs *pcs) -{ - struct altera_tse_pcs *tse_pcs = phylink_pcs_to_tse_pcs(pcs); - u16 bmcr; - - bmcr = tse_pcs_read(tse_pcs, MII_BMCR); - bmcr |= BMCR_ANRESTART; - tse_pcs_write(tse_pcs, MII_BMCR, bmcr); - - /* This PCS seems to require a soft reset to re-sync the AN logic */ - tse_pcs_reset(tse_pcs); -} - -static const struct phylink_pcs_ops alt_tse_pcs_ops = { - .pcs_validate = alt_tse_pcs_validate, - .pcs_get_state = alt_tse_pcs_get_state, - .pcs_config = alt_tse_pcs_config, - .pcs_an_restart = alt_tse_pcs_an_restart, -}; - -struct phylink_pcs *alt_tse_pcs_create(struct net_device *ndev, - void __iomem *pcs_base, int reg_width) -{ - struct altera_tse_pcs *tse_pcs; - - if (reg_width != 4 && reg_width != 2) - return ERR_PTR(-EINVAL); - - tse_pcs = devm_kzalloc(&ndev->dev, sizeof(*tse_pcs), GFP_KERNEL); - if (!tse_pcs) - return ERR_PTR(-ENOMEM); - - tse_pcs->pcs.ops = &alt_tse_pcs_ops; - tse_pcs->base = pcs_base; - tse_pcs->reg_width = reg_width; - - return &tse_pcs->pcs; -} -EXPORT_SYMBOL_GPL(alt_tse_pcs_create); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Altera TSE PCS driver"); -MODULE_AUTHOR("Maxime Chevallier "); diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c index 622c3de3f3a8b4..fca48ebf0b811c 100644 --- a/drivers/net/pcs/pcs-lynx.c +++ b/drivers/net/pcs/pcs-lynx.c @@ -6,6 +6,7 @@ #include #include #include +#include #define SGMII_CLOCK_PERIOD_NS 8 /* PCS is clocked at 125 MHz */ #define LINK_TIMER_VAL(ns) ((u32)((ns) / SGMII_CLOCK_PERIOD_NS)) @@ -34,14 +35,6 @@ enum sgmii_speed { #define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs) #define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs) -struct mdio_device *lynx_get_mdio_device(struct phylink_pcs *pcs) -{ - struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); - - return lynx->mdio; -} -EXPORT_SYMBOL(lynx_get_mdio_device); - static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs, struct phylink_link_state *state) { @@ -315,26 +308,86 @@ static const struct phylink_pcs_ops lynx_pcs_phylink_ops = { .pcs_link_up = lynx_pcs_link_up, }; -struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio) +static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio) { struct lynx_pcs *lynx; lynx = kzalloc(sizeof(*lynx), GFP_KERNEL); if (!lynx) - return NULL; + return ERR_PTR(-ENOMEM); + mdio_device_get(mdio); lynx->mdio = mdio; lynx->pcs.ops = &lynx_pcs_phylink_ops; lynx->pcs.poll = true; return lynx_to_phylink_pcs(lynx); } -EXPORT_SYMBOL(lynx_pcs_create); + +struct phylink_pcs *lynx_pcs_create_mdiodev(struct mii_bus *bus, int addr) +{ + struct mdio_device *mdio; + struct phylink_pcs *pcs; + + mdio = mdio_device_create(bus, addr); + if (IS_ERR(mdio)) + return ERR_CAST(mdio); + + pcs = lynx_pcs_create(mdio); + + /* lynx_create() has taken a refcount on the mdiodev if it was + * successful. If lynx_create() fails, this will free the mdio + * device here. In any case, we don't need to hold our reference + * anymore, and putting it here will allow mdio_device_put() in + * lynx_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdio); + + return pcs; +} +EXPORT_SYMBOL(lynx_pcs_create_mdiodev); + +/* + * lynx_pcs_create_fwnode() creates a lynx PCS instance from the fwnode + * device indicated by node. + * + * Returns: + * -ENODEV if the fwnode is marked unavailable + * -EPROBE_DEFER if we fail to find the device + * -ENOMEM if we fail to allocate memory + * pointer to a phylink_pcs on success + */ +struct phylink_pcs *lynx_pcs_create_fwnode(struct fwnode_handle *node) +{ + struct mdio_device *mdio; + struct phylink_pcs *pcs; + + if (!fwnode_device_is_available(node)) + return ERR_PTR(-ENODEV); + + mdio = fwnode_mdio_find_device(node); + if (!mdio) + return ERR_PTR(-EPROBE_DEFER); + + pcs = lynx_pcs_create(mdio); + + /* lynx_create() has taken a refcount on the mdiodev if it was + * successful. If lynx_create() fails, this will free the mdio + * device here. In any case, we don't need to hold our reference + * anymore, and putting it here will allow mdio_device_put() in + * lynx_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdio); + + return pcs; +} +EXPORT_SYMBOL_GPL(lynx_pcs_create_fwnode); void lynx_pcs_destroy(struct phylink_pcs *pcs) { struct lynx_pcs *lynx = phylink_pcs_to_lynx(pcs); + mdio_device_put(lynx->mdio); kfree(lynx); } EXPORT_SYMBOL(lynx_pcs_destroy); diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 72f25e778840f9..e4e59aa9faf772 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -64,6 +64,16 @@ static const int xpcs_xlgmii_features[] = { __ETHTOOL_LINK_MODE_MASK_NBITS, }; +static const int xpcs_10gbaser_features[] = { + ETHTOOL_LINK_MODE_Pause_BIT, + ETHTOOL_LINK_MODE_Asym_Pause_BIT, + ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, + ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, + ETHTOOL_LINK_MODE_10000baseER_Full_BIT, + __ETHTOOL_LINK_MODE_MASK_NBITS, +}; + static const int xpcs_sgmii_features[] = { ETHTOOL_LINK_MODE_Pause_BIT, ETHTOOL_LINK_MODE_Asym_Pause_BIT, @@ -106,6 +116,10 @@ static const phy_interface_t xpcs_xlgmii_interfaces[] = { PHY_INTERFACE_MODE_XLGMII, }; +static const phy_interface_t xpcs_10gbaser_interfaces[] = { + PHY_INTERFACE_MODE_10GBASER, +}; + static const phy_interface_t xpcs_sgmii_interfaces[] = { PHY_INTERFACE_MODE_SGMII, }; @@ -123,6 +137,7 @@ enum { DW_XPCS_USXGMII, DW_XPCS_10GKR, DW_XPCS_XLGMII, + DW_XPCS_10GBASER, DW_XPCS_SGMII, DW_XPCS_1000BASEX, DW_XPCS_2500BASEX, @@ -246,6 +261,7 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs, switch (compat->an_mode) { case DW_AN_C73: + case DW_10GBASER: dev = MDIO_MMD_PCS; break; case DW_AN_C37_SGMII: @@ -271,15 +287,12 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs, }) static int xpcs_read_fault_c73(struct dw_xpcs *xpcs, - struct phylink_link_state *state) + struct phylink_link_state *state, + u16 pcs_stat1) { int ret; - ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); - if (ret < 0) - return ret; - - if (ret & MDIO_STAT1_FAULT) { + if (pcs_stat1 & MDIO_STAT1_FAULT) { xpcs_warn(xpcs, state, "Link fault condition detected!\n"); return -EFAULT; } @@ -321,37 +334,6 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs, return 0; } -static int xpcs_read_link_c73(struct dw_xpcs *xpcs) -{ - bool link = true; - int ret; - - ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); - if (ret < 0) - return ret; - - if (!(ret & MDIO_STAT1_LSTATUS)) - link = false; - - return link; -} - -static int xpcs_get_max_usxgmii_speed(const unsigned long *supported) -{ - int max = SPEED_UNKNOWN; - - if (phylink_test(supported, 1000baseKX_Full)) - max = SPEED_1000; - if (phylink_test(supported, 2500baseX_Full)) - max = SPEED_2500; - if (phylink_test(supported, 10000baseKX4_Full)) - max = SPEED_10000; - if (phylink_test(supported, 10000baseKR_Full)) - max = SPEED_10000; - - return max; -} - static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed) { int ret, speed_sel; @@ -478,16 +460,12 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs, static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs, struct phylink_link_state *state, - const struct xpcs_compat *compat) + const struct xpcs_compat *compat, u16 an_stat1) { int ret; - ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); - if (ret < 0) - return ret; - - if (ret & MDIO_AN_STAT1_COMPLETE) { - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); + if (an_stat1 & MDIO_AN_STAT1_COMPLETE) { + ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA); if (ret < 0) return ret; @@ -504,64 +482,32 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs, } static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs, - struct phylink_link_state *state) + struct phylink_link_state *state, u16 an_stat1) { - int ret; - - ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); - if (ret < 0) - return ret; + u16 lpa[3]; + int i, ret; - if (!(ret & MDIO_AN_STAT1_LPABLE)) { + if (!(an_stat1 & MDIO_AN_STAT1_LPABLE)) { phylink_clear(state->lp_advertising, Autoneg); return 0; } phylink_set(state->lp_advertising, Autoneg); - /* Clause 73 outcome */ - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3); - if (ret < 0) - return ret; - - if (ret & DW_C73_2500KX) - phylink_set(state->lp_advertising, 2500baseX_Full); - - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2); - if (ret < 0) - return ret; - - if (ret & DW_C73_1000KX) - phylink_set(state->lp_advertising, 1000baseKX_Full); - if (ret & DW_C73_10000KX4) - phylink_set(state->lp_advertising, 10000baseKX4_Full); - if (ret & DW_C73_10000KR) - phylink_set(state->lp_advertising, 10000baseKR_Full); + /* Read Clause 73 link partner advertisement */ + for (i = ARRAY_SIZE(lpa); --i >= 0; ) { + ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i); + if (ret < 0) + return ret; - ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1); - if (ret < 0) - return ret; + lpa[i] = ret; + } - if (ret & DW_C73_PAUSE) - phylink_set(state->lp_advertising, Pause); - if (ret & DW_C73_ASYM_PAUSE) - phylink_set(state->lp_advertising, Asym_Pause); + mii_c73_mod_linkmode(state->lp_advertising, lpa); - linkmode_and(state->lp_advertising, state->lp_advertising, - state->advertising); return 0; } -static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs, - struct phylink_link_state *state) -{ - int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising); - - state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX; - state->speed = max_speed; - state->duplex = DUPLEX_FULL; -} - static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs, struct phylink_link_state *state) { @@ -872,6 +818,8 @@ int xpcs_do_config(struct dw_xpcs *xpcs, phy_interface_t interface, return -ENODEV; switch (compat->an_mode) { + case DW_10GBASER: + break; case DW_AN_C73: if (test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, advertising)) { ret = xpcs_config_aneg_c73(xpcs, compat); @@ -924,13 +872,25 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs, const struct xpcs_compat *compat) { bool an_enabled; + int pcs_stat1; + int an_stat1; int ret; + /* The link status bit is latching-low, so it is important to + * avoid unnecessary re-reads of this register to avoid missing + * a link-down event. + */ + pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1); + if (pcs_stat1 < 0) { + state->link = false; + return pcs_stat1; + } + /* Link needs to be read first ... */ - state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0; + state->link = !!(pcs_stat1 & MDIO_STAT1_LSTATUS); /* ... and then we check the faults. */ - ret = xpcs_read_fault_c73(xpcs, state); + ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1); if (ret) { ret = xpcs_soft_reset(xpcs, compat); if (ret) @@ -941,15 +901,38 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs, return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL); } + /* There is no point doing anything else if the link is down. */ + if (!state->link) + return 0; + an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, state->advertising); - if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) { - state->an_complete = true; - xpcs_read_lpa_c73(xpcs, state); - xpcs_resolve_lpa_c73(xpcs, state); - } else if (an_enabled) { - state->link = 0; - } else if (state->link) { + if (an_enabled) { + /* The link status bit is latching-low, so it is important to + * avoid unnecessary re-reads of this register to avoid missing + * a link-down event. + */ + an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1); + if (an_stat1 < 0) { + state->link = false; + return an_stat1; + } + + state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat, + an_stat1); + if (!state->an_complete) { + state->link = false; + return 0; + } + + ret = xpcs_read_lpa_c73(xpcs, state, an_stat1); + if (ret < 0) { + state->link = false; + return ret; + } + + phylink_resolve_c73(state); + } else { xpcs_resolve_pma(xpcs, state); } @@ -1033,6 +1016,9 @@ static void xpcs_get_state(struct phylink_pcs *pcs, return; switch (compat->an_mode) { + case DW_10GBASER: + phylink_mii_c45_pcs_get_state(xpcs->mdiodev, state); + break; case DW_AN_C73: ret = xpcs_get_state_c73(xpcs, state, compat); if (ret) { @@ -1188,6 +1174,12 @@ static const struct xpcs_compat synopsys_xpcs_compat[DW_XPCS_INTERFACE_MAX] = { .num_interfaces = ARRAY_SIZE(xpcs_xlgmii_interfaces), .an_mode = DW_AN_C73, }, + [DW_XPCS_10GBASER] = { + .supported = xpcs_10gbaser_features, + .interface = xpcs_10gbaser_interfaces, + .num_interfaces = ARRAY_SIZE(xpcs_10gbaser_interfaces), + .an_mode = DW_10GBASER, + }, [DW_XPCS_SGMII] = { .supported = xpcs_sgmii_features, .interface = xpcs_sgmii_interfaces, @@ -1259,8 +1251,8 @@ static const struct phylink_pcs_ops xpcs_phylink_ops = { .pcs_link_up = xpcs_link_up, }; -struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, - phy_interface_t interface) +static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, + phy_interface_t interface) { struct dw_xpcs *xpcs; u32 xpcs_id; @@ -1270,6 +1262,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, if (!xpcs) return ERR_PTR(-ENOMEM); + mdio_device_get(mdiodev); xpcs->mdiodev = mdiodev; xpcs_id = xpcs_get_id(xpcs); @@ -1290,6 +1283,9 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, } xpcs->pcs.ops = &xpcs_phylink_ops; + if (compat->an_mode == DW_10GBASER) + return xpcs; + xpcs->pcs.poll = true; ret = xpcs_soft_reset(xpcs, compat); @@ -1302,16 +1298,42 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, ret = -ENODEV; out: + mdio_device_put(mdiodev); kfree(xpcs); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(xpcs_create); void xpcs_destroy(struct dw_xpcs *xpcs) { + if (xpcs) + mdio_device_put(xpcs->mdiodev); kfree(xpcs); } EXPORT_SYMBOL_GPL(xpcs_destroy); +struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr, + phy_interface_t interface) +{ + struct mdio_device *mdiodev; + struct dw_xpcs *xpcs; + + mdiodev = mdio_device_create(bus, addr); + if (IS_ERR(mdiodev)) + return ERR_CAST(mdiodev); + + xpcs = xpcs_create(mdiodev, interface); + + /* xpcs_create() has taken a refcount on the mdiodev if it was + * successful. If xpcs_create() fails, this will free the mdio + * device here. In any case, we don't need to hold our reference + * anymore, and putting it here will allow mdio_device_put() in + * xpcs_destroy() to automatically free the mdio device. + */ + mdio_device_put(mdiodev); + + return xpcs; +} +EXPORT_SYMBOL_GPL(xpcs_create_mdiodev); + MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 770df50323a017..68c6b5a620881e 100644 --- a/drivers/net/pcs/pcs-xpcs.h +++ b/drivers/net/pcs/pcs-xpcs.h @@ -32,9 +32,6 @@ #define DW_SR_AN_ADV1 0x10 #define DW_SR_AN_ADV2 0x11 #define DW_SR_AN_ADV3 0x12 -#define DW_SR_AN_LP_ABL1 0x13 -#define DW_SR_AN_LP_ABL2 0x14 -#define DW_SR_AN_LP_ABL3 0x15 /* Clause 73 Defines */ /* AN_LP_ABL1 */ diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 93b8efc7922737..a40269c175974a 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -236,6 +236,18 @@ config MEDIATEK_GE_PHY help Supports the MediaTek Gigabit Ethernet PHYs. +config MEDIATEK_GE_SOC_PHY + tristate "MediaTek SoC Ethernet PHYs" + depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST + select NVMEM_MTK_EFUSE + help + Supports MediaTek SoC built-in Gigabit Ethernet PHYs. + + Include support for built-in Ethernet PHYs which are present in + the MT7981 and MT7988 SoCs. These PHYs need calibration data + present in the SoCs efuse and will dynamically calibrate VCM + (common-mode voltage) during startup. + config MICREL_PHY tristate "Micrel PHYs" depends on PTP_1588_CLOCK_OPTIONAL @@ -243,9 +255,10 @@ config MICREL_PHY Supports the KSZ9021, VSC8201, KS8001 PHYs. config MICROCHIP_T1S_PHY - tristate "Microchip 10BASE-T1S Ethernet PHY" + tristate "Microchip 10BASE-T1S Ethernet PHYs" help - Currently supports the LAN8670, LAN8671, LAN8672 + Currently supports the LAN8670/1/2 Rev.B1 and LAN8650/1 Rev.B0 Internal + PHYs. config MICROCHIP_PHY tristate "Microchip PHYs" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index f289ab16a1dab3..2fe51ea83babee 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o +obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o obj-$(CONFIG_MICREL_PHY) += micrel.o diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index 27c57f6ab2112f..876f28fd82565d 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -496,18 +496,20 @@ EXPORT_SYMBOL_GPL(bcm_phy_downshift_set); struct bcm_phy_hw_stat { const char *string; - u8 reg; + int devad; + u16 reg; u8 shift; u8 bits; }; /* Counters freeze at either 0xffff or 0xff, better than nothing */ static const struct bcm_phy_hw_stat bcm_phy_hw_stats[] = { - { "phy_receive_errors", MII_BRCM_CORE_BASE12, 0, 16 }, - { "phy_serdes_ber_errors", MII_BRCM_CORE_BASE13, 8, 8 }, - { "phy_false_carrier_sense_errors", MII_BRCM_CORE_BASE13, 0, 8 }, - { "phy_local_rcvr_nok", MII_BRCM_CORE_BASE14, 8, 8 }, - { "phy_remote_rcv_nok", MII_BRCM_CORE_BASE14, 0, 8 }, + { "phy_receive_errors", -1, MII_BRCM_CORE_BASE12, 0, 16 }, + { "phy_serdes_ber_errors", -1, MII_BRCM_CORE_BASE13, 8, 8 }, + { "phy_false_carrier_sense_errors", -1, MII_BRCM_CORE_BASE13, 0, 8 }, + { "phy_local_rcvr_nok", -1, MII_BRCM_CORE_BASE14, 8, 8 }, + { "phy_remote_rcv_nok", -1, MII_BRCM_CORE_BASE14, 0, 8 }, + { "phy_lpi_count", MDIO_MMD_AN, BRCM_CL45VEN_EEE_LPI_CNT, 0, 16 }, }; int bcm_phy_get_sset_count(struct phy_device *phydev) @@ -536,7 +538,10 @@ static u64 bcm_phy_get_stat(struct phy_device *phydev, u64 *shadow, int val; u64 ret; - val = phy_read(phydev, stat.reg); + if (stat.devad < 0) + val = phy_read(phydev, stat.reg); + else + val = phy_read_mmd(phydev, stat.devad, stat.reg); if (val < 0) { ret = U64_MAX; } else { @@ -1028,6 +1033,39 @@ void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol) } EXPORT_SYMBOL_GPL(bcm_phy_get_wol); +irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id) +{ + return IRQ_HANDLED; +} +EXPORT_SYMBOL_GPL(bcm_phy_wol_isr); + +int bcm_phy_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value) +{ + u8 led_num; + int ret; + u16 reg; + + if (index >= 4) + return -EINVAL; + + /* Two LEDS per register */ + led_num = index % 2; + reg = index >= 2 ? BCM54XX_SHD_LEDS2 : BCM54XX_SHD_LEDS1; + + ret = bcm_phy_read_shadow(phydev, reg); + if (ret < 0) + return ret; + + ret &= ~(BCM_LED_SRC_MASK << BCM54XX_SHD_LEDS_SHIFT(led_num)); + if (value == LED_OFF) + ret |= BCM_LED_SRC_OFF << BCM54XX_SHD_LEDS_SHIFT(led_num); + else + ret |= BCM_LED_SRC_ON << BCM54XX_SHD_LEDS_SHIFT(led_num); + return bcm_phy_write_shadow(phydev, reg, ret); +} +EXPORT_SYMBOL_GPL(bcm_phy_led_brightness_set); + MODULE_DESCRIPTION("Broadcom PHY Library"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Broadcom Corporation"); diff --git a/drivers/net/phy/bcm-phy-lib.h b/drivers/net/phy/bcm-phy-lib.h index c6fed43ec91300..b52189e45a8481 100644 --- a/drivers/net/phy/bcm-phy-lib.h +++ b/drivers/net/phy/bcm-phy-lib.h @@ -8,6 +8,7 @@ #include #include +#include struct ethtool_wolinfo; @@ -115,5 +116,9 @@ static inline void bcm_ptp_stop(struct bcm_ptp_private *priv) int bcm_phy_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); void bcm_phy_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol); +irqreturn_t bcm_phy_wol_isr(int irq, void *dev_id); + +int bcm_phy_led_brightness_set(struct phy_device *phydev, + u8 index, enum led_brightness value); #endif /* _LINUX_BCM_PHY_LIB_H */ diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index 418e6bc0e9981f..9f0a9c575bd771 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -414,13 +414,13 @@ static int bcm54xx_config_init(struct phy_device *phydev) * these settings will cause LOS to malfunction. */ if (!phy_on_sfp(phydev)) { - val = BCM5482_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | - BCM5482_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); - bcm_phy_write_shadow(phydev, BCM5482_SHD_LEDS1, val); + val = BCM54XX_SHD_LEDS1_LED1(BCM_LED_SRC_MULTICOLOR1) | + BCM54XX_SHD_LEDS1_LED3(BCM_LED_SRC_MULTICOLOR1); + bcm_phy_write_shadow(phydev, BCM54XX_SHD_LEDS1, val); val = BCM_LED_MULTICOLOR_IN_PHASE | - BCM5482_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | - BCM5482_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); + BCM54XX_SHD_LEDS1_LED1(BCM_LED_MULTICOLOR_LINK_ACT) | + BCM54XX_SHD_LEDS1_LED3(BCM_LED_MULTICOLOR_LINK_ACT); bcm_phy_write_exp(phydev, BCM_EXP_MULTICOLOR, val); } @@ -927,7 +927,14 @@ static int bcm54xx_phy_probe(struct phy_device *phydev) if (!IS_ERR(wakeup_gpio)) { priv->wake_irq = gpiod_to_irq(wakeup_gpio); - ret = irq_set_irq_type(priv->wake_irq, IRQ_TYPE_LEVEL_LOW); + + /* Dummy interrupt handler which is not enabled but is provided + * in order for the interrupt descriptor to be fully set-up. + */ + ret = devm_request_irq(&phydev->mdio.dev, priv->wake_irq, + bcm_phy_wol_isr, + IRQF_TRIGGER_LOW | IRQF_NO_AUTOEN, + dev_name(&phydev->mdio.dev), phydev); if (ret) return ret; } @@ -1024,6 +1031,7 @@ static struct phy_driver broadcom_drivers[] = { .resume = bcm54xx_resume, .get_wol = bcm54xx_phy_get_wol, .set_wol = bcm54xx_phy_set_wol, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5461, .phy_id_mask = 0xfffffff0, @@ -1037,6 +1045,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54612E, .phy_id_mask = 0xfffffff0, @@ -1050,6 +1059,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54616S, .phy_id_mask = 0xfffffff0, @@ -1063,6 +1073,7 @@ static struct phy_driver broadcom_drivers[] = { .read_status = bcm54616s_read_status, .probe = bcm54616s_probe, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5464, .phy_id_mask = 0xfffffff0, @@ -1078,6 +1089,7 @@ static struct phy_driver broadcom_drivers[] = { .suspend = genphy_suspend, .resume = genphy_resume, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5481, .phy_id_mask = 0xfffffff0, @@ -1092,6 +1104,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54810, .phy_id_mask = 0xfffffff0, @@ -1108,6 +1121,7 @@ static struct phy_driver broadcom_drivers[] = { .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM54811, .phy_id_mask = 0xfffffff0, @@ -1124,6 +1138,7 @@ static struct phy_driver broadcom_drivers[] = { .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM5482, .phy_id_mask = 0xfffffff0, @@ -1137,6 +1152,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM50610, .phy_id_mask = 0xfffffff0, @@ -1152,6 +1168,7 @@ static struct phy_driver broadcom_drivers[] = { .link_change_notify = bcm54xx_link_change_notify, .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM50610M, .phy_id_mask = 0xfffffff0, @@ -1167,6 +1184,7 @@ static struct phy_driver broadcom_drivers[] = { .link_change_notify = bcm54xx_link_change_notify, .suspend = bcm54xx_suspend, .resume = bcm54xx_resume, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM57780, .phy_id_mask = 0xfffffff0, @@ -1180,6 +1198,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCMAC131, .phy_id_mask = 0xfffffff0, @@ -1211,6 +1230,7 @@ static struct phy_driver broadcom_drivers[] = { .get_stats = bcm54xx_get_stats, .probe = bcm54xx_phy_probe, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM53125, .phy_id_mask = 0xfffffff0, @@ -1225,6 +1245,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM53128, .phy_id_mask = 0xfffffff0, @@ -1239,6 +1260,7 @@ static struct phy_driver broadcom_drivers[] = { .config_intr = bcm_phy_config_intr, .handle_interrupt = bcm_phy_handle_interrupt, .link_change_notify = bcm54xx_link_change_notify, + .led_brightness_set = bcm_phy_led_brightness_set, }, { .phy_id = PHY_ID_BCM89610, .phy_id_mask = 0xfffffff0, diff --git a/drivers/net/phy/mediatek-ge-soc.c b/drivers/net/phy/mediatek-ge-soc.c new file mode 100644 index 00000000000000..95369171a7ba6f --- /dev/null +++ b/drivers/net/phy/mediatek-ge-soc.c @@ -0,0 +1,1116 @@ +// SPDX-License-Identifier: GPL-2.0+ +#include +#include +#include +#include +#include +#include +#include + +#define MTK_GPHY_ID_MT7981 0x03a29461 +#define MTK_GPHY_ID_MT7988 0x03a29481 + +#define MTK_EXT_PAGE_ACCESS 0x1f +#define MTK_PHY_PAGE_STANDARD 0x0000 +#define MTK_PHY_PAGE_EXTENDED_3 0x0003 + +#define MTK_PHY_LPI_REG_14 0x14 +#define MTK_PHY_LPI_WAKE_TIMER_1000_MASK GENMASK(8, 0) + +#define MTK_PHY_LPI_REG_1c 0x1c +#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8) + +#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30 +#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5 + +#define ANALOG_INTERNAL_OPERATION_MAX_US 20 +#define TXRESERVE_MIN 0 +#define TXRESERVE_MAX 7 + +#define MTK_PHY_ANARG_RG 0x10 +#define MTK_PHY_TCLKOFFSET_MASK GENMASK(12, 8) + +/* Registers on MDIO_MMD_VEND1 */ +#define MTK_PHY_TXVLD_DA_RG 0x12 +#define MTK_PHY_DA_TX_I2MPB_A_GBE_MASK GENMASK(15, 10) +#define MTK_PHY_DA_TX_I2MPB_A_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_A2 0x16 +#define MTK_PHY_DA_TX_I2MPB_A_HBT_MASK GENMASK(15, 10) +#define MTK_PHY_DA_TX_I2MPB_A_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_B1 0x17 +#define MTK_PHY_DA_TX_I2MPB_B_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_B_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_B2 0x18 +#define MTK_PHY_DA_TX_I2MPB_B_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_B_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_C1 0x19 +#define MTK_PHY_DA_TX_I2MPB_C_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_C_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_C2 0x20 +#define MTK_PHY_DA_TX_I2MPB_C_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_C_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_D1 0x21 +#define MTK_PHY_DA_TX_I2MPB_D_GBE_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_D_TBT_MASK GENMASK(5, 0) + +#define MTK_PHY_TX_I2MPB_TEST_MODE_D2 0x22 +#define MTK_PHY_DA_TX_I2MPB_D_HBT_MASK GENMASK(13, 8) +#define MTK_PHY_DA_TX_I2MPB_D_TST_MASK GENMASK(5, 0) + +#define MTK_PHY_RXADC_CTRL_RG7 0xc6 +#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8) + +#define MTK_PHY_RXADC_CTRL_RG9 0xc8 +#define MTK_PHY_DA_RX_PSBN_TBT_MASK GENMASK(14, 12) +#define MTK_PHY_DA_RX_PSBN_HBT_MASK GENMASK(10, 8) +#define MTK_PHY_DA_RX_PSBN_GBE_MASK GENMASK(6, 4) +#define MTK_PHY_DA_RX_PSBN_LP_MASK GENMASK(2, 0) + +#define MTK_PHY_LDO_OUTPUT_V 0xd7 + +#define MTK_PHY_RG_ANA_CAL_RG0 0xdb +#define MTK_PHY_RG_CAL_CKINV BIT(12) +#define MTK_PHY_RG_ANA_CALEN BIT(8) +#define MTK_PHY_RG_ZCALEN_A BIT(0) + +#define MTK_PHY_RG_ANA_CAL_RG1 0xdc +#define MTK_PHY_RG_ZCALEN_B BIT(12) +#define MTK_PHY_RG_ZCALEN_C BIT(8) +#define MTK_PHY_RG_ZCALEN_D BIT(4) +#define MTK_PHY_RG_TXVOS_CALEN BIT(0) + +#define MTK_PHY_RG_ANA_CAL_RG5 0xe0 +#define MTK_PHY_RG_REXT_TRIM_MASK GENMASK(13, 8) + +#define MTK_PHY_RG_TX_FILTER 0xfe + +#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120 0x120 +#define MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK GENMASK(12, 8) +#define MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK GENMASK(4, 0) + +#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122 0x122 +#define MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK GENMASK(7, 0) + +#define MTK_PHY_RG_TESTMUX_ADC_CTRL 0x144 +#define MTK_PHY_RG_TXEN_DIG_MASK GENMASK(5, 5) + +#define MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B 0x172 +#define MTK_PHY_CR_TX_AMP_OFFSET_A_MASK GENMASK(13, 8) +#define MTK_PHY_CR_TX_AMP_OFFSET_B_MASK GENMASK(6, 0) + +#define MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D 0x173 +#define MTK_PHY_CR_TX_AMP_OFFSET_C_MASK GENMASK(13, 8) +#define MTK_PHY_CR_TX_AMP_OFFSET_D_MASK GENMASK(6, 0) + +#define MTK_PHY_RG_AD_CAL_COMP 0x17a +#define MTK_PHY_AD_CAL_COMP_OUT_SHIFT (8) + +#define MTK_PHY_RG_AD_CAL_CLK 0x17b +#define MTK_PHY_DA_CAL_CLK BIT(0) + +#define MTK_PHY_RG_AD_CALIN 0x17c +#define MTK_PHY_DA_CALIN_FLAG BIT(0) + +#define MTK_PHY_RG_DASN_DAC_IN0_A 0x17d +#define MTK_PHY_DASN_DAC_IN0_A_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_B 0x17e +#define MTK_PHY_DASN_DAC_IN0_B_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_C 0x17f +#define MTK_PHY_DASN_DAC_IN0_C_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN0_D 0x180 +#define MTK_PHY_DASN_DAC_IN0_D_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_A 0x181 +#define MTK_PHY_DASN_DAC_IN1_A_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_B 0x182 +#define MTK_PHY_DASN_DAC_IN1_B_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_C 0x183 +#define MTK_PHY_DASN_DAC_IN1_C_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DASN_DAC_IN1_D 0x184 +#define MTK_PHY_DASN_DAC_IN1_D_MASK GENMASK(9, 0) + +#define MTK_PHY_RG_DEV1E_REG19b 0x19b +#define MTK_PHY_BYPASS_DSP_LPI_READY BIT(8) + +#define MTK_PHY_RG_LP_IIR2_K1_L 0x22a +#define MTK_PHY_RG_LP_IIR2_K1_U 0x22b +#define MTK_PHY_RG_LP_IIR2_K2_L 0x22c +#define MTK_PHY_RG_LP_IIR2_K2_U 0x22d +#define MTK_PHY_RG_LP_IIR2_K3_L 0x22e +#define MTK_PHY_RG_LP_IIR2_K3_U 0x22f +#define MTK_PHY_RG_LP_IIR2_K4_L 0x230 +#define MTK_PHY_RG_LP_IIR2_K4_U 0x231 +#define MTK_PHY_RG_LP_IIR2_K5_L 0x232 +#define MTK_PHY_RG_LP_IIR2_K5_U 0x233 + +#define MTK_PHY_RG_DEV1E_REG234 0x234 +#define MTK_PHY_TR_OPEN_LOOP_EN_MASK GENMASK(0, 0) +#define MTK_PHY_LPF_X_AVERAGE_MASK GENMASK(7, 4) +#define MTK_PHY_TR_LP_IIR_EEE_EN BIT(12) + +#define MTK_PHY_RG_LPF_CNT_VAL 0x235 + +#define MTK_PHY_RG_DEV1E_REG238 0x238 +#define MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK GENMASK(8, 0) +#define MTK_PHY_LPI_SLV_SEND_TX_EN BIT(12) + +#define MTK_PHY_RG_DEV1E_REG239 0x239 +#define MTK_PHY_LPI_SEND_LOC_TIMER_MASK GENMASK(8, 0) +#define MTK_PHY_LPI_TXPCS_LOC_RCV BIT(12) + +#define MTK_PHY_RG_DEV1E_REG27C 0x27c +#define MTK_PHY_VGASTATE_FFE_THR_ST1_MASK GENMASK(12, 8) +#define MTK_PHY_RG_DEV1E_REG27D 0x27d +#define MTK_PHY_VGASTATE_FFE_THR_ST2_MASK GENMASK(4, 0) + +#define MTK_PHY_RG_DEV1E_REG2C7 0x2c7 +#define MTK_PHY_MAX_GAIN_MASK GENMASK(4, 0) +#define MTK_PHY_MIN_GAIN_MASK GENMASK(12, 8) + +#define MTK_PHY_RG_DEV1E_REG2D1 0x2d1 +#define MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK GENMASK(7, 0) +#define MTK_PHY_LPI_SKIP_SD_SLV_TR BIT(8) +#define MTK_PHY_LPI_TR_READY BIT(9) +#define MTK_PHY_LPI_VCO_EEE_STG0_EN BIT(10) + +#define MTK_PHY_RG_DEV1E_REG323 0x323 +#define MTK_PHY_EEE_WAKE_MAS_INT_DC BIT(0) +#define MTK_PHY_EEE_WAKE_SLV_INT_DC BIT(4) + +#define MTK_PHY_RG_DEV1E_REG324 0x324 +#define MTK_PHY_SMI_DETCNT_MAX_MASK GENMASK(5, 0) +#define MTK_PHY_SMI_DET_MAX_EN BIT(8) + +#define MTK_PHY_RG_DEV1E_REG326 0x326 +#define MTK_PHY_LPI_MODE_SD_ON BIT(0) +#define MTK_PHY_RESET_RANDUPD_CNT BIT(1) +#define MTK_PHY_TREC_UPDATE_ENAB_CLR BIT(2) +#define MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF BIT(4) +#define MTK_PHY_TR_READY_SKIP_AFE_WAKEUP BIT(5) + +#define MTK_PHY_LDO_PUMP_EN_PAIRAB 0x502 +#define MTK_PHY_LDO_PUMP_EN_PAIRCD 0x503 + +#define MTK_PHY_DA_TX_R50_PAIR_A 0x53d +#define MTK_PHY_DA_TX_R50_PAIR_B 0x53e +#define MTK_PHY_DA_TX_R50_PAIR_C 0x53f +#define MTK_PHY_DA_TX_R50_PAIR_D 0x540 + +#define MTK_PHY_RG_BG_RASEL 0x115 +#define MTK_PHY_RG_BG_RASEL_MASK GENMASK(2, 0) + +/* These macro privides efuse parsing for internal phy. */ +#define EFS_DA_TX_I2MPB_A(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_B(x) (((x) >> 6) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_C(x) (((x) >> 12) & GENMASK(5, 0)) +#define EFS_DA_TX_I2MPB_D(x) (((x) >> 18) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_A(x) (((x) >> 24) & GENMASK(5, 0)) + +#define EFS_DA_TX_AMP_OFFSET_B(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_C(x) (((x) >> 6) & GENMASK(5, 0)) +#define EFS_DA_TX_AMP_OFFSET_D(x) (((x) >> 12) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_A(x) (((x) >> 18) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_B(x) (((x) >> 24) & GENMASK(5, 0)) + +#define EFS_DA_TX_R50_C(x) (((x) >> 0) & GENMASK(5, 0)) +#define EFS_DA_TX_R50_D(x) (((x) >> 6) & GENMASK(5, 0)) + +#define EFS_RG_BG_RASEL(x) (((x) >> 4) & GENMASK(2, 0)) +#define EFS_RG_REXT_TRIM(x) (((x) >> 7) & GENMASK(5, 0)) + +enum { + NO_PAIR, + PAIR_A, + PAIR_B, + PAIR_C, + PAIR_D, +}; + +enum { + GPHY_PORT0, + GPHY_PORT1, + GPHY_PORT2, + GPHY_PORT3, +}; + +enum calibration_mode { + EFUSE_K, + SW_K +}; + +enum CAL_ITEM { + REXT, + TX_OFFSET, + TX_AMP, + TX_R50, + TX_VCM +}; + +enum CAL_MODE { + EFUSE_M, + SW_M +}; + +static int mtk_socphy_read_page(struct phy_device *phydev) +{ + return __phy_read(phydev, MTK_EXT_PAGE_ACCESS); +} + +static int mtk_socphy_write_page(struct phy_device *phydev, int page) +{ + return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page); +} + +/* One calibration cycle consists of: + * 1.Set DA_CALIN_FLAG high to start calibration. Keep it high + * until AD_CAL_COMP is ready to output calibration result. + * 2.Wait until DA_CAL_CLK is available. + * 3.Fetch AD_CAL_COMP_OUT. + */ +static int cal_cycle(struct phy_device *phydev, int devad, + u32 regnum, u16 mask, u16 cal_val) +{ + int reg_val; + int ret; + + phy_modify_mmd(phydev, devad, regnum, + mask, cal_val); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, + MTK_PHY_DA_CALIN_FLAG); + + ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_AD_CAL_CLK, reg_val, + reg_val & MTK_PHY_DA_CAL_CLK, 500, + ANALOG_INTERNAL_OPERATION_MAX_US, false); + if (ret) { + phydev_err(phydev, "Calibration cycle timeout\n"); + return ret; + } + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN, + MTK_PHY_DA_CALIN_FLAG); + ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >> + MTK_PHY_AD_CAL_COMP_OUT_SHIFT; + phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret); + + return ret; +} + +static int rext_fill_result(struct phy_device *phydev, u16 *buf) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG5, + MTK_PHY_RG_REXT_TRIM_MASK, buf[0] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_RG_BG_RASEL, + MTK_PHY_RG_BG_RASEL_MASK, buf[1]); + + return 0; +} + +static int rext_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 rext_cal_val[2]; + + rext_cal_val[0] = EFS_RG_REXT_TRIM(buf[3]); + rext_cal_val[1] = EFS_RG_BG_RASEL(buf[3]); + rext_fill_result(phydev, rext_cal_val); + + return 0; +} + +static int tx_offset_fill_result(struct phy_device *phydev, u16 *buf) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, + MTK_PHY_CR_TX_AMP_OFFSET_A_MASK, buf[0] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_A_B, + MTK_PHY_CR_TX_AMP_OFFSET_B_MASK, buf[1]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, + MTK_PHY_CR_TX_AMP_OFFSET_C_MASK, buf[2] << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_CR_TX_AMP_OFFSET_C_D, + MTK_PHY_CR_TX_AMP_OFFSET_D_MASK, buf[3]); + + return 0; +} + +static int tx_offset_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 tx_offset_cal_val[4]; + + tx_offset_cal_val[0] = EFS_DA_TX_AMP_OFFSET_A(buf[0]); + tx_offset_cal_val[1] = EFS_DA_TX_AMP_OFFSET_B(buf[1]); + tx_offset_cal_val[2] = EFS_DA_TX_AMP_OFFSET_C(buf[1]); + tx_offset_cal_val[3] = EFS_DA_TX_AMP_OFFSET_D(buf[1]); + + tx_offset_fill_result(phydev, tx_offset_cal_val); + + return 0; +} + +static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf) +{ + int i; + int bias[16] = {}; + const int vals_9461[16] = { 7, 1, 4, 7, + 7, 1, 4, 7, + 7, 1, 4, 7, + 7, 1, 4, 7 }; + const int vals_9481[16] = { 10, 6, 6, 10, + 10, 6, 6, 10, + 10, 6, 6, 10, + 10, 6, 6, 10 }; + switch (phydev->drv->phy_id) { + case MTK_GPHY_ID_MT7981: + /* We add some calibration to efuse values + * due to board level influence. + * GBE: +7, TBT: +1, HBT: +4, TST: +7 + */ + memcpy(bias, (const void *)vals_9461, sizeof(bias)); + break; + case MTK_GPHY_ID_MT7988: + memcpy(bias, (const void *)vals_9481, sizeof(bias)); + break; + } + + /* Prevent overflow */ + for (i = 0; i < 12; i++) { + if (buf[i >> 2] + bias[i] > 63) { + buf[i >> 2] = 63; + bias[i] = 0; + } + } + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, + MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG, + MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, + MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2, + MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, + MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1, + MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, + MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2, + MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, + MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1, + MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, + MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2, + MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, + MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1, + MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, + MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2, + MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]); + + return 0; +} + +static int tx_amp_cal_efuse(struct phy_device *phydev, u32 *buf) +{ + u16 tx_amp_cal_val[4]; + + tx_amp_cal_val[0] = EFS_DA_TX_I2MPB_A(buf[0]); + tx_amp_cal_val[1] = EFS_DA_TX_I2MPB_B(buf[0]); + tx_amp_cal_val[2] = EFS_DA_TX_I2MPB_C(buf[0]); + tx_amp_cal_val[3] = EFS_DA_TX_I2MPB_D(buf[0]); + tx_amp_fill_result(phydev, tx_amp_cal_val); + + return 0; +} + +static int tx_r50_fill_result(struct phy_device *phydev, u16 tx_r50_cal_val, + u8 txg_calen_x) +{ + int bias = 0; + u16 reg, val; + + if (phydev->drv->phy_id == MTK_GPHY_ID_MT7988) + bias = -2; + + val = clamp_val(bias + tx_r50_cal_val, 0, 63); + + switch (txg_calen_x) { + case PAIR_A: + reg = MTK_PHY_DA_TX_R50_PAIR_A; + break; + case PAIR_B: + reg = MTK_PHY_DA_TX_R50_PAIR_B; + break; + case PAIR_C: + reg = MTK_PHY_DA_TX_R50_PAIR_C; + break; + case PAIR_D: + reg = MTK_PHY_DA_TX_R50_PAIR_D; + break; + default: + return -EINVAL; + } + + phy_write_mmd(phydev, MDIO_MMD_VEND1, reg, val | val << 8); + + return 0; +} + +static int tx_r50_cal_efuse(struct phy_device *phydev, u32 *buf, + u8 txg_calen_x) +{ + u16 tx_r50_cal_val; + + switch (txg_calen_x) { + case PAIR_A: + tx_r50_cal_val = EFS_DA_TX_R50_A(buf[1]); + break; + case PAIR_B: + tx_r50_cal_val = EFS_DA_TX_R50_B(buf[1]); + break; + case PAIR_C: + tx_r50_cal_val = EFS_DA_TX_R50_C(buf[2]); + break; + case PAIR_D: + tx_r50_cal_val = EFS_DA_TX_R50_D(buf[2]); + break; + default: + return -EINVAL; + } + tx_r50_fill_result(phydev, tx_r50_cal_val, txg_calen_x); + + return 0; +} + +static int tx_vcm_cal_sw(struct phy_device *phydev, u8 rg_txreserve_x) +{ + u8 lower_idx, upper_idx, txreserve_val; + u8 lower_ret, upper_ret; + int ret; + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ANA_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_CAL_CKINV); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_TXVOS_CALEN); + + switch (rg_txreserve_x) { + case PAIR_A: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_A, + MTK_PHY_DASN_DAC_IN0_A_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_A, + MTK_PHY_DASN_DAC_IN1_A_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ZCALEN_A); + break; + case PAIR_B: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_B, + MTK_PHY_DASN_DAC_IN0_B_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_B, + MTK_PHY_DASN_DAC_IN1_B_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_B); + break; + case PAIR_C: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_C, + MTK_PHY_DASN_DAC_IN0_C_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_C, + MTK_PHY_DASN_DAC_IN1_C_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_C); + break; + case PAIR_D: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN0_D, + MTK_PHY_DASN_DAC_IN0_D_MASK); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DASN_DAC_IN1_D, + MTK_PHY_DASN_DAC_IN1_D_MASK); + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_D); + break; + default: + ret = -EINVAL; + goto restore; + } + + lower_idx = TXRESERVE_MIN; + upper_idx = TXRESERVE_MAX; + + phydev_dbg(phydev, "Start TX-VCM SW cal.\n"); + while ((upper_idx - lower_idx) > 1) { + txreserve_val = DIV_ROUND_CLOSEST(lower_idx + upper_idx, 2); + ret = cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + txreserve_val << 12 | txreserve_val << 8 | + txreserve_val << 4 | txreserve_val); + if (ret == 1) { + upper_idx = txreserve_val; + upper_ret = ret; + } else if (ret == 0) { + lower_idx = txreserve_val; + lower_ret = ret; + } else { + goto restore; + } + } + + if (lower_idx == TXRESERVE_MIN) { + lower_ret = cal_cycle(phydev, MDIO_MMD_VEND1, + MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + lower_idx << 12 | lower_idx << 8 | + lower_idx << 4 | lower_idx); + ret = lower_ret; + } else if (upper_idx == TXRESERVE_MAX) { + upper_ret = cal_cycle(phydev, MDIO_MMD_VEND1, + MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + upper_idx << 12 | upper_idx << 8 | + upper_idx << 4 | upper_idx); + ret = upper_ret; + } + if (ret < 0) + goto restore; + + /* We calibrate TX-VCM in different logic. Check upper index and then + * lower index. If this calibration is valid, apply lower index's result. + */ + ret = upper_ret - lower_ret; + if (ret == 1) { + ret = 0; + /* Make sure we use upper_idx in our calibration system */ + cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + upper_idx << 12 | upper_idx << 8 | + upper_idx << 4 | upper_idx); + phydev_dbg(phydev, "TX-VCM SW cal result: 0x%x\n", upper_idx); + } else if (lower_idx == TXRESERVE_MIN && upper_ret == 1 && + lower_ret == 1) { + ret = 0; + cal_cycle(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG9, + MTK_PHY_DA_RX_PSBN_TBT_MASK | + MTK_PHY_DA_RX_PSBN_HBT_MASK | + MTK_PHY_DA_RX_PSBN_GBE_MASK | + MTK_PHY_DA_RX_PSBN_LP_MASK, + lower_idx << 12 | lower_idx << 8 | + lower_idx << 4 | lower_idx); + phydev_warn(phydev, "TX-VCM SW cal result at low margin 0x%x\n", + lower_idx); + } else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 && + lower_ret == 0) { + ret = 0; + phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n", + upper_idx); + } else { + ret = -EINVAL; + } + +restore: + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ANA_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_TXVOS_CALEN); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG0, + MTK_PHY_RG_ZCALEN_A); + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_ANA_CAL_RG1, + MTK_PHY_RG_ZCALEN_B | MTK_PHY_RG_ZCALEN_C | + MTK_PHY_RG_ZCALEN_D); + + return ret; +} + +static void mt798x_phy_common_finetune(struct phy_device *phydev) +{ + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* EnabRandUpdTrig = 1 */ + __phy_write(phydev, 0x11, 0x2f00); + __phy_write(phydev, 0x12, 0xe); + __phy_write(phydev, 0x10, 0x8fb0); + + /* NormMseLoThresh = 85 */ + __phy_write(phydev, 0x11, 0x55a0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x83aa); + + /* TrFreeze = 0 */ + __phy_write(phydev, 0x11, 0x0); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9686); + + /* SSTrKp1000Slv = 5 */ + __phy_write(phydev, 0x11, 0xbaef); + __phy_write(phydev, 0x12, 0x2e); + __phy_write(phydev, 0x10, 0x968c); + + /* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2, + * MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2 + */ + __phy_write(phydev, 0x11, 0xd10a); + __phy_write(phydev, 0x12, 0x34); + __phy_write(phydev, 0x10, 0x8f82); + + /* VcoSlicerThreshBitsHigh */ + __phy_write(phydev, 0x11, 0x5555); + __phy_write(phydev, 0x12, 0x55); + __phy_write(phydev, 0x10, 0x8ec0); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + /* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9*/ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234, + MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK, + BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9)); + + /* rg_tr_lpf_cnt_val = 512 */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LPF_CNT_VAL, 0x200); + + /* IIR2 related */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_L, 0x82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K1_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_L, 0x103); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K2_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_L, 0x82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K3_U, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_L, 0xd177); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K4_U, 0x3); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_L, 0x2c82); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_LP_IIR2_K5_U, 0xe); + + /* FFE peaking */ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27C, + MTK_PHY_VGASTATE_FFE_THR_ST1_MASK, 0x1b << 8); + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG27D, + MTK_PHY_VGASTATE_FFE_THR_ST2_MASK, 0x1e); + + /* Disable LDO pump */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRAB, 0x0); + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_PUMP_EN_PAIRCD, 0x0); + /* Adjust LDO output voltage */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LDO_OUTPUT_V, 0x2222); +} + +static void mt7981_phy_finetune(struct phy_device *phydev) +{ + u16 val[8] = { 0x01ce, 0x01c1, + 0x020f, 0x0202, + 0x03d0, 0x03c0, + 0x0013, 0x0005 }; + int i, k; + + /* 100M eye finetune: + * Keep middle level of TX MLT3 shapper as default. + * Only change TX MLT3 overshoot level here. + */ + for (k = 0, i = 1; i < 12; i++) { + if (i % 3 == 0) + continue; + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[k++]); + } + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */ + __phy_write(phydev, 0x11, 0xc71); + __phy_write(phydev, 0x12, 0xc); + __phy_write(phydev, 0x10, 0x8fae); + + /* ResetSyncOffset = 6 */ + __phy_write(phydev, 0x11, 0x600); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8fc0); + + /* VgaDecRate = 1 */ + __phy_write(phydev, 0x11, 0x4c2a); + __phy_write(phydev, 0x12, 0x3e); + __phy_write(phydev, 0x10, 0x8fa4); + + /* FfeUpdGainForce = 4 */ + __phy_write(phydev, 0x11, 0x240); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9680); + + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); +} + +static void mt7988_phy_finetune(struct phy_device *phydev) +{ + u16 val[12] = { 0x0187, 0x01cd, 0x01c8, 0x0182, + 0x020d, 0x0206, 0x0384, 0x03d0, + 0x03c6, 0x030a, 0x0011, 0x0005 }; + int i; + + /* Set default MLT3 shaper first */ + for (i = 0; i < 12; i++) + phy_write_mmd(phydev, MDIO_MMD_VEND1, i, val[i]); + + /* TCT finetune */ + phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5); + + /* Disable TX power saving */ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7, + MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3 << 8); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + + /* SlvDSPreadyTime = 24, MasDSPreadyTime = 12 */ + __phy_write(phydev, 0x11, 0x671); + __phy_write(phydev, 0x12, 0xc); + __phy_write(phydev, 0x10, 0x8fae); + + /* ResetSyncOffset = 5 */ + __phy_write(phydev, 0x11, 0x500); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8fc0); + + /* VgaDecRate is 1 at default on mt7988 */ + + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_2A30); + /* TxClkOffset = 2 */ + __phy_modify(phydev, MTK_PHY_ANARG_RG, MTK_PHY_TCLKOFFSET_MASK, + FIELD_PREP(MTK_PHY_TCLKOFFSET_MASK, 0x2)); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); +} + +static void mt798x_phy_eee(struct phy_device *phydev) +{ + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG120, + MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK | + MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_SIG_EN_LO_THRESH1000_MASK, 0x0) | + FIELD_PREP(MTK_PHY_LPI_SIG_EN_HI_THRESH1000_MASK, 0x14)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, + MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + 0xff)); + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_TESTMUX_ADC_CTRL, + MTK_PHY_RG_TXEN_DIG_MASK); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DEV1E_REG19b, MTK_PHY_BYPASS_DSP_LPI_READY); + + phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_DEV1E_REG234, MTK_PHY_TR_LP_IIR_EEE_EN); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG238, + MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK | + MTK_PHY_LPI_SLV_SEND_TX_EN, + FIELD_PREP(MTK_PHY_LPI_SLV_SEND_TX_TIMER_MASK, 0x120)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG239, + MTK_PHY_LPI_SEND_LOC_TIMER_MASK | + MTK_PHY_LPI_TXPCS_LOC_RCV, + FIELD_PREP(MTK_PHY_LPI_SEND_LOC_TIMER_MASK, 0x117)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2C7, + MTK_PHY_MAX_GAIN_MASK | MTK_PHY_MIN_GAIN_MASK, + FIELD_PREP(MTK_PHY_MAX_GAIN_MASK, 0x8) | + FIELD_PREP(MTK_PHY_MIN_GAIN_MASK, 0x13)); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG2D1, + MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, + FIELD_PREP(MTK_PHY_VCO_SLICER_THRESH_BITS_HIGH_EEE_MASK, + 0x33) | + MTK_PHY_LPI_SKIP_SD_SLV_TR | MTK_PHY_LPI_TR_READY | + MTK_PHY_LPI_VCO_EEE_STG0_EN); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG323, + MTK_PHY_EEE_WAKE_MAS_INT_DC | + MTK_PHY_EEE_WAKE_SLV_INT_DC); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG324, + MTK_PHY_SMI_DETCNT_MAX_MASK, + FIELD_PREP(MTK_PHY_SMI_DETCNT_MAX_MASK, 0x3f) | + MTK_PHY_SMI_DET_MAX_EN); + + phy_set_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG326, + MTK_PHY_LPI_MODE_SD_ON | MTK_PHY_RESET_RANDUPD_CNT | + MTK_PHY_TREC_UPDATE_ENAB_CLR | + MTK_PHY_LPI_QUIT_WAIT_DFE_SIG_DET_OFF | + MTK_PHY_TR_READY_SKIP_AFE_WAKEUP); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5); + /* Regsigdet_sel_1000 = 0 */ + __phy_write(phydev, 0x11, 0xb); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x9690); + + /* REG_EEE_st2TrKf1000 = 3 */ + __phy_write(phydev, 0x11, 0x114f); + __phy_write(phydev, 0x12, 0x2); + __phy_write(phydev, 0x10, 0x969a); + + /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */ + __phy_write(phydev, 0x11, 0x3028); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x969e); + + /* RegEEE_slv_wake_int_timer_tar = 8 */ + __phy_write(phydev, 0x11, 0x5010); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96a0); + + /* RegEEE_trfreeze_timer2 = 586 */ + __phy_write(phydev, 0x11, 0x24a); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96a8); + + /* RegEEE100Stg1_tar = 16 */ + __phy_write(phydev, 0x11, 0x3210); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96b8); + + /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 1 */ + __phy_write(phydev, 0x11, 0x1463); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x96ca); + + /* DfeTailEnableVgaThresh1000 = 27 */ + __phy_write(phydev, 0x11, 0x36); + __phy_write(phydev, 0x12, 0x0); + __phy_write(phydev, 0x10, 0x8f80); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3); + __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK, + FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c)); + + __phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK, + FIELD_PREP(MTK_PHY_SMI_DET_ON_THRESH_MASK, 0xc)); + phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0); + + phy_modify_mmd(phydev, MDIO_MMD_VEND1, + MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122, + MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, + FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff)); +} + +static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item, + u8 start_pair, u8 end_pair) +{ + u8 pair_n; + int ret; + + for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { + /* TX_OFFSET & TX_AMP have no SW calibration. */ + switch (cal_item) { + case TX_VCM: + ret = tx_vcm_cal_sw(phydev, pair_n); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + } + return 0; +} + +static int cal_efuse(struct phy_device *phydev, enum CAL_ITEM cal_item, + u8 start_pair, u8 end_pair, u32 *buf) +{ + u8 pair_n; + int ret; + + for (pair_n = start_pair; pair_n <= end_pair; pair_n++) { + /* TX_VCM has no efuse calibration. */ + switch (cal_item) { + case REXT: + ret = rext_cal_efuse(phydev, buf); + break; + case TX_OFFSET: + ret = tx_offset_cal_efuse(phydev, buf); + break; + case TX_AMP: + ret = tx_amp_cal_efuse(phydev, buf); + break; + case TX_R50: + ret = tx_r50_cal_efuse(phydev, buf, pair_n); + break; + default: + return -EINVAL; + } + if (ret) + return ret; + } + + return 0; +} + +static int start_cal(struct phy_device *phydev, enum CAL_ITEM cal_item, + enum CAL_MODE cal_mode, u8 start_pair, + u8 end_pair, u32 *buf) +{ + int ret; + + switch (cal_mode) { + case EFUSE_M: + ret = cal_efuse(phydev, cal_item, start_pair, + end_pair, buf); + break; + case SW_M: + ret = cal_sw(phydev, cal_item, start_pair, end_pair); + break; + default: + return -EINVAL; + } + + if (ret) { + phydev_err(phydev, "cal %d failed\n", cal_item); + return -EIO; + } + + return 0; +} + +static int mt798x_phy_calibration(struct phy_device *phydev) +{ + int ret = 0; + u32 *buf; + size_t len; + struct nvmem_cell *cell; + + cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data"); + if (IS_ERR(cell)) { + if (PTR_ERR(cell) == -EPROBE_DEFER) + return PTR_ERR(cell); + return 0; + } + + buf = (u32 *)nvmem_cell_read(cell, &len); + if (IS_ERR(buf)) + return PTR_ERR(buf); + nvmem_cell_put(cell); + + if (!buf[0] || !buf[1] || !buf[2] || !buf[3] || len < 4 * sizeof(u32)) { + phydev_err(phydev, "invalid efuse data\n"); + ret = -EINVAL; + goto out; + } + + ret = start_cal(phydev, REXT, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_OFFSET, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_AMP, EFUSE_M, NO_PAIR, NO_PAIR, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_R50, EFUSE_M, PAIR_A, PAIR_D, buf); + if (ret) + goto out; + ret = start_cal(phydev, TX_VCM, SW_M, PAIR_A, PAIR_A, buf); + if (ret) + goto out; + +out: + kfree(buf); + return ret; +} + +static int mt798x_phy_config_init(struct phy_device *phydev) +{ + switch (phydev->drv->phy_id) { + case MTK_GPHY_ID_MT7981: + mt7981_phy_finetune(phydev); + break; + case MTK_GPHY_ID_MT7988: + mt7988_phy_finetune(phydev); + break; + } + + mt798x_phy_common_finetune(phydev); + mt798x_phy_eee(phydev); + + return mt798x_phy_calibration(phydev); +} + +static struct phy_driver mtk_socphy_driver[] = { + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981), + .name = "MediaTek MT7981 PHY", + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, + .probe = mt798x_phy_calibration, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, + }, + { + PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988), + .name = "MediaTek MT7988 PHY", + .config_init = mt798x_phy_config_init, + .config_intr = genphy_no_config_intr, + .handle_interrupt = genphy_handle_interrupt_no_ack, + .probe = mt798x_phy_calibration, + .suspend = genphy_suspend, + .resume = genphy_resume, + .read_page = mtk_socphy_read_page, + .write_page = mtk_socphy_write_page, + }, +}; + +module_phy_driver(mtk_socphy_driver); + +static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = { + { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) }, + { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) }, + { } +}; + +MODULE_DESCRIPTION("MediaTek SoC Gigabit Ethernet PHY driver"); +MODULE_AUTHOR("Daniel Golle "); +MODULE_AUTHOR("SkyLake Huang "); +MODULE_LICENSE("GPL"); + +MODULE_DEVICE_TABLE(mdio, mtk_socphy_tbl); diff --git a/drivers/net/phy/mediatek-ge.c b/drivers/net/phy/mediatek-ge.c index 68ee434f9dea31..a493ae01b267a2 100644 --- a/drivers/net/phy/mediatek-ge.c +++ b/drivers/net/phy/mediatek-ge.c @@ -102,7 +102,8 @@ static struct phy_driver mtk_gephy_driver[] = { module_phy_driver(mtk_gephy_driver); static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = { - { PHY_ID_MATCH_VENDOR(0x03a29400) }, + { PHY_ID_MATCH_EXACT(0x03a29441) }, + { PHY_ID_MATCH_EXACT(0x03a29412) }, { } }; diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 3f81bb8dac44d6..6d18ea19e4421f 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -637,7 +637,7 @@ static int ksz8051_ksz8795_match_phy_device(struct phy_device *phydev, { int ret; - if ((phydev->phy_id & MICREL_PHY_ID_MASK) != PHY_ID_KSZ8051) + if (!phy_id_compare(phydev->phy_id, PHY_ID_KSZ8051, MICREL_PHY_ID_MASK)) return 0; ret = phy_read(phydev, MII_BMSR); @@ -1566,7 +1566,7 @@ static int ksz9x31_cable_test_fault_length(struct phy_device *phydev, u16 stat) * * distance to fault = (VCT_DATA - 22) * 4 / cable propagation velocity */ - if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_KSZ9131) + if (phydev_id_compare(phydev, PHY_ID_KSZ9131)) dt = clamp(dt - 22, 0, 255); return (dt * 400) / 10; @@ -1774,6 +1774,79 @@ static int ksz886x_read_status(struct phy_device *phydev) return genphy_read_status(phydev); } +struct ksz9477_errata_write { + u8 dev_addr; + u8 reg_addr; + u16 val; +}; + +static const struct ksz9477_errata_write ksz9477_errata_writes[] = { + /* Register settings are needed to improve PHY receive performance */ + {0x01, 0x6f, 0xdd0b}, + {0x01, 0x8f, 0x6032}, + {0x01, 0x9d, 0x248c}, + {0x01, 0x75, 0x0060}, + {0x01, 0xd3, 0x7777}, + {0x1c, 0x06, 0x3008}, + {0x1c, 0x08, 0x2000}, + + /* Transmit waveform amplitude can be improved (1000BASE-T, 100BASE-TX, 10BASE-Te) */ + {0x1c, 0x04, 0x00d0}, + + /* Energy Efficient Ethernet (EEE) feature select must be manually disabled */ + {0x07, 0x3c, 0x0000}, + + /* Register settings are required to meet data sheet supply current specifications */ + {0x1c, 0x13, 0x6eff}, + {0x1c, 0x14, 0xe6ff}, + {0x1c, 0x15, 0x6eff}, + {0x1c, 0x16, 0xe6ff}, + {0x1c, 0x17, 0x00ff}, + {0x1c, 0x18, 0x43ff}, + {0x1c, 0x19, 0xc3ff}, + {0x1c, 0x1a, 0x6fff}, + {0x1c, 0x1b, 0x07ff}, + {0x1c, 0x1c, 0x0fff}, + {0x1c, 0x1d, 0xe7ff}, + {0x1c, 0x1e, 0xefff}, + {0x1c, 0x20, 0xeeee}, +}; + +static int ksz9477_config_init(struct phy_device *phydev) +{ + int err; + int i; + + /* Apply PHY settings to address errata listed in + * KSZ9477, KSZ9897, KSZ9896, KSZ9567, KSZ8565 + * Silicon Errata and Data Sheet Clarification documents. + * + * Document notes: Before configuring the PHY MMD registers, it is + * necessary to set the PHY to 100 Mbps speed with auto-negotiation + * disabled by writing to register 0xN100-0xN101. After writing the + * MMD registers, and after all errata workarounds that involve PHY + * register settings, write register 0xN100-0xN101 again to enable + * and restart auto-negotiation. + */ + err = phy_write(phydev, MII_BMCR, BMCR_SPEED100 | BMCR_FULLDPLX); + if (err) + return err; + + for (i = 0; i < ARRAY_SIZE(ksz9477_errata_writes); ++i) { + const struct ksz9477_errata_write *errata = &ksz9477_errata_writes[i]; + + err = phy_write_mmd(phydev, errata->dev_addr, errata->reg_addr, errata->val); + if (err) + return err; + } + + err = genphy_restart_aneg(phydev); + if (err) + return err; + + return kszphy_config_init(phydev); +} + static int kszphy_get_sset_count(struct phy_device *phydev) { return ARRAY_SIZE(kszphy_hw_stats); @@ -1998,7 +2071,7 @@ static __always_inline int ksz886x_cable_test_fault_length(struct phy_device *ph */ dt = FIELD_GET(data_mask, status); - if ((phydev->phy_id & MICREL_PHY_ID_MASK) == PHY_ID_LAN8814) + if (phydev_id_compare(phydev, PHY_ID_LAN8814)) return ((dt - 22) * 800) / 10; else return (dt * 400) / 10; @@ -4735,7 +4808,7 @@ static struct phy_driver ksphy_driver[] = { .phy_id_mask = MICREL_PHY_ID_MASK, .name = "Microchip KSZ9477", /* PHY_GBIT_FEATURES */ - .config_init = kszphy_config_init, + .config_init = ksz9477_config_init, .config_intr = kszphy_config_intr, .handle_interrupt = kszphy_handle_interrupt, .suspend = genphy_suspend, diff --git a/drivers/net/phy/microchip_t1s.c b/drivers/net/phy/microchip_t1s.c index 094967b3c1117e..534ca7d1b061dd 100644 --- a/drivers/net/phy/microchip_t1s.c +++ b/drivers/net/phy/microchip_t1s.c @@ -1,19 +1,29 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * Driver for Microchip 10BASE-T1S LAN867X PHY + * Driver for Microchip 10BASE-T1S PHYs * * Support: Microchip Phys: - * lan8670, lan8671, lan8672 + * lan8670/1/2 Rev.B1 + * lan8650/1 Rev.B0 Internal PHYs */ #include #include #include -#define PHY_ID_LAN867X 0x0007C160 +#define PHY_ID_LAN867X_REVB1 0x0007C162 +#define PHY_ID_LAN865X_REVB0 0x0007C1B3 -#define LAN867X_REG_IRQ_1_CTL 0x001C -#define LAN867X_REG_IRQ_2_CTL 0x001D +#define LAN867X_REG_STS2 0x0019 + +#define LAN867x_RESET_COMPLETE_STS BIT(11) + +#define LAN865X_REG_CFGPARAM_ADDR 0x00D8 +#define LAN865X_REG_CFGPARAM_DATA 0x00D9 +#define LAN865X_REG_CFGPARAM_CTRL 0x00DA +#define LAN865X_REG_STS2 0x0019 + +#define LAN865X_CFGPARAM_READ_ENABLE BIT(1) /* The arrays below are pulled from the following table from AN1699 * Access MMD Address Value Mask @@ -31,72 +41,219 @@ * W 0x1F 0x0099 0x7F80 ------ */ -static const int lan867x_fixup_registers[12] = { +static const u32 lan867x_revb1_fixup_registers[12] = { 0x00D0, 0x00D1, 0x0084, 0x0085, 0x008A, 0x0087, 0x0088, 0x008B, 0x0080, 0x00F1, 0x0096, 0x0099, }; -static const int lan867x_fixup_values[12] = { +static const u16 lan867x_revb1_fixup_values[12] = { 0x0002, 0x0000, 0x3380, 0x0006, 0xC000, 0x801C, 0x033F, 0x0404, 0x0600, 0x2400, 0x2000, 0x7F80, }; -static const int lan867x_fixup_masks[12] = { +static const u16 lan867x_revb1_fixup_masks[12] = { 0x0E03, 0x0300, 0xFFC0, 0x000F, 0xF800, 0x801C, 0x1FFF, 0xFFFF, 0x0600, 0x7F00, 0x2000, 0xFFFF, }; -static int lan867x_config_init(struct phy_device *phydev) +/* LAN865x Rev.B0 configuration parameters from AN1760 */ +static const u32 lan865x_revb0_fixup_registers[28] = { + 0x0091, 0x0081, 0x0043, 0x0044, + 0x0045, 0x0053, 0x0054, 0x0055, + 0x0040, 0x0050, 0x00D0, 0x00E9, + 0x00F5, 0x00F4, 0x00F8, 0x00F9, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, + 0x00B4, 0x00B5, 0x00B6, 0x00B7, + 0x00B8, 0x00B9, 0x00BA, 0x00BB, +}; + +static const u16 lan865x_revb0_fixup_values[28] = { + 0x9660, 0x00C0, 0x00FF, 0xFFFF, + 0x0000, 0x00FF, 0xFFFF, 0x0000, + 0x0002, 0x0002, 0x5F21, 0x9E50, + 0x1CF8, 0xC020, 0x9B00, 0x4E53, + 0x0103, 0x0910, 0x1D26, 0x002A, + 0x0103, 0x070D, 0x1720, 0x0027, + 0x0509, 0x0E13, 0x1C25, 0x002B, +}; + +static const u16 lan865x_revb0_fixup_cfg_regs[5] = { + 0x0084, 0x008A, 0x00AD, 0x00AE, 0x00AF +}; + +/* Pulled from AN1760 describing 'indirect read' + * + * write_register(0x4, 0x00D8, addr) + * write_register(0x4, 0x00DA, 0x2) + * return (int8)(read_register(0x4, 0x00D9)) + * + * 0x4 refers to memory map selector 4, which maps to MDIO_MMD_VEND2 + */ +static int lan865x_revb0_indirect_read(struct phy_device *phydev, u16 addr) +{ + int ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_ADDR, + addr); + if (ret) + return ret; + + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_CTRL, + LAN865X_CFGPARAM_READ_ENABLE); + if (ret) + return ret; + + return phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN865X_REG_CFGPARAM_DATA); +} + +/* This is pulled straight from AN1760 from 'calculation of offset 1' & + * 'calculation of offset 2' + */ +static int lan865x_generate_cfg_offsets(struct phy_device *phydev, s8 offsets[2]) +{ + const u16 fixup_regs[2] = {0x0004, 0x0008}; + int ret; + + for (int i = 0; i < ARRAY_SIZE(fixup_regs); i++) { + ret = lan865x_revb0_indirect_read(phydev, fixup_regs[i]); + if (ret < 0) + return ret; + if (ret & BIT(4)) + offsets[i] = ret | 0xE0; + else + offsets[i] = ret; + } + + return 0; +} + +static int lan865x_read_cfg_params(struct phy_device *phydev, u16 cfg_params[]) +{ + int ret; + + for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) { + ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, + lan865x_revb0_fixup_cfg_regs[i]); + if (ret < 0) + return ret; + cfg_params[i] = (u16)ret; + } + + return 0; +} + +static int lan865x_write_cfg_params(struct phy_device *phydev, u16 cfg_params[]) { - /* HW quirk: Microchip states in the application note (AN1699) for the phy - * that a set of read-modify-write (rmw) operations has to be performed - * on a set of seemingly magic registers. - * The result of these operations is just described as 'optimal performance' - * Microchip gives no explanation as to what these mmd regs do, - * in fact they are marked as reserved in the datasheet. - * It is unclear if phy_modify_mmd would be safe to use or if a write - * really has to happen to each register. - * In order to exactly conform to what is stated in the AN phy_write_mmd is - * used, which might then write the same value back as read + modified. + int ret; + + for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs); i++) { + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, + lan865x_revb0_fixup_cfg_regs[i], + cfg_params[i]); + if (ret) + return ret; + } + + return 0; +} + +static int lan865x_setup_cfgparam(struct phy_device *phydev) +{ + u16 cfg_params[ARRAY_SIZE(lan865x_revb0_fixup_cfg_regs)]; + u16 cfg_results[5]; + s8 offsets[2]; + int ret; + + ret = lan865x_generate_cfg_offsets(phydev, offsets); + if (ret) + return ret; + + ret = lan865x_read_cfg_params(phydev, cfg_params); + if (ret) + return ret; + + cfg_results[0] = (cfg_params[0] & 0x000F) | + FIELD_PREP(GENMASK(15, 10), 9 + offsets[0]) | + FIELD_PREP(GENMASK(15, 4), 14 + offsets[0]); + cfg_results[1] = (cfg_params[1] & 0x03FF) | + FIELD_PREP(GENMASK(15, 10), 40 + offsets[1]); + cfg_results[2] = (cfg_params[2] & 0xC0C0) | + FIELD_PREP(GENMASK(15, 8), 5 + offsets[0]) | + (9 + offsets[0]); + cfg_results[3] = (cfg_params[3] & 0xC0C0) | + FIELD_PREP(GENMASK(15, 8), 9 + offsets[0]) | + (14 + offsets[0]); + cfg_results[4] = (cfg_params[4] & 0xC0C0) | + FIELD_PREP(GENMASK(15, 8), 17 + offsets[0]) | + (22 + offsets[0]); + + return lan865x_write_cfg_params(phydev, cfg_results); +} + +static int lan865x_revb0_config_init(struct phy_device *phydev) +{ + int ret; + + /* Reference to AN1760 + * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8650-1-Configuration-60001760.pdf + */ + for (int i = 0; i < ARRAY_SIZE(lan865x_revb0_fixup_registers); i++) { + ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, + lan865x_revb0_fixup_registers[i], + lan865x_revb0_fixup_values[i]); + if (ret) + return ret; + } + /* Function to calculate and write the configuration parameters in the + * 0x0084, 0x008A, 0x00AD, 0x00AE and 0x00AF registers (from AN1760) */ + return lan865x_setup_cfgparam(phydev); +} - int reg_value; +static int lan867x_revb1_config_init(struct phy_device *phydev) +{ int err; - int reg; - /* Read-Modified Write Pseudocode (from AN1699) - * current_val = read_register(mmd, addr) // Read current register value - * new_val = current_val AND (NOT mask) // Clear bit fields to be written - * new_val = new_val OR value // Set bits - * write_register(mmd, addr, new_val) // Write back updated register value + /* The chip completes a reset in 3us, we might get here earlier than + * that, as an added margin we'll conditionally sleep 5us. */ - for (int i = 0; i < ARRAY_SIZE(lan867x_fixup_registers); i++) { - reg = lan867x_fixup_registers[i]; - reg_value = phy_read_mmd(phydev, MDIO_MMD_VEND2, reg); - reg_value &= ~lan867x_fixup_masks[i]; - reg_value |= lan867x_fixup_values[i]; - err = phy_write_mmd(phydev, MDIO_MMD_VEND2, reg, reg_value); - if (err != 0) + err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2); + if (err < 0) + return err; + + if (!(err & LAN867x_RESET_COMPLETE_STS)) { + udelay(5); + err = phy_read_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_STS2); + if (err < 0) return err; + if (!(err & LAN867x_RESET_COMPLETE_STS)) { + phydev_err(phydev, "PHY reset failed\n"); + return -ENODEV; + } } - /* None of the interrupts in the lan867x phy seem relevant. - * Other phys inspect the link status and call phy_trigger_machine - * in the interrupt handler. - * This phy does not support link status, and thus has no interrupt - * for it either. - * So we'll just disable all interrupts on the chip. + /* Reference to AN1699 + * https://ww1.microchip.com/downloads/aemDocuments/documents/AIS/ProductDocuments/SupportingCollateral/AN-LAN8670-1-2-config-60001699.pdf + * AN1699 says Read, Modify, Write, but the Write is not required if the + * register already has the required value. So it is safe to use + * phy_modify_mmd here. */ - err = phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_1_CTL, 0xFFFF); - if (err != 0) - return err; - return phy_write_mmd(phydev, MDIO_MMD_VEND2, LAN867X_REG_IRQ_2_CTL, 0xFFFF); + for (int i = 0; i < ARRAY_SIZE(lan867x_revb1_fixup_registers); i++) { + err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, + lan867x_revb1_fixup_registers[i], + lan867x_revb1_fixup_masks[i], + lan867x_revb1_fixup_values[i]); + if (err) + return err; + } + + return 0; } -static int lan867x_read_status(struct phy_device *phydev) +static int lan86xx_read_status(struct phy_device *phydev) { /* The phy has some limitations, namely: * - always reports link up @@ -111,28 +268,39 @@ static int lan867x_read_status(struct phy_device *phydev) return 0; } -static struct phy_driver lan867x_driver[] = { +static struct phy_driver microchip_t1s_driver[] = { { - PHY_ID_MATCH_MODEL(PHY_ID_LAN867X), - .name = "LAN867X", + PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1), + .name = "LAN867X Rev.B1", .features = PHY_BASIC_T1S_P2MP_FEATURES, - .config_init = lan867x_config_init, - .read_status = lan867x_read_status, + .config_init = lan867x_revb1_config_init, + .read_status = lan86xx_read_status, .get_plca_cfg = genphy_c45_plca_get_cfg, .set_plca_cfg = genphy_c45_plca_set_cfg, .get_plca_status = genphy_c45_plca_get_status, - } + }, + { + PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0), + .name = "LAN865X Rev.B0 Internal Phy", + .features = PHY_BASIC_T1S_P2MP_FEATURES, + .config_init = lan865x_revb0_config_init, + .read_status = lan86xx_read_status, + .get_plca_cfg = genphy_c45_plca_get_cfg, + .set_plca_cfg = genphy_c45_plca_set_cfg, + .get_plca_status = genphy_c45_plca_get_status, + }, }; -module_phy_driver(lan867x_driver); +module_phy_driver(microchip_t1s_driver); static struct mdio_device_id __maybe_unused tbl[] = { - { PHY_ID_MATCH_MODEL(PHY_ID_LAN867X) }, + { PHY_ID_MATCH_EXACT(PHY_ID_LAN867X_REVB1) }, + { PHY_ID_MATCH_EXACT(PHY_ID_LAN865X_REVB0) }, { } }; MODULE_DEVICE_TABLE(mdio, tbl); -MODULE_DESCRIPTION("Microchip 10BASE-T1S lan867x Phy driver"); +MODULE_DESCRIPTION("Microchip 10BASE-T1S PHYs driver"); MODULE_AUTHOR("Ramón Nordin Rodriguez"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/phy/mscc/mscc.h b/drivers/net/phy/mscc/mscc.h index a50235fdf7d99d..7a962050a4d45e 100644 --- a/drivers/net/phy/mscc/mscc.h +++ b/drivers/net/phy/mscc/mscc.h @@ -179,6 +179,7 @@ enum rgmii_clock_delay { #define VSC8502_RGMII_CNTL 20 #define VSC8502_RGMII_RX_DELAY_MASK 0x0070 #define VSC8502_RGMII_TX_DELAY_MASK 0x0007 +#define VSC8502_RGMII_RX_CLK_DISABLE 0x0800 #define MSCC_PHY_WOL_LOWER_MAC_ADDR 21 #define MSCC_PHY_WOL_MID_MAC_ADDR 22 @@ -276,6 +277,7 @@ enum rgmii_clock_delay { /* Microsemi PHY ID's * Code assumes lowest nibble is 0 */ +#define PHY_ID_VSC8501 0x00070530 #define PHY_ID_VSC8502 0x00070630 #define PHY_ID_VSC8504 0x000704c0 #define PHY_ID_VSC8514 0x00070670 @@ -290,6 +292,7 @@ enum rgmii_clock_delay { #define PHY_ID_VSC8575 0x000707d0 #define PHY_ID_VSC8582 0x000707b0 #define PHY_ID_VSC8584 0x000707c0 +#define PHY_VENDOR_MSCC 0x00070400 #define MSCC_VDDMAC_1500 1500 #define MSCC_VDDMAC_1800 1800 diff --git a/drivers/net/phy/mscc/mscc_main.c b/drivers/net/phy/mscc/mscc_main.c index 62bf99e45af16d..669a4a7a28ce93 100644 --- a/drivers/net/phy/mscc/mscc_main.c +++ b/drivers/net/phy/mscc/mscc_main.c @@ -107,6 +107,9 @@ static const struct vsc8531_edge_rate_table edge_table[] = { }; #endif +static const int vsc85xx_internal_delay[] = {200, 800, 1100, 1700, 2000, 2300, + 2600, 3400}; + static int vsc85xx_phy_read_page(struct phy_device *phydev) { return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS); @@ -519,49 +522,69 @@ static int vsc85xx_mac_if_set(struct phy_device *phydev, * * 2.0 ns (which causes the data to be sampled at exactly half way between * clock transitions at 1000 Mbps) if delays should be enabled */ -static int vsc85xx_rgmii_set_skews(struct phy_device *phydev, u32 rgmii_cntl, - u16 rgmii_rx_delay_mask, - u16 rgmii_tx_delay_mask) +static int vsc85xx_update_rgmii_cntl(struct phy_device *phydev, u32 rgmii_cntl, + u16 rgmii_rx_delay_mask, + u16 rgmii_tx_delay_mask) { u16 rgmii_rx_delay_pos = ffs(rgmii_rx_delay_mask) - 1; u16 rgmii_tx_delay_pos = ffs(rgmii_tx_delay_mask) - 1; + int delay_size = ARRAY_SIZE(vsc85xx_internal_delay); + struct device *dev = &phydev->mdio.dev; u16 reg_val = 0; - int rc; + u16 mask = 0; + s32 rx_delay; + s32 tx_delay; + int rc = 0; - mutex_lock(&phydev->lock); + /* For traffic to pass, the VSC8502 family needs the RX_CLK disable bit + * to be unset for all PHY modes, so do that as part of the paged + * register modification. + * For some family members (like VSC8530/31/40/41) this bit is reserved + * and read-only, and the RX clock is enabled by default. + */ + if (rgmii_cntl == VSC8502_RGMII_CNTL) + mask |= VSC8502_RGMII_RX_CLK_DISABLE; + + if (phy_interface_is_rgmii(phydev)) + mask |= rgmii_rx_delay_mask | rgmii_tx_delay_mask; + + rx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay, + delay_size, true); + if (rx_delay < 0) { + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + rx_delay = RGMII_CLK_DELAY_2_0_NS; + else + rx_delay = RGMII_CLK_DELAY_0_2_NS; + } - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_rx_delay_pos; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || - phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg_val |= RGMII_CLK_DELAY_2_0_NS << rgmii_tx_delay_pos; + tx_delay = phy_get_internal_delay(phydev, dev, vsc85xx_internal_delay, + delay_size, false); + if (tx_delay < 0) { + if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID || + phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) + rx_delay = RGMII_CLK_DELAY_2_0_NS; + else + rx_delay = RGMII_CLK_DELAY_0_2_NS; + } - rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, - rgmii_cntl, - rgmii_rx_delay_mask | rgmii_tx_delay_mask, - reg_val); + reg_val |= rx_delay << rgmii_rx_delay_pos; + reg_val |= tx_delay << rgmii_tx_delay_pos; - mutex_unlock(&phydev->lock); + if (mask) + rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, + rgmii_cntl, mask, reg_val); return rc; } static int vsc85xx_default_config(struct phy_device *phydev) { - int rc; - phydev->mdix_ctrl = ETH_TP_MDI_AUTO; - if (phy_interface_mode_is_rgmii(phydev->interface)) { - rc = vsc85xx_rgmii_set_skews(phydev, VSC8502_RGMII_CNTL, - VSC8502_RGMII_RX_DELAY_MASK, - VSC8502_RGMII_TX_DELAY_MASK); - if (rc) - return rc; - } - - return 0; + return vsc85xx_update_rgmii_cntl(phydev, VSC8502_RGMII_CNTL, + VSC8502_RGMII_RX_DELAY_MASK, + VSC8502_RGMII_TX_DELAY_MASK); } static int vsc85xx_get_tunable(struct phy_device *phydev, @@ -1758,13 +1781,11 @@ static int vsc8584_config_init(struct phy_device *phydev) if (ret) return ret; - if (phy_interface_is_rgmii(phydev)) { - ret = vsc85xx_rgmii_set_skews(phydev, VSC8572_RGMII_CNTL, - VSC8572_RGMII_RX_DELAY_MASK, - VSC8572_RGMII_TX_DELAY_MASK); - if (ret) - return ret; - } + ret = vsc85xx_update_rgmii_cntl(phydev, VSC8572_RGMII_CNTL, + VSC8572_RGMII_RX_DELAY_MASK, + VSC8572_RGMII_TX_DELAY_MASK); + if (ret) + return ret; ret = genphy_soft_reset(phydev); if (ret) @@ -2316,6 +2337,30 @@ static int vsc85xx_probe(struct phy_device *phydev) /* Microsemi VSC85xx PHYs */ static struct phy_driver vsc85xx_driver[] = { +{ + .phy_id = PHY_ID_VSC8501, + .name = "Microsemi GE VSC8501 SyncE", + .phy_id_mask = 0xfffffff0, + /* PHY_BASIC_FEATURES */ + .soft_reset = &genphy_soft_reset, + .config_init = &vsc85xx_config_init, + .config_aneg = &vsc85xx_config_aneg, + .read_status = &vsc85xx_read_status, + .handle_interrupt = vsc85xx_handle_interrupt, + .config_intr = &vsc85xx_config_intr, + .suspend = &genphy_suspend, + .resume = &genphy_resume, + .probe = &vsc85xx_probe, + .set_wol = &vsc85xx_wol_set, + .get_wol = &vsc85xx_wol_get, + .get_tunable = &vsc85xx_get_tunable, + .set_tunable = &vsc85xx_set_tunable, + .read_page = &vsc85xx_phy_read_page, + .write_page = &vsc85xx_phy_write_page, + .get_sset_count = &vsc85xx_get_sset_count, + .get_strings = &vsc85xx_get_strings, + .get_stats = &vsc85xx_get_stats, +}, { .phy_id = PHY_ID_VSC8502, .name = "Microsemi GE VSC8502 SyncE", @@ -2656,19 +2701,7 @@ static struct phy_driver vsc85xx_driver[] = { module_phy_driver(vsc85xx_driver); static struct mdio_device_id __maybe_unused vsc85xx_tbl[] = { - { PHY_ID_VSC8504, 0xfffffff0, }, - { PHY_ID_VSC8514, 0xfffffff0, }, - { PHY_ID_VSC8530, 0xfffffff0, }, - { PHY_ID_VSC8531, 0xfffffff0, }, - { PHY_ID_VSC8540, 0xfffffff0, }, - { PHY_ID_VSC8541, 0xfffffff0, }, - { PHY_ID_VSC8552, 0xfffffff0, }, - { PHY_ID_VSC856X, 0xfffffff0, }, - { PHY_ID_VSC8572, 0xfffffff0, }, - { PHY_ID_VSC8574, 0xfffffff0, }, - { PHY_ID_VSC8575, 0xfffffff0, }, - { PHY_ID_VSC8582, 0xfffffff0, }, - { PHY_ID_VSC8584, 0xfffffff0, }, + { PHY_ID_MATCH_VENDOR(PHY_VENDOR_MSCC) }, { } }; diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c index 6301a9abfb9559..ea1073adc5a16a 100644 --- a/drivers/net/phy/mxl-gpy.c +++ b/drivers/net/phy/mxl-gpy.c @@ -274,13 +274,6 @@ static int gpy_config_init(struct phy_device *phydev) return ret < 0 ? ret : 0; } -static bool gpy_has_broken_mdint(struct phy_device *phydev) -{ - /* At least these PHYs are known to have broken interrupt handling */ - return phydev->drv->phy_id == PHY_ID_GPY215B || - phydev->drv->phy_id == PHY_ID_GPY215C; -} - static int gpy_probe(struct phy_device *phydev) { struct device *dev = &phydev->mdio.dev; @@ -300,8 +293,7 @@ static int gpy_probe(struct phy_device *phydev) phydev->priv = priv; mutex_init(&priv->mbox_lock); - if (gpy_has_broken_mdint(phydev) && - !device_property_present(dev, "maxlinear,use-broken-interrupts")) + if (!device_property_present(dev, "maxlinear,use-broken-interrupts")) phydev->dev_flags |= PHY_F_NO_IRQ; fw_version = phy_read(phydev, PHY_FWV); @@ -659,11 +651,9 @@ static irqreturn_t gpy_handle_interrupt(struct phy_device *phydev) * frame. Therefore, polling is the best we can do and won't do any more * harm. * It was observed that this bug happens on link state and link speed - * changes on a GPY215B and GYP215C independent of the firmware version - * (which doesn't mean that this list is exhaustive). + * changes independent of the firmware version. */ - if (gpy_has_broken_mdint(phydev) && - (reg & (PHY_IMASK_LSTC | PHY_IMASK_LSPC))) { + if (reg & (PHY_IMASK_LSTC | PHY_IMASK_LSPC)) { reg = gpy_mbox_read(phydev, REG_GPIO0_OUT); if (reg < 0) { phy_error(phydev); diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 0c0df38cd1ab8a..bdf00b2b2c1dc3 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -52,6 +52,7 @@ static const char *phy_state_to_str(enum phy_state st) PHY_STATE_STR(NOLINK) PHY_STATE_STR(CABLETEST) PHY_STATE_STR(HALTED) + PHY_STATE_STR(ERROR) } return NULL; @@ -1184,7 +1185,7 @@ void phy_stop_machine(struct phy_device *phydev) static void phy_process_error(struct phy_device *phydev) { mutex_lock(&phydev->lock); - phydev->state = PHY_HALTED; + phydev->state = PHY_ERROR; mutex_unlock(&phydev->lock); phy_trigger_machine(phydev); @@ -1198,10 +1199,10 @@ static void phy_error_precise(struct phy_device *phydev, } /** - * phy_error - enter HALTED state for this PHY device + * phy_error - enter ERROR state for this PHY device * @phydev: target phy_device struct * - * Moves the PHY to the HALTED state in response to a read + * Moves the PHY to the ERROR state in response to a read * or write error, and tells the controller the link is down. * Must not be called from interrupt context, or while the * phydev->lock is held. @@ -1326,7 +1327,8 @@ void phy_stop(struct phy_device *phydev) struct net_device *dev = phydev->attached_dev; enum phy_state old_state; - if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) { + if (!phy_is_started(phydev) && phydev->state != PHY_DOWN && + phydev->state != PHY_ERROR) { WARN(1, "called from state %s\n", phy_state_to_str(phydev->state)); return; @@ -1443,6 +1445,7 @@ void phy_state_machine(struct work_struct *work) } break; case PHY_HALTED: + case PHY_ERROR: if (phydev->link) { phydev->link = 0; phy_link_down(phydev); diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8852b0c5311468..2cad9cc3f6b805 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -454,8 +454,7 @@ int phy_unregister_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask) fixup = list_entry(pos, struct phy_fixup, list); if ((!strcmp(fixup->bus_id, bus_id)) && - ((fixup->phy_uid & phy_uid_mask) == - (phy_uid & phy_uid_mask))) { + phy_id_compare(fixup->phy_uid, phy_uid, phy_uid_mask)) { list_del(&fixup->list); kfree(fixup); ret = 0; @@ -491,8 +490,8 @@ static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) return 0; - if ((fixup->phy_uid & fixup->phy_uid_mask) != - (phydev->phy_id & fixup->phy_uid_mask)) + if (!phy_id_compare(phydev->phy_id, fixup->phy_uid, + fixup->phy_uid_mask)) if (fixup->phy_uid != PHY_ANY_UID) return 0; @@ -539,15 +538,14 @@ static int phy_bus_match(struct device *dev, struct device_driver *drv) if (phydev->c45_ids.device_ids[i] == 0xffffffff) continue; - if ((phydrv->phy_id & phydrv->phy_id_mask) == - (phydev->c45_ids.device_ids[i] & - phydrv->phy_id_mask)) + if (phy_id_compare(phydev->c45_ids.device_ids[i], + phydrv->phy_id, phydrv->phy_id_mask)) return 1; } return 0; } else { - return (phydrv->phy_id & phydrv->phy_id_mask) == - (phydev->phy_id & phydrv->phy_id_mask); + return phy_id_compare(phydev->phy_id, phydrv->phy_id, + phydrv->phy_id_mask); } } diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index f2106d17847a50..1ae7868d213768 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -712,14 +712,11 @@ static int phylink_validate(struct phylink *pl, unsigned long *supported, { const unsigned long *interfaces = pl->config->supported_interfaces; - if (!phy_interface_empty(interfaces)) { - if (state->interface == PHY_INTERFACE_MODE_NA) - return phylink_validate_mask(pl, supported, state, - interfaces); + if (state->interface == PHY_INTERFACE_MODE_NA) + return phylink_validate_mask(pl, supported, state, interfaces); - if (!test_bit(state->interface, interfaces)) - return -EINVAL; - } + if (!test_bit(state->interface, interfaces)) + return -EINVAL; return phylink_validate_mac_and_pcs(pl, supported, state); } @@ -980,11 +977,10 @@ static void phylink_apply_manual_flow(struct phylink *pl, state->pause = pl->link_config.pause; } -static void phylink_resolve_flow(struct phylink_link_state *state) +static void phylink_resolve_an_pause(struct phylink_link_state *state) { bool tx_pause, rx_pause; - state->pause = MLO_PAUSE_NONE; if (state->duplex == DUPLEX_FULL) { linkmode_resolve_pause(state->advertising, state->lp_advertising, @@ -996,6 +992,25 @@ static void phylink_resolve_flow(struct phylink_link_state *state) } } +static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int mode, + const struct phylink_link_state *state, + bool permit_pause_to_mac) +{ + if (!pcs) + return 0; + + return pcs->ops->pcs_config(pcs, mode, state->interface, + state->advertising, permit_pause_to_mac); +} + +static void phylink_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode, + phy_interface_t interface, int speed, + int duplex) +{ + if (pcs && pcs->ops->pcs_link_up) + pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex); +} + static void phylink_pcs_poll_stop(struct phylink *pl) { if (pl->cfg_link_an_mode == MLO_AN_INBAND) @@ -1079,18 +1094,15 @@ static void phylink_major_config(struct phylink *pl, bool restart, phylink_mac_config(pl, state); - if (pl->pcs) { - err = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, - state->interface, - state->advertising, - !!(pl->link_config.pause & - MLO_PAUSE_AN)); - if (err < 0) - phylink_err(pl, "pcs_config failed: %pe\n", - ERR_PTR(err)); - if (err > 0) - restart = true; - } + err = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, state, + !!(pl->link_config.pause & + MLO_PAUSE_AN)); + if (err < 0) + phylink_err(pl, "pcs_config failed: %pe\n", + ERR_PTR(err)); + else if (err > 0) + restart = true; + if (restart) phylink_mac_pcs_an_restart(pl); @@ -1141,11 +1153,9 @@ static int phylink_change_inband_advert(struct phylink *pl) * restart negotiation if the pcs_config() helper indicates that * the programmed advertisement has changed. */ - ret = pl->pcs->ops->pcs_config(pl->pcs, pl->cur_link_an_mode, - pl->link_config.interface, - pl->link_config.advertising, - !!(pl->link_config.pause & - MLO_PAUSE_AN)); + ret = phylink_pcs_config(pl->pcs, pl->cur_link_an_mode, + &pl->link_config, + !!(pl->link_config.pause & MLO_PAUSE_AN)); if (ret < 0) return ret; @@ -1196,7 +1206,8 @@ static void phylink_get_fixed_state(struct phylink *pl, else if (pl->link_gpio) state->link = !!gpiod_get_value_cansleep(pl->link_gpio); - phylink_resolve_flow(state); + state->pause = MLO_PAUSE_NONE; + phylink_resolve_an_pause(state); } static void phylink_mac_initial_config(struct phylink *pl, bool force_restart) @@ -1276,9 +1287,8 @@ static void phylink_link_up(struct phylink *pl, pl->cur_interface = link_state.interface; - if (pl->pcs && pl->pcs->ops->pcs_link_up) - pl->pcs->ops->pcs_link_up(pl->pcs, pl->cur_link_an_mode, - pl->cur_interface, speed, duplex); + phylink_pcs_link_up(pl->pcs, pl->cur_link_an_mode, pl->cur_interface, + speed, duplex); pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode, pl->cur_interface, speed, duplex, @@ -1513,19 +1523,18 @@ struct phylink *phylink_create(struct phylink_config *config, struct phylink *pl; int ret; - if (mac_ops->mac_select_pcs && - mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != - ERR_PTR(-EOPNOTSUPP)) - using_mac_select_pcs = true; - /* Validate the supplied configuration */ - if (using_mac_select_pcs && - phy_interface_empty(config->supported_interfaces)) { + if (phy_interface_empty(config->supported_interfaces)) { dev_err(config->dev, - "phylink: error: empty supported_interfaces but mac_select_pcs() method present\n"); + "phylink: error: empty supported_interfaces\n"); return ERR_PTR(-EINVAL); } + if (mac_ops->mac_select_pcs && + mac_ops->mac_select_pcs(config, PHY_INTERFACE_MODE_NA) != + ERR_PTR(-EOPNOTSUPP)) + using_mac_select_pcs = true; + pl = kzalloc(sizeof(*pl), GFP_KERNEL); if (!pl) return ERR_PTR(-ENOMEM); @@ -2250,11 +2259,13 @@ int phylink_ethtool_ksettings_set(struct phylink *pl, ASSERT_RTNL(); - /* Mask out unsupported advertisements */ - linkmode_and(config.advertising, kset->link_modes.advertising, - pl->supported); - if (pl->phydev) { + struct ethtool_link_ksettings phy_kset = *kset; + + linkmode_and(phy_kset.link_modes.advertising, + phy_kset.link_modes.advertising, + pl->supported); + /* We can rely on phylib for this update; we also do not need * to update the pl->link_config settings: * - the configuration returned via ksettings_get() will come @@ -2273,10 +2284,13 @@ int phylink_ethtool_ksettings_set(struct phylink *pl, * the presence of a PHY, this should not be changed as that * should be determined from the media side advertisement. */ - return phy_ethtool_ksettings_set(pl->phydev, kset); + return phy_ethtool_ksettings_set(pl->phydev, &phy_kset); } config = pl->link_config; + /* Mask out unsupported advertisements */ + linkmode_and(config.advertising, kset->link_modes.advertising, + pl->supported); /* FIXME: should we reject autoneg if phy/mac does not support it? */ switch (kset->base.autoneg) { @@ -3151,8 +3165,8 @@ static void phylink_sfp_link_up(void *upstream) */ static bool phylink_phy_no_inband(struct phy_device *phy) { - return phy->is_c45 && - (phy->c45_ids.device_ids[1] & 0xfffffff0) == 0xae025150; + return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1], + 0xae025150, 0xfffffff0); } static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) @@ -3216,10 +3230,48 @@ static const struct sfp_upstream_ops sfp_phylink_ops = { /* Helpers for MAC drivers */ +static struct { + int bit; + int speed; +} phylink_c73_priority_resolution[] = { + { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 }, + { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 }, + /* 100GBASE-KP4 and 100GBASE-CR10 not supported */ + { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 }, + { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 }, + { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 }, + { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 }, + /* 5GBASE-KR not supported */ + { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 }, + { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 }, +}; + +void phylink_resolve_c73(struct phylink_link_state *state) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) { + int bit = phylink_c73_priority_resolution[i].bit; + if (linkmode_test_bit(bit, state->advertising) && + linkmode_test_bit(bit, state->lp_advertising)) + break; + } + + if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) { + state->speed = phylink_c73_priority_resolution[i].speed; + state->duplex = DUPLEX_FULL; + } else { + /* negotiation failure */ + state->link = false; + } + + phylink_resolve_an_pause(state); +} +EXPORT_SYMBOL_GPL(phylink_resolve_c73); + static void phylink_decode_c37_word(struct phylink_link_state *state, uint16_t config_reg, int speed) { - bool tx_pause, rx_pause; int fd_bit; if (speed == SPEED_2500) @@ -3238,13 +3290,7 @@ static void phylink_decode_c37_word(struct phylink_link_state *state, state->link = false; } - linkmode_resolve_pause(state->advertising, state->lp_advertising, - &tx_pause, &rx_pause); - - if (tx_pause) - state->pause |= MLO_PAUSE_TX; - if (rx_pause) - state->pause |= MLO_PAUSE_RX; + phylink_resolve_an_pause(state); } static void phylink_decode_sgmii_word(struct phylink_link_state *state, diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 3d99fd6664d7a3..894172a3e15fe8 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -12,6 +12,7 @@ #include #include #include +#include #define RTL821x_PHYSR 0x11 #define RTL821x_PHYSR_DUPLEX BIT(13) @@ -80,6 +81,7 @@ struct rtl821x_priv { u16 phycr1; u16 phycr2; bool has_phycr2; + struct clk *clk; }; static int rtl821x_read_page(struct phy_device *phydev) @@ -103,6 +105,11 @@ static int rtl821x_probe(struct phy_device *phydev) if (!priv) return -ENOMEM; + priv->clk = devm_clk_get_optional_enabled(dev, NULL); + if (IS_ERR(priv->clk)) + return dev_err_probe(dev, PTR_ERR(priv->clk), + "failed to get phy clock\n"); + ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR1); if (ret < 0) return ret; @@ -419,10 +426,31 @@ static int rtl8211f_config_init(struct phy_device *phydev) return genphy_soft_reset(phydev); } +static int rtl821x_suspend(struct phy_device *phydev) +{ + struct rtl821x_priv *priv = phydev->priv; + int ret = 0; + + if (!phydev->wol_enabled) { + ret = genphy_suspend(phydev); + + if (ret) + return ret; + + clk_disable_unprepare(priv->clk); + } + + return ret; +} + static int rtl821x_resume(struct phy_device *phydev) { + struct rtl821x_priv *priv = phydev->priv; int ret; + if (!phydev->wol_enabled) + clk_prepare_enable(priv->clk); + ret = genphy_resume(phydev); if (ret < 0) return ret; @@ -927,10 +955,11 @@ static struct phy_driver realtek_drvs[] = { .read_status = rtlgen_read_status, .config_intr = &rtl8211f_config_intr, .handle_interrupt = rtl8211f_handle_interrupt, - .suspend = genphy_suspend, + .suspend = rtl821x_suspend, .resume = rtl821x_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .flags = PHY_ALWAYS_CALL_SUSPEND, }, { PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID), .name = "RTL8211F-VD Gigabit Ethernet", @@ -939,10 +968,11 @@ static struct phy_driver realtek_drvs[] = { .read_status = rtlgen_read_status, .config_intr = &rtl8211f_config_intr, .handle_interrupt = rtl8211f_handle_interrupt, - .suspend = genphy_suspend, + .suspend = rtl821x_suspend, .resume = rtl821x_resume, .read_page = rtl821x_read_page, .write_page = rtl821x_write_page, + .flags = PHY_ALWAYS_CALL_SUSPEND, }, { .name = "Generic FE-GE Realtek PHY", .match_phy_device = rtlgen_match_phy_device, diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c index 4799976a160953..d855a18308d789 100644 --- a/drivers/net/phy/sfp.c +++ b/drivers/net/phy/sfp.c @@ -170,7 +170,6 @@ static const enum gpiod_flags gpio_flags[] = { * on board (for a copper SFP) time to initialise. */ #define T_WAIT msecs_to_jiffies(50) -#define T_WAIT_ROLLBALL msecs_to_jiffies(25000) #define T_START_UP msecs_to_jiffies(300) #define T_START_UP_BAD_GPON msecs_to_jiffies(60000) @@ -351,6 +350,27 @@ static void sfp_fixup_ignore_tx_fault(struct sfp *sfp) sfp->tx_fault_ignore = true; } +// For 10GBASE-T short-reach modules +static void sfp_fixup_10gbaset_30m(struct sfp *sfp) +{ + sfp->id.base.connector = SFF8024_CONNECTOR_RJ45; + sfp->id.base.extended_cc = SFF8024_ECC_10GBASE_T_SR; +} + +static void sfp_fixup_rollball_proto(struct sfp *sfp, unsigned int secs) +{ + sfp->mdio_protocol = MDIO_I2C_ROLLBALL; + sfp->module_t_wait = msecs_to_jiffies(secs * 1000); +} + +static void sfp_fixup_fs_10gt(struct sfp *sfp) +{ + sfp_fixup_10gbaset_30m(sfp); + + // These SFPs need 4 seconds before the PHY can be accessed + sfp_fixup_rollball_proto(sfp, 4); +} + static void sfp_fixup_halny_gsfp(struct sfp *sfp) { /* Ignore the TX_FAULT and LOS signals on this module. @@ -362,8 +382,8 @@ static void sfp_fixup_halny_gsfp(struct sfp *sfp) static void sfp_fixup_rollball(struct sfp *sfp) { - sfp->mdio_protocol = MDIO_I2C_ROLLBALL; - sfp->module_t_wait = T_WAIT_ROLLBALL; + // Rollball SFPs need 25 seconds before the PHY can be accessed + sfp_fixup_rollball_proto(sfp, 25); } static void sfp_fixup_rollball_cc(struct sfp *sfp) @@ -428,6 +448,10 @@ static const struct sfp_quirk sfp_quirks[] = { SFP_QUIRK("ALCATELLUCENT", "3FE46541AA", sfp_quirk_2500basex, sfp_fixup_long_startup), + // Fiberstore SFP-10G-T doesn't identify as copper, and uses the + // Rollball protocol to talk to the PHY. + SFP_QUIRK_F("FS", "SFP-10G-T", sfp_fixup_fs_10gt), + SFP_QUIRK_F("HALNy", "HL-GSFP", sfp_fixup_halny_gsfp), // HG MXPD-483II-F 2.5G supports 2500Base-X, but incorrectly reports @@ -445,6 +469,11 @@ static const struct sfp_quirk sfp_quirks[] = { SFP_QUIRK_M("UBNT", "UF-INSTANT", sfp_quirk_ubnt_uf_instant), + // Walsun HXSX-ATR[CI]-1 don't identify as copper, and use the + // Rollball protocol to talk to the PHY. + SFP_QUIRK_F("Walsun", "HXSX-ATRC-1", sfp_fixup_fs_10gt), + SFP_QUIRK_F("Walsun", "HXSX-ATRI-1", sfp_fixup_fs_10gt), + SFP_QUIRK_F("OEM", "SFP-10G-T", sfp_fixup_rollball_cc), SFP_QUIRK_M("OEM", "SFP-2.5G-T", sfp_quirk_oem_2_5g), SFP_QUIRK_F("OEM", "RTSFP-10", sfp_fixup_rollball_cc), diff --git a/drivers/net/ppp/Kconfig b/drivers/net/ppp/Kconfig index 2fbcae31fc0235..8c9ed1889d1af2 100644 --- a/drivers/net/ppp/Kconfig +++ b/drivers/net/ppp/Kconfig @@ -141,7 +141,7 @@ choice This hash table is on a per outer ethernet interface. -config PPPOE_HASH_BITS_2 +config PPPOE_HASH_BITS_1 bool "1 bit (2 buckets)" config PPPOE_HASH_BITS_2 diff --git a/drivers/net/tap.c b/drivers/net/tap.c index d30d730ed5a71b..9137fb8c1c420a 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index d10606f257c433..555b0b1e9a7893 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1629,6 +1629,7 @@ static int team_init(struct net_device *dev) team->dev = dev; team_set_no_mode(team); + team->notifier_ctx = false; team->pcpu_stats = netdev_alloc_pcpu_stats(struct team_pcpu_stats); if (!team->pcpu_stats) @@ -3022,7 +3023,11 @@ static int team_device_event(struct notifier_block *unused, team_del_slave(port->team->dev, dev); break; case NETDEV_FEAT_CHANGE: - team_compute_features(port->team); + if (!port->team->notifier_ctx) { + port->team->notifier_ctx = true; + team_compute_features(port->team); + port->team->notifier_ctx = false; + } break; case NETDEV_PRECHANGEMTU: /* Forbid to change mtu of underlaying device */ diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 4402eedb3d1a24..3fd7dccf0f9c98 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -583,12 +583,10 @@ config USB_IPHETH default n help Module used to share Internet connection (tethering) from your - iPhone (Original, 3G and 3GS) to your system. - Note that you need userspace libraries and programs that are needed - to pair your device with your system and that understand the iPhone - protocol. - - For more information: http://giagio.com/wiki/moin.cgi/iPhoneEthernetDriver + iPhone to your system. + Note that you need a corresponding userspace library/program + to pair your device with your system, for example usbmuxd + . config USB_SIERRA_NET tristate "USB-to-WWAN Driver for Sierra Wireless modems" diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 6ce8f4f0c70e89..db05622f1f703e 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -181,9 +181,12 @@ static u32 cdc_ncm_check_tx_max(struct usbnet *dev, u32 new_tx) else min = ctx->max_datagram_size + ctx->max_ndp_size + sizeof(struct usb_cdc_ncm_nth32); - max = min_t(u32, CDC_NCM_NTB_MAX_SIZE_TX, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize)); - if (max == 0) + if (le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize) == 0) max = CDC_NCM_NTB_MAX_SIZE_TX; /* dwNtbOutMaxSize not set */ + else + max = clamp_t(u32, le32_to_cpu(ctx->ncm_parm.dwNtbOutMaxSize), + USB_CDC_NCM_NTB_MIN_OUT_SIZE, + CDC_NCM_NTB_MAX_SIZE_TX); /* some devices set dwNtbOutMaxSize too low for the above default */ min = min(min, max); @@ -1244,6 +1247,9 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) * further. */ if (skb_out == NULL) { + /* If even the smallest allocation fails, abort. */ + if (ctx->tx_curr_size == USB_CDC_NCM_NTB_MIN_OUT_SIZE) + goto alloc_failed; ctx->tx_low_mem_max_cnt = min(ctx->tx_low_mem_max_cnt + 1, (unsigned)CDC_NCM_LOW_MEM_MAX_CNT); ctx->tx_low_mem_val = ctx->tx_low_mem_max_cnt; @@ -1262,13 +1268,8 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) skb_out = alloc_skb(ctx->tx_curr_size, GFP_ATOMIC); /* No allocation possible so we will abort */ - if (skb_out == NULL) { - if (skb != NULL) { - dev_kfree_skb_any(skb); - dev->net->stats.tx_dropped++; - } - goto exit_no_skb; - } + if (!skb_out) + goto alloc_failed; ctx->tx_low_mem_val--; } if (ctx->is_ndp16) { @@ -1461,6 +1462,11 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign) return skb_out; +alloc_failed: + if (skb) { + dev_kfree_skb_any(skb); + dev->net->stats.tx_dropped++; + } exit_no_skb: /* Start timer, if there is a remaining non-empty skb */ if (ctx->tx_curr_skb != NULL && n > 0) diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 6a769df0b4213c..687d70cfc55635 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -52,6 +52,7 @@ #include #include #include +#include #define USB_VENDOR_APPLE 0x05ac @@ -59,8 +60,12 @@ #define IPHETH_USBINTF_SUBCLASS 253 #define IPHETH_USBINTF_PROTO 1 -#define IPHETH_BUF_SIZE 1514 #define IPHETH_IP_ALIGN 2 /* padding at front of URB */ +#define IPHETH_NCM_HEADER_SIZE (12 + 96) /* NCMH + NCM0 */ +#define IPHETH_TX_BUF_SIZE ETH_FRAME_LEN +#define IPHETH_RX_BUF_SIZE_LEGACY (IPHETH_IP_ALIGN + ETH_FRAME_LEN) +#define IPHETH_RX_BUF_SIZE_NCM 65536 + #define IPHETH_TX_TIMEOUT (5 * HZ) #define IPHETH_INTFNUM 2 @@ -71,6 +76,7 @@ #define IPHETH_CTRL_TIMEOUT (5 * HZ) #define IPHETH_CMD_GET_MACADDR 0x00 +#define IPHETH_CMD_ENABLE_NCM 0x04 #define IPHETH_CMD_CARRIER_CHECK 0x45 #define IPHETH_CARRIER_CHECK_TIMEOUT round_jiffies_relative(1 * HZ) @@ -97,6 +103,8 @@ struct ipheth_device { u8 bulk_out; struct delayed_work carrier_work; bool confirmed_pairing; + int (*rcvbulk_callback)(struct urb *urb); + size_t rx_buf_len; }; static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags); @@ -116,12 +124,12 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) if (rx_urb == NULL) goto free_tx_urb; - tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE, + tx_buf = usb_alloc_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, GFP_KERNEL, &tx_urb->transfer_dma); if (tx_buf == NULL) goto free_rx_urb; - rx_buf = usb_alloc_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + rx_buf = usb_alloc_coherent(iphone->udev, iphone->rx_buf_len, GFP_KERNEL, &rx_urb->transfer_dma); if (rx_buf == NULL) goto free_tx_buf; @@ -134,7 +142,7 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) return 0; free_tx_buf: - usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, tx_buf, + usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, tx_buf, tx_urb->transfer_dma); free_rx_urb: usb_free_urb(rx_urb); @@ -146,9 +154,9 @@ static int ipheth_alloc_urbs(struct ipheth_device *iphone) static void ipheth_free_urbs(struct ipheth_device *iphone) { - usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, iphone->rx_buf, + usb_free_coherent(iphone->udev, iphone->rx_buf_len, iphone->rx_buf, iphone->rx_urb->transfer_dma); - usb_free_coherent(iphone->udev, IPHETH_BUF_SIZE, iphone->tx_buf, + usb_free_coherent(iphone->udev, IPHETH_TX_BUF_SIZE, iphone->tx_buf, iphone->tx_urb->transfer_dma); usb_free_urb(iphone->rx_urb); usb_free_urb(iphone->tx_urb); @@ -160,14 +168,105 @@ static void ipheth_kill_urbs(struct ipheth_device *dev) usb_kill_urb(dev->rx_urb); } -static void ipheth_rcvbulk_callback(struct urb *urb) +static int ipheth_consume_skb(char *buf, int len, struct ipheth_device *dev) { - struct ipheth_device *dev; struct sk_buff *skb; - int status; + + skb = dev_alloc_skb(len); + if (!skb) { + dev->net->stats.rx_dropped++; + return -ENOMEM; + } + + skb_put_data(skb, buf, len); + skb->dev = dev->net; + skb->protocol = eth_type_trans(skb, dev->net); + + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += len; + netif_rx(skb); + + return 0; +} + +static int ipheth_rcvbulk_callback_legacy(struct urb *urb) +{ + struct ipheth_device *dev; char *buf; int len; + dev = urb->context; + + if (urb->actual_length <= IPHETH_IP_ALIGN) { + dev->net->stats.rx_length_errors++; + return -EINVAL; + } + len = urb->actual_length - IPHETH_IP_ALIGN; + buf = urb->transfer_buffer + IPHETH_IP_ALIGN; + + return ipheth_consume_skb(buf, len, dev); +} + +static int ipheth_rcvbulk_callback_ncm(struct urb *urb) +{ + struct usb_cdc_ncm_nth16 *ncmh; + struct usb_cdc_ncm_ndp16 *ncm0; + struct usb_cdc_ncm_dpe16 *dpe; + struct ipheth_device *dev; + int retval = -EINVAL; + char *buf; + int len; + + dev = urb->context; + + if (urb->actual_length < IPHETH_NCM_HEADER_SIZE) { + dev->net->stats.rx_length_errors++; + return retval; + } + + ncmh = urb->transfer_buffer; + if (ncmh->dwSignature != cpu_to_le32(USB_CDC_NCM_NTH16_SIGN) || + le16_to_cpu(ncmh->wNdpIndex) >= urb->actual_length) { + dev->net->stats.rx_errors++; + return retval; + } + + ncm0 = urb->transfer_buffer + le16_to_cpu(ncmh->wNdpIndex); + if (ncm0->dwSignature != cpu_to_le32(USB_CDC_NCM_NDP16_NOCRC_SIGN) || + le16_to_cpu(ncmh->wHeaderLength) + le16_to_cpu(ncm0->wLength) >= + urb->actual_length) { + dev->net->stats.rx_errors++; + return retval; + } + + dpe = ncm0->dpe16; + while (le16_to_cpu(dpe->wDatagramIndex) != 0 && + le16_to_cpu(dpe->wDatagramLength) != 0) { + if (le16_to_cpu(dpe->wDatagramIndex) >= urb->actual_length || + le16_to_cpu(dpe->wDatagramIndex) + + le16_to_cpu(dpe->wDatagramLength) > urb->actual_length) { + dev->net->stats.rx_length_errors++; + return retval; + } + + buf = urb->transfer_buffer + le16_to_cpu(dpe->wDatagramIndex); + len = le16_to_cpu(dpe->wDatagramLength); + + retval = ipheth_consume_skb(buf, len, dev); + if (retval != 0) + return retval; + + dpe++; + } + + return 0; +} + +static void ipheth_rcvbulk_callback(struct urb *urb) +{ + struct ipheth_device *dev; + int retval, status; + dev = urb->context; if (dev == NULL) return; @@ -191,25 +290,27 @@ static void ipheth_rcvbulk_callback(struct urb *urb) dev->net->stats.rx_length_errors++; return; } - len = urb->actual_length - IPHETH_IP_ALIGN; - buf = urb->transfer_buffer + IPHETH_IP_ALIGN; - skb = dev_alloc_skb(len); - if (!skb) { - dev_err(&dev->intf->dev, "%s: dev_alloc_skb: -ENOMEM\n", - __func__); - dev->net->stats.rx_dropped++; + /* RX URBs starting with 0x00 0x01 do not encapsulate Ethernet frames, + * but rather are control frames. Their purpose is not documented, and + * they don't affect driver functionality, okay to drop them. + * There is usually just one 4-byte control frame as the very first + * URB received from the bulk IN endpoint. + */ + if (unlikely + (((char *)urb->transfer_buffer)[0] == 0 && + ((char *)urb->transfer_buffer)[1] == 1)) + goto rx_submit; + + retval = dev->rcvbulk_callback(urb); + if (retval != 0) { + dev_err(&dev->intf->dev, "%s: callback retval: %d\n", + __func__, retval); return; } - skb_put_data(skb, buf, len); - skb->dev = dev->net; - skb->protocol = eth_type_trans(skb, dev->net); - - dev->net->stats.rx_packets++; - dev->net->stats.rx_bytes += len; +rx_submit: dev->confirmed_pairing = true; - netif_rx(skb); ipheth_rx_submit(dev, GFP_ATOMIC); } @@ -310,6 +411,27 @@ static int ipheth_get_macaddr(struct ipheth_device *dev) return retval; } +static int ipheth_enable_ncm(struct ipheth_device *dev) +{ + struct usb_device *udev = dev->udev; + int retval; + + retval = usb_control_msg(udev, + usb_sndctrlpipe(udev, IPHETH_CTRL_ENDP), + IPHETH_CMD_ENABLE_NCM, /* request */ + 0x41, /* request type */ + 0x00, /* value */ + 0x02, /* index */ + NULL, + 0, + IPHETH_CTRL_TIMEOUT); + + dev_info(&dev->intf->dev, "%s: usb_control_msg: %d\n", + __func__, retval); + + return retval; +} + static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) { struct usb_device *udev = dev->udev; @@ -317,7 +439,7 @@ static int ipheth_rx_submit(struct ipheth_device *dev, gfp_t mem_flags) usb_fill_bulk_urb(dev->rx_urb, udev, usb_rcvbulkpipe(udev, dev->bulk_in), - dev->rx_buf, IPHETH_BUF_SIZE + IPHETH_IP_ALIGN, + dev->rx_buf, dev->rx_buf_len, ipheth_rcvbulk_callback, dev); dev->rx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -365,7 +487,7 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net) int retval; /* Paranoid */ - if (skb->len > IPHETH_BUF_SIZE) { + if (skb->len > IPHETH_TX_BUF_SIZE) { WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len); dev->net->stats.tx_dropped++; dev_kfree_skb_any(skb); @@ -373,12 +495,10 @@ static netdev_tx_t ipheth_tx(struct sk_buff *skb, struct net_device *net) } memcpy(dev->tx_buf, skb->data, skb->len); - if (skb->len < IPHETH_BUF_SIZE) - memset(dev->tx_buf + skb->len, 0, IPHETH_BUF_SIZE - skb->len); usb_fill_bulk_urb(dev->tx_urb, udev, usb_sndbulkpipe(udev, dev->bulk_out), - dev->tx_buf, IPHETH_BUF_SIZE, + dev->tx_buf, skb->len, ipheth_sndbulk_callback, dev); dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; @@ -450,6 +570,8 @@ static int ipheth_probe(struct usb_interface *intf, dev->net = netdev; dev->intf = intf; dev->confirmed_pairing = false; + dev->rx_buf_len = IPHETH_RX_BUF_SIZE_LEGACY; + dev->rcvbulk_callback = ipheth_rcvbulk_callback_legacy; /* Set up endpoints */ hintf = usb_altnum_to_altsetting(intf, IPHETH_ALT_INTFNUM); if (hintf == NULL) { @@ -481,6 +603,12 @@ static int ipheth_probe(struct usb_interface *intf, if (retval) goto err_get_macaddr; + retval = ipheth_enable_ncm(dev); + if (!retval) { + dev->rx_buf_len = IPHETH_RX_BUF_SIZE_NCM; + dev->rcvbulk_callback = ipheth_rcvbulk_callback_ncm; + } + INIT_DELAYED_WORK(&dev->carrier_work, ipheth_carrier_check_work); retval = ipheth_alloc_urbs(dev); @@ -510,8 +638,8 @@ static int ipheth_probe(struct usb_interface *intf, ipheth_free_urbs(dev); err_alloc_urbs: err_get_macaddr: -err_alloc_ctrl_buf: kfree(dev->ctrl_buf); +err_alloc_ctrl_buf: err_endpoints: free_netdev(netdev); return retval; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 571e37e67f9ce1..f1865d047971b5 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -1325,7 +1325,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x2001, 0x7e3d, 4)}, /* D-Link DWM-222 A2 */ {QMI_FIXED_INTF(0x2020, 0x2031, 4)}, /* Olicard 600 */ {QMI_FIXED_INTF(0x2020, 0x2033, 4)}, /* BroadMobi BM806U */ - {QMI_FIXED_INTF(0x2020, 0x2060, 4)}, /* BroadMobi BM818 */ + {QMI_QUIRK_SET_DTR(0x2020, 0x2060, 4)}, /* BroadMobi BM818 */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 0999a58ca9d269..0738baa5b82e42 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -27,6 +27,7 @@ #include #include #include +#include /* Information for net-next */ #define NETNEXT_VERSION "12" diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 5a7f7a76b920ac..0db14f6b87d3ed 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -205,6 +205,8 @@ struct control_buf { __virtio16 vid; __virtio64 offloads; struct virtio_net_ctrl_rss rss; + struct virtio_net_ctrl_coal_tx coal_tx; + struct virtio_net_ctrl_coal_rx coal_rx; }; struct virtnet_info { @@ -3043,12 +3045,10 @@ static int virtnet_send_notf_coal_cmds(struct virtnet_info *vi, struct ethtool_coalesce *ec) { struct scatterlist sgs_tx, sgs_rx; - struct virtio_net_ctrl_coal_tx coal_tx; - struct virtio_net_ctrl_coal_rx coal_rx; - coal_tx.tx_usecs = cpu_to_le32(ec->tx_coalesce_usecs); - coal_tx.tx_max_packets = cpu_to_le32(ec->tx_max_coalesced_frames); - sg_init_one(&sgs_tx, &coal_tx, sizeof(coal_tx)); + vi->ctrl->coal_tx.tx_usecs = cpu_to_le32(ec->tx_coalesce_usecs); + vi->ctrl->coal_tx.tx_max_packets = cpu_to_le32(ec->tx_max_coalesced_frames); + sg_init_one(&sgs_tx, &vi->ctrl->coal_tx, sizeof(vi->ctrl->coal_tx)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL, VIRTIO_NET_CTRL_NOTF_COAL_TX_SET, @@ -3059,9 +3059,9 @@ static int virtnet_send_notf_coal_cmds(struct virtnet_info *vi, vi->tx_usecs = ec->tx_coalesce_usecs; vi->tx_max_packets = ec->tx_max_coalesced_frames; - coal_rx.rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs); - coal_rx.rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames); - sg_init_one(&sgs_rx, &coal_rx, sizeof(coal_rx)); + vi->ctrl->coal_rx.rx_usecs = cpu_to_le32(ec->rx_coalesce_usecs); + vi->ctrl->coal_rx.rx_max_packets = cpu_to_le32(ec->rx_max_coalesced_frames); + sg_init_one(&sgs_rx, &vi->ctrl->coal_rx, sizeof(vi->ctrl->coal_rx)); if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_NOTF_COAL, VIRTIO_NET_CTRL_NOTF_COAL_RX_SET, diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c index d58e9f818d3b79..258dcc1039216f 100644 --- a/drivers/net/wireguard/device.c +++ b/drivers/net/wireguard/device.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 5eb131ab916fd0..533ed7169e1172 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -3643,6 +3643,9 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, mutex_init(&ar->dump_mutex); spin_lock_init(&ar->data_lock); + for (int ac = 0; ac < IEEE80211_NUM_ACS; ac++) + spin_lock_init(&ar->queue_lock[ac]); + INIT_LIST_HEAD(&ar->peers); init_waitqueue_head(&ar->peer_mapping_wq); init_waitqueue_head(&ar->htt.empty_tx_wq); diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index f5de8ce8fb4561..4b5239de401840 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -1170,6 +1170,9 @@ struct ath10k { /* protects shared structure data */ spinlock_t data_lock; + /* serialize wake_tx_queue calls per ac */ + spinlock_t queue_lock[IEEE80211_NUM_ACS]; + struct list_head arvifs; struct list_head peers; struct ath10k_peer *peer_map[ATH10K_MAX_NUM_PEER_IDS]; diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index b9aea1510f7bb7..f9518e1c99039e 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -293,8 +293,8 @@ void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) goto free; } - num_peers = ath10k_wmi_fw_stats_num_peers(&ar->debug.fw_stats.peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&ar->debug.fw_stats.vdevs); + num_peers = list_count_nodes(&ar->debug.fw_stats.peers); + num_vdevs = list_count_nodes(&ar->debug.fw_stats.vdevs); is_start = (list_empty(&ar->debug.fw_stats.pdevs) && !list_empty(&stats.pdevs)); is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 7675858f069bd2..9c4bf2fdbc0f81 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -4732,13 +4732,14 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, { struct ath10k *ar = hw->priv; int ret; - u8 ac; + u8 ac = txq->ac; ath10k_htt_tx_txq_update(hw, txq); if (ar->htt.tx_q_state.mode != HTT_TX_MODE_SWITCH_PUSH) return; - ac = txq->ac; + spin_lock_bh(&ar->queue_lock[ac]); + ieee80211_txq_schedule_start(hw, ac); txq = ieee80211_next_txq(hw, ac); if (!txq) @@ -4753,6 +4754,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw, ath10k_htt_tx_txq_update(hw, txq); out: ieee80211_txq_schedule_end(hw, ac); + spin_unlock_bh(&ar->queue_lock[ac]); } /* Must not be called with conf_mutex held as workers can use that also. */ diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 980d4124fa287d..05fa7d4c0e1aba 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -8164,28 +8164,6 @@ ath10k_wmi_10_2_4_op_gen_pdev_get_tpc_config(struct ath10k *ar, u32 param) return skb; } -size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head) -{ - struct ath10k_fw_stats_peer *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - -size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head) -{ - struct ath10k_fw_stats_vdev *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - static void ath10k_wmi_fw_pdev_base_stats_fill(const struct ath10k_fw_stats_pdev *pdev, char *buf, u32 *length) @@ -8462,8 +8440,8 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, goto unlock; } - num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + num_peers = list_count_nodes(&fw_stats->peers); + num_vdevs = list_count_nodes(&fw_stats->vdevs); ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ath10k_wmi_fw_pdev_tx_stats_fill(pdev, buf, &len); @@ -8520,8 +8498,8 @@ void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, goto unlock; } - num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + num_peers = list_count_nodes(&fw_stats->peers); + num_vdevs = list_count_nodes(&fw_stats->vdevs); ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); @@ -8668,8 +8646,8 @@ void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, goto unlock; } - num_peers = ath10k_wmi_fw_stats_num_peers(&fw_stats->peers); - num_vdevs = ath10k_wmi_fw_stats_num_vdevs(&fw_stats->vdevs); + num_peers = list_count_nodes(&fw_stats->peers); + num_vdevs = list_count_nodes(&fw_stats->vdevs); ath10k_wmi_fw_pdev_base_stats_fill(pdev, buf, &len); ath10k_wmi_fw_pdev_extra_stats_fill(pdev, buf, &len); diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 6de3cc4640a0b6..6d04a66fe5e024 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -7502,8 +7502,6 @@ void ath10k_wmi_main_op_fw_stats_fill(struct ath10k *ar, void ath10k_wmi_10x_op_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); -size_t ath10k_wmi_fw_stats_num_peers(struct list_head *head); -size_t ath10k_wmi_fw_stats_num_vdevs(struct list_head *head); void ath10k_wmi_10_4_op_fw_stats_fill(struct ath10k *ar, struct ath10k_fw_stats *fw_stats, char *buf); diff --git a/drivers/net/wireless/ath/ath11k/hw.c b/drivers/net/wireless/ath/ath11k/hw.c index eb995f9cf0fa12..3b5181e054d343 100644 --- a/drivers/net/wireless/ath/ath11k/hw.c +++ b/drivers/net/wireless/ath/ath11k/hw.c @@ -202,6 +202,9 @@ static void ath11k_init_wmi_config_ipq8074(struct ath11k_base *ab, config->twt_ap_sta_count = 1000; config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI; + config->ema_max_vap_cnt = ab->num_radios; + config->ema_max_profile_period = TARGET_EMA_MAX_PROFILE_PERIOD; + config->beacon_tx_offload_max_vdev += config->ema_max_vap_cnt; } static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 6a5dd2dbdb3abb..f5533630a7f9d3 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -64,6 +64,7 @@ #define TARGET_NUM_WDS_ENTRIES 32 #define TARGET_DMA_BURST_SIZE 1 #define TARGET_RX_BATCHMODE 1 +#define TARGET_EMA_MAX_PROFILE_PERIOD 8 #define ATH11K_HW_MAX_QUEUES 4 #define ATH11K_QUEUE_LEN 4096 diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 1c93f1afccc57b..c947d1c8d8c155 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -433,7 +433,7 @@ u8 ath11k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, } static u32 -ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath11k_mac_max_ht_nss(const u8 *ht_mcs_mask) { int nss; @@ -445,7 +445,7 @@ ath11k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static u32 -ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +ath11k_mac_max_vht_nss(const u16 *vht_mcs_mask) { int nss; @@ -457,7 +457,7 @@ ath11k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) } static u32 -ath11k_mac_max_he_nss(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) +ath11k_mac_max_he_nss(const u16 *he_mcs_mask) { int nss; @@ -964,7 +964,7 @@ static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id, return ret; } - ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr); + ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr, NULL, 0, 0); if (ret) { ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n", vdev_id, ret); @@ -1351,28 +1351,92 @@ static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed) return ret; } -static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) +static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif, + bool tx_arvif_rsnie_present, + const u8 *profile, u8 profile_len) { - struct ath11k *ar = arvif->ar; - struct ath11k_base *ab = ar->ab; - struct ieee80211_hw *hw = ar->hw; - struct ieee80211_vif *vif = arvif->vif; - struct ieee80211_mutable_offsets offs = {}; - struct sk_buff *bcn; - struct ieee80211_mgmt *mgmt; - u8 *ies; - int ret; + if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) { + arvif->rsnie_present = true; + } else if (tx_arvif_rsnie_present) { + int i; + u8 nie_len; + const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE, + profile, profile_len); + if (!nie) + return; - if (arvif->vdev_type != WMI_VDEV_TYPE_AP) - return 0; + nie_len = nie[1]; + nie += 2; + for (i = 0; i < nie_len; i++) { + if (nie[i] == WLAN_EID_RSN) { + arvif->rsnie_present = false; + break; + } + } + } +} - bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); - if (!bcn) { - ath11k_warn(ab, "failed to get beacon template from mac80211\n"); - return -EPERM; +static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif, + struct ath11k_vif *arvif, + struct sk_buff *bcn) +{ + struct ieee80211_mgmt *mgmt; + const u8 *ies, *profile, *next_profile; + int ies_len; + + ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); + mgmt = (struct ieee80211_mgmt *)bcn->data; + ies += sizeof(mgmt->u.beacon); + ies_len = skb_tail_pointer(bcn) - ies; + + ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len); + arvif->rsnie_present = tx_arvif->rsnie_present; + + while (ies) { + u8 mbssid_len; + + ies_len -= (2 + ies[1]); + mbssid_len = ies[1] - 1; + profile = &ies[3]; + + while (mbssid_len) { + u8 profile_len; + + profile_len = profile[1]; + next_profile = profile + (2 + profile_len); + mbssid_len -= (2 + profile_len); + + profile += 2; + profile_len -= (2 + profile[1]); + profile += (2 + profile[1]); /* nontx capabilities */ + profile_len -= (2 + profile[1]); + profile += (2 + profile[1]); /* SSID */ + if (profile[2] == arvif->vif->bss_conf.bssid_index) { + profile_len -= 5; + profile = profile + 5; + ath11k_mac_setup_nontx_vif_rsnie(arvif, + tx_arvif->rsnie_present, + profile, + profile_len); + return true; + } + profile = next_profile; + } + ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile, + ies_len); } + return false; +} + +static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif, + struct sk_buff *bcn) +{ + struct ieee80211_mgmt *mgmt; + u8 *ies; + ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn); + mgmt = (struct ieee80211_mgmt *)bcn->data; ies += sizeof(mgmt->u.beacon); if (cfg80211_find_ie(WLAN_EID_RSN, ies, (skb_tail_pointer(bcn) - ies))) @@ -1386,9 +1450,95 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) arvif->wpaie_present = true; else arvif->wpaie_present = false; +} + +static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif) +{ + struct ath11k_vif *tx_arvif; + struct ieee80211_ema_beacons *beacons; + int ret = 0; + bool nontx_vif_params_set = false; + u32 params = 0; + u8 i = 0; + + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + + beacons = ieee80211_beacon_get_template_ema_list(tx_arvif->ar->hw, + tx_arvif->vif, 0); + if (!beacons || !beacons->cnt) { + ath11k_warn(arvif->ar->ab, + "failed to get ema beacon templates from mac80211\n"); + return -EPERM; + } + + if (tx_arvif == arvif) + ath11k_mac_set_vif_params(tx_arvif, beacons->bcn[0].skb); + else + arvif->wpaie_present = tx_arvif->wpaie_present; + + for (i = 0; i < beacons->cnt; i++) { + if (tx_arvif != arvif && !nontx_vif_params_set) + nontx_vif_params_set = + ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, + beacons->bcn[i].skb); + + params = beacons->cnt; + params |= (i << WMI_EMA_TMPL_IDX_SHIFT); + params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT); + params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT); + + ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id, + &beacons->bcn[i].offs, + beacons->bcn[i].skb, params); + if (ret) { + ath11k_warn(tx_arvif->ar->ab, + "failed to set ema beacon template id %i error %d\n", + i, ret); + break; + } + } - ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn); + ieee80211_beacon_free_ema_list(beacons); + if (tx_arvif != arvif && !nontx_vif_params_set) + return -EINVAL; /* Profile not found in the beacons */ + + return ret; +} + +static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif) +{ + struct ath11k *ar = arvif->ar; + struct ath11k_base *ab = ar->ab; + struct ath11k_vif *tx_arvif = arvif; + struct ieee80211_hw *hw = ar->hw; + struct ieee80211_vif *vif = arvif->vif; + struct ieee80211_mutable_offsets offs = {}; + struct sk_buff *bcn; + int ret; + + if (arvif->vif->mbssid_tx_vif) { + tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv; + if (tx_arvif != arvif) { + ar = tx_arvif->ar; + ab = ar->ab; + hw = ar->hw; + vif = tx_arvif->vif; + } + } + + bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0); + if (!bcn) { + ath11k_warn(ab, "failed to get beacon template from mac80211\n"); + return -EPERM; + } + + if (tx_arvif == arvif) + ath11k_mac_set_vif_params(tx_arvif, bcn); + else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn)) + return -EINVAL; + + ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0); kfree_skb(bcn); if (ret) @@ -1398,6 +1548,26 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) return ret; } +static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif) +{ + struct ieee80211_vif *vif = arvif->vif; + + if (arvif->vdev_type != WMI_VDEV_TYPE_AP) + return 0; + + /* Target does not expect beacon templates for the already up + * non-transmitting interfaces, and results in a crash if sent. + */ + if (vif->mbssid_tx_vif && + arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up) + return 0; + + if (vif->bss_conf.ema_ap && vif->mbssid_tx_vif) + return ath11k_mac_setup_bcn_tmpl_ema(arvif); + + return ath11k_mac_setup_bcn_tmpl_mbssid(arvif); +} + void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif) { struct ieee80211_vif *vif = arvif->vif; @@ -1423,6 +1593,7 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, struct ieee80211_bss_conf *info) { struct ath11k *ar = arvif->ar; + struct ath11k_vif *tx_arvif = NULL; int ret = 0; lockdep_assert_held(&arvif->ar->conf_mutex); @@ -1451,8 +1622,14 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif, ether_addr_copy(arvif->bssid, info->bssid); + if (arvif->vif->mbssid_tx_vif) + tx_arvif = (struct ath11k_vif *)arvif->vif->mbssid_tx_vif->drv_priv; + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); + arvif->bssid, + tx_arvif ? tx_arvif->bssid : NULL, + info->bssid_index, + 1 << info->bssid_indicator); if (ret) { ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n", arvif->vdev_id, ret); @@ -1658,7 +1835,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar, } static bool -ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath11k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask) { int nss; @@ -1670,7 +1847,7 @@ ath11k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static bool -ath11k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[]) +ath11k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask) { int nss; @@ -2065,7 +2242,7 @@ static u16 ath11k_peer_assoc_h_he_limit(u16 tx_mcs_set, } static bool -ath11k_peer_assoc_h_he_masked(const u16 he_mcs_mask[NL80211_HE_NSS_MAX]) +ath11k_peer_assoc_h_he_masked(const u16 *he_mcs_mask) { int nss; @@ -2879,7 +3056,8 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw, arvif->aid = vif->cfg.aid; ether_addr_copy(arvif->bssid, bss_conf->bssid); - ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid); + ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid, + NULL, 0, 0); if (ret) { ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n", arvif->vdev_id, ret); @@ -4159,6 +4337,20 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, return ret; } +static int +ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar, + enum nl80211_band band, + const struct cfg80211_bitrate_mask *mask) +{ + int num_rates = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) + num_rates += hweight8(mask->control[band].ht_mcs[i]); + + return num_rates; +} + static int ath11k_mac_bitrate_mask_num_vht_rates(struct ath11k *ar, enum nl80211_band band, @@ -4288,6 +4480,54 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif, return ret; } +static int +ath11k_mac_set_peer_ht_fixed_rate(struct ath11k_vif *arvif, + struct ieee80211_sta *sta, + const struct cfg80211_bitrate_mask *mask, + enum nl80211_band band) +{ + struct ath11k *ar = arvif->ar; + u8 ht_rate, nss = 0; + u32 rate_code; + int ret, i; + + lockdep_assert_held(&ar->conf_mutex); + + for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) { + if (hweight8(mask->control[band].ht_mcs[i]) == 1) { + nss = i + 1; + ht_rate = ffs(mask->control[band].ht_mcs[i]) - 1; + } + } + + if (!nss) { + ath11k_warn(ar->ab, "No single HT Fixed rate found to set for %pM", + sta->addr); + return -EINVAL; + } + + /* Avoid updating invalid nss as fixed rate*/ + if (nss > sta->deflink.rx_nss) + return -EINVAL; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "Setting Fixed HT Rate for peer %pM. Device will not switch to any other selected rates", + sta->addr); + + rate_code = ATH11K_HW_RATE_CODE(ht_rate, nss - 1, + WMI_RATE_PREAMBLE_HT); + ret = ath11k_wmi_set_peer_param(ar, sta->addr, + arvif->vdev_id, + WMI_PEER_PARAM_FIXED_RATE, + rate_code); + if (ret) + ath11k_warn(ar->ab, + "failed to update STA %pM HT Fixed Rate %d: %d\n", + sta->addr, rate_code, ret); + + return ret; +} + static int ath11k_station_assoc(struct ath11k *ar, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -4299,7 +4539,7 @@ static int ath11k_station_assoc(struct ath11k *ar, struct cfg80211_chan_def def; enum nl80211_band band; struct cfg80211_bitrate_mask *mask; - u8 num_vht_rates, num_he_rates; + u8 num_ht_rates, num_vht_rates, num_he_rates; lockdep_assert_held(&ar->conf_mutex); @@ -4327,6 +4567,7 @@ static int ath11k_station_assoc(struct ath11k *ar, num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask); num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask); + num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, mask); /* If single VHT/HE rate is configured (by set_bitrate_mask()), * peer_assoc will disable VHT/HE. This is now enabled by a peer specific @@ -4343,6 +4584,11 @@ static int ath11k_station_assoc(struct ath11k *ar, band); if (ret) return ret; + } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ret = ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); + if (ret) + return ret; } /* Re-assoc is run only to update supported rates for given station. It @@ -4416,7 +4662,7 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) const u16 *vht_mcs_mask; const u16 *he_mcs_mask; u32 changed, bw, nss, smps, bw_prev; - int err, num_vht_rates, num_he_rates; + int err, num_ht_rates, num_vht_rates, num_he_rates; const struct cfg80211_bitrate_mask *mask; struct peer_assoc_params peer_arg; enum wmi_phy_mode peer_phymode; @@ -4532,6 +4778,8 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) { mask = &arvif->bitrate_mask; + num_ht_rates = ath11k_mac_bitrate_mask_num_ht_rates(ar, band, + mask); num_vht_rates = ath11k_mac_bitrate_mask_num_vht_rates(ar, band, mask); num_he_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, @@ -4554,6 +4802,9 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk) } else if (sta->deflink.he_cap.has_he && num_he_rates == 1) { ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask, band); + } else if (sta->deflink.ht_cap.ht_supported && num_ht_rates == 1) { + ath11k_mac_set_peer_ht_fixed_rate(arvif, sta, mask, + band); } else { /* If the peer is non-VHT/HE or no fixed VHT/HE rate * is provided in the new bitrate mask we set the @@ -6181,17 +6432,62 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw) atomic_set(&ar->num_pending_mgmt_tx, 0); } -static void -ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, - struct vdev_create_params *params) +static int ath11k_mac_setup_vdev_params_mbssid(struct ath11k_vif *arvif, + u32 *flags, u32 *tx_vdev_id) +{ + struct ath11k *ar = arvif->ar; + struct ath11k_vif *tx_arvif; + struct ieee80211_vif *tx_vif; + + *tx_vdev_id = 0; + tx_vif = arvif->vif->mbssid_tx_vif; + if (!tx_vif) { + *flags = WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP; + return 0; + } + + tx_arvif = (void *)tx_vif->drv_priv; + + if (arvif->vif->bss_conf.nontransmitted) { + if (ar->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy) + return -EINVAL; + + *flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP; + *tx_vdev_id = ath11k_vif_to_arvif(tx_vif)->vdev_id; + } else if (tx_arvif == arvif) { + *flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP; + } else { + return -EINVAL; + } + + if (arvif->vif->bss_conf.ema_ap) + *flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE; + + return 0; +} + +static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, + struct vdev_create_params *params) { struct ath11k *ar = arvif->ar; struct ath11k_pdev *pdev = ar->pdev; + int ret; params->if_id = arvif->vdev_id; params->type = arvif->vdev_type; params->subtype = arvif->vdev_subtype; params->pdev_id = pdev->pdev_id; + params->mbssid_flags = 0; + params->mbssid_tx_vdev_id = 0; + + if (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + ret = ath11k_mac_setup_vdev_params_mbssid(arvif, + ¶ms->mbssid_flags, + ¶ms->mbssid_tx_vdev_id); + if (ret) + return ret; + } if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) { params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains; @@ -6206,6 +6502,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif, params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains; params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains; } + return 0; } static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, @@ -6500,7 +6797,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++) vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1); - ath11k_mac_setup_vdev_create_params(arvif, &vdev_param); + ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param); + if (ret) { + ath11k_warn(ab, "failed to create vdev parameters %d: %d\n", + arvif->vdev_id, ret); + goto err; + } ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param); if (ret) { @@ -6905,6 +7207,17 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif, arg.pref_tx_streams = ar->num_tx_chains; arg.pref_rx_streams = ar->num_rx_chains; + arg.mbssid_flags = 0; + arg.mbssid_tx_vdev_id = 0; + if (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT, + ar->ab->wmi_ab.svc_map)) { + ret = ath11k_mac_setup_vdev_params_mbssid(arvif, + &arg.mbssid_flags, + &arg.mbssid_tx_vdev_id); + if (ret) + return ret; + } + if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { arg.ssid = arvif->u.ap.ssid; arg.ssid_len = arvif->u.ap.ssid_len; @@ -7071,7 +7384,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, int n_vifs) { struct ath11k_base *ab = ar->ab; - struct ath11k_vif *arvif; + struct ath11k_vif *arvif, *tx_arvif = NULL; + struct ieee80211_vif *mbssid_tx_vif; int ret; int i; bool monitor_vif = false; @@ -7125,8 +7439,15 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", ret); + mbssid_tx_vif = arvif->vif->mbssid_tx_vif; + if (mbssid_tx_vif) + tx_arvif = (struct ath11k_vif *)mbssid_tx_vif->drv_priv; + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, - arvif->bssid); + arvif->bssid, + tx_arvif ? tx_arvif->bssid : NULL, + arvif->vif->bss_conf.bssid_index, + 1 << arvif->vif->bss_conf.bssid_indicator); if (ret) { ath11k_warn(ab, "failed to bring vdev up %d: %d\n", arvif->vdev_id, ret); @@ -7244,7 +7565,8 @@ static int ath11k_start_vdev_delay(struct ieee80211_hw *hw, } if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { - ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr); + ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr, + NULL, 0, 0); if (ret) { ath11k_warn(ab, "failed put monitor up: %d\n", ret); return ret; @@ -7542,20 +7864,6 @@ static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v ath11k_mac_flush_tx_complete(ar); } -static int -ath11k_mac_bitrate_mask_num_ht_rates(struct ath11k *ar, - enum nl80211_band band, - const struct cfg80211_bitrate_mask *mask) -{ - int num_rates = 0; - int i; - - for (i = 0; i < ARRAY_SIZE(mask->control[band].ht_mcs); i++) - num_rates += hweight16(mask->control[band].ht_mcs[i]); - - return num_rates; -} - static bool ath11k_mac_has_single_legacy_rate(struct ath11k *ar, enum nl80211_band band, @@ -8892,7 +9200,7 @@ static int ath11k_mac_setup_channels_rates(struct ath11k *ar, } if (supported_bands & WMI_HOST_WLAN_5G_CAP) { - if (reg_cap->high_5ghz_chan >= ATH11K_MAX_6G_FREQ) { + if (reg_cap->high_5ghz_chan >= ATH11K_MIN_6G_FREQ) { channels = kmemdup(ath11k_6ghz_channels, sizeof(ath11k_6ghz_channels), GFP_KERNEL); if (!channels) { @@ -9001,19 +9309,23 @@ static int ath11k_mac_setup_iface_combinations(struct ath11k *ar) static const u8 ath11k_if_types_ext_capa[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, }; static const u8 ath11k_if_types_ext_capa_sta[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, [9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT, }; static const u8 ath11k_if_types_ext_capa_ap[] = { [0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING, + [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT, [7] = WLAN_EXT_CAPA8_OPMODE_NOTIF, [9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT, + [10] = WLAN_EXT_CAPA11_EMA_SUPPORT, }; static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = { @@ -9251,6 +9563,9 @@ static int __ath11k_mac_register(struct ath11k *ar) wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER); + ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab); + ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD; + ath11k_reg_init(ar); if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index d0b59bc2905a9b..443199e85fa2c9 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -724,6 +724,9 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr, cmd->vdev_subtype = param->subtype; cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX; cmd->pdev_id = param->pdev_id; + cmd->mbssid_flags = param->mbssid_flags; + cmd->mbssid_tx_vdev_id = param->mbssid_tx_vdev_id; + ether_addr_copy(cmd->vdev_macaddr.addr, macaddr); ptr = skb->data + sizeof(*cmd); @@ -941,6 +944,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, cmd->cac_duration_ms = arg->cac_duration_ms; cmd->regdomain = arg->regdomain; cmd->he_ops = arg->he_ops; + cmd->mbssid_flags = arg->mbssid_flags; + cmd->mbssid_tx_vdev_id = arg->mbssid_tx_vdev_id; if (!restart) { if (arg->ssid) { @@ -996,7 +1001,8 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, return ret; } -int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid) +int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid, + u8 *tx_bssid, u32 nontx_profile_idx, u32 nontx_profile_cnt) { struct ath11k_pdev_wmi *wmi = ar->wmi; struct wmi_vdev_up_cmd *cmd; @@ -1020,14 +1026,19 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid) ether_addr_copy(cmd->vdev_bssid.addr, bssid); + cmd->nontx_profile_idx = nontx_profile_idx; + cmd->nontx_profile_cnt = nontx_profile_cnt; + if (tx_bssid) + ether_addr_copy(cmd->tx_vdev_bssid.addr, tx_bssid); + if (arvif && arvif->vif->type == NL80211_IFTYPE_STATION) { bss_conf = &arvif->vif->bss_conf; if (bss_conf->nontransmitted) { - ether_addr_copy(cmd->trans_bssid.addr, + ether_addr_copy(cmd->tx_vdev_bssid.addr, bss_conf->transmitter_bssid); - cmd->profile_idx = bss_conf->bssid_index; - cmd->profile_num = bss_conf->bssid_indicator; + cmd->nontx_profile_idx = bss_conf->bssid_index; + cmd->nontx_profile_cnt = bss_conf->bssid_indicator; } } @@ -1688,7 +1699,7 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar, int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, - struct sk_buff *bcn) + struct sk_buff *bcn, u32 ema_params) { struct ath11k_pdev_wmi *wmi = ar->wmi; struct wmi_bcn_tmpl_cmd *cmd; @@ -1726,6 +1737,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, } cmd->buf_len = bcn->len; + cmd->mbssid_ie_offset = offs->mbssid_off; + cmd->ema_params = ema_params; ptr = skb->data + sizeof(*cmd); @@ -3987,6 +4000,9 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg, ~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); + wmi_cfg->flags2 = WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET; + wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt; + wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period; } static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, @@ -6548,28 +6564,6 @@ int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb, &parse); } -size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head) -{ - struct ath11k_fw_stats_vdev *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - -static size_t ath11k_wmi_fw_stats_num_bcn(struct list_head *head) -{ - struct ath11k_fw_stats_bcn *i; - size_t num = 0; - - list_for_each_entry(i, head, list) - ++num; - - return num; -} - static void ath11k_wmi_fw_pdev_base_stats_fill(const struct ath11k_fw_stats_pdev *pdev, char *buf, u32 *length) @@ -6880,7 +6874,7 @@ void ath11k_wmi_fw_stats_fill(struct ath11k *ar, } if (stats_id == WMI_REQUEST_BCN_STAT) { - num_bcn = ath11k_wmi_fw_stats_num_bcn(&fw_stats->bcn); + num_bcn = list_count_nodes(&fw_stats->bcn); len += scnprintf(buf + len, buf_len - len, "\n"); len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 92fddb77669c23..43aaf55b7f2a17 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -137,6 +137,14 @@ enum { WMI_AUTORATE_3200NS_GI = BIT(11), }; +enum { + WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 0x00000001, + WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 0x00000002, + WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 0x00000004, + WMI_HOST_VDEV_FLAGS_EMA_MODE = 0x00000008, + WMI_HOST_VDEV_FLAGS_SCAN_MODE_VAP = 0x00000010, +}; + /* * wmi command groups. */ @@ -2096,6 +2104,7 @@ enum wmi_tlv_service { WMI_TLV_SERVICE_EXT2_MSG = 220, WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246, WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249, + WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253, WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE = 263, /* The second 128 bits */ @@ -2317,6 +2326,7 @@ struct wmi_init_cmd { } __packed; #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) +#define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9) #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) #define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4 @@ -2389,6 +2399,9 @@ struct wmi_resource_config { u32 msdu_flow_override_config1; u32 flags2; u32 host_service_flags; + u32 max_rnr_neighbours; + u32 ema_max_vap_cnt; + u32 ema_max_profile_period; } __packed; struct wmi_service_ready_event { @@ -2579,6 +2592,8 @@ struct vdev_create_params { u8 rx; } chains[NUM_NL80211_BANDS]; u32 pdev_id; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; }; struct wmi_vdev_create_cmd { @@ -2589,6 +2604,8 @@ struct wmi_vdev_create_cmd { struct wmi_mac_addr vdev_macaddr; u32 num_cfg_txrx_streams; u32 pdev_id; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; } __packed; struct wmi_vdev_txrx_streams { @@ -2608,9 +2625,9 @@ struct wmi_vdev_up_cmd { u32 vdev_id; u32 vdev_assoc_id; struct wmi_mac_addr vdev_bssid; - struct wmi_mac_addr trans_bssid; - u32 profile_idx; - u32 profile_num; + struct wmi_mac_addr tx_vdev_bssid; + u32 nontx_profile_idx; + u32 nontx_profile_cnt; } __packed; struct wmi_vdev_stop_cmd { @@ -2652,6 +2669,9 @@ struct wmi_vdev_start_request_cmd { u32 he_ops; u32 cac_duration_ms; u32 regdomain; + u32 min_data_rate; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; } __packed; #define MGMT_TX_DL_FRM_LEN 64 @@ -2821,6 +2841,9 @@ struct wmi_vdev_start_req_arg { u32 pref_rx_streams; u32 pref_tx_streams; u32 num_noa_descriptors; + u32 min_data_rate; + u32 mbssid_flags; + u32 mbssid_tx_vdev_id; }; struct peer_create_params { @@ -3543,6 +3566,10 @@ struct wmi_get_pdev_temperature_cmd { #define WMI_BEACON_TX_BUFFER_SIZE 512 +#define WMI_EMA_TMPL_IDX_SHIFT 8 +#define WMI_EMA_FIRST_TMPL_SHIFT 16 +#define WMI_EMA_LAST_TMPL_SHIFT 24 + struct wmi_bcn_tmpl_cmd { u32 tlv_header; u32 vdev_id; @@ -3553,6 +3580,11 @@ struct wmi_bcn_tmpl_cmd { u32 csa_event_bitmap; u32 mbssid_ie_offset; u32 esp_ie_offset; + u32 csc_switch_count_offset; + u32 csc_event_bitmap; + u32 mu_edca_ie_offset; + u32 feature_enable_bitmap; + u32 ema_params; } __packed; struct wmi_key_seq_counter { @@ -5646,6 +5678,8 @@ struct target_resource_config { u32 twt_ap_pdev_count; u32 twt_ap_sta_count; u8 is_reg_cc_ext_event_supported; + u32 ema_max_vap_cnt; + u32 ema_max_profile_period; }; enum wmi_debug_log_param { @@ -6273,10 +6307,11 @@ int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id, struct sk_buff *frame); int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id, struct ieee80211_mutable_offsets *offs, - struct sk_buff *bcn); + struct sk_buff *bcn, u32 ema_param); int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id); int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, - const u8 *bssid); + const u8 *bssid, u8 *tx_bssid, u32 nontx_profile_idx, + u32 nontx_profile_cnt); int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id); int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg, bool restart); @@ -6372,9 +6407,6 @@ int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar, struct pdev_set_regdomain_params *param); int ath11k_wmi_pull_fw_stats(struct ath11k_base *ab, struct sk_buff *skb, struct ath11k_fw_stats *stats); -size_t ath11k_wmi_fw_stats_num_peers(struct list_head *head); -size_t ath11k_wmi_fw_stats_num_peers_extd(struct list_head *head); -size_t ath11k_wmi_fw_stats_num_vdevs(struct list_head *head); void ath11k_wmi_fw_stats_fill(struct ath11k *ar, struct ath11k_fw_stats *fw_stats, u32 stats_id, char *buf); diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index a89e66653f044f..499b81cd938ea6 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -706,6 +706,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar); idr_destroy(&ar->txmgmt_idr); + wake_up(&ar->txmgmt_empty_waitq); } wake_up(&ab->wmi_ab.tx_credits_wq); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 9439052a652e81..2f93296db792a5 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -533,6 +533,7 @@ struct ath12k { /* protects txmgmt_idr data */ spinlock_t txmgmt_idr_lock; atomic_t num_pending_mgmt_tx; + wait_queue_head_t txmgmt_empty_waitq; /* cycle count is reported twice for each visited channel during scan. * access protected by data_lock diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index e78478a5b97822..8c8162fbe5c610 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -978,7 +978,19 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_ return ret; } - return ret; + if (!ab->hw_params->reoq_lut_support) { + ret = ath12k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, + peer_mac, + paddr, tid, 1, + ba_win_sz); + if (ret) { + ath12k_warn(ab, "failed to setup peer rx reorder queuefor tid %d: %d\n", + tid, ret); + return ret; + } + } + + return 0; } rx_tid->tid = tid; @@ -1362,11 +1374,6 @@ ath12k_update_per_peer_tx_stats(struct ath12k *ar, * Firmware rate's control to be skipped for this? */ - if (flags == WMI_RATE_PREAMBLE_HE && mcs > 11) { - ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs); - return; - } - if (flags == WMI_RATE_PREAMBLE_HE && mcs > ATH12K_HE_MCS_MAX) { ath12k_warn(ab, "Invalid HE mcs %d peer stats", mcs); return; diff --git a/drivers/net/wireless/ath/ath12k/hw.c b/drivers/net/wireless/ath/ath12k/hw.c index 1ffac7e3deaaf2..5991cc91cd00f0 100644 --- a/drivers/net/wireless/ath/ath12k/hw.c +++ b/drivers/net/wireless/ath/ath12k/hw.c @@ -906,6 +906,7 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .hal_ops = &hal_qcn9274_ops, + .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01), }, { .name = "wcn7850 hw2.0", @@ -960,6 +961,9 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .wmi_init = ath12k_wmi_init_wcn7850, .hal_ops = &hal_wcn7850_ops, + + .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01) | + BIT(CNSS_PCIE_PERST_NO_PULL_V01), }, { .name = "qcn9274 hw2.0", @@ -1013,6 +1017,8 @@ static const struct ath12k_hw_params ath12k_hw_params[] = { .wmi_init = ath12k_wmi_init_qcn9274, .hal_ops = &hal_qcn9274_ops, + + .qmi_cnss_feature_bitmap = BIT(CNSS_QDSS_CFG_MISS_V01), }, }; diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index e3461004188bd2..e6c4223c283c30 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -184,6 +184,8 @@ struct ath12k_hw_params { struct ath12k_wmi_resource_config_arg *config); const struct hal_ops *hal_ops; + + u64 qmi_cnss_feature_bitmap; }; struct ath12k_hw_ops { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index ee792822b41132..d814d74bc16810 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -381,7 +381,7 @@ u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband, } static u32 -ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath12k_mac_max_ht_nss(const u8 *ht_mcs_mask) { int nss; @@ -393,7 +393,7 @@ ath12k_mac_max_ht_nss(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static u32 -ath12k_mac_max_vht_nss(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +ath12k_mac_max_vht_nss(const u16 *vht_mcs_mask) { int nss; @@ -771,6 +771,9 @@ static int ath12k_mac_vdev_setup_sync(struct ath12k *ar) if (test_bit(ATH12K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) return -ESHUTDOWN; + ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "vdev setup timeout %d\n", + ATH12K_VDEV_SETUP_TIMEOUT_HZ); + if (!wait_for_completion_timeout(&ar->vdev_setup_done, ATH12K_VDEV_SETUP_TIMEOUT_HZ)) return -ETIMEDOUT; @@ -1303,7 +1306,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar, } static bool -ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) +ath12k_peer_assoc_h_ht_masked(const u8 *ht_mcs_mask) { int nss; @@ -1315,7 +1318,7 @@ ath12k_peer_assoc_h_ht_masked(const u8 ht_mcs_mask[IEEE80211_HT_MCS_MASK_LEN]) } static bool -ath12k_peer_assoc_h_vht_masked(const u16 vht_mcs_mask[NL80211_VHT_NSS_MAX]) +ath12k_peer_assoc_h_vht_masked(const u16 *vht_mcs_mask) { int nss; @@ -4375,6 +4378,21 @@ static int __ath12k_set_antenna(struct ath12k *ar, u32 tx_ant, u32 rx_ant) return 0; } +static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb) +{ + int num_mgmt; + + ieee80211_free_txskb(ar->hw, skb); + + num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); + + if (num_mgmt < 0) + WARN_ON_ONCE(1); + + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); +} + int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) { struct sk_buff *msdu = skb; @@ -4391,7 +4409,7 @@ int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) info = IEEE80211_SKB_CB(msdu); memset(&info->status, 0, sizeof(info->status)); - ieee80211_free_txskb(ar->hw, msdu); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); return 0; } @@ -4475,7 +4493,7 @@ static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar) struct sk_buff *skb; while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) - ieee80211_free_txskb(ar->hw, skb); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) @@ -4490,7 +4508,7 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) skb_cb = ATH12K_SKB_CB(skb); if (!skb_cb->vif) { ath12k_warn(ar->ab, "no vif found for mgmt frame\n"); - ieee80211_free_txskb(ar->hw, skb); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); continue; } @@ -4501,16 +4519,14 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work) if (ret) { ath12k_warn(ar->ab, "failed to tx mgmt frame, vdev_id %d :%d\n", arvif->vdev_id, ret); - ieee80211_free_txskb(ar->hw, skb); - } else { - atomic_inc(&ar->num_pending_mgmt_tx); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } } else { ath12k_warn(ar->ab, "dropping mgmt frame for vdev %d, is_started %d\n", arvif->vdev_id, arvif->is_started); - ieee80211_free_txskb(ar->hw, skb); + ath12k_mgmt_over_wmi_tx_drop(ar, skb); } } } @@ -4535,12 +4551,13 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb, return -ENOSPC; } - if (skb_queue_len(q) == ATH12K_TX_MGMT_NUM_PENDING_MAX) { + if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) { ath12k_warn(ar->ab, "mgmt tx queue is full\n"); return -ENOSPC; } skb_queue_tail(q, skb); + atomic_inc(&ar->num_pending_mgmt_tx); ieee80211_queue_work(ar->hw, &ar->wmi_mgmt_tx_work); return 0; @@ -6014,6 +6031,13 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v ATH12K_FLUSH_TIMEOUT); if (time_left == 0) ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left); + + time_left = wait_event_timeout(ar->txmgmt_empty_waitq, + (atomic_read(&ar->num_pending_mgmt_tx) == 0), + ATH12K_FLUSH_TIMEOUT); + if (time_left == 0) + ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n", + time_left); } static int @@ -6991,6 +7015,7 @@ int ath12k_mac_register(struct ath12k_base *ab) if (ret) goto err_cleanup; + init_waitqueue_head(&ar->txmgmt_empty_waitq); idr_init(&ar->txmgmt_idr); spin_lock_init(&ar->txmgmt_idr_lock); } diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 03ba245fbee92e..4afba76b90fe68 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -1942,8 +1942,10 @@ static int ath12k_qmi_host_cap_send(struct ath12k_base *ab) req.cal_done_valid = 1; req.cal_done = ab->qmi.cal_done; - req.feature_list_valid = 1; - req.feature_list = BIT(CNSS_QDSS_CFG_MISS_V01); + if (ab->hw_params->qmi_cnss_feature_bitmap) { + req.feature_list_valid = 1; + req.feature_list = ab->hw_params->qmi_cnss_feature_bitmap; + } /* BRINGUP: here we are piggybacking a lot of stuff using * internal_sleep_clock, should it be split? diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index ad87f19903db8f..df76149c49f5fe 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -189,6 +189,7 @@ struct wlfw_host_mlo_chip_info_s_v01 { enum ath12k_qmi_cnss_feature { CNSS_FEATURE_MIN_ENUM_VAL_V01 = INT_MIN, CNSS_QDSS_CFG_MISS_V01 = 3, + CNSS_PCIE_PERST_NO_PULL_V01 = 4, CNSS_MAX_FEATURE_V01 = 64, CNSS_FEATURE_MAX_ENUM_VAL_V01 = INT_MAX, }; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 7ae0bb78b2b538..f1d0743eb3498f 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -4640,6 +4640,7 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, struct sk_buff *msdu; struct ieee80211_tx_info *info; struct ath12k_skb_cb *skb_cb; + int num_mgmt; spin_lock_bh(&ar->txmgmt_idr_lock); msdu = idr_find(&ar->txmgmt_idr, desc_id); @@ -4663,10 +4664,15 @@ static int wmi_process_mgmt_tx_comp(struct ath12k *ar, u32 desc_id, ieee80211_tx_status_irqsafe(ar->hw, msdu); + num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx); + /* WARN when we received this event without doing any mgmt tx */ - if (atomic_dec_if_positive(&ar->num_pending_mgmt_tx) < 0) + if (num_mgmt < 0) WARN_ON_ONCE(1); + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); + return 0; } diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 08a8c9e0f59fbd..5cae2522fc7c2d 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -2682,7 +2682,7 @@ struct ath12k_wmi_ssid_params { u8 ssid[ATH12K_WMI_SSID_LEN]; } __packed; -#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (1 * HZ) +#define ATH12K_VDEV_SETUP_TIMEOUT_HZ (5 * HZ) struct wmi_vdev_start_request_cmd { __le32 tlv_header; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index 4f27a9fb1482bf..e9bd13eeee92fd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c @@ -1099,17 +1099,22 @@ static bool ath9k_hw_verify_hang(struct ath_hw *ah, unsigned int queue) { u32 dma_dbg_chain, dma_dbg_complete; u8 dcu_chain_state, dcu_complete_state; + unsigned int dbg_reg, reg_offset; int i; - for (i = 0; i < NUM_STATUS_READS; i++) { - if (queue < 6) - dma_dbg_chain = REG_READ(ah, AR_DMADBG_4); - else - dma_dbg_chain = REG_READ(ah, AR_DMADBG_5); + if (queue < 6) { + dbg_reg = AR_DMADBG_4; + reg_offset = queue * 5; + } else { + dbg_reg = AR_DMADBG_5; + reg_offset = (queue - 6) * 5; + } + for (i = 0; i < NUM_STATUS_READS; i++) { + dma_dbg_chain = REG_READ(ah, dbg_reg); dma_dbg_complete = REG_READ(ah, AR_DMADBG_6); - dcu_chain_state = (dma_dbg_chain >> (5 * queue)) & 0x1f; + dcu_chain_state = (dma_dbg_chain >> reg_offset) & 0x1f; dcu_complete_state = dma_dbg_complete & 0x3; if ((dcu_chain_state != 0x6) || (dcu_complete_state != 0x1)) @@ -1128,6 +1133,7 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) u8 dcu_chain_state, dcu_complete_state; bool dcu_wait_frdone = false; unsigned long chk_dcu = 0; + unsigned int reg_offset; unsigned int i = 0; dma_dbg_4 = REG_READ(ah, AR_DMADBG_4); @@ -1139,12 +1145,15 @@ static bool ar9003_hw_detect_mac_hang(struct ath_hw *ah) goto exit; for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (i < 6) + if (i < 6) { chk_dbg = dma_dbg_4; - else + reg_offset = i * 5; + } else { chk_dbg = dma_dbg_5; + reg_offset = (i - 6) * 5; + } - dcu_chain_state = (chk_dbg >> (5 * i)) & 0x1f; + dcu_chain_state = (chk_dbg >> reg_offset) & 0x1f; if (dcu_chain_state == 0x6) { dcu_wait_frdone = true; chk_dcu |= BIT(i); diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c index 19345b8f7bfd59..d652c647d56b55 100644 --- a/drivers/net/wireless/ath/ath9k/wmi.c +++ b/drivers/net/wireless/ath/ath9k/wmi.c @@ -221,6 +221,10 @@ static void ath9k_wmi_ctrl_rx(void *priv, struct sk_buff *skb, if (unlikely(wmi->stopped)) goto free_skb; + /* Validate the obtained SKB. */ + if (unlikely(skb->len < sizeof(struct wmi_cmd_hdr))) + goto free_skb; + hdr = (struct wmi_cmd_hdr *) skb->data; cmd_id = be16_to_cpu(hdr->command_id); diff --git a/drivers/net/wireless/atmel/Kconfig b/drivers/net/wireless/atmel/Kconfig index ca45a1021cf4ea..bafdd57b049a11 100644 --- a/drivers/net/wireless/atmel/Kconfig +++ b/drivers/net/wireless/atmel/Kconfig @@ -14,7 +14,7 @@ if WLAN_VENDOR_ATMEL config ATMEL tristate "Atmel at76c50x chipset 802.11b support" - depends on CFG80211 && (PCI || PCMCIA) + depends on CFG80211 && (PCI || PCMCIA) && HAS_IOPORT select WIRELESS_EXT select WEXT_PRIV select FW_LOADER diff --git a/drivers/net/wireless/atmel/atmel_cs.c b/drivers/net/wireless/atmel/atmel_cs.c index 453bb84cb3386b..58bba9875d3667 100644 --- a/drivers/net/wireless/atmel/atmel_cs.c +++ b/drivers/net/wireless/atmel/atmel_cs.c @@ -72,6 +72,7 @@ struct local_info { static int atmel_probe(struct pcmcia_device *p_dev) { struct local_info *local; + int ret; dev_dbg(&p_dev->dev, "atmel_attach()\n"); @@ -82,8 +83,16 @@ static int atmel_probe(struct pcmcia_device *p_dev) p_dev->priv = local; - return atmel_config(p_dev); -} /* atmel_attach */ + ret = atmel_config(p_dev); + if (ret) + goto err_free_priv; + + return 0; + +err_free_priv: + kfree(p_dev->priv); + return ret; +} static void atmel_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c index 9f9bf08a70bb46..2ef92ef25517e8 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/chip.c @@ -972,6 +972,7 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) u32 regdata; u32 socitype; int ret; + const u32 READ_FAILED = 0xFFFFFFFF; /* Get CC core rev * Chipid is assume to be at offset 0 from SI_ENUM_BASE @@ -980,6 +981,11 @@ static int brcmf_chip_recognition(struct brcmf_chip_priv *ci) */ regdata = ci->ops->read32(ci->ctx, CORE_CC_REG(ci->pub.enum_base, chipid)); + if (regdata == READ_FAILED) { + brcmf_err("MMIO read failed: 0x%08x\n", regdata); + return -ENODEV; + } + ci->pub.chip = regdata & CID_ID_MASK; ci->pub.chiprev = (regdata & CID_REV_MASK) >> CID_REV_SHIFT; socitype = (regdata & CID_TYPE_MASK) >> CID_TYPE_SHIFT; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c index 02de99818efa70..5573a47766ad5f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/core.c @@ -12,13 +12,13 @@ static int brcmf_wcc_attach(struct brcmf_pub *drvr) { - pr_err("%s: executing\n", __func__); + pr_debug("%s: executing\n", __func__); return 0; } static void brcmf_wcc_detach(struct brcmf_pub *drvr) { - pr_err("%s: executing\n", __func__); + pr_debug("%s: executing\n", __func__); } const struct brcmf_fwvid_ops brcmf_wcc_ops = { diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c index e87e68cc46e229..fe94db0ba3f33c 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/utils.c @@ -186,7 +186,7 @@ struct sk_buff *brcmu_pktq_peek_tail(struct pktq *pq, int *prec_out) { int prec; - if (pq->len == 0) + if (pktq_empty(pq)) return NULL; for (prec = 0; prec < pq->hi_prec; prec++) @@ -223,7 +223,7 @@ struct sk_buff *brcmu_pktq_mdeq(struct pktq *pq, uint prec_bmp, struct sk_buff *p; int prec; - if (pq->len == 0) + if (pktq_empty(pq)) return NULL; while ((prec = pq->hi_prec) > 0 && diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index b6f82510e9807b..2cf3af284680c3 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -11,6 +11,7 @@ /* Highest firmware API version supported */ #define IWL_22000_UCODE_API_MAX 78 +#define IWL_22500_UCODE_API_MAX 77 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 @@ -222,7 +223,6 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = { }; #define IWL_DEVICE_22000_COMMON \ - .ucode_api_max = IWL_22000_UCODE_API_MAX, \ .ucode_api_min = IWL_22000_UCODE_API_MIN, \ .led_mode = IWL_LED_RF_STATE, \ .nvm_hw_section_num = 10, \ @@ -261,6 +261,7 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = { #define IWL_DEVICE_22500 \ IWL_DEVICE_22000_COMMON, \ + .ucode_api_max = IWL_22500_UCODE_API_MAX, \ .trans.device_family = IWL_DEVICE_FAMILY_22000, \ .trans.base_params = &iwl_22000_base_params, \ .gp2_reg_addr = 0xa02c68, \ @@ -277,6 +278,7 @@ static const struct iwl_ht_params iwl_gl_a_ht_params = { #define IWL_DEVICE_AX210 \ IWL_DEVICE_22000_COMMON, \ + .ucode_api_max = IWL_22000_UCODE_API_MAX, \ .trans.umac_prph_offset = 0x300000, \ .trans.device_family = IWL_DEVICE_FAMILY_AX210, \ .trans.base_params = &iwl_ax210_base_params, \ @@ -1178,14 +1180,14 @@ const struct iwl_cfg iwl_cfg_bnj_b0_fm_b0 = { .features = IWL_TX_CSUM_NETIF_FLAGS_BZ | NETIF_F_RXCSUM, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; -MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22500_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c index cb9181f0550113..018d820ae231ff 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.c @@ -41,6 +41,34 @@ static const struct dmi_system_id dmi_ppag_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), }, }, + { .ident = "GOOGLE-HP", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "HP"), + }, + }, + { .ident = "GOOGLE-ASUS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."), + }, + }, + { .ident = "GOOGLE-SAMSUNG", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), + }, + }, + { .ident = "DELL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + }, + }, + { .ident = "DELL", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), + }, + }, {} }; @@ -1149,7 +1177,15 @@ int iwl_read_ppag_table(struct iwl_fw_runtime *fwrt, union iwl_ppag_table_cmd *c IWL_DEBUG_RADIO(fwrt, "PPAG table rev is %d but FW supports v1, sending truncated table\n", fwrt->ppag_ver); - cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); + if (!fw_has_capa(&fwrt->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) { + cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); + IWL_DEBUG_RADIO(fwrt, + "FW doesn't support ppag China bit\n"); + } else { + IWL_DEBUG_RADIO(fwrt, + "FW supports ppag China bit\n"); + } } } else if (cmd_ver >= 2 && cmd_ver <= 4) { num_sub_bands = IWL_NUM_SUB_BANDS_V2; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h index 29e2816e70520f..b6b5959cb2595d 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/binding.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2020 Intel Corporation + * Copyright (C) 2012-2014, 2020, 2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -18,7 +18,7 @@ * ( BINDING_CONTEXT_CMD = 0x2b ) * @id_and_color: ID and color of the relevant Binding, * &enum iwl_ctxt_id_and_color - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @macs: array of MAC id and colors which belong to the binding, * &enum iwl_ctxt_id_and_color * @phy: PHY id and color which belongs to the binding, @@ -38,7 +38,7 @@ struct iwl_binding_cmd_v1 { * ( BINDING_CONTEXT_CMD = 0x2b ) * @id_and_color: ID and color of the relevant Binding, * &enum iwl_ctxt_id_and_color - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @macs: array of MAC id and colors which belong to the binding * &enum iwl_ctxt_id_and_color * @phy: PHY id and color which belongs to the binding diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h index 111d96cbde6f81..13cb0d53a1a37c 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/commands.h @@ -138,11 +138,6 @@ enum iwl_legacy_cmds { */ REMOVE_STA = 0x19, - /** - * @FW_GET_ITEM_CMD: uses &struct iwl_fw_get_item_cmd - */ - FW_GET_ITEM_CMD = 0x1a, - /** * @TX_CMD: uses &struct iwl_tx_cmd or &struct iwl_tx_cmd_gen2 or * &struct iwl_tx_cmd_gen3, @@ -533,12 +528,6 @@ enum iwl_legacy_cmds { */ PROT_OFFLOAD_CONFIG_CMD = 0xd4, - /** - * @OFFLOADS_QUERY_CMD: - * No data in command, response in &struct iwl_wowlan_status - */ - OFFLOADS_QUERY_CMD = 0xd5, - /** * @D0I3_END_CMD: End D0i3/D3 state, no command data */ @@ -566,18 +555,22 @@ enum iwl_legacy_cmds { WOWLAN_TKIP_PARAM = 0xe3, /** - * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd + * @WOWLAN_KEK_KCK_MATERIAL: &struct iwl_wowlan_kek_kck_material_cmd_v2, + * &struct iwl_wowlan_kek_kck_material_cmd_v3 or + * &struct iwl_wowlan_kek_kck_material_cmd_v4 */ WOWLAN_KEK_KCK_MATERIAL = 0xe4, /** - * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status + * @WOWLAN_GET_STATUSES: response in &struct iwl_wowlan_status_v6, + * &struct iwl_wowlan_status_v7, &struct iwl_wowlan_status_v9 or + * &struct iwl_wowlan_status_v12 */ WOWLAN_GET_STATUSES = 0xe5, /** - * @SCAN_OFFLOAD_PROFILES_QUERY_CMD: - * No command data, response is &struct iwl_scan_offload_profiles_query + * @SCAN_OFFLOAD_PROFILES_QUERY_CMD: No command data, response is + * &struct iwl_scan_offload_profiles_query_v1 */ SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h index 105ba7170c3f08..1fa5678c1cd6b7 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/context.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/context.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014 Intel Corporation + * Copyright (C) 2012-2014, 2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -26,13 +26,18 @@ enum iwl_ctxt_id_and_color { #define FW_CMD_ID_AND_COLOR(_id, _color) (((_id) << FW_CTXT_ID_POS) |\ ((_color) << FW_CTXT_COLOR_POS)) -/* Possible actions on PHYs, MACs and Bindings */ +/** + * enum iwl_ctxt_action - Posssible actions on PHYs, MACs, Bindings and other + * @FW_CTXT_ACTION_INVALID: unused, invalid action + * @FW_CTXT_ACTION_ADD: add the context + * @FW_CTXT_ACTION_MODIFY: modify the context + * @FW_CTXT_ACTION_REMOVE: remove the context + */ enum iwl_ctxt_action { - FW_CTXT_ACTION_STUB = 0, + FW_CTXT_ACTION_INVALID = 0, FW_CTXT_ACTION_ADD, FW_CTXT_ACTION_MODIFY, FW_CTXT_ACTION_REMOVE, - FW_CTXT_ACTION_NUM }; /* COMMON_CONTEXT_ACTION_API_E_VER_1 */ #endif /* __iwl_fw_api_context_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h index 8a613e150a0245..37ac2364e71451 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/d3.h @@ -47,12 +47,14 @@ struct iwl_d3_manager_config { * @IWL_D3_PROTO_OFFLOAD_NS: NS (Neighbor Solicitation) is enabled * @IWL_D3_PROTO_IPV4_VALID: IPv4 data is valid * @IWL_D3_PROTO_IPV6_VALID: IPv6 data is valid + * @IWL_D3_PROTO_REJECT_BTM: reject BTM request */ enum iwl_proto_offloads { IWL_D3_PROTO_OFFLOAD_ARP = BIT(0), IWL_D3_PROTO_OFFLOAD_NS = BIT(1), IWL_D3_PROTO_IPV4_VALID = BIT(2), IWL_D3_PROTO_IPV6_VALID = BIT(3), + IWL_D3_PROTO_REJECT_BTM = BIT(4), }; #define IWL_PROTO_OFFLOAD_NUM_IPV6_ADDRS_V1 2 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h index 6f59381b9f9a97..751b596ea1a51b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h @@ -38,7 +38,9 @@ enum iwl_data_path_subcmd_ids { WNM_80211V_TIMING_MEASUREMENT_CONFIG_CMD = 0x4, /** - * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd + * @STA_HE_CTXT_CMD: &struct iwl_he_sta_context_cmd_v1, + * &struct iwl_he_sta_context_cmd_v2 or + * &struct iwl_he_sta_context_cmd_v3 */ STA_HE_CTXT_CMD = 0x7, @@ -447,7 +449,7 @@ struct iwl_sad_properties { * @phy_id: PHY index * @rlc: RLC properties, &struct iwl_rlc_properties * @sad: SAD (single antenna diversity) options, &struct iwl_sad_properties - * @flags: flags, &enum iwl_rlc_flags + * @flags: flags (unused) * @reserved: reserved */ struct iwl_rlc_config_cmd { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 12af94e166ed0b..b044990c7b8764 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #ifndef __iwl_fw_api_location_h__ #define __iwl_fw_api_location_h__ @@ -35,8 +35,11 @@ enum iwl_location_subcmd_ids { */ TOF_RANGE_REQ_EXT_CMD = 0x3, /** - * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, - * uses &struct iwl_tof_responder_config_cmd + * @TOF_RESPONDER_CONFIG_CMD: FTM responder configuration, one of + * &struct iwl_tof_responder_config_cmd_v6, + * &struct iwl_tof_responder_config_cmd_v7, + * &struct iwl_tof_responder_config_cmd_v8 or + * &struct iwl_tof_responder_config_cmd_v9 */ TOF_RESPONDER_CONFIG_CMD = 0x4, /** @@ -69,8 +72,11 @@ enum iwl_location_subcmd_ids { */ TOF_MCSI_DEBUG_NOTIF = 0xFE, /** - * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using - * &struct iwl_tof_range_rsp_ntfy + * @TOF_RANGE_RESPONSE_NOTIF: ranging response, using one of + * &struct iwl_tof_range_rsp_ntfy_v5, + * &struct iwl_tof_range_rsp_ntfy_v6, + * &struct iwl_tof_range_rsp_ntfy_v7 or + * &struct iwl_tof_range_rsp_ntfy_v8 */ TOF_RANGE_RESPONSE_NOTIF = 0xFF, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h index 74f2efbad34e46..a4cb24934a01a9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac-cfg.h @@ -140,40 +140,60 @@ struct iwl_missed_vap_notif { * * @id_and_color: ID and color of the MAC */ -struct iwl_channel_switch_start_notif { +struct iwl_channel_switch_start_notif_v1 { __le32 id_and_color; } __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_1 */ +/** + * struct iwl_channel_switch_start_notif - Channel switch start notification + * + * @link_id: FW link id + */ +struct iwl_channel_switch_start_notif { + __le32 link_id; +} __packed; /* CHANNEL_SWITCH_START_NTFY_API_S_VER_3 */ + #define CS_ERR_COUNT_ERROR BIT(0) #define CS_ERR_LONG_DELAY_AFTER_CS BIT(1) #define CS_ERR_LONG_TX_BLOCK BIT(2) #define CS_ERR_TX_BLOCK_TIMER_EXPIRED BIT(3) /** - * struct iwl_channel_switch_error_notif - Channel switch error notification + * struct iwl_channel_switch_error_notif_v1 - Channel switch error notification * * @mac_id: the mac for which the ucode sends the notification for * @csa_err_mask: mask of channel switch error that can occur */ -struct iwl_channel_switch_error_notif { +struct iwl_channel_switch_error_notif_v1 { __le32 mac_id; __le32 csa_err_mask; } __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_1 */ +/** + * struct iwl_channel_switch_error_notif - Channel switch error notification + * + * @link_id: FW link id + * @csa_err_mask: mask of channel switch error that can occur + */ +struct iwl_channel_switch_error_notif { + __le32 link_id; + __le32 csa_err_mask; +} __packed; /* CHANNEL_SWITCH_ERROR_NTFY_API_S_VER_2 */ + /** * struct iwl_cancel_channel_switch_cmd - Cancel Channel Switch command * - * @mac_id: the mac that should cancel the channel switch + * @id: the id of the link or mac that should cancel the channel switch */ struct iwl_cancel_channel_switch_cmd { - __le32 mac_id; + __le32 id; } __packed; /* MAC_CANCEL_CHANNEL_SWITCH_S_VER_1 */ /** * struct iwl_chan_switch_te_cmd - Channel Switch Time Event command * * @mac_id: MAC ID for channel switch - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @tsf: beacon tsf * @cs_count: channel switch count from CSA/eCSA IE * @cs_delayed_bcn_count: if set to N (!= 0) GO/AP can delay N beacon intervals @@ -211,17 +231,30 @@ struct iwl_mac_low_latency_cmd { * struct iwl_mac_client_data - configuration data for client MAC context * * @is_assoc: 1 for associated state, 0 otherwise + * @esr_transition_timeout: the timeout required by the AP for the + * eSR transition. + * Available only from version 2 of the command. + * This values comes from the EMLSR transition delay in the EML + * Capabilities subfield. + * @reserved: alignment * @assoc_id: unique ID assigned by the AP during association + * @reserved1: alignment * @data_policy: see &enum iwl_mac_data_policy + * @reserved2: alignment * @ctwin: client traffic window in TU (period after TBTT when GO is present). * 0 indicates that there is no CT window. */ struct iwl_mac_client_data { - __le32 is_assoc; - __le32 assoc_id; - __le32 data_policy; + u8 is_assoc; + u8 esr_transition_timeout; + __le16 reserved; + + __le16 assoc_id; + __le16 reserved1; + __le16 data_policy; + __le16 reserved2; __le32 ctwin; -} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_1 */ +} __packed; /* MAC_CONTEXT_CONFIG_CLIENT_DATA_API_S_VER_2 */ /** * struct iwl_mac_p2p_dev_data - configuration data for P2P device MAC context @@ -263,7 +296,7 @@ enum iwl_mac_config_filter_flags { * ( MAC_CONTEXT_CONFIG_CMD = 0x8 ) * * @id_and_color: ID and color of the MAC - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @mac_type: one of &enum iwl_mac_types * @local_mld_addr: mld address * @reserved_for_local_mld_addr: reserved @@ -292,12 +325,12 @@ struct iwl_mac_config_cmd { __le16 he_ap_support; __le32 eht_support; __le32 nic_not_ack_enabled; - /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_1 */ + /* MAC_CONTEXT_CONFIG_SPECIFIC_DATA_API_U_VER_2 */ union { struct iwl_mac_client_data client; struct iwl_mac_p2p_dev_data p2p_dev; }; -} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_1 */ +} __packed; /* MAC_CONTEXT_CONFIG_CMD_API_S_VER_2 */ /** * enum iwl_link_ctx_modify_flags - indicate to the fw what fields are being @@ -390,7 +423,7 @@ enum iwl_link_ctx_flags { * in MLD API * ( LINK_CONFIG_CMD =0x9 ) * - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @link_id: the id of the link that this cmd configures * @mac_id: interface ID. Relevant only if action is FW_CTXT_ACTION_ADD * @phy_id: PHY index. Can be changed only if the link was inactive @@ -430,6 +463,7 @@ enum iwl_link_ctx_flags { * @reserved_for_ref_bssid_addr: reserved * @bssid_index: index of the associated VAP * @bss_color: 11ax AP ID that is used in the HE SIG-A to mark inter BSS frame + * @spec_link_id: link_id as the AP knows it * @reserved: alignment * @ibss_bssid_addr: bssid for ibss * @reserved_for_ibss_bssid_addr: reserved @@ -469,7 +503,8 @@ struct iwl_link_config_cmd { __le16 reserved_for_ref_bssid_addr; u8 bssid_index; u8 bss_color; - u8 reserved[2]; + u8 spec_link_id; + u8 reserved; u8 ibss_bssid_addr[6]; __le16 reserved_for_ibss_bssid_addr; __le32 reserved1[8]; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h index e3eda251c728a6..55882190251c58 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/mac.h @@ -295,7 +295,7 @@ struct iwl_ac_qos { * struct iwl_mac_ctx_cmd - command structure to configure MAC contexts * ( MAC_CONTEXT_CMD = 0x28 ) * @id_and_color: ID and color of the MAC - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @mac_type: one of &enum iwl_mac_types * @tsf_id: TSF HW timer, one of &enum iwl_tsf_id * @node_addr: MAC address @@ -353,7 +353,7 @@ struct iwl_nonqos_seq_query_cmd { } __packed; /* NON_QOS_TX_COUNTER_GET_SET_API_S_VER_1 */ /** - * struct iwl_missed_beacons_notif - information on missed beacons + * struct iwl_missed_beacons_notif_ver_3 - information on missed beacons * ( MISSED_BEACONS_NOTIFICATION = 0xa2 ) * @mac_id: interface ID * @consec_missed_beacons_since_last_rx: number of consecutive missed @@ -362,7 +362,7 @@ struct iwl_nonqos_seq_query_cmd { * @num_expected_beacons: number of expected beacons * @num_recvd_beacons: number of received beacons */ -struct iwl_missed_beacons_notif { +struct iwl_missed_beacons_notif_ver_3 { __le32 mac_id; __le32 consec_missed_beacons_since_last_rx; __le32 consec_missed_beacons; @@ -370,6 +370,24 @@ struct iwl_missed_beacons_notif { __le32 num_recvd_beacons; } __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */ +/** + * struct iwl_missed_beacons_notif - information on missed beacons + * ( MISSED_BEACONS_NOTIFICATION = 0xa2 ) + * @link_id: fw link ID + * @consec_missed_beacons_since_last_rx: number of consecutive missed + * beacons since last RX. + * @consec_missed_beacons: number of consecutive missed beacons + * @num_expected_beacons: number of expected beacons + * @num_recvd_beacons: number of received beacons + */ +struct iwl_missed_beacons_notif { + __le32 link_id; + __le32 consec_missed_beacons_since_last_rx; + __le32 consec_missed_beacons; + __le32 num_expected_beacons; + __le32 num_recvd_beacons; +} __packed; /* MISSED_BEACON_NTFY_API_S_VER_4 */ + /** * struct iwl_he_backoff_conf - used for backoff configuration * Per each trigger-based AC, (set by MU EDCA Parameter set info-element) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 91bfde6d5367f1..71cce6dfeaf9d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -17,7 +17,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids { NVM_ACCESS_COMPLETE = 0x0, /** - * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd + * @LARI_CONFIG_CHANGE: &struct iwl_lari_config_change_cmd_v1, + * &struct iwl_lari_config_change_cmd_v2, + * &struct iwl_lari_config_change_cmd_v3, + * &struct iwl_lari_config_change_cmd_v4, + * &struct iwl_lari_config_change_cmd_v5 or + * &struct iwl_lari_config_change_cmd_v6 */ LARI_CONFIG_CHANGE = 0x1, @@ -29,12 +34,12 @@ enum iwl_regulatory_and_nvm_subcmd_ids { NVM_GET_INFO = 0x2, /** - * @TAS_CONFIG: &struct iwl_tas_config_cmd + * @TAS_CONFIG: &union iwl_tas_config_cmd */ TAS_CONFIG = 0x3, /** - * @SAR_OFFSET_MAPPING_TABLE_CMD: &iwl_sar_offset_mapping_cmd + * @SAR_OFFSET_MAPPING_TABLE_CMD: &struct iwl_sar_offset_mapping_cmd */ SAR_OFFSET_MAPPING_TABLE_CMD = 0x4, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h index a0123f81f5d8a3..898bf351f6e4d1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/offload.h @@ -28,7 +28,8 @@ enum iwl_prot_offload_subcmd_ids { D3_END_NOTIFICATION = 0xFE, /** - * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif + * @STORED_BEACON_NTF: &struct iwl_stored_beacon_notif_v2 or + * &struct iwl_stored_beacon_notif_v3 */ STORED_BEACON_NTF = 0xFF, }; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h index 2f7d8558becd22..8fe42cff1102ff 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy-ctxt.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018, 2020-2021 Intel Corporation + * Copyright (C) 2012-2014, 2018, 2020-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -116,7 +116,7 @@ struct iwl_phy_context_cmd_tail { * struct iwl_phy_context_cmd - config of the PHY context * ( PHY_CONTEXT_CMD = 0x8 ) * @id_and_color: ID and color of the relevant Binding - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @apply_time: 0 means immediate apply and context switch. * other value means apply new params after X usecs * @tx_param_color: ??? @@ -138,7 +138,7 @@ struct iwl_phy_context_cmd_v1 { * struct iwl_phy_context_cmd - config of the PHY context * ( PHY_CONTEXT_CMD = 0x8 ) * @id_and_color: ID and color of the relevant Binding - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @lmac_id: the lmac id the phy context belongs to * @ci: channel info * @rxchain_info: ??? diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h index b1b9c29859c17e..5a3f30e5e06d76 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/phy.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2019-2021 Intel Corporation + * Copyright (C) 2012-2014, 2019-2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -29,12 +29,16 @@ enum iwl_phy_ops_subcmd_ids { TEMP_REPORTING_THRESHOLDS_CMD = 0x04, /** - * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd + * @PER_CHAIN_LIMIT_OFFSET_CMD: &struct iwl_geo_tx_power_profiles_cmd_v1, + * &struct iwl_geo_tx_power_profiles_cmd_v2, + * &struct iwl_geo_tx_power_profiles_cmd_v3, + * &struct iwl_geo_tx_power_profiles_cmd_v4 or + * &struct iwl_geo_tx_power_profiles_cmd_v5 */ PER_CHAIN_LIMIT_OFFSET_CMD = 0x05, /** - * @PER_PLATFORM_ANT_GAIN_CMD: &struct iwl_ppag_table_cmd + * @PER_PLATFORM_ANT_GAIN_CMD: &union iwl_ppag_table_cmd */ PER_PLATFORM_ANT_GAIN_CMD = 0x07, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h index f92cac1da764ac..85d89f559f6c85 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/power.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/power.h @@ -537,7 +537,7 @@ union iwl_ppag_table_cmd { struct iwl_sar_offset_mapping_cmd { u8 offset_map[MCC_TO_SAR_OFFSET_TABLE_ROW_SIZE] [MCC_TO_SAR_OFFSET_TABLE_COL_SIZE]; - u16 reserved; + __le16 reserved; } __packed; /*SAR_OFFSET_MAPPING_TABLE_CMD_API_S*/ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index fdd8b01f09e4ca..67af922fd3bae1 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -367,8 +367,8 @@ enum iwl_rx_phy_eht_data1 { /* number of EHT-LTF symbols 0 - 1 EHT-LTF, 1 - 2 EHT-LTFs, 2 - 4 EHT-LTFs, * 3 - 6 EHT-LTFs, 4 - 8 EHT-LTFs */ IWL_RX_PHY_DATA1_EHT_SIG_LTF_NUM = 0x000000e0, - IWL_RX_PHY_DATA1_EHT_B0 = 0x00000100, - IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC = 0x0000fe00, + IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0 = 0x00000100, + IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7 = 0x0000fe00, }; /* goes into Metadata DW 7 */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h index 904cd78a9fa03d..7cc706731d706a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/time-event.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright (C) 2012-2014, 2018-2020 Intel Corporation + * Copyright (C) 2012-2014, 2018-2020, 2022 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -292,7 +292,7 @@ struct iwl_hs20_roc_req_tail { * ( HOT_SPOT_CMD 0x53 ) * * @id_and_color: ID and color of the MAC - * @action: action to perform, one of FW_CTXT_ACTION_* + * @action: action to perform, see &enum iwl_ctxt_action * @event_unique_id: If the action FW_CTXT_ACTION_REMOVE then the * event_unique_id should be the id of the time event assigned by ucode. * Otherwise ignore the event_unique_id. @@ -377,7 +377,8 @@ enum iwl_mvm_session_prot_conf_id { * struct iwl_mvm_session_prot_cmd - configure a session protection * @id_and_color: the id and color of the mac for which this session protection * is sent - * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE + * @action: can be either FW_CTXT_ACTION_ADD or FW_CTXT_ACTION_REMOVE, + * see &enum iwl_ctxt_action * @conf_id: see &enum iwl_mvm_session_prot_conf_id * @duration_tu: the duration of the whole protection in TUs. * @repetition_count: not used diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 55219974b92bf7..3c5a43a619c68a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -2034,7 +2034,6 @@ static u32 iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt, struct iwl_dump_ini_region_data *reg_data) { - u32 size = 0; u32 ranges = 0; u32 imr_enable = fwrt->trans->dbg.imr_data.imr_enable; u32 imr_size = fwrt->trans->dbg.imr_data.imr_size; @@ -2044,17 +2043,16 @@ iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt, IWL_DEBUG_INFO(fwrt, "WRT: Invalid imr data enable: %d, imr_size: %d, sram_size: %d\n", imr_enable, imr_size, sram_size); - return size; + return 0; } - size = imr_size; ranges = iwl_dump_ini_imr_ranges(fwrt, reg_data); - if (!size && !ranges) { - IWL_ERR(fwrt, "WRT: imr_size :=%d, ranges :=%d\n", size, ranges); + if (!ranges) { + IWL_ERR(fwrt, "WRT: ranges :=%d\n", ranges); return 0; } - size += sizeof(struct iwl_fw_ini_error_dump) + + imr_size += sizeof(struct iwl_fw_ini_error_dump) + ranges * sizeof(struct iwl_fw_ini_error_dump_range); - return size; + return imr_size; } /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/file.h b/drivers/net/wireless/intel/iwlwifi/fw/file.h index cddf09d6be1c5c..a78b68c2ae3d92 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/file.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/file.h @@ -323,6 +323,7 @@ typedef unsigned int __bitwise iwl_ucode_tlv_capa_t; * is supported. * @IWL_UCODE_TLV_CAPA_BT_COEX_RRC: supports BT Coex RRC * @IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT: supports gscan (no longer used) + * @IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG: supports fragmented PNVM image * @IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT: the firmware supports setting * stabilization latency for SoCs. * @IWL_UCODE_TLV_CAPA_STA_PM_NOTIF: firmware will send STA PM notification @@ -398,6 +399,7 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_GSCAN_SUPPORT = (__force iwl_ucode_tlv_capa_t)31, /* set 1 */ + IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG = (__force iwl_ucode_tlv_capa_t)32, IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT = (__force iwl_ucode_tlv_capa_t)37, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF = (__force iwl_ucode_tlv_capa_t)38, IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT = (__force iwl_ucode_tlv_capa_t)39, @@ -462,6 +464,9 @@ enum iwl_ucode_tlv_capa { IWL_UCODE_TLV_CAPA_BIGTK_TX_SUPPORT = (__force iwl_ucode_tlv_capa_t)109, IWL_UCODE_TLV_CAPA_MLD_API_SUPPORT = (__force iwl_ucode_tlv_capa_t)110, IWL_UCODE_TLV_CAPA_SCAN_DONT_TOGGLE_ANT = (__force iwl_ucode_tlv_capa_t)111, + IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT = (__force iwl_ucode_tlv_capa_t)112, + IWL_UCODE_TLV_CAPA_OFFLOAD_REJ_BTM_SUPPORT = (__force iwl_ucode_tlv_capa_t)113, + IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT = (__force iwl_ucode_tlv_capa_t)114, #ifdef __CHECKER__ /* sparse says it cannot increment the previous enum member */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c index c6f2672fdc7376..650e4bde9c17b9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright(c) 2020-2022 Intel Corporation + * Copyright(c) 2020-2023 Intel Corporation */ #include "iwl-drv.h" @@ -31,18 +31,18 @@ static bool iwl_pnvm_complete_fn(struct iwl_notif_wait_data *notif_wait, } static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, - size_t len) + size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; u32 sha1 = 0; u16 mac_type = 0, rf_id = 0; - u8 *pnvm_data = NULL, *tmp; bool hw_match = false; - u32 size = 0; - int ret; IWL_DEBUG_FW(trans, "Handling PNVM section\n"); + memset(pnvm_data, 0, sizeof(*pnvm_data)); + while (len >= sizeof(*tlv)) { u32 tlv_len, tlv_type; @@ -55,8 +55,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - ret = -EINVAL; - goto out; + return -EINVAL; } data += sizeof(*tlv); @@ -75,6 +74,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, IWL_DEBUG_FW(trans, "Got IWL_UCODE_TLV_PNVM_VERSION %0x\n", sha1); + pnvm_data->version = sha1; break; case IWL_UCODE_TLV_HW_TYPE: if (tlv_len < 2 * sizeof(__le16)) { @@ -112,26 +112,26 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, break; } - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", - data_len); - - tmp = krealloc(pnvm_data, size + data_len, GFP_KERNEL); - if (!tmp) { + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { IWL_DEBUG_FW(trans, - "Couldn't allocate (more) pnvm_data\n"); - - ret = -ENOMEM; - goto out; + "too many payloads to allocate in DRAM.\n"); + return -EINVAL; } - pnvm_data = tmp; - - memcpy(pnvm_data + size, section->data, data_len); + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", + data_len); - size += data_len; + pnvm_data->chunks[pnvm_data->n_chunks].data = section->data; + pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; + pnvm_data->n_chunks++; break; } + case IWL_UCODE_TLV_MEM_DESC: + if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, + pnvm_data)) + return -EINVAL; + break; case IWL_UCODE_TLV_PNVM_SKU: IWL_DEBUG_FW(trans, "New PNVM section started, stop parsing.\n"); @@ -152,26 +152,20 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data, "HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n", CSR_HW_REV_TYPE(trans->hw_rev), CSR_HW_RFID_TYPE(trans->hw_rf_id)); - ret = -ENOENT; - goto out; + return -ENOENT; } - if (!size) { + if (!pnvm_data->n_chunks) { IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n"); - ret = -ENOENT; - goto out; + return -ENOENT; } - IWL_INFO(trans, "loaded PNVM version %08x\n", sha1); - - ret = iwl_trans_set_pnvm(trans, pnvm_data, size); -out: - kfree(pnvm_data); - return ret; + return 0; } static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, - size_t len) + size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; @@ -212,7 +206,8 @@ static int iwl_pnvm_parse(struct iwl_trans *trans, const u8 *data, trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { int ret; - ret = iwl_pnvm_handle_section(trans, data, len); + ret = iwl_pnvm_handle_section(trans, data, len, + pnvm_data); if (!ret) return 0; } else { @@ -255,89 +250,136 @@ static int iwl_pnvm_get_from_fs(struct iwl_trans *trans, u8 **data, size_t *len) return 0; } -int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait) +static u8 *iwl_get_pnvm_image(struct iwl_trans *trans_p, size_t *len) { - u8 *data; - size_t len; struct pnvm_sku_package *package; - struct iwl_notification_wait pnvm_wait; - static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, - PNVM_INIT_COMPLETE_NTFY) }; - int ret; - - /* if the SKU_ID is empty, there's nothing to do */ - if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) - return 0; - - /* - * If we already loaded (or tried to load) it before, we just - * need to set it again. - */ - if (trans->pnvm_loaded) { - ret = iwl_trans_set_pnvm(trans, NULL, 0); - if (ret) - return ret; - goto skip_parse; - } + u8 *image = NULL; /* First attempt to get the PNVM from BIOS */ - package = iwl_uefi_get_pnvm(trans, &len); + package = iwl_uefi_get_pnvm(trans_p, len); if (!IS_ERR_OR_NULL(package)) { - if (len >= sizeof(*package)) { + if (*len >= sizeof(*package)) { /* we need only the data */ - len -= sizeof(*package); - data = kmemdup(package->data, len, GFP_KERNEL); - } else { - data = NULL; + *len -= sizeof(*package); + image = kmemdup(package->data, *len, GFP_KERNEL); } - /* free package regardless of whether kmemdup succeeded */ kfree(package); - - if (data) - goto parse; + if (image) + return image; } /* If it's not available, try from the filesystem */ - ret = iwl_pnvm_get_from_fs(trans, &data, &len); + if (iwl_pnvm_get_from_fs(trans_p, &image, len)) + return NULL; + return image; +} + +static void iwl_pnvm_load_pnvm_to_trans(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_pnvm_image *pnvm_data = NULL; + u8 *data = NULL; + size_t length; + int ret; + + /* failed to get/parse the image in the past, no use trying again */ + if (trans->fail_to_parse_pnvm_image) + return; + + if (trans->pnvm_loaded) + goto set; + + data = iwl_get_pnvm_image(trans, &length); + if (!data) { + trans->fail_to_parse_pnvm_image = true; + return; + } + + pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL); + if (!pnvm_data) + goto free; + + ret = iwl_pnvm_parse(trans, data, length, pnvm_data); if (ret) { - /* - * Pretend we've loaded it - at least we've tried and - * couldn't load it at all, so there's no point in - * trying again over and over. - */ - trans->pnvm_loaded = true; - - goto skip_parse; + trans->fail_to_parse_pnvm_image = true; + goto free; } -parse: - iwl_pnvm_parse(trans, data, len); + ret = iwl_trans_load_pnvm(trans, pnvm_data, capa); + if (ret) + goto free; + IWL_INFO(trans, "loaded PNVM version %08x\n", pnvm_data->version); +set: + iwl_trans_set_pnvm(trans, capa); +free: kfree(data); + kfree(pnvm_data); +} -skip_parse: - /* now try to get the reduce power table, if not loaded yet */ - if (!trans->reduce_power_loaded) { - data = iwl_uefi_get_reduced_power(trans, &len); - if (IS_ERR_OR_NULL(data)) { - /* - * Pretend we've loaded it - at least we've tried and - * couldn't load it at all, so there's no point in - * trying again over and over. - */ - trans->reduce_power_loaded = true; - } else { - ret = iwl_trans_set_reduce_power(trans, data, len); - if (ret) - IWL_DEBUG_FW(trans, - "Failed to set reduce power table %d\n", - ret); - kfree(data); - } +static void +iwl_pnvm_load_reduce_power_to_trans(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_pnvm_image *pnvm_data = NULL; + u8 *data = NULL; + size_t length; + int ret; + + if (trans->failed_to_load_reduce_power_image) + return; + + if (trans->reduce_power_loaded) + goto set; + + data = iwl_uefi_get_reduced_power(trans, &length); + if (IS_ERR(data)) { + trans->failed_to_load_reduce_power_image = true; + return; } + pnvm_data = kzalloc(sizeof(*pnvm_data), GFP_KERNEL); + if (!pnvm_data) + goto free; + + ret = iwl_uefi_reduce_power_parse(trans, data, length, pnvm_data); + if (ret) { + trans->failed_to_load_reduce_power_image = true; + goto free; + } + + ret = iwl_trans_load_reduce_power(trans, pnvm_data, capa); + if (ret) { + IWL_DEBUG_FW(trans, + "Failed to load reduce power table %d\n", + ret); + trans->failed_to_load_reduce_power_image = true; + goto free; + } + +set: + iwl_trans_set_reduce_power(trans, capa); +free: + kfree(data); + kfree(pnvm_data); +} + +int iwl_pnvm_load(struct iwl_trans *trans, + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa) +{ + struct iwl_notification_wait pnvm_wait; + static const u16 ntf_cmds[] = { WIDE_ID(REGULATORY_AND_NVM_GROUP, + PNVM_INIT_COMPLETE_NTFY) }; + + /* if the SKU_ID is empty, there's nothing to do */ + if (!trans->sku_id[0] && !trans->sku_id[1] && !trans->sku_id[2]) + return 0; + + iwl_pnvm_load_pnvm_to_trans(trans, capa); + iwl_pnvm_load_reduce_power_to_trans(trans, capa); + iwl_init_notification_wait(notif_wait, &pnvm_wait, ntf_cmds, ARRAY_SIZE(ntf_cmds), iwl_pnvm_complete_fn, trans); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h index 203c367dd4deec..4e10baa017386f 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /****************************************************************************** * - * Copyright(c) 2020-2021 Intel Corporation + * Copyright(c) 2020-2022 Intel Corporation * *****************************************************************************/ @@ -15,7 +15,8 @@ #define MAX_PNVM_NAME 64 int iwl_pnvm_load(struct iwl_trans *trans, - struct iwl_notif_wait_data *notif_wait); + struct iwl_notif_wait_data *notif_wait, + const struct iwl_ucode_capabilities *capa); static inline void iwl_pnvm_get_fs_name(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c index 01afea33c38cc0..9877988db0d277 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright(c) 2021-2022 Intel Corporation + * Copyright(c) 2021-2023 Intel Corporation */ #include "iwl-drv.h" @@ -17,52 +17,109 @@ 0xb2, 0xec, 0xf5, 0xa3, \ 0x59, 0x4f, 0x4a, 0xea) -void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +struct iwl_uefi_pnvm_mem_desc { + __le32 addr; + __le32 size; + const u8 data[]; +} __packed; + +static void *iwl_uefi_get_variable(efi_char16_t *name, efi_guid_t *guid, + unsigned long *data_size) { - void *data; - unsigned long package_size; efi_status_t status; + void *data; - *len = 0; + if (!data_size) + return ERR_PTR(-EINVAL); if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) return ERR_PTR(-ENODEV); - /* - * TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_PNVM_SIZE; + /* first call with NULL data to get the exact entry size */ + *data_size = 0; + status = efi.get_variable(name, guid, NULL, data_size, NULL); + if (status != EFI_BUFFER_TOO_SMALL || !*data_size) + return ERR_PTR(-EIO); - data = kmalloc(package_size, GFP_KERNEL); + data = kmalloc(*data_size, GFP_KERNEL); if (!data) return ERR_PTR(-ENOMEM); - status = efi.get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); + status = efi.get_variable(name, guid, NULL, data_size, data); if (status != EFI_SUCCESS) { - IWL_DEBUG_FW(trans, - "PNVM UEFI variable not found 0x%lx (len %lu)\n", - status, package_size); kfree(data); return ERR_PTR(-ENOENT); } + return data; +} + +void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +{ + unsigned long package_size; + void *data; + + *len = 0; + + data = iwl_uefi_get_variable(IWL_UEFI_OEM_PNVM_NAME, &IWL_EFI_VAR_GUID, + &package_size); + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "PNVM UEFI variable not found 0x%lx (len %lu)\n", + PTR_ERR(data), package_size); + return data; + } + IWL_DEBUG_FW(trans, "Read PNVM from UEFI with size %lu\n", package_size); *len = package_size; return data; } -static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, - const u8 *data, size_t len) +int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data) +{ + const struct iwl_uefi_pnvm_mem_desc *desc = (const void *)data; + u32 data_len; + + if (tlv_len < sizeof(*desc)) { + IWL_DEBUG_FW(trans, "TLV len (%d) is too small\n", tlv_len); + return -EINVAL; + } + + data_len = tlv_len - sizeof(*desc); + + IWL_DEBUG_FW(trans, + "Handle IWL_UCODE_TLV_MEM_DESC, len %d data_len %d\n", + tlv_len, data_len); + + if (le32_to_cpu(desc->size) != data_len) { + IWL_DEBUG_FW(trans, "invalid mem desc size %d\n", desc->size); + return -EINVAL; + } + + if (pnvm_data->n_chunks == IPC_DRAM_MAP_ENTRY_NUM_MAX) { + IWL_DEBUG_FW(trans, "too many payloads to allocate in DRAM.\n"); + return -EINVAL; + } + + IWL_DEBUG_FW(trans, "Adding data (size %d)\n", data_len); + + pnvm_data->chunks[pnvm_data->n_chunks].data = desc->data; + pnvm_data->chunks[pnvm_data->n_chunks].len = data_len; + pnvm_data->n_chunks++; + + return 0; +} + +static int iwl_uefi_reduce_power_section(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; - u8 *reduce_power_data = NULL, *tmp; - u32 size = 0; IWL_DEBUG_FW(trans, "Handling REDUCE_POWER section\n"); + memset(pnvm_data, 0, sizeof(*pnvm_data)); while (len >= sizeof(*tlv)) { u32 tlv_len, tlv_type; @@ -76,39 +133,17 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-EINVAL); - goto out; + return -EINVAL; } data += sizeof(*tlv); switch (tlv_type) { - case IWL_UCODE_TLV_MEM_DESC: { - IWL_DEBUG_FW(trans, - "Got IWL_UCODE_TLV_MEM_DESC len %d\n", - tlv_len); - - IWL_DEBUG_FW(trans, "Adding data (size %d)\n", tlv_len); - - tmp = krealloc(reduce_power_data, size + tlv_len, GFP_KERNEL); - if (!tmp) { - IWL_DEBUG_FW(trans, - "Couldn't allocate (more) reduce_power_data\n"); - - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOMEM); - goto out; - } - - reduce_power_data = tmp; - - memcpy(reduce_power_data + size, data, tlv_len); - - size += tlv_len; - + case IWL_UCODE_TLV_MEM_DESC: + if (iwl_uefi_handle_tlv_mem_desc(trans, data, tlv_len, + pnvm_data)) + return -EINVAL; break; - } case IWL_UCODE_TLV_PNVM_SKU: IWL_DEBUG_FW(trans, "New REDUCE_POWER section started, stop parsing.\n"); @@ -124,27 +159,18 @@ static void *iwl_uefi_reduce_power_section(struct iwl_trans *trans, } done: - if (!size) { + if (!pnvm_data->n_chunks) { IWL_DEBUG_FW(trans, "Empty REDUCE_POWER, skipping.\n"); - /* Better safe than sorry, but 'reduce_power_data' should - * always be NULL if !size. - */ - kfree(reduce_power_data); - reduce_power_data = ERR_PTR(-ENOENT); - goto out; + return -ENOENT; } - - IWL_INFO(trans, "loaded REDUCE_POWER\n"); - -out: - return reduce_power_data; + return 0; } -static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, - const u8 *data, size_t len) +int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) { const struct iwl_ucode_tlv *tlv; - void *sec_data; IWL_DEBUG_FW(trans, "Parsing REDUCE_POWER data\n"); @@ -160,7 +186,7 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, if (len < tlv_len) { IWL_ERR(trans, "invalid TLV len: %zd/%u\n", len, tlv_len); - return ERR_PTR(-EINVAL); + return -EINVAL; } if (tlv_type == IWL_UCODE_TLV_PNVM_SKU) { @@ -181,11 +207,11 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, if (trans->sku_id[0] == le32_to_cpu(sku_id->data[0]) && trans->sku_id[1] == le32_to_cpu(sku_id->data[1]) && trans->sku_id[2] == le32_to_cpu(sku_id->data[2])) { - sec_data = iwl_uefi_reduce_power_section(trans, - data, - len); - if (!IS_ERR(sec_data)) - return sec_data; + int ret = iwl_uefi_reduce_power_section(trans, + data, len, + pnvm_data); + if (!ret) + return 0; } else { IWL_DEBUG_FW(trans, "SKU ID didn't match!\n"); } @@ -195,51 +221,45 @@ static void *iwl_uefi_reduce_power_parse(struct iwl_trans *trans, } } - return ERR_PTR(-ENOENT); + return -ENOENT; } -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) { struct pnvm_sku_package *package; - void *data = NULL; unsigned long package_size; - efi_status_t status; + u8 *data; - *len = 0; + package = iwl_uefi_get_variable(IWL_UEFI_REDUCED_POWER_NAME, + &IWL_EFI_VAR_GUID, &package_size); - if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return ERR_PTR(-ENODEV); - - /* - * TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_REDUCE_POWER_SIZE; - - package = kmalloc(package_size, GFP_KERNEL); - if (!package) - return ERR_PTR(-ENOMEM); - - status = efi.get_variable(IWL_UEFI_REDUCED_POWER_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, package); - if (status != EFI_SUCCESS) { + if (IS_ERR(package)) { IWL_DEBUG_FW(trans, "Reduced Power UEFI variable not found 0x%lx (len %lu)\n", - status, package_size); + PTR_ERR(package), package_size); + return ERR_CAST(package); + } + + if (package_size < sizeof(*package)) { + IWL_DEBUG_FW(trans, + "Invalid Reduced Power UEFI variable len (%lu)\n", + package_size); kfree(package); - return ERR_PTR(-ENOENT); + return ERR_PTR(-EINVAL); } IWL_DEBUG_FW(trans, "Read reduced power from UEFI with size %lu\n", package_size); - *len = package_size; IWL_DEBUG_FW(trans, "rev %d, total_size %d, n_skus %d\n", package->rev, package->total_size, package->n_skus); - data = iwl_uefi_reduce_power_parse(trans, package->data, - *len - sizeof(*package)); + *len = package_size - sizeof(*package); + data = kmemdup(package->data, *len, GFP_KERNEL); + if (!data) { + kfree(package); + return ERR_PTR(-ENOMEM); + } kfree(package); @@ -264,31 +284,27 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) { struct uefi_cnv_common_step_data *data; unsigned long package_size; - efi_status_t status; int ret; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return; - if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) - return; + data = iwl_uefi_get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, + &package_size); - /* TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_STEP_SIZE; - - data = kmalloc(package_size, GFP_KERNEL); - if (!data) + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "STEP UEFI variable not found 0x%lx\n", + PTR_ERR(data)); return; + } - status = efi.get_variable(IWL_UEFI_STEP_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); - if (status != EFI_SUCCESS) { + if (package_size < sizeof(*data)) { IWL_DEBUG_FW(trans, - "STEP UEFI variable not found 0x%lx\n", status); - goto out_free; + "Invalid STEP table UEFI variable len (%lu)\n", + package_size); + kfree(data); + return; } IWL_DEBUG_FW(trans, "Read STEP from UEFI with size %lu\n", @@ -298,7 +314,6 @@ void iwl_uefi_get_step_table(struct iwl_trans *trans) if (ret < 0) IWL_DEBUG_FW(trans, "Cannot read STEP tables. rev is invalid\n"); -out_free: kfree(data); } IWL_EXPORT_SYMBOL(iwl_uefi_get_step_table); @@ -341,29 +356,26 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, { struct uefi_cnv_wlan_sgom_data *data; unsigned long package_size; - efi_status_t status; int ret; - if (!fwrt->geo_enabled || - !efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) + if (!fwrt->geo_enabled) return; - /* TODO: we hardcode a maximum length here, because reading - * from the UEFI is not working. To implement this properly, - * we have to call efivar_entry_size(). - */ - package_size = IWL_HARDCODED_SGOM_SIZE; - - data = kmalloc(package_size, GFP_KERNEL); - if (!data) + data = iwl_uefi_get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, + &package_size); + if (IS_ERR(data)) { + IWL_DEBUG_FW(trans, + "SGOM UEFI variable not found 0x%lx\n", + PTR_ERR(data)); return; + } - status = efi.get_variable(IWL_UEFI_SGOM_NAME, &IWL_EFI_VAR_GUID, - NULL, &package_size, data); - if (status != EFI_SUCCESS) { + if (package_size < sizeof(*data)) { IWL_DEBUG_FW(trans, - "SGOM UEFI variable not found 0x%lx\n", status); - goto out_free; + "Invalid SGOM table UEFI variable len (%lu)\n", + package_size); + kfree(data); + return; } IWL_DEBUG_FW(trans, "Read SGOM from UEFI with size %lu\n", @@ -373,9 +385,7 @@ void iwl_uefi_get_sgom_table(struct iwl_trans *trans, if (ret < 0) IWL_DEBUG_FW(trans, "Cannot read SGOM tables. rev is invalid\n"); -out_free: kfree(data); - } IWL_EXPORT_SYMBOL(iwl_uefi_get_sgom_table); #endif /* CONFIG_ACPI */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h index 17089bc74cf922..1369cc4855c3a5 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/uefi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/uefi.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* - * Copyright(c) 2021-2022 Intel Corporation + * Copyright(c) 2021-2023 Intel Corporation */ #ifndef __iwl_fw_uefi__ #define __iwl_fw_uefi__ @@ -10,16 +10,7 @@ #define IWL_UEFI_SGOM_NAME L"UefiCnvWlanSarGeoOffsetMapping" #define IWL_UEFI_STEP_NAME L"UefiCnvCommonSTEP" -/* - * TODO: we have these hardcoded values that the caller must pass, - * because reading from the UEFI is not working. To implement this - * properly, we have to change iwl_pnvm_get_from_uefi() to call - * efivar_entry_size() and return the value to the caller instead. - */ -#define IWL_HARDCODED_PNVM_SIZE 4096 -#define IWL_HARDCODED_REDUCE_POWER_SIZE 32768 -#define IWL_HARDCODED_SGOM_SIZE 339 -#define IWL_HARDCODED_STEP_SIZE 6 +#define IWL_SGOM_MAP_SIZE 339 struct pnvm_sku_package { u8 rev; @@ -31,7 +22,7 @@ struct pnvm_sku_package { struct uefi_cnv_wlan_sgom_data { u8 revision; - u8 offset_map[IWL_HARDCODED_SGOM_SIZE - 1]; + u8 offset_map[IWL_SGOM_MAP_SIZE - 1]; } __packed; struct uefi_cnv_common_step_data { @@ -50,24 +41,42 @@ struct uefi_cnv_common_step_data { */ #ifdef CONFIG_EFI void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len); -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len); +u8 *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len); +int iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data); void iwl_uefi_get_step_table(struct iwl_trans *trans); +int iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data); #else /* CONFIG_EFI */ -static inline -void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) +static inline void *iwl_uefi_get_pnvm(struct iwl_trans *trans, size_t *len) { return ERR_PTR(-EOPNOTSUPP); } -static inline -void *iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) +static inline int +iwl_uefi_reduce_power_parse(struct iwl_trans *trans, + const u8 *data, size_t len, + struct iwl_pnvm_image *pnvm_data) +{ + return -EOPNOTSUPP; +} + +static inline u8 * +iwl_uefi_get_reduced_power(struct iwl_trans *trans, size_t *len) { return ERR_PTR(-EOPNOTSUPP); } -static inline -void iwl_uefi_get_step_table(struct iwl_trans *trans) +static inline void iwl_uefi_get_step_table(struct iwl_trans *trans) +{ +} + +static inline int +iwl_uefi_handle_tlv_mem_desc(struct iwl_trans *trans, const u8 *data, + u32 tlv_len, struct iwl_pnvm_image *pnvm_data) { + return 0; } #endif /* CONFIG_EFI */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h index 3f727801400910..96bf353469b8d6 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h @@ -13,6 +13,8 @@ #define CSR_IML_SIZE_ADDR 0x128 #define CSR_IML_RESP_ADDR 0x12c +#define UNFRAGMENTED_PNVM_PAYLOADS_NUMBER 2 + /* Set bit for enabling automatic function boot */ #define CSR_AUTO_FUNC_BOOT_ENA BIT(1) /* Set bit for initiating function boot */ @@ -96,9 +98,9 @@ struct iwl_prph_scratch_control { } __packed; /* PERIPH_SCRATCH_CONTROL_S */ /* - * struct iwl_prph_scratch_pnvm_cfg - ror config + * struct iwl_prph_scratch_pnvm_cfg - PNVM scratch * @pnvm_base_addr: PNVM start address - * @pnvm_size: PNVM size in DWs + * @pnvm_size: the size of the PNVM image in bytes * @reserved: reserved */ struct iwl_prph_scratch_pnvm_cfg { @@ -107,6 +109,14 @@ struct iwl_prph_scratch_pnvm_cfg { __le32 reserved; } __packed; /* PERIPH_SCRATCH_PNVM_CFG_S */ +/** + * struct iwl_prph_scrath_mem_desc_addr_array + * @mem_descs: array of dram addresses. + * Each address is the beggining of a pnvm payload. + */ +struct iwl_prph_scrath_mem_desc_addr_array { + __le64 mem_descs[IPC_DRAM_MAP_ENTRY_NUM_MAX]; +} __packed; /* PERIPH_SCRATCH_MEM_DESC_ADDR_ARRAY_S_VER_1 */ /* * struct iwl_prph_scratch_hwm_cfg - hwm config * @hwm_base_addr: hwm start address @@ -132,7 +142,7 @@ struct iwl_prph_scratch_rbd_cfg { /* * struct iwl_prph_scratch_uefi_cfg - prph scratch reduce power table * @base_addr: reduce power table address - * @size: table size in dwords + * @size: the size of the entire power table image */ struct iwl_prph_scratch_uefi_cfg { __le64 base_addr; @@ -277,10 +287,18 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, const struct fw_img *fw); void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive); -int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len); -int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len); +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa); +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); +int +iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); +void +iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); int iwl_trans_pcie_ctx_info_gen3_set_step(struct iwl_trans *trans, u32 mbx_addr_0_step, u32 mbx_addr_1_step); #endif /* __iwl_context_info_file_gen3_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h index 4354d5acac9f88..1a1321db137ca9 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-context-info.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2020, 2022 Intel Corporation */ #ifndef __iwl_context_info_file_h__ #define __iwl_context_info_file_h__ @@ -177,6 +177,9 @@ void iwl_pcie_ctxt_info_free_paging(struct iwl_trans *trans); int iwl_pcie_init_fw_sec(struct iwl_trans *trans, const struct fw_img *fw, struct iwl_context_info_dram *ctxt_dram); +void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, + size_t size, + dma_addr_t *phys); int iwl_pcie_ctxt_info_alloc_dma(struct iwl_trans *trans, const void *data, u32 len, struct iwl_dram_data *dram); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 898d5dcf1012ef..fb0277bd12cfa8 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -738,7 +738,8 @@ static int iwl_dbg_tlv_update_dram(struct iwl_fw_runtime *fwrt, if (le32_to_cpu(fwrt->trans->dbg.fw_mon_cfg[alloc_id].buf_location) != IWL_FW_INI_LOCATION_DRAM_PATH) { - IWL_DEBUG_FW(fwrt, "DRAM_PATH is not supported alloc_id %u\n", alloc_id); + IWL_DEBUG_FW(fwrt, "WRT: alloc_id %u location is not in DRAM_PATH\n", + alloc_id); return -1; } @@ -799,6 +800,10 @@ static void iwl_dbg_tlv_update_drams(struct iwl_fw_runtime *fwrt) for (i = IWL_FW_INI_ALLOCATION_ID_DBGC1; i < IWL_FW_INI_ALLOCATION_NUM; i++) { + if (fwrt->trans->dbg.fw_mon_cfg[i].buf_location == + IWL_FW_INI_LOCATION_INVALID) + continue; + ret = iwl_dbg_tlv_update_dram(fwrt, i, dram_info); if (!ret) dram_alloc = true; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 7dcb1c3ab72823..cf19e8a561e99e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -464,6 +464,9 @@ static void iwl_init_vht_hw_capab(struct iwl_trans *trans, IEEE80211_VHT_MAX_AMPDU_1024K << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT; + if (!trans->cfg->ht_params->stbc) + vht_cap->cap &= ~IEEE80211_VHT_CAP_RXSTBC_MASK; + if (data->vht160_supported) vht_cap->cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | IEEE80211_VHT_CAP_SHORT_GI_160; @@ -986,6 +989,13 @@ iwl_nvm_fixup_sband_iftd(struct iwl_trans *trans, iftype_data->vendor_elems.data = iwl_vendor_caps; iftype_data->vendor_elems.len = ARRAY_SIZE(iwl_vendor_caps); } + + if (!trans->cfg->ht_params->stbc) { + iftype_data->he_cap.he_cap_elem.phy_cap_info[2] &= + ~IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ; + iftype_data->he_cap.he_cap_elem.phy_cap_info[7] &= + ~IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ; + } } static void iwl_init_he_hw_capab(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 9f1228b5a38432..d9e465d0f4af35 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -459,6 +459,24 @@ struct iwl_trans_rxq_dma_data { u64 ur_bd_cb; }; +/* maximal number of DRAM MAP entries supported by FW */ +#define IPC_DRAM_MAP_ENTRY_NUM_MAX 64 + +/** + * struct iwl_pnvm_image - contains info about the parsed pnvm image + * @chunks: array of pointers to pnvm payloads and their sizes + * @n_chunks: the number of the pnvm payloads. + * @version: the version of the loaded PNVM image + */ +struct iwl_pnvm_image { + struct { + const void *data; + u32 len; + } chunks[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + u32 n_chunks; + u32 version; +}; + /** * struct iwl_trans_ops - transport specific operations * @@ -541,8 +559,11 @@ struct iwl_trans_rxq_dma_data { * Note that the transport must fill in the proper file headers. * @debugfs_cleanup: used in the driver unload flow to make a proper cleanup * of the trans debugfs + * @load_pnvm: save the pnvm data in DRAM * @set_pnvm: set the pnvm data in the prph scratch buffer, inside the * context info. + * @load_reduce_power: copy reduce power table to the corresponding DRAM memory + * @set_reduce_power: set reduce power table addresses in the sratch buffer * @interrupts: disable/enable interrupts to transport */ struct iwl_trans_ops { @@ -614,9 +635,17 @@ struct iwl_trans_ops { void *sanitize_ctx); void (*debugfs_cleanup)(struct iwl_trans *trans); void (*sync_nmi)(struct iwl_trans *trans); - int (*set_pnvm)(struct iwl_trans *trans, const void *data, u32 len); - int (*set_reduce_power)(struct iwl_trans *trans, - const void *data, u32 len); + int (*load_pnvm)(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_pnvm)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); + int (*load_reduce_power)(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa); + void (*set_reduce_power)(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa); + void (*interrupts)(struct iwl_trans *trans, bool enable); int (*imr_dma_data)(struct iwl_trans *trans, u32 dst_addr, u64 src_addr, @@ -704,6 +733,19 @@ struct iwl_dram_data { int size; }; +/** + * @drams: array of several DRAM areas that contains the pnvm and power + * reduction table payloads. + * @n_regions: number of DRAM regions that were allocated + * @prph_scratch_mem_desc: points to a structure allocated in dram, + * designed to show FW where all the payloads are. + */ +struct iwl_dram_regions { + struct iwl_dram_data drams[IPC_DRAM_MAP_ENTRY_NUM_MAX]; + struct iwl_dram_data prph_scratch_mem_desc; + u8 n_regions; +}; + /** * struct iwl_fw_mon - fw monitor per allocation id * @num_frags: number of fragments @@ -1004,6 +1046,8 @@ struct iwl_trans_txqs { * @hw_rev_step: The mac step of the HW * @pm_support: set to true in start_hw if link pm is supported * @ltr_enabled: set to true if the LTR is enabled + * @fail_to_parse_pnvm_image: set to true if pnvm parsing failed + * @failed_to_load_reduce_power_image: set to true if pnvm loading failed * @wide_cmd_header: true when ucode supports wide command header format * @wait_command_queue: wait queue for sync commands * @num_rx_queues: number of RX queues allocated by the transport; @@ -1051,7 +1095,9 @@ struct iwl_trans { bool pm_support; bool ltr_enabled; u8 pnvm_loaded:1; + u8 fail_to_parse_pnvm_image:1; u8 reduce_power_loaded:1; + u8 failed_to_load_reduce_power_image:1; const struct iwl_hcmd_arr *command_groups; int command_groups_size; @@ -1160,7 +1206,7 @@ static inline int iwl_trans_d3_suspend(struct iwl_trans *trans, bool test, { might_sleep(); if (!trans->ops->d3_suspend) - return 0; + return -EOPNOTSUPP; return trans->ops->d3_suspend(trans, test, reset); } @@ -1171,7 +1217,7 @@ static inline int iwl_trans_d3_resume(struct iwl_trans *trans, { might_sleep(); if (!trans->ops->d3_resume) - return 0; + return -EOPNOTSUPP; return trans->ops->d3_resume(trans, status, test, reset); } @@ -1515,33 +1561,34 @@ static inline void iwl_trans_sync_nmi(struct iwl_trans *trans) void iwl_trans_sync_nmi_with_addr(struct iwl_trans *trans, u32 inta_addr, u32 sw_err_bit); -static inline int iwl_trans_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len) +static inline int iwl_trans_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data, + const struct iwl_ucode_capabilities *capa) { - if (trans->ops->set_pnvm) { - int ret = trans->ops->set_pnvm(trans, data, len); - - if (ret) - return ret; - } - - trans->pnvm_loaded = true; - - return 0; + return trans->ops->load_pnvm(trans, pnvm_data, capa); } -static inline int iwl_trans_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len) +static inline void iwl_trans_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) { - if (trans->ops->set_reduce_power) { - int ret = trans->ops->set_reduce_power(trans, data, len); + if (trans->ops->set_pnvm) + trans->ops->set_pnvm(trans, capa); +} - if (ret) - return ret; - } +static inline int iwl_trans_load_reduce_power + (struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa) +{ + return trans->ops->load_reduce_power(trans, payloads, capa); +} - trans->reduce_power_loaded = true; - return 0; +static inline void +iwl_trans_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->ops->set_reduce_power) + trans->ops->set_reduce_power(trans, capa); } static inline bool iwl_trans_dbg_ini_valid(struct iwl_trans *trans) diff --git a/drivers/net/wireless/intel/iwlwifi/mei/main.c b/drivers/net/wireless/intel/iwlwifi/mei/main.c index 0a29fb013005db..54445f39fd551a 100644 --- a/drivers/net/wireless/intel/iwlwifi/mei/main.c +++ b/drivers/net/wireless/intel/iwlwifi/mei/main.c @@ -1791,9 +1791,8 @@ int iwl_mei_register(void *priv, const struct iwl_mei_ops *ops) if (iwl_mei_is_connected()) { if (mei->amt_enabled) iwl_mei_send_sap_msg(mei->cldev, - SAP_MSG_NOTIF_WIFIDR_UP, - false); - ops->rfkill(priv, mei->link_prot_state); + SAP_MSG_NOTIF_WIFIDR_UP); + ops->rfkill(priv, mei->link_prot_state, false); } } ret = 0; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 37aa4676dc9485..6d1007f24b4aa9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2732,17 +2732,13 @@ static bool iwl_mvm_wait_d3_notif(struct iwl_notif_wait_data *notif_wait, if (wowlan_info_ver < 2) { struct iwl_wowlan_info_notif_v1 *notif_v1 = (void *)pkt->data; - notif = kmemdup(notif_v1, - offsetofend(struct iwl_wowlan_info_notif, - received_beacons), - GFP_ATOMIC); - + notif = kmemdup(notif_v1, sizeof(*notif), GFP_ATOMIC); if (!notif) return false; notif->tid_tear_down = notif_v1->tid_tear_down; notif->station_id = notif_v1->station_id; - + memset_after(notif, 0, station_id); } else { notif = (void *)pkt->data; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 205c09bc986342..d1a559c4c6b963 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -433,7 +433,8 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, /* if reached this point, Alive notification was received */ iwl_mei_alive_notif(true); - ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait); + ret = iwl_pnvm_load(mvm->trans, &mvm->notif_wait, + &mvm->fw->ucode_capa); if (ret) { IWL_ERR(mvm, "Timeout waiting for PNVM load!\n"); iwl_fw_set_current_image(&mvm->fwrt, old_type); @@ -1104,7 +1105,26 @@ static const struct dmi_system_id dmi_tas_approved_list[] = { DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), }, }, - + { .ident = "Acer", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + }, + }, + { .ident = "ASUS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + }, + }, + { .ident = "MSI", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), + }, + }, + { .ident = "Honor", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "HONOR"), + }, + }, /* keep last */ {} }; @@ -1176,6 +1196,10 @@ static void iwl_mvm_tas_init(struct iwl_mvm *mvm) "Unable to add US/Canada to TAS block list, disabling TAS\n"); return; } + } else { + IWL_DEBUG_RADIO(mvm, + "System vendor '%s' is in the approved list.\n", + dmi_get_system_info(DMI_SYS_VENDOR)); } /* v4 is the same size as v3, so no need to differentiate here */ @@ -1591,6 +1615,9 @@ int iwl_mvm_up(struct iwl_mvm *mvm) RCU_INIT_POINTER(mvm->fw_id_to_link_sta[i], NULL); } + for (i = 0; i < IWL_MVM_FW_MAX_LINK_ID + 1; i++) + RCU_INIT_POINTER(mvm->link_id_to_link_conf[i], NULL); + memset(&mvm->fw_link_ids_map, 0, sizeof(mvm->fw_link_ids_map)); mvm->tdls_cs.peer.sta_id = IWL_MVM_INVALID_STA; @@ -1699,9 +1726,11 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { iwl_mvm_send_recovery_cmd(mvm, ERROR_RECOVERY_UPDATE_DB); - iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr, - IWL_TIME_SYNC_PROTOCOL_TM | - IWL_TIME_SYNC_PROTOCOL_FTM); + + if (mvm->time_sync.active) + iwl_mvm_time_sync_config(mvm, mvm->time_sync.peer_addr, + IWL_TIME_SYNC_PROTOCOL_TM | + IWL_TIME_SYNC_PROTOCOL_FTM); } if (!mvm->ptp_data.ptp_clock) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/link.c b/drivers/net/wireless/intel/iwlwifi/mvm/link.c index 3814915cb1a67d..dc31f8de7d1d80 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/link.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/link.c @@ -63,6 +63,9 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, mvmvif); if (link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID) return -EINVAL; + + rcu_assign_pointer(mvm->link_id_to_link_conf[link_info->fw_link_id], + link_conf); } /* Update SF - Disable if needed. if this fails, SF might still be on @@ -73,6 +76,7 @@ int iwl_mvm_add_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd.link_id = cpu_to_le32(link_info->fw_link_id); cmd.mac_id = cpu_to_le32(mvmvif->id); + cmd.spec_link_id = link_conf->link_id; /* P2P-Device already has a valid PHY context during add */ phyctxt = link_info->phy_ctxt; if (phyctxt) @@ -262,6 +266,8 @@ int iwl_mvm_remove_link(struct iwl_mvm *mvm, struct ieee80211_vif *vif, link_info->fw_link_id == IWL_MVM_FW_LINK_ID_INVALID)) return -EINVAL; + RCU_INIT_POINTER(mvm->link_id_to_link_conf[link_info->fw_link_id], + NULL); cmd.link_id = cpu_to_le32(link_info->fw_link_id); iwl_mvm_release_fw_link_id(mvm, link_info->fw_link_id); link_info->fw_link_id = IWL_MVM_FW_LINK_ID_INVALID; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c index cc90f2884cff62..059ede6f7b6594 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c @@ -629,17 +629,17 @@ __le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm, IEEE80211_P2P_OPPPS_CTWINDOW_MASK); } -__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) +u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { - __le32 twt_policy = cpu_to_le32(0); + u32 twt_policy = 0; if (vif->bss_conf.twt_requester && IWL_MVM_USE_TWT) - twt_policy |= cpu_to_le32(TWT_SUPPORTED); + twt_policy |= TWT_SUPPORTED; if (vif->bss_conf.twt_protected) - twt_policy |= cpu_to_le32(PROTECTED_TWT_SUPPORTED); + twt_policy |= PROTECTED_TWT_SUPPORTED; if (vif->bss_conf.twt_broadcast) - twt_policy |= cpu_to_le32(BROADCAST_TWT_SUPPORTED); + twt_policy |= BROADCAST_TWT_SUPPORTED; return twt_policy; } @@ -711,7 +711,7 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) { cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_11AX); ctxt_sta->data_policy |= - iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif); + cpu_to_le32(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif)); } @@ -1555,21 +1555,38 @@ void iwl_mvm_rx_missed_beacons_notif(struct iwl_mvm *mvm, u32 stop_trig_missed_bcon, stop_trig_missed_bcon_since_rx; u32 rx_missed_bcon, rx_missed_bcon_since_rx; struct ieee80211_vif *vif; - u32 id = le32_to_cpu(mb->mac_id); + /* Id can be mac/link id depending on the notification version */ + u32 id = le32_to_cpu(mb->link_id); union iwl_dbg_tlv_tp_data tp_data = { .fw_pkt = pkt }; u32 mac_type; + u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, LEGACY_GROUP, + MISSED_BEACONS_NOTIFICATION, + 0); + + rcu_read_lock(); + + /* before version four the ID in the notification refers to mac ID */ + if (notif_ver < 4) { + vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); + } else { + struct ieee80211_bss_conf *bss_conf = + iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, id, true); + + if (!bss_conf) + goto out; + + vif = bss_conf->vif; + } IWL_DEBUG_INFO(mvm, - "missed bcn mac_id=%u, consecutive=%u (%u, %u, %u)\n", - le32_to_cpu(mb->mac_id), + "missed bcn %s_id=%u, consecutive=%u (%u, %u, %u)\n", + notif_ver < 4 ? "mac" : "link", + id, le32_to_cpu(mb->consec_missed_beacons), le32_to_cpu(mb->consec_missed_beacons_since_last_rx), le32_to_cpu(mb->num_recvd_beacons), le32_to_cpu(mb->num_expected_beacons)); - rcu_read_lock(); - - vif = iwl_mvm_rcu_dereference_vif_id(mvm, id, true); if (!vif) goto out; @@ -1730,20 +1747,44 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) { struct iwl_rx_packet *pkt = rxb_addr(rxb); - struct iwl_channel_switch_start_notif *notif = (void *)pkt->data; struct ieee80211_vif *csa_vif, *vif; - struct iwl_mvm_vif *mvmvif; - u32 id_n_color, csa_id, mac_id; + struct iwl_mvm_vif *mvmvif, *csa_mvmvif; + u32 id_n_color, csa_id; + /* save mac_id or link_id to use later to cancel csa if needed */ + u32 id; + u8 notif_ver = iwl_fw_lookup_notif_ver(mvm->fw, MAC_CONF_GROUP, + CHANNEL_SWITCH_START_NOTIF, 0); - id_n_color = le32_to_cpu(notif->id_and_color); - mac_id = id_n_color & FW_CTXT_ID_MSK; + rcu_read_lock(); - if (WARN_ON_ONCE(mac_id >= NUM_MAC_INDEX_DRIVER)) - return; + if (notif_ver < 3) { + struct iwl_channel_switch_start_notif_v1 *notif = (void *)pkt->data; + u32 mac_id; + + id_n_color = le32_to_cpu(notif->id_and_color); + mac_id = id_n_color & FW_CTXT_ID_MSK; + + vif = iwl_mvm_rcu_dereference_vif_id(mvm, mac_id, true); + if (!vif) + goto out_unlock; + + id = mac_id; + } else { + struct iwl_channel_switch_start_notif *notif = (void *)pkt->data; + u32 link_id = le32_to_cpu(notif->link_id); + struct ieee80211_bss_conf *bss_conf = + iwl_mvm_rcu_fw_link_id_to_link_conf(mvm, link_id, true); + + if (!bss_conf) + goto out_unlock; + + id = link_id; + vif = bss_conf->vif; + } - rcu_read_lock(); - vif = rcu_dereference(mvm->vif_id_to_mac[mac_id]); mvmvif = iwl_mvm_vif_from_mac80211(vif); + if (notif_ver >= 3) + id_n_color = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); switch (vif->type) { case NL80211_IFTYPE_AP: @@ -1752,7 +1793,8 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, csa_vif != vif)) goto out_unlock; - csa_id = FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color); + csa_mvmvif = iwl_mvm_vif_from_mac80211(csa_vif); + csa_id = FW_CMD_ID_AND_COLOR(csa_mvmvif->id, csa_mvmvif->color); if (WARN(csa_id != id_n_color, "channel switch noa notification on unexpected vif (csa_vif=%d, notif=%d)", csa_id, id_n_color)) @@ -1779,7 +1821,7 @@ void iwl_mvm_channel_switch_start_notif(struct iwl_mvm *mvm, CHANNEL_SWITCH_ERROR_NOTIF, 0) && !vif->bss_conf.csa_active) { IWL_DEBUG_INFO(mvm, "Channel Switch was canceled\n"); - iwl_mvm_cancel_channel_switch(mvm, vif, mac_id); + iwl_mvm_cancel_channel_switch(mvm, vif, id); break; } @@ -1802,7 +1844,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, struct iwl_rx_packet *pkt = rxb_addr(rxb); struct iwl_channel_switch_error_notif *notif = (void *)pkt->data; struct ieee80211_vif *vif; - u32 id = le32_to_cpu(notif->mac_id); + u32 id = le32_to_cpu(notif->link_id); u32 csa_err_mask = le32_to_cpu(notif->csa_err_mask); rcu_read_lock(); @@ -1812,7 +1854,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm, return; } - IWL_DEBUG_INFO(mvm, "FW reports CSA error: mac_id=%u, csa_err_mask=%u\n", + IWL_DEBUG_INFO(mvm, "FW reports CSA error: id=%u, csa_err_mask=%u\n", id, csa_err_mask); if (csa_err_mask & (CS_ERR_COUNT_ERROR | CS_ERR_LONG_DELAY_AFTER_CS | diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 17f788a5ff6ba6..1ade1f00342068 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1478,21 +1478,37 @@ iwl_mvm_chandef_get_primary_80(struct cfg80211_chan_def *chandef) return (control_start - data_start) / 80; } -/* - * Returns true if addding the interface is done - * (either with success or failure) - * - * FIXME: remove this again and merge it in - */ -static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm, - struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - int *ret) +static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm, + struct ieee80211_vif *vif) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int ret; lockdep_assert_held(&mvm->mutex); + ret = iwl_mvm_alloc_bcast_sta(mvm, vif); + if (ret) { + IWL_ERR(mvm, "Failed to allocate bcast sta\n"); + return ret; + } + + /* Only queue for this station is the mcast queue, + * which shouldn't be in TFD mask anyway + */ + return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0, + vif->type, + IWL_STA_MULTICAST); +} + +static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); + struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); + int ret; + + mutex_lock(&mvm->mutex); + mvmvif->mvm = mvm; /* the first link always points to the default one */ @@ -1510,12 +1526,18 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm, mvmvif->deflink.beacon_stats.num_beacons; /* Allocate resources for the MAC context, and add it to the fw */ - *ret = iwl_mvm_mac_ctxt_init(mvm, vif); - if (*ret) - return true; + ret = iwl_mvm_mac_ctxt_init(mvm, vif); + if (ret) + goto out; rcu_assign_pointer(mvm->vif_id_to_mac[mvmvif->id], vif); + /* Currently not much to do for NAN */ + if (vif->type == NL80211_IFTYPE_NAN) { + ret = 0; + goto out; + } + /* * The AP binding flow can be done only after the beacon * template is configured (which happens only in the mac80211 @@ -1530,50 +1552,12 @@ static bool iwl_mvm_mac_add_interface_common(struct iwl_mvm *mvm, if (vif->type == NL80211_IFTYPE_AP || vif->type == NL80211_IFTYPE_ADHOC) { iwl_mvm_vif_dbgfs_register(mvm, vif); - return true; + ret = 0; + goto out; } mvmvif->features |= hw->netdev_features; - return false; -} - -static int iwl_mvm_alloc_bcast_mcast_sta(struct iwl_mvm *mvm, - struct ieee80211_vif *vif) -{ - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - int ret; - - lockdep_assert_held(&mvm->mutex); - - ret = iwl_mvm_alloc_bcast_sta(mvm, vif); - if (ret) { - IWL_ERR(mvm, "Failed to allocate bcast sta\n"); - return ret; - } - - /* - * Only queue for this station is the mcast queue, - * which shouldn't be in TFD mask anyway - */ - return iwl_mvm_allocate_int_sta(mvm, &mvmvif->deflink.mcast_sta, 0, - vif->type, - IWL_STA_MULTICAST); -} - -static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); - struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - int ret; - - mutex_lock(&mvm->mutex); - - /* Common for MLD and non-MLD API */ - if (iwl_mvm_mac_add_interface_common(mvm, hw, vif, &ret)) - goto out; - ret = iwl_mvm_mac_ctxt_add(mvm, vif); if (ret) goto out_unlock; @@ -3054,7 +3038,7 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw, struct ieee80211_bss_conf *bss_conf, u64 changes) { - struct iwl_mvm_bss_info_changed_ops callbacks = { + static const struct iwl_mvm_bss_info_changed_ops callbacks = { .bss_info_changed_sta = iwl_mvm_bss_info_changed_station, .bss_info_changed_ap_ibss = iwl_mvm_bss_info_changed_ap_ibss, }; @@ -3067,7 +3051,7 @@ void iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, - struct iwl_mvm_bss_info_changed_ops *callbacks, + const struct iwl_mvm_bss_info_changed_ops *callbacks, u64 changes) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); @@ -3564,7 +3548,7 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct iwl_mvm_sta_state_ops callbacks = { + static const struct iwl_mvm_sta_state_ops callbacks = { .add_sta = iwl_mvm_add_sta, .update_sta = iwl_mvm_update_sta, .rm_sta = iwl_mvm_rm_sta, @@ -3669,7 +3653,7 @@ static int iwl_mvm_sta_state_notexist_to_none(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_link_sta *link_sta; @@ -3713,7 +3697,7 @@ iwl_mvm_sta_state_auth_to_assoc(struct ieee80211_hw *hw, struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); @@ -3770,7 +3754,7 @@ static int iwl_mvm_sta_state_assoc_to_authorized(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta); @@ -3805,11 +3789,10 @@ static int iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - int ret; lockdep_assert_held(&mvm->mutex); @@ -3828,10 +3811,7 @@ iwl_mvm_sta_state_authorized_to_assoc(struct iwl_mvm *mvm, mvmvif->authorized = 0; /* disable beacon filtering */ - ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0); - WARN_ON(ret && - !test_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, - &mvm->status)); + iwl_mvm_disable_beacon_filter(mvm, vif, 0); } return 0; @@ -3843,7 +3823,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state, - struct iwl_mvm_sta_state_ops *callbacks) + const struct iwl_mvm_sta_state_ops *callbacks) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); @@ -4573,7 +4553,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, int duration, enum ieee80211_roc_type type) { - struct iwl_mvm_roc_ops ops = { + static const struct iwl_mvm_roc_ops ops = { .add_aux_sta_for_hs20 = iwl_mvm_add_aux_sta_for_hs20, .switch_phy_ctxt = iwl_mvm_roc_switch_binding, }; @@ -4585,7 +4565,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, int duration, enum ieee80211_roc_type type, - struct iwl_mvm_roc_ops *ops) + const struct iwl_mvm_roc_ops *ops) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); @@ -5092,7 +5072,7 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw, static int iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, struct ieee80211_vif_chanctx_switch *vifs, - struct iwl_mvm_switch_vif_chanctx_ops *ops) + const struct iwl_mvm_switch_vif_chanctx_ops *ops) { int ret; @@ -5151,7 +5131,7 @@ iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm, static int iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm, struct ieee80211_vif_chanctx_switch *vifs, - struct iwl_mvm_switch_vif_chanctx_ops *ops) + const struct iwl_mvm_switch_vif_chanctx_ops *ops) { int ret; @@ -5194,7 +5174,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw, struct ieee80211_vif_chanctx_switch *vifs, int n_vifs, enum ieee80211_chanctx_switch_mode mode, - struct iwl_mvm_switch_vif_chanctx_ops *ops) + const struct iwl_mvm_switch_vif_chanctx_ops *ops) { struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); int ret; @@ -5223,7 +5203,7 @@ static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw, int n_vifs, enum ieee80211_chanctx_switch_mode mode) { - struct iwl_mvm_switch_vif_chanctx_ops ops = { + static const struct iwl_mvm_switch_vif_chanctx_ops ops = { .__assign_vif_chanctx = __iwl_mvm_assign_vif_chanctx, .__unassign_vif_chanctx = __iwl_mvm_unassign_vif_chanctx, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c index 8853821b371681..3e6f86f644b581 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-key.c @@ -51,10 +51,10 @@ static u32 iwl_mvm_get_sec_sta_mask(struct iwl_mvm *mvm, return iwl_mvm_sta_fw_id_mask(mvm, sta, keyconf->link_id); } -static u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *keyconf) +u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); u32 flags = 0; @@ -164,13 +164,9 @@ static int __iwl_mvm_sec_key_del(struct iwl_mvm *mvm, u32 sta_mask, return iwl_mvm_send_cmd_pdu(mvm, cmd_id, flags, sizeof(cmd), &cmd); } -int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *keyconf) +int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags, + struct ieee80211_key_conf *keyconf) { - u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); - u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, SEC_KEY_CMD); struct iwl_sec_key_cmd cmd = { .action = cpu_to_le32(FW_CTXT_ACTION_ADD), @@ -223,6 +219,17 @@ int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, return ret; } +int iwl_mvm_sec_key_add(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf) +{ + u32 sta_mask = iwl_mvm_get_sec_sta_mask(mvm, vif, sta, keyconf); + u32 key_flags = iwl_mvm_get_sec_flags(mvm, vif, sta, keyconf); + + return iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); +} + static int _iwl_mvm_sec_key_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct ieee80211_sta *sta, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c index 1717fb52dc1237..99bf71a2b69056 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac.c @@ -115,16 +115,16 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, if (vif->cfg.assoc && !force_assoc_off) { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - cmd.client.is_assoc = cpu_to_le32(1); + cmd.client.is_assoc = 1; if (!mvmvif->authorized && fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_COEX_HIGH_PRIO)) cmd.client.data_policy |= - cpu_to_le32(COEX_HIGH_PRIORITY_ENABLE); + cpu_to_le16(COEX_HIGH_PRIORITY_ENABLE); } else { - cmd.client.is_assoc = cpu_to_le32(0); + cmd.client.is_assoc = 0; /* Allow beacons to pass through as long as we are not * associated, or we do not have dtim period information. @@ -132,14 +132,14 @@ static int iwl_mvm_mld_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_BEACON); } - cmd.client.assoc_id = cpu_to_le32(vif->cfg.aid); + cmd.client.assoc_id = cpu_to_le16(vif->cfg.aid); if (vif->probe_req_reg && vif->cfg.assoc && vif->p2p) cmd.filter_flags |= cpu_to_le32(MAC_CFG_FILTER_ACCEPT_PROBE_REQ); if (vif->bss_conf.he_support && !iwlwifi_mod_params.disable_11ax) cmd.client.data_policy |= - iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif); + cpu_to_le16(iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(mvm, vif)); return iwl_mvm_mld_mac_ctxt_send_cmd(mvm, &cmd); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c index 7fb66c5709596a..fb06cf94fcc3ad 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c @@ -492,7 +492,7 @@ static int iwl_mvm_mld_mac_sta_state(struct ieee80211_hw *hw, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state) { - struct iwl_mvm_sta_state_ops callbacks = { + static const struct iwl_mvm_sta_state_ops callbacks = { .add_sta = iwl_mvm_mld_add_sta, .update_sta = iwl_mvm_mld_update_sta, .rm_sta = iwl_mvm_mld_rm_sta, @@ -779,7 +779,7 @@ iwl_mvm_mld_switch_vif_chanctx(struct ieee80211_hw *hw, int n_vifs, enum ieee80211_chanctx_switch_mode mode) { - struct iwl_mvm_switch_vif_chanctx_ops ops = { + static const struct iwl_mvm_switch_vif_chanctx_ops ops = { .__assign_vif_chanctx = __iwl_mvm_mld_assign_vif_chanctx, .__unassign_vif_chanctx = __iwl_mvm_mld_unassign_vif_chanctx, }; @@ -871,7 +871,7 @@ static int iwl_mvm_mld_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, int duration, enum ieee80211_roc_type type) { - struct iwl_mvm_roc_ops ops = { + static const struct iwl_mvm_roc_ops ops = { .add_aux_sta_for_hs20 = iwl_mvm_mld_add_aux_sta, .switch_phy_ctxt = iwl_mvm_link_switch_phy_ctx, }; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c index 85a4ce8449ade8..bb8868cd439657 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mld-sta.c @@ -71,6 +71,11 @@ static int iwl_mvm_mld_add_int_sta_to_fw(struct iwl_mvm *mvm, cmd.station_type = cpu_to_le32(sta->type); + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) && + sta->type == STATION_TYPE_BCAST_MGMT) + cmd.mfp = cpu_to_le32(1); + if (addr) { memcpy(cmd.peer_mld_address, addr, ETH_ALEN); memcpy(cmd.peer_link_address, addr, ETH_ALEN); @@ -128,11 +133,11 @@ static int iwl_mvm_add_aux_sta_to_fw(struct iwl_mvm *mvm, /* * Adds an internal sta to the FW table with its queues */ -static int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm, - struct iwl_mvm_int_sta *sta, - const u8 *addr, int link_id, - u16 *queue, u8 tid, - unsigned int *_wdg_timeout) +int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm, + struct iwl_mvm_int_sta *sta, + const u8 *addr, int link_id, + u16 *queue, u8 tid, + unsigned int *_wdg_timeout) { int ret, txq; unsigned int wdg_timeout = _wdg_timeout ? *_wdg_timeout : @@ -442,6 +447,11 @@ static int iwl_mvm_mld_cfg_sta(struct iwl_mvm *mvm, struct ieee80211_sta *sta, if (mvm_sta->sta_state >= IEEE80211_STA_ASSOC) cmd.assoc_id = cpu_to_le32(sta->aid); + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_STA_EXP_MFP_SUPPORT) && + (sta->mfp || mvm_sta->sta_state < IEEE80211_STA_AUTHORIZED)) + cmd.mfp = cpu_to_le32(1); + switch (link_sta->rx_nss) { case 1: cmd.mimo = cpu_to_le32(0); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 9e5008e0e47f5c..7b5db55ebe9281 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1003,6 +1003,8 @@ struct iwl_mvm { struct ieee80211_vif __rcu *vif_id_to_mac[NUM_MAC_INDEX_DRIVER]; + struct ieee80211_bss_conf __rcu *link_id_to_link_conf[IWL_MVM_FW_MAX_LINK_ID + 1]; + /* -1 for always, 0 for never, >0 for that many times */ s8 fw_restart; u8 *error_recovery_buf; @@ -1302,6 +1304,19 @@ iwl_mvm_rcu_dereference_vif_id(struct iwl_mvm *mvm, u8 vif_id, bool rcu) lockdep_is_held(&mvm->mutex)); } +static inline struct ieee80211_bss_conf * +iwl_mvm_rcu_fw_link_id_to_link_conf(struct iwl_mvm *mvm, u8 link_id, bool rcu) +{ + if (WARN_ON(link_id >= ARRAY_SIZE(mvm->link_id_to_link_conf))) + return NULL; + + if (rcu) + return rcu_dereference(mvm->link_id_to_link_conf[link_id]); + + return rcu_dereference_protected(mvm->link_id_to_link_conf[link_id], + lockdep_is_held(&mvm->mutex)); +} + static inline bool iwl_mvm_is_adaptive_dwell_supported(struct iwl_mvm *mvm) { return fw_has_api(&mvm->fw->ucode_capa, @@ -1774,8 +1789,8 @@ void iwl_mvm_mac_ctxt_cmd_ap_set_filter_flags(struct iwl_mvm *mvm, int iwl_mvm_get_mac_type(struct ieee80211_vif *vif); __le32 iwl_mvm_mac_ctxt_cmd_p2p_sta_get_oppps_ctwin(struct iwl_mvm *mvm, struct ieee80211_vif *vif); -__le32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, - struct ieee80211_vif *vif); +u32 iwl_mvm_mac_ctxt_cmd_sta_get_twt_policy(struct iwl_mvm *mvm, + struct ieee80211_vif *vif); int iwl_mvm_mld_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); int iwl_mvm_mld_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, bool force_assoc_off); @@ -1873,7 +1888,7 @@ void iwl_mvm_bss_info_changed_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *bss_conf, - struct iwl_mvm_bss_info_changed_ops *callbacks, + const struct iwl_mvm_bss_info_changed_ops *callbacks, u64 changes); void iwl_mvm_bss_info_changed_station_common(struct iwl_mvm *mvm, @@ -1907,7 +1922,7 @@ struct iwl_mvm_roc_ops { int iwl_mvm_roc_common(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel *channel, int duration, enum ieee80211_roc_type type, - struct iwl_mvm_roc_ops *ops); + const struct iwl_mvm_roc_ops *ops); int iwl_mvm_cancel_roc(struct ieee80211_hw *hw, struct ieee80211_vif *vif); /*Session Protection */ @@ -2346,6 +2361,12 @@ int iwl_mvm_mld_update_sta_keys(struct iwl_mvm *mvm, struct ieee80211_sta *sta, u32 old_sta_mask, u32 new_sta_mask); +int iwl_mvm_mld_send_key(struct iwl_mvm *mvm, u32 sta_mask, u32 key_flags, + struct ieee80211_key_conf *keyconf); +u32 iwl_mvm_get_sec_flags(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, + struct ieee80211_key_conf *keyconf); bool iwl_rfi_supported(struct iwl_mvm *mvm); int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, @@ -2406,7 +2427,7 @@ iwl_mvm_switch_vif_chanctx_common(struct ieee80211_hw *hw, struct ieee80211_vif_chanctx_switch *vifs, int n_vifs, enum ieee80211_chanctx_switch_mode mode, - struct iwl_mvm_switch_vif_chanctx_ops *ops); + const struct iwl_mvm_switch_vif_chanctx_ops *ops); /* Channel info utils */ static inline bool iwl_mvm_has_ultra_hb_channel(struct iwl_mvm *mvm) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c index a8bd0f5f795cc1..797b1f70937eb8 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/offloading.c @@ -198,6 +198,10 @@ int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm, memcpy(common->arp_mac_addr, vif->addr, ETH_ALEN); } + if (fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_OFFLOAD_REJ_BTM_SUPPORT)) + enabled |= IWL_D3_PROTO_REJECT_BTM; + if (!disable_offloading) common->enabled = cpu_to_le32(enabled); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 32625bfacaaef3..8cc2e2145cf9b7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -449,7 +449,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(ADD_STA_KEY), HCMD_NAME(ADD_STA), HCMD_NAME(REMOVE_STA), - HCMD_NAME(FW_GET_ITEM_CMD), HCMD_NAME(TX_CMD), HCMD_NAME(SCD_QUEUE_CFG), HCMD_NAME(TXPATH_FLUSH), @@ -512,7 +511,6 @@ static const struct iwl_hcmd_names iwl_mvm_legacy_names[] = { HCMD_NAME(REPLY_BEACON_FILTERING_CMD), HCMD_NAME(D3_CONFIG_CMD), HCMD_NAME(PROT_OFFLOAD_CONFIG_CMD), - HCMD_NAME(OFFLOADS_QUERY_CMD), HCMD_NAME(MATCH_FOUND_NOTIFICATION), HCMD_NAME(DTS_MEASUREMENT_NOTIFICATION), HCMD_NAME(WOWLAN_PATTERNS), diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 6226e4e54a51d2..89ab440ad3775c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -1782,9 +1782,9 @@ static void iwl_mvm_decode_eht_phy_data(struct iwl_mvm *mvm, eht->known |= cpu_to_le32(IEEE80211_RADIOTAP_EHT_KNOWN_RU_ALLOC_TB_FMT); eht->data[8] |= LE32_DEC_ENC(data0, IWL_RX_PHY_DATA0_EHT_PS160, IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_PS_160); - eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_B0, + eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B0, IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B0); - eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_B1_B7_ALLOC, + eht->data[8] |= LE32_DEC_ENC(data1, IWL_RX_PHY_DATA1_EHT_RU_ALLOC_B1_B7, IEEE80211_RADIOTAP_EHT_DATA8_RU_ALLOC_TB_FMT_B7_B1); iwl_mvm_decode_eht_ru(mvm, rx_status, eht); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 05a54a69c1357c..b9b9082676d47b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -2070,13 +2070,6 @@ bool iwl_mvm_sta_del(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cancel_delayed_work(&mvm->tdls_cs.dwork); } - /* - * Make sure that the tx response code sees the station as -EBUSY and - * calls the drain worker. - */ - spin_lock_bh(&mvm_sta->lock); - spin_unlock_bh(&mvm_sta->lock); - return false; } @@ -4306,16 +4299,27 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u16 queue; struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct ieee80211_key_conf *keyconf; + unsigned int wdg_timeout = + iwl_mvm_get_wd_timeout(mvm, vif, false, false); + bool mld = iwl_mvm_has_mld_api(mvm->fw); + u32 type = mld ? STATION_TYPE_PEER : IWL_STA_LINK; ret = iwl_mvm_allocate_int_sta(mvm, sta, 0, - NL80211_IFTYPE_UNSPECIFIED, - IWL_STA_LINK); + NL80211_IFTYPE_UNSPECIFIED, type); if (ret) return ret; - ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, mvmvif->color, - addr, sta, &queue, - IWL_MVM_TX_FIFO_BE); + if (mld) + ret = iwl_mvm_mld_add_int_sta_with_queue(mvm, sta, addr, + mvmvif->deflink.fw_link_id, + &queue, + IWL_MAX_TID_COUNT, + &wdg_timeout); + else + ret = iwl_mvm_add_int_sta_with_queue(mvm, mvmvif->id, + mvmvif->color, addr, sta, + &queue, + IWL_MVM_TX_FIFO_BE); if (ret) goto out; @@ -4328,9 +4332,23 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, keyconf->cipher = cipher; memcpy(keyconf->key, key, key_len); keyconf->keylen = key_len; + keyconf->flags = IEEE80211_KEY_FLAG_PAIRWISE; + + if (mld) { + /* The MFP flag is set according to the station mfp field. Since + * we don't have a station, set it manually. + */ + u32 key_flags = + iwl_mvm_get_sec_flags(mvm, vif, NULL, keyconf) | + IWL_SEC_KEY_FLAG_MFP; + u32 sta_mask = BIT(sta->sta_id); + + ret = iwl_mvm_mld_send_key(mvm, sta_mask, key_flags, keyconf); + } else { + ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false, + 0, NULL, 0, 0, true); + } - ret = iwl_mvm_send_sta_key(mvm, sta->sta_id, keyconf, false, - 0, NULL, 0, 0, true); kfree(keyconf); return 0; out: @@ -4340,10 +4358,10 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - u32 mac_id) + u32 id) { struct iwl_cancel_channel_switch_cmd cancel_channel_switch_cmd = { - .mac_id = cpu_to_le32(mac_id), + .id = cpu_to_le32(id), }; int ret; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index a61d4f88125f02..9acc01b7a4c9e0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -365,6 +365,7 @@ struct iwl_mvm_link_sta { * and from Tx response flow, it needs a spinlock. * @tid_data: per tid data + mgmt. Look at %iwl_mvm_tid_data. * @tid_to_baid: a simple map of TID to baid + * @vif: a vif pointer * @reserved_queue: the queue reserved for this STA for DQA purposes * Every STA has is given one reserved queue to allow it to operate. If no * such queue can be guaranteed, the STA addition will fail. @@ -378,6 +379,7 @@ struct iwl_mvm_link_sta { * debugfs. If it's set to 0, it means that it is it's not set via * debugfs. * @agg_tids: bitmap of tids whose status is operational aggregated (IWL_AGG_ON) + * @sleeping: sta sleep transitions in power management * @sleep_tx_count: the number of frames that we told the firmware to let out * even when that station is asleep. This is useful in case the queue * gets empty before all the frames were sent, which can happen when @@ -580,7 +582,7 @@ int iwl_mvm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u8 *key, u32 key_len); void iwl_mvm_cancel_channel_switch(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - u32 mac_id); + u32 id); /* Queues */ int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, struct ieee80211_sta *sta, @@ -616,7 +618,7 @@ int iwl_mvm_mac_sta_state_common(struct ieee80211_hw *hw, struct ieee80211_sta *sta, enum ieee80211_sta_state old_state, enum ieee80211_sta_state new_state, - struct iwl_mvm_sta_state_ops *callbacks); + const struct iwl_mvm_sta_state_ops *callbacks); /* New MLD STA related APIs */ /* STA */ @@ -646,6 +648,11 @@ int iwl_mvm_mld_update_sta_links(struct iwl_mvm *mvm, u16 old_links, u16 new_links); u32 iwl_mvm_sta_fw_id_mask(struct iwl_mvm *mvm, struct ieee80211_sta *sta, int filter_link_id); +int iwl_mvm_mld_add_int_sta_with_queue(struct iwl_mvm *mvm, + struct iwl_mvm_int_sta *sta, + const u8 *addr, int link_id, + u16 *queue, u8 tid, + unsigned int *_wdg_timeout); /* Queues */ void iwl_mvm_mld_modify_all_sta_disable_tx(struct iwl_mvm *mvm, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 00719e13043864..ef0f53b3b89ff6 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -308,6 +309,54 @@ static u32 iwl_mvm_get_tx_ant(struct iwl_mvm *mvm, return BIT(mvm->mgmt_last_antenna_idx) << RATE_MCS_ANT_POS; } +static u32 iwl_mvm_get_inject_tx_rate(struct iwl_mvm *mvm, + struct ieee80211_tx_info *info) +{ + struct ieee80211_tx_rate *rate = &info->control.rates[0]; + u32 result; + + /* + * we only care about legacy/HT/VHT so far, so we can + * build in v1 and use iwl_new_rate_from_v1() + */ + + if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { + u8 mcs = ieee80211_rate_get_vht_mcs(rate); + u8 nss = ieee80211_rate_get_vht_nss(rate); + + result = RATE_MCS_VHT_MSK_V1; + result |= u32_encode_bits(mcs, RATE_VHT_MCS_RATE_CODE_MSK); + result |= u32_encode_bits(nss, RATE_MCS_NSS_MSK); + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + result |= RATE_MCS_SGI_MSK_V1; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1); + else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) + result |= u32_encode_bits(2, RATE_MCS_CHAN_WIDTH_MSK_V1); + else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) + result |= u32_encode_bits(3, RATE_MCS_CHAN_WIDTH_MSK_V1); + } else if (rate->flags & IEEE80211_TX_RC_MCS) { + result = RATE_MCS_HT_MSK_V1; + result |= u32_encode_bits(rate->idx, + RATE_HT_MCS_RATE_CODE_MSK_V1 | + RATE_HT_MCS_NSS_MSK_V1); + if (rate->flags & IEEE80211_TX_RC_SHORT_GI) + result |= RATE_MCS_SGI_MSK_V1; + if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) + result |= u32_encode_bits(1, RATE_MCS_CHAN_WIDTH_MSK_V1); + if (rate->flags & IEEE80211_TX_CTL_LDPC) + result |= RATE_MCS_LDPC_MSK_V1; + if (u32_get_bits(rate->flags, IEEE80211_TX_CTL_STBC)) + result |= RATE_MCS_STBC_MSK; + } else { + return 0; + } + + if (iwl_fw_lookup_notif_ver(mvm->fw, LONG_GROUP, TX_CMD, 0) > 6) + return iwl_new_rate_from_v1(result); + return result; +} + static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, struct ieee80211_tx_info *info, struct ieee80211_sta *sta, __le16 fc) @@ -317,8 +366,15 @@ static u32 iwl_mvm_get_tx_rate(struct iwl_mvm *mvm, u32 rate_flags = 0; bool is_cck; - /* info->control is only relevant for non HW rate control */ - if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) { + if (unlikely(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT)) { + u32 result = iwl_mvm_get_inject_tx_rate(mvm, info); + + if (result) + return result; + rate_idx = info->control.rates[0].idx; + } else if (!ieee80211_hw_check(mvm->hw, HAS_RATE_CONTROL)) { + /* info->control is only relevant for non HW rate control */ + /* HT rate doesn't make sense for a non data frame */ WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS && !ieee80211_is_data(fc), @@ -398,7 +454,8 @@ void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd, * table is controlled by LINK_QUALITY commands */ - if (ieee80211_is_data(fc) && sta) { + if (likely(ieee80211_is_data(fc) && sta && + !(info->control.flags & IEEE80211_TX_CTRL_RATE_INJECT))) { struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); if (mvmsta->sta_state >= IEEE80211_STA_AUTHORIZED) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index af31b09c396644..2a10d851d2e416 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -413,16 +413,20 @@ static void iwl_mvm_diversity_iter(void *_data, u8 *mac, { struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_diversity_iter_data *data = _data; - int i; + int i, link_id; - if (mvmvif->deflink.phy_ctxt != data->ctxt) - return; + for_each_mvm_vif_valid_link(mvmvif, link_id) { + struct iwl_mvm_vif_link_info *link_info = mvmvif->link[link_id]; - for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { - if (mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_STATIC || - mvmvif->deflink.smps_requests[i] == IEEE80211_SMPS_DYNAMIC) { - data->result = false; - break; + if (link_info->phy_ctxt != data->ctxt) + continue; + + for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) { + if (link_info->smps_requests[i] == IEEE80211_SMPS_STATIC || + link_info->smps_requests[i] == IEEE80211_SMPS_DYNAMIC) { + data->result = false; + break; + } } } } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index cb60ba40fe973d..fa4a1454686012 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2022 Intel Corporation + * Copyright (C) 2018-2023 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -281,70 +281,273 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans, bool alive) trans_pcie->prph_info = NULL; } -int iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, - const void *data, u32 len) +static int iwl_pcie_load_payloads_continuously(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_data, + struct iwl_dram_data *dram) +{ + u32 len, len0, len1; + + if (pnvm_data->n_chunks != UNFRAGMENTED_PNVM_PAYLOADS_NUMBER) { + IWL_DEBUG_FW(trans, "expected 2 payloads, got %d.\n", + pnvm_data->n_chunks); + return -EINVAL; + } + + len0 = pnvm_data->chunks[0].len; + len1 = pnvm_data->chunks[1].len; + if (len1 > 0xFFFFFFFF - len0) { + IWL_DEBUG_FW(trans, "sizes of payloads overflow.\n"); + return -EINVAL; + } + len = len0 + len1; + + dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent(trans, len, + &dram->physical); + if (!dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; + } + + dram->size = len; + memcpy(dram->block, pnvm_data->chunks[0].data, len0); + memcpy((u8 *)dram->block + len0, pnvm_data->chunks[1].data, len1); + + return 0; +} + +static int iwl_pcie_load_payloads_segments + (struct iwl_trans *trans, + struct iwl_dram_regions *dram_regions, + const struct iwl_pnvm_image *pnvm_data) +{ + struct iwl_dram_data *cur_payload_dram = &dram_regions->drams[0]; + struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; + struct iwl_prph_scrath_mem_desc_addr_array *addresses; + const void *data; + u32 len; + int i; + + /* allocate and init DRAM descriptors array */ + len = sizeof(struct iwl_prph_scrath_mem_desc_addr_array); + desc_dram->block = iwl_pcie_ctxt_info_dma_alloc_coherent + (trans, + len, + &desc_dram->physical); + if (!desc_dram->block) { + IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA.\n"); + return -ENOMEM; + } + desc_dram->size = len; + memset(desc_dram->block, 0, len); + + /* allocate DRAM region for each payload */ + dram_regions->n_regions = 0; + for (i = 0; i < pnvm_data->n_chunks; i++) { + len = pnvm_data->chunks[i].len; + data = pnvm_data->chunks[i].data; + + if (iwl_pcie_ctxt_info_alloc_dma(trans, + data, + len, + cur_payload_dram)) { + iwl_trans_pcie_free_pnvm_dram_regions(dram_regions, + trans->dev); + return -ENOMEM; + } + + dram_regions->n_regions++; + cur_payload_dram++; + } + + /* fill desc with the DRAM payloads addresses */ + addresses = desc_dram->block; + for (i = 0; i < pnvm_data->n_chunks; i++) { + addresses->mem_descs[i] = + cpu_to_le64(dram_regions->drams[i].physical); + } + + return 0; + +} + +int iwl_trans_pcie_ctx_info_gen3_load_pnvm(struct iwl_trans *trans, + const struct iwl_pnvm_image *pnvm_payloads, + const struct iwl_ucode_capabilities *capa) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - int ret; + struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data; + int ret = 0; + + /* only allocate the DRAM if not allocated yet */ + if (trans->pnvm_loaded) + return 0; + + if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) + return -EBUSY; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; - /* only allocate the DRAM if not allocated yet */ - if (!trans->pnvm_loaded) { - if (WARN_ON(prph_sc_ctrl->pnvm_cfg.pnvm_size)) - return -EBUSY; - - ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->pnvm_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, "Failed to allocate PNVM DMA %d.\n", - ret); - return ret; + if (!pnvm_payloads->n_chunks) { + IWL_DEBUG_FW(trans, "no payloads\n"); + return -EINVAL; + } + + /* save payloads in several DRAM sections */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) { + ret = iwl_pcie_load_payloads_segments(trans, + dram_regions, + pnvm_payloads); + if (!ret) + trans->pnvm_loaded = true; + } else { + /* save only in one DRAM section */ + ret = iwl_pcie_load_payloads_continuously + (trans, + pnvm_payloads, + &dram_regions->drams[0]); + if (!ret) { + dram_regions->n_regions = 1; + trans->pnvm_loaded = true; } } + return ret; +} + +static inline size_t +iwl_dram_regions_size(const struct iwl_dram_regions *dram_regions) +{ + size_t total_size = 0; + int i; + + for (i = 0; i < dram_regions->n_regions; i++) + total_size += dram_regions->drams[i].size; + + return total_size; +} + +static void iwl_pcie_set_pnvm_segments(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_regions *dram_regions = &trans_pcie->pnvm_data; + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = - cpu_to_le64(trans_pcie->pnvm_dram.physical); + cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical); prph_sc_ctrl->pnvm_cfg.pnvm_size = - cpu_to_le32(trans_pcie->pnvm_dram.size); + cpu_to_le32(iwl_dram_regions_size(dram_regions)); +} - return 0; +static void iwl_pcie_set_continuous_pnvm(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + prph_sc_ctrl->pnvm_cfg.pnvm_base_addr = + cpu_to_le64(trans_pcie->pnvm_data.drams[0].physical); + prph_sc_ctrl->pnvm_cfg.pnvm_size = + cpu_to_le32(trans_pcie->pnvm_data.drams[0].size); +} + +void iwl_trans_pcie_ctx_info_gen3_set_pnvm(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + iwl_pcie_set_pnvm_segments(trans); + else + iwl_pcie_set_continuous_pnvm(trans); } -int iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, - const void *data, u32 len) +int iwl_trans_pcie_ctx_info_gen3_load_reduce_power(struct iwl_trans *trans, + const struct iwl_pnvm_image *payloads, + const struct iwl_ucode_capabilities *capa) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = &trans_pcie->prph_scratch->ctrl_cfg; - int ret; + struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data; + int ret = 0; + + /* only allocate the DRAM if not allocated yet */ + if (trans->reduce_power_loaded) + return 0; if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) return 0; - /* only allocate the DRAM if not allocated yet */ - if (!trans->reduce_power_loaded) { - if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) - return -EBUSY; + if (WARN_ON(prph_sc_ctrl->reduce_power_cfg.size)) + return -EBUSY; - ret = iwl_pcie_ctxt_info_alloc_dma(trans, data, len, - &trans_pcie->reduce_power_dram); - if (ret < 0) { - IWL_DEBUG_FW(trans, - "Failed to allocate reduce power DMA %d.\n", - ret); - return ret; + if (!payloads->n_chunks) { + IWL_DEBUG_FW(trans, "no payloads\n"); + return -EINVAL; + } + + /* save payloads in several DRAM sections */ + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) { + ret = iwl_pcie_load_payloads_segments(trans, + dram_regions, + payloads); + if (!ret) + trans->reduce_power_loaded = true; + } else { + /* save only in one DRAM section */ + ret = iwl_pcie_load_payloads_continuously + (trans, + payloads, + &dram_regions->drams[0]); + if (!ret) { + dram_regions->n_regions = 1; + trans->reduce_power_loaded = true; } } + return ret; +} + +static void iwl_pcie_set_reduce_power_segments(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + struct iwl_dram_regions *dram_regions = &trans_pcie->reduced_tables_data; + prph_sc_ctrl->reduce_power_cfg.base_addr = - cpu_to_le64(trans_pcie->reduce_power_dram.physical); + cpu_to_le64(dram_regions->prph_scratch_mem_desc.physical); prph_sc_ctrl->reduce_power_cfg.size = - cpu_to_le32(trans_pcie->reduce_power_dram.size); + cpu_to_le32(iwl_dram_regions_size(dram_regions)); +} - return 0; +static void iwl_pcie_set_continuous_reduce_power(struct iwl_trans *trans) +{ + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl = + &trans_pcie->prph_scratch->ctrl_cfg; + + prph_sc_ctrl->reduce_power_cfg.base_addr = + cpu_to_le64(trans_pcie->reduced_tables_data.drams[0].physical); + prph_sc_ctrl->reduce_power_cfg.size = + cpu_to_le32(trans_pcie->reduced_tables_data.drams[0].size); +} + +void +iwl_trans_pcie_ctx_info_gen3_set_reduce_power(struct iwl_trans *trans, + const struct iwl_ucode_capabilities *capa) +{ + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + return; + + if (fw_has_capa(capa, IWL_UCODE_TLV_CAPA_FRAGMENTED_PNVM_IMG)) + iwl_pcie_set_reduce_power_segments(trans); + else + iwl_pcie_set_continuous_reduce_power(trans); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index 74ce31fdf45e97..5f55efe64bf5c4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2021 Intel Corporation + * Copyright (C) 2018-2022 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -38,9 +38,9 @@ static void *_iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, return result; } -static void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, - size_t size, - dma_addr_t *phys) +void *iwl_pcie_ctxt_info_dma_alloc_coherent(struct iwl_trans *trans, + size_t size, + dma_addr_t *phys) { return _iwl_pcie_ctxt_info_dma_alloc_coherent(trans, size, phys, 0); } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index 69b95ad5993b0a..0adcf0e13e85aa 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -23,6 +23,7 @@ #include "iwl-op-mode.h" #include "iwl-drv.h" #include "queue/tx.h" +#include "iwl-context-info.h" /* * RX related structures and functions @@ -306,7 +307,9 @@ enum iwl_pcie_imr_status { * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @kw: keep warm address - * @pnvm_dram: DRAM area that contains the PNVM data + * @pnvm_data: holds info about pnvm payloads allocated in DRAM + * @reduced_tables_data: holds info about power reduced tablse + * payloads allocated in DRAM * @pci_dev: basic pci-network driver stuff * @hw_base: pci hardware address support * @ucode_write_complete: indicates that the ucode has been copied. @@ -380,8 +383,9 @@ struct iwl_trans_pcie { u32 scd_base_addr; struct iwl_dma_ptr kw; - struct iwl_dram_data pnvm_dram; - struct iwl_dram_data reduce_power_dram; + /* pnvm data */ + struct iwl_dram_regions pnvm_data; + struct iwl_dram_regions reduced_tables_data; struct iwl_txq *txq_memory; @@ -478,6 +482,8 @@ struct iwl_trans const struct pci_device_id *ent, const struct iwl_cfg_trans_params *cfg_trans); void iwl_trans_pcie_free(struct iwl_trans *trans); +void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, + struct device *dev); bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); #define _iwl_trans_pcie_grab_nic_access(trans) \ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index b281850fbf7a99..15419397ac7303 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -131,13 +131,15 @@ static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans, bool retake_ownership) { /* Reset entire device - do controller reset (results in SHRD_HW_RST) */ - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) { iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_SW_RESET); - else + usleep_range(10000, 20000); + } else { iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - usleep_range(5000, 6000); + usleep_range(5000, 6000); + } if (retake_ownership) return iwl_pcie_prepare_card_hw(trans); @@ -475,7 +477,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans) CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS, 100); - msleep(100); + usleep_range(10000, 20000); } else { iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); @@ -1993,6 +1995,29 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans, trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake; } +void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions, + struct device *dev) +{ + u8 i; + struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc; + + /* free DRAM payloads */ + for (i = 0; i < dram_regions->n_regions; i++) { + dma_free_coherent(dev, dram_regions->drams[i].size, + dram_regions->drams[i].block, + dram_regions->drams[i].physical); + } + dram_regions->n_regions = 0; + + /* free DRAM addresses array */ + if (desc_dram->block) { + dma_free_coherent(dev, desc_dram->size, + desc_dram->block, + desc_dram->physical); + } + memset(desc_dram, 0, sizeof(*desc_dram)); +} + void iwl_trans_pcie_free(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); @@ -2025,16 +2050,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans) iwl_pcie_free_fw_monitor(trans); - if (trans_pcie->pnvm_dram.size) - dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size, - trans_pcie->pnvm_dram.block, - trans_pcie->pnvm_dram.physical); - - if (trans_pcie->reduce_power_dram.size) - dma_free_coherent(trans->dev, - trans_pcie->reduce_power_dram.size, - trans_pcie->reduce_power_dram.block, - trans_pcie->reduce_power_dram.physical); + iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data, + trans->dev); + iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->reduced_tables_data, + trans->dev); mutex_destroy(&trans_pcie->mutex); iwl_trans_free(trans); @@ -3534,7 +3553,9 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = { .txq_free = iwl_txq_dyn_free, .wait_txq_empty = iwl_trans_pcie_wait_txq_empty, .rxq_dma_data = iwl_trans_pcie_rxq_dma_data, + .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm, .set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm, + .load_reduce_power = iwl_trans_pcie_ctx_info_gen3_load_reduce_power, .set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power, #ifdef CONFIG_IWLWIFI_DEBUGFS .debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup, diff --git a/drivers/net/wireless/intersil/hostap/Kconfig b/drivers/net/wireless/intersil/hostap/Kconfig index c865d3156ceaa2..2edff8efbcbb11 100644 --- a/drivers/net/wireless/intersil/hostap/Kconfig +++ b/drivers/net/wireless/intersil/hostap/Kconfig @@ -56,7 +56,7 @@ config HOSTAP_FIRMWARE_NVRAM config HOSTAP_PLX tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors" - depends on PCI && HOSTAP + depends on PCI && HOSTAP && HAS_IOPORT help Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based PCI adaptors. diff --git a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c index a956f965a1e5ec..03bfd2482656c0 100644 --- a/drivers/net/wireless/intersil/orinoco/orinoco_cs.c +++ b/drivers/net/wireless/intersil/orinoco/orinoco_cs.c @@ -96,6 +96,7 @@ orinoco_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, orinoco_cs_hard_reset, NULL); @@ -107,8 +108,16 @@ orinoco_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return orinoco_cs_config(link); -} /* orinoco_cs_attach */ + ret = orinoco_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void orinoco_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c index 291ef97ed45ec4..841d623c621ac7 100644 --- a/drivers/net/wireless/intersil/orinoco/spectrum_cs.c +++ b/drivers/net/wireless/intersil/orinoco/spectrum_cs.c @@ -157,6 +157,7 @@ spectrum_cs_probe(struct pcmcia_device *link) { struct orinoco_private *priv; struct orinoco_pccard *card; + int ret; priv = alloc_orinocodev(sizeof(*card), &link->dev, spectrum_cs_hard_reset, @@ -169,8 +170,16 @@ spectrum_cs_probe(struct pcmcia_device *link) card->p_dev = link; link->priv = priv; - return spectrum_cs_config(link); -} /* spectrum_cs_attach */ + ret = spectrum_cs_config(link); + if (ret) + goto err_free_orinocodev; + + return 0; + +err_free_orinocodev: + free_orinocodev(priv); + return ret; +} static void spectrum_cs_detach(struct pcmcia_device *link) { diff --git a/drivers/net/wireless/legacy/ray_cs.c b/drivers/net/wireless/legacy/ray_cs.c index 1f57a0055bbd80..4b53a9c70e7e7f 100644 --- a/drivers/net/wireless/legacy/ray_cs.c +++ b/drivers/net/wireless/legacy/ray_cs.c @@ -270,13 +270,14 @@ static int ray_probe(struct pcmcia_device *p_dev) { ray_dev_t *local; struct net_device *dev; + int ret; dev_dbg(&p_dev->dev, "ray_attach()\n"); /* Allocate space for private device-specific data */ dev = alloc_etherdev(sizeof(ray_dev_t)); if (!dev) - goto fail_alloc_dev; + return -ENOMEM; local = netdev_priv(dev); local->finder = p_dev; @@ -313,16 +314,20 @@ static int ray_probe(struct pcmcia_device *p_dev) timer_setup(&local->timer, NULL, 0); this_device = p_dev; - return ray_config(p_dev); + ret = ray_config(p_dev); + if (ret) + goto err_free_dev; -fail_alloc_dev: - return -ENOMEM; -} /* ray_attach */ + return 0; + +err_free_dev: + free_netdev(dev); + return ret; +} static void ray_detach(struct pcmcia_device *link) { struct net_device *dev; - ray_dev_t *local; dev_dbg(&link->dev, "ray_detach\n"); @@ -331,9 +336,6 @@ static void ray_detach(struct pcmcia_device *link) ray_release(link); - local = netdev_priv(dev); - del_timer_sync(&local->timer); - if (link->priv) { unregister_netdev(dev); free_netdev(dev); @@ -734,11 +736,14 @@ static void ray_release(struct pcmcia_device *link) dev_dbg(&link->dev, "ray_release\n"); - del_timer(&local->timer); + del_timer_sync(&local->timer); - iounmap(local->sram); - iounmap(local->rmem); - iounmap(local->amem); + if (local->sram) + iounmap(local->sram); + if (local->rmem) + iounmap(local->rmem); + if (local->amem) + iounmap(local->amem); pcmcia_disable_device(link); dev_dbg(&link->dev, "ray_release ending\n"); diff --git a/drivers/net/wireless/legacy/wl3501_cs.c b/drivers/net/wireless/legacy/wl3501_cs.c index 7fb2f951347600..c45c4b7cbbaf18 100644 --- a/drivers/net/wireless/legacy/wl3501_cs.c +++ b/drivers/net/wireless/legacy/wl3501_cs.c @@ -1862,6 +1862,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) { struct net_device *dev; struct wl3501_card *this; + int ret; /* The io structure describes IO port mapping */ p_dev->resource[0]->end = 16; @@ -1873,8 +1874,7 @@ static int wl3501_probe(struct pcmcia_device *p_dev) dev = alloc_etherdev(sizeof(struct wl3501_card)); if (!dev) - goto out_link; - + return -ENOMEM; dev->netdev_ops = &wl3501_netdev_ops; dev->watchdog_timeo = 5 * HZ; @@ -1887,9 +1887,15 @@ static int wl3501_probe(struct pcmcia_device *p_dev) netif_stop_queue(dev); p_dev->priv = dev; - return wl3501_config(p_dev); -out_link: - return -ENOMEM; + ret = wl3501_config(p_dev); + if (ret) + goto out_free_etherdev; + + return 0; + +out_free_etherdev: + free_netdev(dev); + return ret; } static int wl3501_config(struct pcmcia_device *link) diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 467afef98ba206..ee72869e5572dd 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -566,7 +566,7 @@ int mt76_create_page_pool(struct mt76_dev *dev, struct mt76_queue *q) { struct page_pool_params pp_params = { .order = 0, - .flags = PP_FLAG_PAGE_FRAG, + .flags = 0, .nid = NUMA_NO_NODE, .dev = dev->dma_dev, }; diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index 6b07b8fafec2fb..95c16f11d15601 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "util.h" #include "testmode.h" diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index da1d17b73a2553..64002484ccadbc 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -914,7 +914,10 @@ void mt7615_mac_sta_poll(struct mt7615_dev *dev) msta = list_first_entry(&sta_poll_list, struct mt7615_sta, poll_list); + + spin_lock_bh(&dev->sta_poll_lock); list_del_init(&msta->poll_list); + spin_unlock_bh(&dev->sta_poll_lock); addr = mt7615_mac_wtbl_addr(dev, msta->wcid.idx) + 19 * 4; diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c index 39a4a73ef8e6a1..9b0f6053e0fa62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c @@ -1004,10 +1004,10 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, { struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_vif *vif = info->control.vif; - struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; + struct mt7996_vif *mvif; u16 tx_count = 15; u32 val; bool beacon = !!(changed & (BSS_CHANGED_BEACON | @@ -1015,7 +1015,8 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, bool inband_disc = !!(changed & (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | BSS_CHANGED_FILS_DISCOVERY)); - if (vif) { + mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL; + if (mvif) { omac_idx = mvif->mt76.omac_idx; wmm_idx = mvif->mt76.wmm_idx; band_idx = mvif->mt76.band_idx; @@ -1081,12 +1082,16 @@ void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi, struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; bool mcast = ieee80211_is_data(hdr->frame_control) && is_multicast_ether_addr(hdr->addr1); - u8 idx = mvif->basic_rates_idx; + u8 idx = MT7996_BASIC_RATES_TBL; - if (mcast && mvif->mcast_rates_idx) - idx = mvif->mcast_rates_idx; - else if (beacon && mvif->beacon_rates_idx) - idx = mvif->beacon_rates_idx; + if (mvif) { + if (mcast && mvif->mcast_rates_idx) + idx = mvif->mcast_rates_idx; + else if (beacon && mvif->beacon_rates_idx) + idx = mvif->beacon_rates_idx; + else + idx = mvif->basic_rates_idx; + } txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, idx)); txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig index 82bcaf44a65f58..44ad94757a03e9 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig +++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig @@ -11,7 +11,8 @@ config RTL8XXXU parts written to utilize the Linux mac80211 stack. The driver is known to work with a number of RTL8723AU, RL8188CU, RTL8188RU, RTL8191CU, RTL8192CU, RTL8723BU, RTL8192EU, - RTL8188FU, RTL8188EU, and RTL8710BU (aka RTL8188GU) devices. + RTL8188FU, RTL8188EU, RTL8710BU (aka RTL8188GU), and RTL8192FU + devices. This driver is under development and has a limited feature set. In particular it does not yet support 40MHz channels diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Makefile b/drivers/net/wireless/realtek/rtl8xxxu/Makefile index 1bf083c15dcd39..fa466589eccb9c 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/Makefile +++ b/drivers/net/wireless/realtek/rtl8xxxu/Makefile @@ -3,4 +3,4 @@ obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o rtl8xxxu-y := rtl8xxxu_core.o rtl8xxxu_8192e.o rtl8xxxu_8723b.o \ rtl8xxxu_8723a.o rtl8xxxu_8192c.o rtl8xxxu_8188f.o \ - rtl8xxxu_8188e.o rtl8xxxu_8710b.o + rtl8xxxu_8188e.o rtl8xxxu_8710b.o rtl8xxxu_8192f.o diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index 376b4b72eb8017..4695fb4e2d2dba 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -39,6 +39,7 @@ #define TX_TOTAL_PAGE_NUM_8188E 0xa9 #define TX_TOTAL_PAGE_NUM_8192E 0xf3 #define TX_TOTAL_PAGE_NUM_8723B 0xf7 +#define TX_TOTAL_PAGE_NUM_8192F 0xf7 /* (HPQ + LPQ + NPQ + PUBQ) = TX_TOTAL_PAGE_NUM */ #define TX_PAGE_NUM_PUBQ 0xe7 #define TX_PAGE_NUM_HI_PQ 0x0c @@ -65,6 +66,11 @@ #define TX_PAGE_NUM_LO_PQ_8723B 0x02 #define TX_PAGE_NUM_NORM_PQ_8723B 0x02 +#define TX_PAGE_NUM_PUBQ_8192F 0xde +#define TX_PAGE_NUM_HI_PQ_8192F 0x08 +#define TX_PAGE_NUM_LO_PQ_8192F 0x08 +#define TX_PAGE_NUM_NORM_PQ_8192F 0x08 + #define RTL_FW_PAGE_SIZE 4096 #define RTL8XXXU_FIRMWARE_POLL_MAX 1000 @@ -81,6 +87,7 @@ #define EFUSE_REAL_CONTENT_LEN_8723A 512 #define EFUSE_BT_MAP_LEN_8723A 1024 #define EFUSE_MAX_WORD_UNIT 4 +#define EFUSE_UNDEFINED 0xff enum rtl8xxxu_rtl_chip { RTL8192S = 0x81920, @@ -105,6 +112,7 @@ enum rtl8xxxu_rtl_chip { RTL8195A = 0x8195a, RTL8188F = 0x8188f, RTL8710B = 0x8710b, + RTL8192F = 0x8192f, }; enum rtl8xxxu_rx_type { @@ -1246,6 +1254,40 @@ struct rtl8710bu_efuse { u8 res7[0x3c]; } __packed; +struct rtl8192fu_efuse { + __le16 rtl_id; + u8 res0[0x0e]; + struct rtl8192eu_efuse_tx_power tx_power_index_A; /* 0x10 */ + struct rtl8192eu_efuse_tx_power tx_power_index_B; /* 0x3a */ + u8 res2[0x54]; + u8 channel_plan; /* 0xb8 */ + u8 xtal_k; /* 0xb9 */ + u8 thermal_meter; /* 0xba */ + u8 iqk_lck; /* 0xbb */ + u8 pa_type; /* 0xbc */ + u8 lna_type_2g; /* 0xbd */ + u8 res3[1]; + u8 lna_type_5g; /* 0xbf */ + u8 res4[1]; + u8 rf_board_option; /* 0xc1 */ + u8 rf_feature_option; /* 0xc2 */ + u8 rf_bt_setting; /* 0xc3 */ + u8 eeprom_version; /* 0xc4 */ + u8 eeprom_customer_id; /* 0xc5 */ + u8 res5[3]; + u8 rf_antenna_option; /* 0xc9 */ + u8 rfe_option; /* 0xca */ + u8 country_code; /* 0xcb */ + u8 res6[52]; + u8 vid[2]; /* 0x100 */ + u8 pid[2]; /* 0x102 */ + u8 usb_optional_function; /* 0x104 */ + u8 res7[2]; + u8 mac_addr[ETH_ALEN]; /* 0x107 */ + u8 device_info[80]; /* 0x10d */ + u8 res9[163]; +} __packed; + struct rtl8xxxu_reg8val { u16 reg; u8 val; @@ -1796,6 +1838,7 @@ struct rtl8xxxu_priv { u32 cck_agc_report_type:1; u32 cck_new_agc:1; u8 default_crystal_cap; + u8 rfe_type; unsigned int pipe_interrupt; unsigned int pipe_in; unsigned int pipe_out[TXDESC_QUEUE_MAX]; @@ -1836,6 +1879,7 @@ struct rtl8xxxu_priv { struct rtl8188fu_efuse efuse8188fu; struct rtl8188eu_efuse efuse8188eu; struct rtl8710bu_efuse efuse8710bu; + struct rtl8192fu_efuse efuse8192fu; } efuse_wifi; u32 adda_backup[RTL8XXXU_ADDA_REGS]; u32 mac_backup[RTL8XXXU_MAC_REGS]; @@ -1944,6 +1988,7 @@ struct rtl8xxxu_fileops { u8 init_reg_hmtfr:1; u8 ampdu_max_time; u8 ustime_tsf_edca; + u16 max_aggr_num; u8 supports_ap:1; u16 max_macid_num; u32 adda_1t_init; @@ -2032,6 +2077,7 @@ void rtl8xxxu_gen1_phy_iq_calibrate(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen1_init_phy_bb(struct rtl8xxxu_priv *priv); void rtl8xxxu_gen1_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40); +void rtl8188f_channel_to_group(int channel, int *group, int *cck_group); void rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40); void rtl8xxxu_gen1_config_channel(struct ieee80211_hw *hw); @@ -2096,6 +2142,7 @@ void rtl8xxxu_update_ra_report(struct rtl8xxxu_ra_report *rarpt, void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra); void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb); +extern struct rtl8xxxu_fileops rtl8192fu_fops; extern struct rtl8xxxu_fileops rtl8710bu_fops; extern struct rtl8xxxu_fileops rtl8188fu_fops; extern struct rtl8xxxu_fileops rtl8188eu_fops; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c index 71b7f0d31bf436..1e1c8fa194cb83 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8188f.c @@ -351,7 +351,7 @@ static int rtl8188fu_identify_chip(struct rtl8xxxu_priv *priv) return ret; } -static void rtl8188f_channel_to_group(int channel, int *group, int *cck_group) +void rtl8188f_channel_to_group(int channel, int *group, int *cck_group) { if (channel < 3) *group = 0; @@ -654,7 +654,7 @@ static void rtl8188fu_config_channel(struct ieee80211_hw *hw) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_BB2, val32); /* RC Corner */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00140); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00140); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_G2, 0x01c6c); } @@ -854,8 +854,8 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7); /* PA,PAD gain adjust */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a); /* enter IQK mode */ val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK); @@ -886,7 +886,7 @@ static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); /* save LOK result */ *lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC); @@ -927,8 +927,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173); /* PA,PAD gain adjust */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x5102a); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a); /* * Enter IQK mode @@ -967,7 +967,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); /* Check failed */ reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); @@ -1002,8 +1002,8 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) /* * PA, PAD setting */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x51000); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x51000); /* * Enter IQK mode @@ -1041,7 +1041,7 @@ static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) val32 &= 0x000000ff; rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); /* reload LOK value */ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result); @@ -1748,6 +1748,7 @@ struct rtl8xxxu_fileops rtl8188fu_fops = { .init_reg_hmtfr = 1, .ampdu_max_time = 0x70, .ustime_tsf_edca = 0x28, + .max_aggr_num = 0x0c14, .supports_ap = 1, .max_macid_num = 16, .adda_1t_init = 0x03c00014, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index fcc2926ea93894..f673aa9ba15a57 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -716,7 +716,7 @@ static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv) * PA/PAD controlled by 0x0 */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00180); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000); @@ -776,8 +776,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x511e0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x511e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -816,7 +816,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) } else { /* PA/PAD controlled by 0x0 */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); goto out; } @@ -838,8 +838,8 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, 0x510e0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x510e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -869,7 +869,7 @@ static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180); if (!(reg_eac & BIT(27)) && ((reg_ea4 & 0x03ff0000) != 0x01320000) && @@ -889,7 +889,7 @@ static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv) int result = 0; rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00180); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00180); rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0); rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x20000); @@ -952,8 +952,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x511e0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x511e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -995,7 +995,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) * Vendor driver restores RF_A here which I believe is a bug */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180); goto out; } @@ -1017,8 +1017,8 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2); /* PA/PAD control by 0x56, and set = 0x0 */ - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x00980); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_56, 0x510e0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x510e0); /* Enter IQK mode */ rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000); @@ -1049,7 +1049,7 @@ static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000); - rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_UNKNOWN_DF, 0x180); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180); if (!(reg_eac & BIT(30)) && ((reg_ec4 & 0x03ff0000) != 0x01320000) && diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c new file mode 100644 index 00000000000000..18dc5221a9c0c4 --- /dev/null +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192f.c @@ -0,0 +1,2090 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * RTL8XXXU mac80211 USB driver - 8192fu specific subdriver + * + * Copyright (c) 2023 Bitterblue Smith + * + * Portions copied from existing rtl8xxxu code: + * Copyright (c) 2014 - 2017 Jes Sorensen + * + * Portions, notably calibration code: + * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rtl8xxxu.h" +#include "rtl8xxxu_regs.h" + +static const struct rtl8xxxu_reg8val rtl8192f_mac_init_table[] = { + {0x420, 0x00}, {0x422, 0x78}, {0x428, 0x0a}, {0x429, 0x10}, + {0x430, 0x00}, {0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01}, + {0x434, 0x04}, {0x435, 0x05}, {0x436, 0x07}, {0x437, 0x08}, + {0x43c, 0x04}, {0x43d, 0x05}, {0x43e, 0x07}, {0x43f, 0x08}, + {0x440, 0x5d}, {0x441, 0x01}, {0x442, 0x00}, {0x444, 0x10}, + {0x445, 0xf0}, {0x446, 0x0e}, {0x447, 0x1f}, {0x448, 0x00}, + {0x449, 0x00}, {0x44a, 0x00}, {0x44b, 0x00}, {0x44c, 0x10}, + {0x44d, 0xf0}, {0x44e, 0x0e}, {0x44f, 0x00}, {0x450, 0x00}, + {0x451, 0x00}, {0x452, 0x00}, {0x453, 0x00}, {0x480, 0x20}, + {0x49c, 0x30}, {0x49d, 0xf0}, {0x49e, 0x03}, {0x49f, 0x3e}, + {0x4a0, 0x00}, {0x4a1, 0x00}, {0x4a2, 0x00}, {0x4a3, 0x00}, + {0x4a4, 0x15}, {0x4a5, 0xf0}, {0x4a6, 0x01}, {0x4a7, 0x0e}, + {0x4a8, 0xe0}, {0x4a9, 0x00}, {0x4aa, 0x00}, {0x4ab, 0x00}, + {0x2448, 0x06}, {0x244a, 0x06}, {0x244c, 0x06}, {0x244e, 0x06}, + {0x4c7, 0x80}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4ca, 0x3c}, + {0x4cb, 0x3c}, {0x4cc, 0xff}, {0x4cd, 0xff}, {0x4ce, 0x01}, + {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f}, {0x503, 0x00}, + {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e}, {0x507, 0x00}, + {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e}, {0x50b, 0x00}, + {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00}, {0x50f, 0x00}, + {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a}, {0x521, 0x2f}, + {0x525, 0x0f}, {0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, + {0x55c, 0x50}, {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, + {0x609, 0x2a}, {0x60c, 0x18}, {0x620, 0xff}, {0x621, 0xff}, + {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff}, {0x625, 0xff}, + {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50}, {0x63c, 0x0a}, + {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e}, {0x640, 0x40}, + {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8}, {0x66e, 0x05}, + {0x6a0, 0xff}, {0x6a1, 0xff}, {0x6a2, 0xff}, {0x6a3, 0xff}, + {0x6a4, 0xff}, {0x6a5, 0xff}, {0x6de, 0x84}, {0x700, 0x21}, + {0x701, 0x43}, {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, + {0x709, 0x43}, {0x70a, 0x65}, {0x70b, 0x87}, {0x718, 0x40}, + {0x7c0, 0x38}, {0x7c2, 0x0f}, {0x7c3, 0xc0}, {0x073, 0x04}, + {0x7c4, 0x77}, {0x024, 0xc7}, {0x7ec, 0xff}, {0x7ed, 0xff}, + {0x7ee, 0xff}, {0x7ef, 0xff}, + {0xffff, 0xff}, +}; + +/* If updating the phy init table, also update rtl8192f_revise_cck_tx_psf(). */ +static const struct rtl8xxxu_reg32val rtl8192fu_phy_init_table[] = { + {0x800, 0x80006C00}, {0x804, 0x00004001}, + {0x808, 0x0000FC00}, {0x80C, 0x00000000}, + {0x810, 0x20200322}, {0x814, 0x020C3910}, + {0x818, 0x00000385}, {0x81C, 0x07000000}, + {0x820, 0x01000100}, {0x824, 0x00390204}, + {0x828, 0x01000100}, {0x82C, 0x00390204}, + {0x830, 0x25252525}, {0x834, 0x25252525}, + {0x838, 0x25252525}, {0x83C, 0x25252525}, + {0x840, 0x00010000}, {0x844, 0x00010000}, + {0x848, 0x25252525}, {0x84C, 0x25252525}, + {0x850, 0x00031FE0}, {0x854, 0x00000000}, + {0x858, 0x569A569A}, {0x85C, 0x00400040}, + {0x860, 0x66F60000}, {0x864, 0x061F0000}, + {0x868, 0x25252525}, {0x86C, 0x25252525}, + {0x870, 0x00000300}, {0x874, 0x04003400}, + {0x878, 0x08080808}, {0x87C, 0x004F0201}, + {0x880, 0xD8001402}, {0x884, 0xC0000120}, + {0x888, 0x00000000}, {0x88C, 0xCC0000C0}, + {0x890, 0x00000000}, {0x894, 0xFFFFFFFE}, + {0x898, 0x40302010}, {0x89C, 0x00706050}, + {0x900, 0x00000000}, {0x904, 0x00000023}, + {0x908, 0x00000F00}, {0x90C, 0x81121313}, + {0x910, 0x024C0000}, {0x914, 0x00000000}, + {0x918, 0x00000000}, {0x91C, 0x00000000}, + {0x920, 0x00000000}, {0x924, 0x00000000}, + {0x928, 0x00000000}, {0x92C, 0x00000000}, + {0x930, 0x88000000}, {0x934, 0x00000245}, + {0x938, 0x00024588}, {0x93C, 0x00000000}, + {0x940, 0x000007FF}, {0x944, 0x3F3F0000}, + {0x948, 0x000001A3}, {0x94C, 0x20200008}, + {0x950, 0x00338A98}, {0x954, 0x00000000}, + {0x958, 0xCBCAD87A}, {0x95C, 0x06EB5735}, + {0x960, 0x00000000}, {0x964, 0x00000000}, + {0x968, 0x00000000}, {0x96C, 0x00000003}, + {0x970, 0x00000000}, {0x974, 0x00000000}, + {0x978, 0x00000000}, {0x97C, 0x10030000}, + {0x980, 0x00000000}, {0x984, 0x02800280}, + {0x988, 0x020A5704}, {0x98C, 0x1461C826}, + {0x990, 0x0001469E}, {0x994, 0x008858D1}, + {0x998, 0x400086C9}, {0x99C, 0x44444242}, + {0x9A0, 0x00000000}, {0x9A4, 0x00000000}, + {0x9A8, 0x00000000}, {0x9AC, 0xC0000000}, + {0xA00, 0x00D047C8}, {0xA04, 0xC1FF0008}, + {0xA08, 0x88838300}, {0xA0C, 0x2E20100F}, + {0xA10, 0x9500BB78}, {0xA14, 0x11144028}, + {0xA18, 0x00881117}, {0xA1C, 0x89140F00}, + {0xA20, 0xE82C0001}, {0xA24, 0x64B80C1C}, + {0xA28, 0x00158810}, {0xA2C, 0x10BB8000}, + {0xA70, 0x00008000}, {0xA74, 0x80800100}, + {0xA78, 0x000089F0}, {0xA7C, 0x225B0606}, + {0xA80, 0x20803210}, {0xA84, 0x00200200}, + {0xA88, 0x00000000}, {0xA8C, 0x00000000}, + {0xA90, 0x00000000}, {0xA94, 0x00000000}, + {0xA98, 0x00000000}, {0xA9C, 0x00460000}, + {0xAA0, 0x00000000}, {0xAA4, 0x00020014}, + {0xAA8, 0xBA0A0008}, {0xAAC, 0x01235667}, + {0xAB0, 0x00000000}, {0xAB4, 0x00201402}, + {0xAB8, 0x0000001C}, {0xABC, 0x0000F7FF}, + {0xAC0, 0xD4C0A742}, {0xAC4, 0x00000000}, + {0xAC8, 0x00000F08}, {0xACC, 0x00000F07}, + {0xAD0, 0xA1052A10}, {0xAD4, 0x0D9D8452}, + {0xAD8, 0x9E024024}, {0xADC, 0x0023C001}, + {0xAE0, 0x00000391}, {0xB2C, 0x00000000}, + {0xC00, 0x00000080}, {0xC04, 0x6F005433}, + {0xC08, 0x000004E4}, {0xC0C, 0x6C6C6C6C}, + {0xC10, 0x22000000}, {0xC14, 0x40000100}, + {0xC18, 0x22000000}, {0xC1C, 0x40000100}, + {0xC20, 0x00000000}, {0xC24, 0x40000100}, + {0xC28, 0x00000000}, {0xC2C, 0x40000100}, + {0xC30, 0x0401E809}, {0xC34, 0x30000020}, + {0xC38, 0x23808080}, {0xC3C, 0x00002F44}, + {0xC40, 0x1CF8403F}, {0xC44, 0x000100C7}, + {0xC48, 0xEC060106}, {0xC4C, 0x007F037F}, + {0xC50, 0x00E48020}, {0xC54, 0x04008017}, + {0xC58, 0x00000020}, {0xC5C, 0x00708492}, + {0xC60, 0x09280200}, {0xC64, 0x5014838B}, + {0xC68, 0x47C006C7}, {0xC6C, 0x00000035}, + {0xC70, 0x00001007}, {0xC74, 0x02815269}, + {0xC78, 0x0FE07F1F}, {0xC7C, 0x00B91612}, + {0xC80, 0x40000100}, {0xC84, 0x32000000}, + {0xC88, 0x40000100}, {0xC8C, 0xA0240000}, + {0xC90, 0x400E161E}, {0xC94, 0x00000F00}, + {0xC98, 0x400E161E}, {0xC9C, 0x0000BDC8}, + {0xCA0, 0x00000000}, {0xCA4, 0x098300A0}, + {0xCA8, 0x00006B00}, {0xCAC, 0x87F45B1A}, + {0xCB0, 0x0000002D}, {0xCB4, 0x00000000}, + {0xCB8, 0x00000000}, {0xCBC, 0x28100200}, + {0xCC0, 0x0010A3D0}, {0xCC4, 0x00000F7D}, + {0xCC8, 0x00000000}, {0xCCC, 0x00000000}, + {0xCD0, 0x593659AD}, {0xCD4, 0xB7545121}, + {0xCD8, 0x64B22427}, {0xCDC, 0x00766932}, + {0xCE0, 0x40201000}, {0xCE4, 0x00000000}, + {0xCE8, 0x40E04407}, {0xCEC, 0x2E572000}, + {0xD00, 0x000D8780}, {0xD04, 0x40020403}, + {0xD08, 0x0002907F}, {0xD0C, 0x20010201}, + {0xD10, 0x06288888}, {0xD14, 0x8888367B}, + {0xD18, 0x7D806DB3}, {0xD1C, 0x0000007F}, + {0xD20, 0x567600B8}, {0xD24, 0x0000018B}, + {0xD28, 0xD513FF7D}, {0xD2C, 0xCC979975}, + {0xD30, 0x04928000}, {0xD34, 0x40608000}, + {0xD38, 0x88DDA000}, {0xD3C, 0x00026EE2}, + {0xD50, 0x67270001}, {0xD54, 0x20500000}, + {0xD58, 0x16161616}, {0xD5C, 0x71F20064}, + {0xD60, 0x4653DA60}, {0xD64, 0x3E718A3C}, + {0xD68, 0x00000183}, {0xD7C, 0x00000000}, + {0xD80, 0x50000000}, {0xD84, 0x31310400}, + {0xD88, 0xF5B50000}, {0xD8C, 0x00000000}, + {0xD90, 0x00000000}, {0xD94, 0x44BBBB44}, + {0xD98, 0x44BB44FF}, {0xD9C, 0x06033688}, + {0xE00, 0x25252525}, {0xE04, 0x25252525}, + {0xE08, 0x25252525}, {0xE10, 0x25252525}, + {0xE14, 0x25252525}, {0xE18, 0x25252525}, + {0xE1C, 0x25252525}, {0xE20, 0x00000000}, + {0xE24, 0x00200000}, {0xE28, 0x00000000}, + {0xE2C, 0x00000000}, {0xE30, 0x01007C00}, + {0xE34, 0x01004800}, {0xE38, 0x10008C0F}, + {0xE3C, 0x3C008C0F}, {0xE40, 0x01007C00}, + {0xE44, 0x00000000}, {0xE48, 0x00000000}, + {0xE4C, 0x00000000}, {0xE50, 0x01007C00}, + {0xE54, 0x01004800}, {0xE58, 0x10008C0F}, + {0xE5C, 0x3C008C0F}, {0xE60, 0x02100000}, + {0xE64, 0xBBBBBBBB}, {0xE68, 0x40404040}, + {0xE6C, 0x80408040}, {0xE70, 0x80408040}, + {0xE74, 0x40404040}, {0xE78, 0x00400040}, + {0xE7C, 0x40404040}, {0xE80, 0x00FF0000}, + {0xE84, 0x80408040}, {0xE88, 0x40404040}, + {0xE8C, 0x80408040}, {0xED0, 0x80408040}, + {0xED4, 0x80408040}, {0xED8, 0x80408040}, + {0xEDC, 0xC040C040}, {0xEE0, 0xC040C040}, + {0xEE4, 0x00400040}, {0xEE8, 0xD8001402}, + {0xEEC, 0xC0000120}, {0xEF0, 0x02000B09}, + {0xEF4, 0x00000001}, {0xEF8, 0x00000000}, + {0xF00, 0x00000300}, {0xF04, 0x00000002}, + {0xF08, 0x00007D0C}, {0xF0C, 0x0000A907}, + {0xF10, 0x00005807}, {0xF14, 0x00000003}, + {0xF18, 0x07D003E8}, {0xF1C, 0x8000001F}, + {0xF20, 0x00000000}, {0xF24, 0x00000000}, + {0xF28, 0x00000000}, {0xF2C, 0x00000000}, + {0xF30, 0x00000000}, {0xF34, 0x00000000}, + {0xF38, 0x00030055}, {0xF3C, 0x0000003A}, + {0xF40, 0x00000002}, {0xF44, 0x00000000}, + {0xF48, 0x00000000}, {0xF4C, 0x0B000000}, + {0xF50, 0x00000000}, + {0xffff, 0xffffffff}, +}; + +static const struct rtl8xxxu_reg32val rtl8192f_agc_table[] = { + {0xC78, 0x0FA0001F}, {0xC78, 0x0FA0011F}, + {0xC78, 0x0FA0021F}, {0xC78, 0x0FA0031F}, + {0xC78, 0x0FA0041F}, {0xC78, 0x0FA0051F}, + {0xC78, 0x0F90061F}, {0xC78, 0x0F80071F}, + {0xC78, 0x0F70081F}, {0xC78, 0x0F60091F}, + {0xC78, 0x0F500A1F}, {0xC78, 0x0F400B1F}, + {0xC78, 0x0F300C1F}, {0xC78, 0x0F200D1F}, + {0xC78, 0x0F100E1F}, {0xC78, 0x0F000F1F}, + {0xC78, 0x0EF0101F}, {0xC78, 0x0EE0111F}, + {0xC78, 0x0ED0121F}, {0xC78, 0x0EC0131F}, + {0xC78, 0x0EB0141F}, {0xC78, 0x0EA0151F}, + {0xC78, 0x0E90161F}, {0xC78, 0x0E80171F}, + {0xC78, 0x0E70181F}, {0xC78, 0x0E60191F}, + {0xC78, 0x0E501A1F}, {0xC78, 0x0E401B1F}, + {0xC78, 0x0E301C1F}, {0xC78, 0x0C701D1F}, + {0xC78, 0x0C601E1F}, {0xC78, 0x0C501F1F}, + {0xC78, 0x0C40201F}, {0xC78, 0x0C30211F}, + {0xC78, 0x0A60221F}, {0xC78, 0x0A50231F}, + {0xC78, 0x0A40241F}, {0xC78, 0x0A30251F}, + {0xC78, 0x0860261F}, {0xC78, 0x0850271F}, + {0xC78, 0x0840281F}, {0xC78, 0x0830291F}, + {0xC78, 0x06702A1F}, {0xC78, 0x06602B1F}, + {0xC78, 0x06502C1F}, {0xC78, 0x06402D1F}, + {0xC78, 0x06302E1F}, {0xC78, 0x04602F1F}, + {0xC78, 0x0450301F}, {0xC78, 0x0440311F}, + {0xC78, 0x0430321F}, {0xC78, 0x0260331F}, + {0xC78, 0x0250341F}, {0xC78, 0x0240351F}, + {0xC78, 0x0230361F}, {0xC78, 0x0050371F}, + {0xC78, 0x0040381F}, {0xC78, 0x0030391F}, + {0xC78, 0x00203A1F}, {0xC78, 0x00103B1F}, + {0xC78, 0x00003C1F}, {0xC78, 0x00003D1F}, + {0xC78, 0x00003E1F}, {0xC78, 0x00003F1F}, + + {0xC78, 0x0FA0401F}, {0xC78, 0x0FA0411F}, + {0xC78, 0x0FA0421F}, {0xC78, 0x0FA0431F}, + {0xC78, 0x0F90441F}, {0xC78, 0x0F80451F}, + {0xC78, 0x0F70461F}, {0xC78, 0x0F60471F}, + {0xC78, 0x0F50481F}, {0xC78, 0x0F40491F}, + {0xC78, 0x0F304A1F}, {0xC78, 0x0F204B1F}, + {0xC78, 0x0F104C1F}, {0xC78, 0x0F004D1F}, + {0xC78, 0x0EF04E1F}, {0xC78, 0x0EE04F1F}, + {0xC78, 0x0ED0501F}, {0xC78, 0x0EC0511F}, + {0xC78, 0x0EB0521F}, {0xC78, 0x0EA0531F}, + {0xC78, 0x0E90541F}, {0xC78, 0x0E80551F}, + {0xC78, 0x0E70561F}, {0xC78, 0x0E60571F}, + {0xC78, 0x0E50581F}, {0xC78, 0x0E40591F}, + {0xC78, 0x0E305A1F}, {0xC78, 0x0E205B1F}, + {0xC78, 0x0E105C1F}, {0xC78, 0x0C505D1F}, + {0xC78, 0x0C405E1F}, {0xC78, 0x0C305F1F}, + {0xC78, 0x0C20601F}, {0xC78, 0x0C10611F}, + {0xC78, 0x0A40621F}, {0xC78, 0x0A30631F}, + {0xC78, 0x0A20641F}, {0xC78, 0x0A10651F}, + {0xC78, 0x0840661F}, {0xC78, 0x0830671F}, + {0xC78, 0x0820681F}, {0xC78, 0x0810691F}, + {0xC78, 0x06506A1F}, {0xC78, 0x06406B1F}, + {0xC78, 0x06306C1F}, {0xC78, 0x06206D1F}, + {0xC78, 0x06106E1F}, {0xC78, 0x04406F1F}, + {0xC78, 0x0430701F}, {0xC78, 0x0420711F}, + {0xC78, 0x0410721F}, {0xC78, 0x0240731F}, + {0xC78, 0x0230741F}, {0xC78, 0x0220751F}, + {0xC78, 0x0210761F}, {0xC78, 0x0030771F}, + {0xC78, 0x0020781F}, {0xC78, 0x0010791F}, + {0xC78, 0x00007A1F}, {0xC78, 0x00007B1F}, + {0xC78, 0x00007C1F}, {0xC78, 0x00007D1F}, + {0xC78, 0x00007E1F}, {0xC78, 0x00007F1F}, + + {0xC78, 0x0FA0801F}, {0xC78, 0x0FA0811F}, + {0xC78, 0x0FA0821F}, {0xC78, 0x0FA0831F}, + {0xC78, 0x0FA0841F}, {0xC78, 0x0FA0851F}, + {0xC78, 0x0F90861F}, {0xC78, 0x0F80871F}, + {0xC78, 0x0F70881F}, {0xC78, 0x0F60891F}, + {0xC78, 0x0F508A1F}, {0xC78, 0x0F408B1F}, + {0xC78, 0x0F308C1F}, {0xC78, 0x0F208D1F}, + {0xC78, 0x0F108E1F}, {0xC78, 0x0B908F1F}, + {0xC78, 0x0B80901F}, {0xC78, 0x0B70911F}, + {0xC78, 0x0B60921F}, {0xC78, 0x0B50931F}, + {0xC78, 0x0B40941F}, {0xC78, 0x0B30951F}, + {0xC78, 0x0B20961F}, {0xC78, 0x0B10971F}, + {0xC78, 0x0B00981F}, {0xC78, 0x0AF0991F}, + {0xC78, 0x0AE09A1F}, {0xC78, 0x0AD09B1F}, + {0xC78, 0x0AC09C1F}, {0xC78, 0x0AB09D1F}, + {0xC78, 0x0AA09E1F}, {0xC78, 0x0A909F1F}, + {0xC78, 0x0A80A01F}, {0xC78, 0x0A70A11F}, + {0xC78, 0x0A60A21F}, {0xC78, 0x0A50A31F}, + {0xC78, 0x0A40A41F}, {0xC78, 0x0A30A51F}, + {0xC78, 0x0A20A61F}, {0xC78, 0x0A10A71F}, + {0xC78, 0x0A00A81F}, {0xC78, 0x0830A91F}, + {0xC78, 0x0820AA1F}, {0xC78, 0x0810AB1F}, + {0xC78, 0x0800AC1F}, {0xC78, 0x0640AD1F}, + {0xC78, 0x0630AE1F}, {0xC78, 0x0620AF1F}, + {0xC78, 0x0610B01F}, {0xC78, 0x0600B11F}, + {0xC78, 0x0430B21F}, {0xC78, 0x0420B31F}, + {0xC78, 0x0410B41F}, {0xC78, 0x0400B51F}, + {0xC78, 0x0230B61F}, {0xC78, 0x0220B71F}, + {0xC78, 0x0210B81F}, {0xC78, 0x0200B91F}, + {0xC78, 0x0000BA1F}, {0xC78, 0x0000BB1F}, + {0xC78, 0x0000BC1F}, {0xC78, 0x0000BD1F}, + {0xC78, 0x0000BE1F}, {0xC78, 0x0000BF1F}, + {0xC50, 0x00E48024}, {0xC50, 0x00E48020}, + {0xffff, 0xffffffff} +}; + +static const struct rtl8xxxu_rfregval rtl8192fu_radioa_init_table[] = { + {0x00, 0x30000}, {0x18, 0x0FC07}, {0x81, 0x0FC00}, {0x82, 0x003C0}, + {0x84, 0x00005}, {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010}, + {0x8E, 0x64540}, {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007}, + {0x53, 0x10061}, {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6}, + {0x57, 0x2CC00}, {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006}, + {0x5C, 0x00015}, {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180}, + {0xEF, 0x00002}, {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A}, + {0xEF, 0x00000}, {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008}, + {0xEF, 0x00800}, {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848}, + {0x33, 0x0C84B}, {0x33, 0x1088A}, {0x33, 0x14C50}, {0x33, 0x18C8E}, + {0x33, 0x1CCCD}, {0x33, 0x20CD0}, {0x33, 0x24CD3}, {0x33, 0x28CD6}, + {0x33, 0x4002B}, {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849}, + {0x33, 0x50888}, {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC}, + {0x33, 0x60CCF}, {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000}, + {0xEF, 0x00400}, {0x33, 0x01C23}, {0x33, 0x05C23}, {0x33, 0x09D23}, + {0x33, 0x0DD23}, {0x33, 0x11FA3}, {0x33, 0x15FA3}, {0x33, 0x19FAB}, + {0x33, 0x1DFAB}, {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030}, + {0x33, 0x04030}, {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030}, + {0x33, 0x14030}, {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030}, + {0x33, 0x24030}, {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030}, + {0x33, 0x34030}, {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000}, + {0xEF, 0x00100}, {0x33, 0x44001}, {0x33, 0x48001}, {0x33, 0x4C001}, + {0x33, 0x50001}, {0x33, 0x54001}, {0x33, 0x58001}, {0x33, 0x5C001}, + {0x33, 0x60001}, {0x33, 0x64001}, {0x33, 0x68001}, {0x33, 0x6C001}, + {0x33, 0x70001}, {0x33, 0x74001}, {0x33, 0x78001}, {0x33, 0x04000}, + {0x33, 0x08000}, {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000}, + {0x33, 0x18001}, {0x33, 0x1C002}, {0x33, 0x20002}, {0x33, 0x24002}, + {0x33, 0x28002}, {0x33, 0x2C002}, {0x33, 0x30002}, {0x33, 0x34002}, + {0x33, 0x38002}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010}, + {0x30, 0x20000}, {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000}, + {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F}, + {0x32, 0xF1DF3}, {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000}, + {0x30, 0x38000}, {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000}, + {0x1B, 0x746CE}, {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000}, + {0x33, 0x70000}, {0x33, 0x78000}, {0xEF, 0x00000}, {0xDF, 0x08000}, + {0xB0, 0xFFBCB}, {0xB3, 0x06000}, {0xB7, 0x18DF0}, {0xB8, 0x38FF0}, + {0xC9, 0x00600}, {0xDF, 0x00000}, {0xB1, 0x33B8F}, {0xB2, 0x33762}, + {0xB4, 0x141F0}, {0xB5, 0x14080}, {0xB6, 0x12425}, {0xB9, 0xC0008}, + {0xBA, 0x40005}, {0xC2, 0x02C01}, {0xC3, 0x0000B}, {0xC4, 0x81E2F}, + {0xC5, 0x5C28F}, {0xC6, 0x000A0}, {0xCA, 0x02000}, {0xFE, 0x00000}, + {0x18, 0x08C07}, {0xFE, 0x00000}, {0xFE, 0x00000}, {0xFE, 0x00000}, + {0x00, 0x31DD5}, + {0xff, 0xffffffff} +}; + +static const struct rtl8xxxu_rfregval rtl8192fu_radiob_init_table[] = { + {0x00, 0x30000}, {0x81, 0x0FC00}, {0x82, 0x003C0}, {0x84, 0x00005}, + {0x86, 0xA33A5}, {0x87, 0x00000}, {0x88, 0x58010}, {0x8E, 0x64540}, + {0x8F, 0x282D8}, {0x51, 0x02C06}, {0x52, 0x7A007}, {0x53, 0x10061}, + {0x54, 0x60018}, {0x55, 0x82020}, {0x56, 0x08CC6}, {0x57, 0x2CC00}, + {0x58, 0x00000}, {0x5A, 0x50000}, {0x5B, 0x00006}, {0x5C, 0x00015}, + {0x65, 0x20000}, {0x6E, 0x38319}, {0xF5, 0x43180}, {0xEF, 0x00002}, + {0x33, 0x00301}, {0x33, 0x1032A}, {0x33, 0x2032A}, {0xEF, 0x00000}, + {0xDF, 0x00002}, {0x35, 0x00000}, {0xF0, 0x08008}, {0xEF, 0x00800}, + {0x33, 0x0040E}, {0x33, 0x04845}, {0x33, 0x08848}, {0x33, 0x0C84B}, + {0x33, 0x1088A}, {0x33, 0x14CC8}, {0x33, 0x18CCB}, {0x33, 0x1CCCE}, + {0x33, 0x20CD1}, {0x33, 0x24CD4}, {0x33, 0x28CD7}, {0x33, 0x4002B}, + {0x33, 0x4402E}, {0x33, 0x48846}, {0x33, 0x4C849}, {0x33, 0x50888}, + {0x33, 0x54CC6}, {0x33, 0x58CC9}, {0x33, 0x5CCCC}, {0x33, 0x60CCF}, + {0x33, 0x64CD2}, {0x33, 0x68CD5}, {0xEF, 0x00000}, {0xEF, 0x00400}, + {0x33, 0x01D23}, {0x33, 0x05D23}, {0x33, 0x09FA3}, {0x33, 0x0DFA3}, + {0x33, 0x11D2B}, {0x33, 0x15D2B}, {0x33, 0x19FAB}, {0x33, 0x1DFAB}, + {0xEF, 0x00000}, {0xEF, 0x00200}, {0x33, 0x00030}, {0x33, 0x04030}, + {0x33, 0x08030}, {0x33, 0x0C030}, {0x33, 0x10030}, {0x33, 0x14030}, + {0x33, 0x18030}, {0x33, 0x1C030}, {0x33, 0x20030}, {0x33, 0x24030}, + {0x33, 0x28030}, {0x33, 0x2C030}, {0x33, 0x30030}, {0x33, 0x34030}, + {0x33, 0x38030}, {0x33, 0x3C030}, {0xEF, 0x00000}, {0xEF, 0x00100}, + {0x33, 0x44000}, {0x33, 0x48000}, {0x33, 0x4C000}, {0x33, 0x50000}, + {0x33, 0x54000}, {0x33, 0x58000}, {0x33, 0x5C000}, {0x33, 0x60000}, + {0x33, 0x64000}, {0x33, 0x68000}, {0x33, 0x6C000}, {0x33, 0x70000}, + {0x33, 0x74000}, {0x33, 0x78000}, {0x33, 0x04000}, {0x33, 0x08000}, + {0x33, 0x0C000}, {0x33, 0x10000}, {0x33, 0x14000}, {0x33, 0x18000}, + {0x33, 0x1C001}, {0x33, 0x20001}, {0x33, 0x24001}, {0x33, 0x28001}, + {0x33, 0x2C001}, {0x33, 0x30001}, {0x33, 0x34001}, {0x33, 0x38001}, + {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80010}, {0x30, 0x20000}, + {0x31, 0x0006F}, {0x32, 0x01FF7}, {0xEF, 0x00000}, {0x84, 0x00000}, + {0xEF, 0x80000}, {0x30, 0x30000}, {0x31, 0x0006F}, {0x32, 0xF1DF3}, + {0xEF, 0x00000}, {0x84, 0x00000}, {0xEF, 0x80000}, {0x30, 0x38000}, + {0x31, 0x0006F}, {0x32, 0xF1FF2}, {0xEF, 0x00000}, {0x1B, 0x746CE}, + {0xEF, 0x20000}, {0x33, 0x30000}, {0x33, 0x38000}, {0x33, 0x70000}, + {0x33, 0x78000}, {0xEF, 0x00000}, {0x00, 0x31DD5}, + {0xff, 0xffffffff} +}; + +static int rtl8192fu_identify_chip(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u32 sys_cfg, vendor, val32; + + strscpy(priv->chip_name, "8192FU", sizeof(priv->chip_name)); + priv->rtl_chip = RTL8192F; + priv->rf_paths = 2; + priv->rx_paths = 2; + priv->tx_paths = 2; + + sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG); + priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK); + if (sys_cfg & SYS_CFG_TRP_VAUX_EN) { + dev_info(dev, "Unsupported test chip\n"); + return -EOPNOTSUPP; + } + + val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL); + priv->has_wifi = u32_get_bits(val32, MULTI_WIFI_FUNC_EN); + priv->has_bluetooth = u32_get_bits(val32, MULTI_BT_FUNC_EN); + priv->has_gps = u32_get_bits(val32, MULTI_GPS_FUNC_EN); + priv->is_multi_func = 1; + + vendor = sys_cfg & SYS_CFG_VENDOR_ID; + rtl8xxxu_identify_vendor_1bit(priv, vendor); + + val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS); + priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID); + + return rtl8xxxu_config_endpoints_no_sie(priv); +} + +static void +rtl8192f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) +{ + u8 cck, ofdmbase, mcsbase; + u32 val32, ofdm, mcs; + int group, cck_group; + + rtl8188f_channel_to_group(channel, &group, &cck_group); + + cck = priv->cck_tx_power_index_A[cck_group]; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_CCK1_MCS32, 0x00007f00, cck); + + val32 = (cck << 16) | (cck << 8) | cck; + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, + 0x7f7f7f00, val32); + + ofdmbase = priv->ht40_1s_tx_power_index_A[group]; + ofdmbase += priv->ofdm_tx_power_diff[RF_A].a; + ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE18_06, 0x7f7f7f7f, ofdm); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_RATE54_24, 0x7f7f7f7f, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_A[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[RF_A].a; + else + mcsbase += priv->ht20_tx_power_diff[RF_A].a; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS03_MCS00, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS07_MCS04, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS11_MCS08, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_A_MCS15_MCS12, 0x7f7f7f7f, mcs); + + if (priv->tx_paths == 1) + return; + + cck = priv->cck_tx_power_index_B[cck_group]; + + val32 = (cck << 16) | (cck << 8) | cck; + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK1_55_MCS32, + 0x7f7f7f00, val32); + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, + 0x0000007f, cck); + + ofdmbase = priv->ht40_1s_tx_power_index_B[group]; + ofdmbase += priv->ofdm_tx_power_diff[RF_B].b; + ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE18_06, 0x7f7f7f7f, ofdm); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_RATE54_24, 0x7f7f7f7f, ofdm); + + mcsbase = priv->ht40_1s_tx_power_index_B[group]; + if (ht40) + mcsbase += priv->ht40_tx_power_diff[RF_B].b; + else + mcsbase += priv->ht20_tx_power_diff[RF_B].b; + mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24; + + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS03_MCS00, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS07_MCS04, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS11_MCS08, 0x7f7f7f7f, mcs); + rtl8xxxu_write32_mask(priv, REG_TX_AGC_B_MCS15_MCS12, 0x7f7f7f7f, mcs); +} + +static void rtl8192f_revise_cck_tx_psf(struct rtl8xxxu_priv *priv, u8 channel) +{ + if (channel == 13) { + /* Special value for channel 13 */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xf8fe0001); + /* Normal values */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C); + rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667); + } else if (channel == 14) { + /* Normal value */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001); + /* Special values for channel 14 */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x0000B81C); + rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x0000); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x00003667); + } else { + /* Restore normal values from the phy init table */ + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER1, 0xE82C0001); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER2, 0x64B80C1C); + rtl8xxxu_write16(priv, REG_CCK0_DEBUG_PORT, 0x8810); + rtl8xxxu_write32(priv, REG_CCK0_TX_FILTER3, 0x01235667); + } +} + +static void rtl8192fu_config_kfree(struct rtl8xxxu_priv *priv, u8 channel) +{ + u8 bb_gain[3] = { EFUSE_UNDEFINED, EFUSE_UNDEFINED, EFUSE_UNDEFINED }; + u8 bb_gain_path_mask[2] = { 0x0f, 0xf0 }; + enum rtl8xxxu_rfpath rfpath; + u8 bb_gain_for_path; + u8 channel_idx = 0; + + if (channel >= 1 && channel <= 3) + channel_idx = 0; + if (channel >= 4 && channel <= 9) + channel_idx = 1; + if (channel >= 10 && channel <= 14) + channel_idx = 2; + + rtl8xxxu_read_efuse8(priv, 0x1ee, &bb_gain[1]); + rtl8xxxu_read_efuse8(priv, 0x1ec, &bb_gain[0]); + rtl8xxxu_read_efuse8(priv, 0x1ea, &bb_gain[2]); + + if (bb_gain[1] == EFUSE_UNDEFINED) + return; + + if (bb_gain[0] == EFUSE_UNDEFINED) + bb_gain[0] = bb_gain[1]; + + if (bb_gain[2] == EFUSE_UNDEFINED) + bb_gain[2] = bb_gain[1]; + + for (rfpath = RF_A; rfpath < priv->rf_paths; rfpath++) { + /* power_trim based on 55[19:14] */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_UNKNOWN_55, + BIT(5), 1); + + /* enable 55[14] for 0.5db step */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CTRL, + BIT(18), 1); + + /* enter power_trim debug mode */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA, + BIT(7), 1); + + /* write enable */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 1); + + bb_gain_for_path = (bb_gain[channel_idx] & bb_gain_path_mask[rfpath]); + bb_gain_for_path >>= __ffs(bb_gain_path_mask[rfpath]); + + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x70000, channel_idx * 2); + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x3f, bb_gain_for_path); + + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x70000, channel_idx * 2 + 1); + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_TXPA_G3, + 0x3f, bb_gain_for_path); + + /* leave power_trim debug mode */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_GAIN_CCA, + BIT(7), 0); + + /* write disable */ + rtl8xxxu_write_rfreg_mask(priv, rfpath, RF6052_REG_WE_LUT, BIT(7), 0); + } +} + +static void rtl8192fu_config_channel(struct ieee80211_hw *hw) +{ + struct rtl8xxxu_priv *priv = hw->priv; + bool ht40 = conf_is_ht40(&hw->conf); + u8 channel, subchannel = 0; + bool sec_ch_above = 0; + u32 val32; + + channel = (u8)hw->conf.chandef.chan->hw_value; + + if (conf_is_ht40_plus(&hw->conf)) { + sec_ch_above = 1; + channel += 2; + subchannel = 2; + } else if (conf_is_ht40_minus(&hw->conf)) { + sec_ch_above = 0; + channel -= 2; + subchannel = 1; + } + + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); + + rtl8192f_revise_cck_tx_psf(priv, channel); + + /* Set channel */ + val32 &= ~(BIT(18) | BIT(17)); /* select the 2.4G band(?) */ + u32p_replace_bits(&val32, channel, 0xff); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32); + if (priv->rf_paths > 1) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32); + + rtl8192fu_config_kfree(priv, channel); + + rtl8xxxu_write8(priv, REG_DATA_SUBCHANNEL, subchannel); + + /* small BW */ + rtl8xxxu_write32_clear(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, GENMASK(31, 30)); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE, ht40); + rtl8xxxu_write32_mask(priv, REG_FPGA1_RF_MODE, FPGA_RF_MODE, ht40); + + /* ADC clock = 160M */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, GENMASK(10, 8), 4); + + /* DAC clock = 80M */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_RF_MODE, BIT(13) | BIT(12), 2); + + /* ADC buffer clk */ + rtl8xxxu_write32_mask(priv, REG_ANTDIV_PARA1, BIT(27) | BIT(26), 2); + + if (ht40) + /* Set Control channel to upper or lower. */ + rtl8xxxu_write32_mask(priv, REG_CCK0_SYSTEM, + CCK0_SIDEBAND, !sec_ch_above); + + /* Enable CCK */ + rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_CCK); + + /* RF TRX_BW */ + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG); + val32 &= ~MODE_AG_BW_MASK; + if (ht40) + val32 |= MODE_AG_BW_40MHZ_8723B; + else + val32 |= MODE_AG_BW_20MHZ_8723B; + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32); + if (priv->rf_paths > 1) + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_MODE_AG, val32); + + /* Modify RX DFIR parameters */ + rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, BIT(21) | BIT(20), 2); + + rtl8xxxu_write32_mask(priv, REG_DOWNSAM_FACTOR, BIT(29) | BIT(28), 2); + + if (ht40) + val32 = 0x3; + else + val32 = 0x1a3; + rtl8xxxu_write32_mask(priv, REG_RX_DFIR_MOD_97F, 0x1ff, val32); +} + +static void rtl8192fu_init_aggregation(struct rtl8xxxu_priv *priv) +{ + u32 agg_rx; + u8 agg_ctrl; + + /* RX aggregation */ + agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL); + agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN; + + agg_rx = rtl8xxxu_read32(priv, REG_RXDMA_AGG_PG_TH); + agg_rx &= ~RXDMA_USB_AGG_ENABLE; + agg_rx &= ~0xFF0F; /* reset agg size and timeout */ + + rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, agg_ctrl); + rtl8xxxu_write32(priv, REG_RXDMA_AGG_PG_TH, agg_rx); +} + +static int rtl8192fu_parse_efuse(struct rtl8xxxu_priv *priv) +{ + struct rtl8192fu_efuse *efuse = &priv->efuse_wifi.efuse8192fu; + int i; + + if (efuse->rtl_id != cpu_to_le16(0x8129)) + return -EINVAL; + + ether_addr_copy(priv->mac_addr, efuse->mac_addr); + + memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base, + sizeof(efuse->tx_power_index_A.cck_base)); + memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base, + sizeof(efuse->tx_power_index_B.cck_base)); + + memcpy(priv->ht40_1s_tx_power_index_A, + efuse->tx_power_index_A.ht40_base, + sizeof(efuse->tx_power_index_A.ht40_base)); + memcpy(priv->ht40_1s_tx_power_index_B, + efuse->tx_power_index_B.ht40_base, + sizeof(efuse->tx_power_index_B.ht40_base)); + + priv->ht20_tx_power_diff[0].a = + efuse->tx_power_index_A.ht20_ofdm_1s_diff.b; + priv->ht20_tx_power_diff[0].b = + efuse->tx_power_index_B.ht20_ofdm_1s_diff.b; + + priv->ht40_tx_power_diff[0].a = 0; + priv->ht40_tx_power_diff[0].b = 0; + + for (i = 1; i < RTL8723B_TX_COUNT; i++) { + priv->ofdm_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ofdm; + priv->ofdm_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ofdm; + + priv->ht20_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht20; + priv->ht20_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht20; + + priv->ht40_tx_power_diff[i].a = + efuse->tx_power_index_A.pwr_diff[i - 1].ht40; + priv->ht40_tx_power_diff[i].b = + efuse->tx_power_index_B.pwr_diff[i - 1].ht40; + } + + priv->default_crystal_cap = efuse->xtal_k & 0x3f; + + priv->rfe_type = efuse->rfe_option & 0x1f; + + if (priv->rfe_type != 5 && priv->rfe_type != 1) + dev_warn(&priv->udev->dev, + "%s: RFE type %d was not tested. Please send an email to linux-wireless@vger.kernel.org about this.\n", + __func__, priv->rfe_type); + + return 0; +} + +static int rtl8192fu_load_firmware(struct rtl8xxxu_priv *priv) +{ + return rtl8xxxu_load_firmware(priv, "rtlwifi/rtl8192fufw.bin"); +} + +static void rtl8192fu_init_phy_bb(struct rtl8xxxu_priv *priv) +{ + /* Enable BB and RF */ + rtl8xxxu_write16_set(priv, REG_SYS_FUNC, + SYS_FUNC_BBRSTB | SYS_FUNC_BB_GLB_RSTN); + + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB); + + /* To Fix MAC loopback mode fail. */ + rtl8xxxu_write8(priv, REG_LDOHCI12_CTRL, 0xf); + rtl8xxxu_write8(priv, REG_SYS_SWR_CTRL2 + 1, 0xe9); + + rtl8xxxu_init_phy_regs(priv, rtl8192fu_phy_init_table); + + rtl8xxxu_init_phy_regs(priv, rtl8192f_agc_table); +} + +static int rtl8192fu_init_phy_rf(struct rtl8xxxu_priv *priv) +{ + int ret; + + ret = rtl8xxxu_init_phy_rf(priv, rtl8192fu_radioa_init_table, RF_A); + if (ret) + return ret; + + return rtl8xxxu_init_phy_rf(priv, rtl8192fu_radiob_init_table, RF_B); +} + +static void rtl8192f_phy_lc_calibrate(struct rtl8xxxu_priv *priv) +{ + u32 backup_mask = BIT(31) | BIT(30); + u32 backup; + u32 val32; + + /* Aries's NarrowBand */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT); + backup = u32_get_bits(val32, backup_mask); + + u32p_replace_bits(&val32, 0, backup_mask); + rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32); + + rtl8188f_phy_lc_calibrate(priv); + + /* Aries's NarrowBand */ + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT); + u32p_replace_bits(&val32, backup, backup_mask); + rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32); + + /* reset OFDM state */ + rtl8xxxu_write32_clear(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM); + rtl8xxxu_write32_set(priv, REG_FPGA0_RF_MODE, FPGA_RF_MODE_OFDM); +} + +static int rtl8192fu_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_e94, reg_e9c, val32; + u32 rf_0x58_i, rf_0x58_q; + u8 rfe = priv->rfe_type; + int result = 0; + int ktime, i; + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(4), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1); + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) + val32 = 0x30; + else + val32 = 0xe9; + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, val32); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8214000f); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28140000); + + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + /* reload 0xdf and CCK_IND off */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 1); + + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXMOD); + rf_0x58_i = u32_get_bits(val32, 0xfc000); + rf_0x58_q = u32_get_bits(val32, 0x003f0); + + for (i = 0; i < 8; i++) { + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, + 0x1c000, i); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, + 0x00fc0, rf_0x58_i); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_TXPA_G3, + 0x0003f, rf_0x58_q); + } + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, BIT(14), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_WE_LUT, BIT(4), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00810, 0); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) + result |= 0x01; + + return result; +} + +static int rtl8192fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) +{ + u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32; + int result = 0; + int ktime; + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x27); + + /* Enter IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160027); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000); + + /* Tx IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXA) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + + if (!(reg_eac & BIT(28)) && + ((reg_e94 & 0x03ff0000) != 0x01420000) && + ((reg_e9c & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { /* If TX not OK, ignore RX */ + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, + BIT(11), 0); + + return result; + } + + val32 = 0x80007c00 | (reg_e94 & 0x3ff0000) | ((reg_e9c & 0x3ff0000) >> 16); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + /* PA/PAD control by 0x56, and set = 0x0 */ + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + /* Enter IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-A IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82170000); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28170000); + + /* RX IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a8d1); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXA) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_GAIN_CCA, BIT(11), 0); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, 0x02000); + + if (!(reg_eac & BIT(27)) && + ((reg_ea4 & 0x03ff0000) != 0x01320000) && + ((reg_eac & 0x03ff0000) != 0x00360000)) + result |= 0x02; + + return result; +} + +static int rtl8192fu_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, val32; + u32 rf_0x58_i, rf_0x58_q; + u8 rfe = priv->rfe_type; + int result = 0; + int ktime, i; + + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(4), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1); + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, + 0x003ff, 0x30); + else + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, + 0x00fff, 0xe9); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* Path B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8214000F); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28140000); + + rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00); + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00e62911); + + /* One shot, path B LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + /* reload 0xdf and CCK_IND off */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 1); + + val32 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_TXMOD); + rf_0x58_i = u32_get_bits(val32, 0xfc000); + rf_0x58_q = u32_get_bits(val32, 0x003f0); + + for (i = 0; i < 8; i++) { + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, + 0x1c000, i); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, + 0x00fc0, rf_0x58_i); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_TXPA_G3, + 0x0003f, rf_0x58_q); + } + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_AC, BIT(14), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_WE_LUT, BIT(4), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00810, 0); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) + result |= 0x01; + else + dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n", + __func__); + + return result; +} + +static int rtl8192fu_rx_iqk_path_b(struct rtl8xxxu_priv *priv) +{ + u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32; + int result = 0; + int ktime; + + /* Leave IQK mode */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x67); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* path-B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82160027); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28160000); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0086a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_TXB) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + /* Check failed */ + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + + if (!(reg_eac & BIT(31)) && + ((reg_eb4 & 0x03ff0000) != 0x01420000) && + ((reg_ebc & 0x03ff0000) != 0x00420000)) { + result |= 0x01; + } else { + /* PA/PAD controlled by 0x0 */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, + BIT(11), 0); + + return result; + } + + val32 = 0x80007c00 | (reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff); + rtl8xxxu_write32(priv, REG_TX_IQK, val32); + + /* Modify RX IQK mode table */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 1); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 1); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_PAD_TXG, 0x003ff, 0x1e0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0); + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44ffbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x00400040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005403); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000804e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04203400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + + /* Path B IQK setting */ + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c); + rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c); + rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c); + + rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82170000); + rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x28170000); + + /* IQK setting */ + rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800); + + /* LO calibration setting */ + rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911); + + /* One shot, path A LOK & IQK */ + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa005800); + rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8005800); + + mdelay(15); + + ktime = 0; + while (rtl8xxxu_read32(priv, REG_IQK_RPT_RXB) == 0 && ktime < 21) { + mdelay(5); + ktime += 5; + } + + reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(11), 0); + rtl8xxxu_write_rfreg_mask(priv, RF_B, RF6052_REG_GAIN_CCA, BIT(1), 0); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, 0x02000); + + if (!(reg_eac & BIT(30)) && + ((reg_ec4 & 0x03ff0000) != 0x01320000) && + ((reg_ecc & 0x03ff0000) != 0x00360000)) + result |= 0x02; + else + dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n", + __func__); + + return result; +} + +static void rtl8192fu_phy_iqcalibrate(struct rtl8xxxu_priv *priv, + int result[][8], int t) +{ + static const u32 adda_regs[2] = { + REG_ANAPWR1, REG_RX_WAIT_CCA + }; + static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = { + REG_TXPAUSE, REG_BEACON_CTRL, + REG_BEACON_CTRL_1, REG_GPIO_MUXCFG + }; + static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = { + REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR, + REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B, + REG_DPDT_CTRL, REG_RFE_CTRL_ANTA_SRC, + REG_RFE_CTRL_ANT_SRC2, REG_CCK0_AFE_SETTING + }; + u32 rx_initial_gain_a, rx_initial_gain_b; + struct device *dev = &priv->udev->dev; + int path_a_ok, path_b_ok; + u8 rfe = priv->rfe_type; + int retry = 2; + u32 i, val32; + + /* + * Note: IQ calibration must be performed after loading + * PHY_REG.txt , and radio_a, radio_b.txt + */ + + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rx_initial_gain_a = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1); + rx_initial_gain_b = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1); + + if (t == 0) { + /* Save ADDA parameters, turn Path A ADDA on */ + rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup, + ARRAY_SIZE(adda_regs)); + rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + rtl8xxxu_save_regs(priv, iqk_bb_regs, + priv->bb_backup, RTL8XXXU_BB_REGS); + } + + /* Instead of rtl8xxxu_path_adda_on */ + rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, BIT(31)); + + /* MAC settings */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + rtl8xxxu_write8_clear(priv, REG_GPIO_MUXCFG, GPIO_MUXCFG_IO_SEL_ENBT); + + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) { + /* in ePA IQK, rfe_func_config & SW both pull down */ + /* path A */ + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x1, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF00, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x4, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, 0xF000, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8, 0x0); + + /* path B */ + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x20000, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, 0xF0000, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x100000, 0x0); + + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, 0xF000, 0x7); + rtl8xxxu_write32_mask(priv, REG_DPDT_CTRL, 0x8000000, 0x0); + } + + if (priv->rf_paths > 1) { + /* path B standby */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x000000); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_AC, 0x10000); + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0x808000); + } + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192fu_iqk_path_a(priv); + + if (path_a_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A); + result[t][0] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A); + result[t][1] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][0] = 0x100; + result[t][1] = 0x0; + } + } + + for (i = 0; i < retry; i++) { + path_a_ok = rtl8192fu_rx_iqk_path_a(priv); + + if (path_a_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); + result[t][2] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); + result[t][3] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][2] = 0x100; + result[t][3] = 0x0; + } + } + + if (!path_a_ok) + dev_warn(dev, "%s: Path A IQK failed!\n", __func__); + + if (priv->rf_paths > 1) { + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192fu_iqk_path_b(priv); + + if (path_b_ok == 0x01) { + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B); + result[t][4] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B); + result[t][5] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][4] = 0x100; + result[t][5] = 0x0; + } + } + + for (i = 0; i < retry; i++) { + path_b_ok = rtl8192fu_rx_iqk_path_b(priv); + + if (path_b_ok == 0x03) { + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2); + result[t][6] = (val32 >> 16) & 0x3ff; + + val32 = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2); + result[t][7] = (val32 >> 16) & 0x3ff; + break; + } else { + result[t][6] = 0x100; + result[t][7] = 0x0; + } + } + + if (!path_b_ok) + dev_warn(dev, "%s: Path B IQK failed!\n", __func__); + } + + /* Back to BB mode, load original value */ + rtl8xxxu_write32_mask(priv, REG_FPGA0_IQK, 0xffffff00, 0); + + rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xcc0000c0); + + rtl8xxxu_write32(priv, REG_ANAPWR1, 0x44bbbb44); + rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, 0x80408040); + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x6f005433); + rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000004e4); + rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x04003400); + rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100); + + /* Reload ADDA power saving parameters */ + rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup, + ARRAY_SIZE(adda_regs)); + + /* Reload MAC parameters */ + rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup); + + /* Reload BB parameters */ + rtl8xxxu_restore_regs(priv, iqk_bb_regs, priv->bb_backup, RTL8XXXU_BB_REGS); + + rtl8xxxu_write32_clear(priv, REG_FPGA0_XCD_RF_PARM, BIT(31)); + + /* Restore RX initial gain */ + rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, 0x50); + rtl8xxxu_write32_mask(priv, REG_OFDM0_XA_AGC_CORE1, 0xff, + rx_initial_gain_a & 0xff); + if (priv->rf_paths > 1) { + rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, 0x50); + rtl8xxxu_write32_mask(priv, REG_OFDM0_XB_AGC_CORE1, 0xff, + rx_initial_gain_b & 0xff); + } +} + +static void rtl8192fu_phy_iq_calibrate(struct rtl8xxxu_priv *priv) +{ + s32 reg_e94, reg_e9c, reg_ea4, reg_eac; + s32 reg_eb4, reg_ebc, reg_ec4, reg_ecc; + struct device *dev = &priv->udev->dev; + u32 path_a_0xdf, path_a_0x35; + u32 path_b_0xdf, path_b_0x35; + bool path_a_ok, path_b_ok; + u8 rfe = priv->rfe_type; + u32 rfe_path_select; + int result[4][8]; /* last is final result */ + int i, candidate; + s32 reg_tmp = 0; + bool simu; + u32 val32; + + rfe_path_select = rtl8xxxu_read32(priv, REG_RFE_PATH_SELECT); + + path_a_0xdf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); + path_a_0x35 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_P1); + path_b_0xdf = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA); + path_b_0x35 = rtl8xxxu_read_rfreg(priv, RF_B, RF6052_REG_GAIN_P1); + + memset(result, 0, sizeof(result)); + candidate = -1; + + path_a_ok = false; + path_b_ok = false; + + for (i = 0; i < 3; i++) { + rtl8192fu_phy_iqcalibrate(priv, result, i); + + if (i == 1) { + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 1); + if (simu) { + candidate = 0; + break; + } + } + + if (i == 2) { + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 2); + if (simu) { + candidate = 0; + break; + } + + simu = rtl8xxxu_gen2_simularity_compare(priv, result, 1, 2); + if (simu) { + candidate = 1; + } else { + for (i = 0; i < 8; i++) + reg_tmp += result[3][i]; + + if (reg_tmp) + candidate = 3; + else + candidate = -1; + } + } + } + + if (candidate >= 0) { + reg_e94 = result[candidate][0]; + reg_e9c = result[candidate][1]; + reg_ea4 = result[candidate][2]; + reg_eac = result[candidate][3]; + reg_eb4 = result[candidate][4]; + reg_ebc = result[candidate][5]; + reg_ec4 = result[candidate][6]; + reg_ecc = result[candidate][7]; + + dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate); + dev_dbg(dev, "%s: e94=%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%c\n", + __func__, reg_e94, reg_e9c, reg_ea4, reg_eac, + reg_eb4, reg_ebc, reg_ec4, reg_ecc); + + path_a_ok = true; + path_b_ok = true; + } + + rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_A, 0x3ff00000, 0x100); + rtl8xxxu_write32_mask(priv, REG_NP_ANTA, 0x3ff, 0); + rtl8xxxu_write32_mask(priv, REG_TX_IQK_TONE_B, 0x3ff00000, 0x100); + rtl8xxxu_write32_mask(priv, REG_TAP_UPD_97F, 0x3ff, 0); + + if (candidate >= 0) { + if (reg_e94) + rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result, + candidate, (reg_ea4 == 0)); + + if (reg_eb4) + rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result, + candidate, (reg_ec4 == 0)); + } + + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, path_a_0xdf); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_P1, path_a_0x35); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, path_b_0xdf); + rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_P1, path_b_0x35); + + if (rfe == 7 || rfe == 8 || rfe == 9 || rfe == 12) { + rtl8xxxu_write32_set(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x70000); + rtl8xxxu_write32_clear(priv, REG_LEDCFG0, 0x6c00000); + rtl8xxxu_write32_set(priv, REG_PAD_CTRL1, BIT(29) | BIT(28)); + rtl8xxxu_write32_clear(priv, REG_SW_GPIO_SHARE_CTRL_0, + 0x600000 | BIT(4)); + + /* + * Originally: + * odm_set_bb_reg(dm, R_0x944, BIT(11) | 0x1F, 0x3F); + * + * It clears bit 11 and sets bits 0..4. The mask doesn't cover + * bit 5 so it's not modified. Is that what it's supposed to + * accomplish? + */ + val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER); + val32 &= ~BIT(11); + val32 |= 0x1f; + rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32); + + if (rfe == 7) { + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, + 0xfffff, 0x23200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, + 0xfffff, 0x23200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1, + 0xf000, 0x3); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, + 0xf000, 0x3); + } else { + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANTA_SRC, + 0xfffff, 0x22200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC2, + 0xfffff, 0x22200); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC1, + 0xf000, 0x2); + rtl8xxxu_write32_mask(priv, REG_RFE_CTRL_ANT_SRC3, + 0xf000, 0x2); + } + + rtl8xxxu_write32_clear(priv, REG_RFE_OPT62, BIT(2)); + + if (rfe == 7) + rtl8xxxu_write32(priv, REG_RFE_OPT, 0x03000003); + + rtl8xxxu_write32(priv, REG_RFE_PATH_SELECT, rfe_path_select); + } +} + +static void rtl8192fu_disabled_to_emu(struct rtl8xxxu_priv *priv) +{ + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, + APS_FSMCO_HW_POWERDOWN | APS_FSMCO_HW_SUSPEND); + + rtl8xxxu_write32_clear(priv, REG_GPIO_INTM, BIT(16)); + + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, + APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND); +} + +static int rtl8192fu_emu_to_active(struct rtl8xxxu_priv *priv) +{ + u32 val32; + u16 val16; + int count; + + /* enable LDOA12 MACRO block for all interface */ + rtl8xxxu_write8_set(priv, REG_LDOA15_CTRL, LDOA15_ENABLE); + + /* disable BT_GPS_SEL pins */ + rtl8xxxu_write32_clear(priv, REG_PAD_CTRL1, BIT(28)); + + mdelay(1); + + /* release analog Ips to digital */ + rtl8xxxu_write8_clear(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS); + + val16 = APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND | APS_FSMCO_SW_LPS; + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, val16); + + /* wait till 0x04[17] = 1 power ready */ + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if (val32 & BIT(17)) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & (APS_FSMCO_MAC_ENABLE | APS_FSMCO_MAC_OFF)) == 0) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + /* SWR OCP enable */ + rtl8xxxu_write32_set(priv, REG_AFE_MISC, BIT(18)); + + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, APS_FSMCO_HW_POWERDOWN); + + rtl8xxxu_write16_clear(priv, REG_APS_FSMCO, + APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND); + + /* 0x7c[31]=1, LDO has max output capability */ + rtl8xxxu_write32_set(priv, REG_LDO_SW_CTRL, BIT(31)); + + rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_ENABLE); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + /* Enable WL control XTAL setting */ + rtl8xxxu_write8_set(priv, REG_AFE_MISC, AFE_MISC_WL_XTAL_CTRL); + + /* Enable falling edge triggering interrupt */ + rtl8xxxu_write16_set(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ); + + /* Enable GPIO9 data mode */ + rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_IRQ); + + /* Enable GPIO9 input mode */ + rtl8xxxu_write16_clear(priv, REG_GPIO_IO_SEL_2, GPIO_IO_SEL_2_GPIO09_INPUT); + + /* Enable HSISR GPIO[C:0] interrupt */ + rtl8xxxu_write8_set(priv, REG_HSIMR, BIT(0)); + + /* RF HW ON/OFF Enable */ + rtl8xxxu_write8_clear(priv, REG_MULTI_FUNC_CTRL, MULTI_WIFI_HW_ROF_EN); + + /* Register Lock Disable */ + rtl8xxxu_write8_set(priv, REG_RSV_CTRL, BIT(7)); + + /* For GPIO9 internal pull high setting */ + rtl8xxxu_write16_set(priv, REG_MULTI_FUNC_CTRL, BIT(14)); + + /* reset RF path S1 */ + rtl8xxxu_write8(priv, REG_RF_CTRL, 0); + + /* reset RF path S0 */ + rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, 0); + + /* enable RF path S1 */ + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_SDMRSTB | RF_RSTB | RF_ENABLE); + + /* enable RF path S0 */ + rtl8xxxu_write8(priv, REG_AFE_CTRL4 + 3, RF_SDMRSTB | RF_RSTB | RF_ENABLE); + + /* AFE_Ctrl */ + rtl8xxxu_write8_set(priv, REG_RSVD_1, BIT(5)); + + /* AFE_Ctrl */ + rtl8xxxu_write8(priv, REG_RSVD_4, 0xcc); + + /* AFE_Ctrl 0x24[4:3]=00 for xtal gmn */ + rtl8xxxu_write8_clear(priv, REG_AFE_XTAL_CTRL, BIT(4) | BIT(3)); + + /* GPIO_A[31:0] Pull down software register */ + rtl8xxxu_write32(priv, REG_GPIO_A0, 0xffffffff); + + /* GPIO_B[7:0] Pull down software register */ + rtl8xxxu_write8(priv, REG_GPIO_B0, 0xff); + + /* Register Lock Enable */ + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(7)); + + return 0; +} + +static int rtl8192fu_active_to_emu(struct rtl8xxxu_priv *priv) +{ + u32 val32; + int count; + + /* Reset BB, RF enter Power Down mode */ + rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB); + + /* Enable rising edge triggering interrupt */ + rtl8xxxu_write16_clear(priv, REG_GPIO_INTM, GPIO_INTM_EDGE_TRIG_IRQ); + + /* release WLON reset */ + rtl8xxxu_write32_set(priv, REG_APS_FSMCO, APS_FSMCO_WLON_RESET); + + /* turn off MAC by HW state machine */ + rtl8xxxu_write16_set(priv, REG_APS_FSMCO, APS_FSMCO_MAC_OFF); + + for (count = RTL8XXXU_MAX_REG_POLL; count; count--) { + val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO); + if ((val32 & APS_FSMCO_MAC_OFF) == 0) + break; + + udelay(10); + } + + if (!count) + return -EBUSY; + + /* analog Ips to digital, 1:isolation */ + rtl8xxxu_write8_set(priv, REG_SYS_ISO_CTRL, SYS_ISO_ANALOG_IPS); + + /* disable LDOA12 MACRO block */ + rtl8xxxu_write8_clear(priv, REG_LDOA15_CTRL, LDOA15_ENABLE); + + return 0; +} + +static int rtl8192fu_emu_to_disabled(struct rtl8xxxu_priv *priv) +{ + u16 val16; + + /* SOP option to disable BG/MB */ + rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20); + + /* 0x04[12:11] = 2b'01 enable WL suspend */ + val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO); + val16 &= ~APS_FSMCO_PCIE; + val16 |= APS_FSMCO_HW_SUSPEND; + rtl8xxxu_write16(priv, REG_APS_FSMCO, val16); + + /* enable GPIO9 as EXT WAKEUP */ + rtl8xxxu_write32_set(priv, REG_GPIO_INTM, BIT(16)); + + return 0; +} + +static int rtl8192fu_active_to_lps(struct rtl8xxxu_priv *priv) +{ + struct device *dev = &priv->udev->dev; + u16 val16; + u32 val32; + int retry; + + /* Tx Pause */ + rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff); + + retry = 100; + + /* Poll 32 bit wide REG_SCH_TX_CMD for 0 to ensure no TX is pending. */ + do { + val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD); + if (!val32) + break; + + udelay(10); + } while (retry--); + + if (!retry) { + dev_warn(dev, "%s: Failed to flush TX queue\n", __func__); + return -EBUSY; + } + + /* Disable CCK and OFDM, clock gated */ + rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BBRSTB); + + udelay(2); + + /* Whole BB is reset */ + rtl8xxxu_write8_clear(priv, REG_SYS_FUNC, SYS_FUNC_BB_GLB_RSTN); + + /* Reset MAC TRX */ + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 &= 0xff00; + val16 |= CR_HCI_RXDMA_ENABLE | CR_HCI_TXDMA_ENABLE; + val16 &= ~CR_SECURITY_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + /* Respond TxOK to scheduler */ + rtl8xxxu_write8_set(priv, REG_DUAL_TSF_RST, DUAL_TSF_TX_OK); + + return 0; +} + +static int rtl8192fu_power_on(struct rtl8xxxu_priv *priv) +{ + u16 val16; + int ret; + + rtl8xxxu_write8(priv, REG_USB_ACCESS_TIMEOUT, 0x80); + + rtl8192fu_disabled_to_emu(priv); + + ret = rtl8192fu_emu_to_active(priv); + if (ret) + return ret; + + rtl8xxxu_write16(priv, REG_CR, 0); + + val16 = rtl8xxxu_read16(priv, REG_CR); + + val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE | + CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | + CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE | + CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE; + rtl8xxxu_write16(priv, REG_CR, val16); + + return 0; +} + +static void rtl8192fu_power_off(struct rtl8xxxu_priv *priv) +{ + rtl8xxxu_flush_fifo(priv); + + /* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */ + rtl8xxxu_write8_clear(priv, REG_TX_REPORT_CTRL, + TX_REPORT_CTRL_TIMER_ENABLE); + + /* stop rx */ + rtl8xxxu_write8(priv, REG_CR, 0x00); + + rtl8192fu_active_to_lps(priv); + + /* Reset Firmware if running in RAM */ + if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL) + rtl8xxxu_firmware_self_reset(priv); + + /* Reset MCU */ + rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE); + + /* Reset MCU ready status */ + rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00); + + rtl8192fu_active_to_emu(priv); + rtl8192fu_emu_to_disabled(priv); +} + +static void rtl8192f_reset_8051(struct rtl8xxxu_priv *priv) +{ + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1)); + + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL + 1, BIT(0)); + + rtl8xxxu_write16_clear(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE); + + rtl8xxxu_write8_clear(priv, REG_RSV_CTRL, BIT(1)); + + rtl8xxxu_write8_set(priv, REG_RSV_CTRL + 1, BIT(0)); + + rtl8xxxu_write16_set(priv, REG_SYS_FUNC, SYS_FUNC_CPU_ENABLE); +} + +static void rtl8192f_enable_rf(struct rtl8xxxu_priv *priv) +{ + u32 val32; + + rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB); + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK); + val32 |= OFDM_RF_PATH_RX_A | OFDM_RF_PATH_RX_B | + OFDM_RF_PATH_TX_A | OFDM_RF_PATH_TX_B; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00); +} + +static void rtl8192f_disable_rf(struct rtl8xxxu_priv *priv) +{ + u32 val32; + + val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE); + val32 &= ~OFDM_RF_PATH_TX_MASK; + rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32); + + /* Power down RF module */ + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0); +} + +static void rtl8192f_usb_quirks(struct rtl8xxxu_priv *priv) +{ + u16 val16; + + rtl8xxxu_gen2_usb_quirks(priv); + + val16 = rtl8xxxu_read16(priv, REG_CR); + val16 |= (CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE); + rtl8xxxu_write16(priv, REG_CR, val16); +} + +#define XTAL1 GENMASK(6, 1) +#define XTAL0 GENMASK(30, 25) + +static void rtl8192f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap) +{ + struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking; + u32 xtal1, xtal0; + + if (crystal_cap == cfo->crystal_cap) + return; + + xtal1 = rtl8xxxu_read32(priv, REG_AFE_PLL_CTRL); + xtal0 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL); + + dev_dbg(&priv->udev->dev, + "%s: Adjusting crystal cap from 0x%x (actually 0x%x 0x%x) to 0x%x\n", + __func__, + cfo->crystal_cap, + u32_get_bits(xtal1, XTAL1), + u32_get_bits(xtal0, XTAL0), + crystal_cap); + + u32p_replace_bits(&xtal1, crystal_cap, XTAL1); + u32p_replace_bits(&xtal0, crystal_cap, XTAL0); + rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, xtal1); + rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, xtal0); + + cfo->crystal_cap = crystal_cap; +} + +static s8 rtl8192f_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats) +{ + struct jaguar2_phy_stats_type0 *phy_stats0 = (struct jaguar2_phy_stats_type0 *)phy_stats; + u8 lna_idx = (phy_stats0->lna_h << 3) | phy_stats0->lna_l; + u8 vga_idx = phy_stats0->vga; + s8 rx_pwr_all; + + switch (lna_idx) { + case 7: + rx_pwr_all = -44 - (2 * vga_idx); + break; + case 5: + rx_pwr_all = -28 - (2 * vga_idx); + break; + case 3: + rx_pwr_all = -10 - (2 * vga_idx); + break; + case 0: + rx_pwr_all = 14 - (2 * vga_idx); + break; + default: + rx_pwr_all = 0; + break; + } + + return rx_pwr_all; +} + +static int rtl8192fu_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct rtl8xxxu_priv *priv = container_of(led_cdev, + struct rtl8xxxu_priv, + led_cdev); + u16 ledcfg; + + /* Values obtained by observing the USB traffic from the Windows driver. */ + rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_0, 0x20080); + rtl8xxxu_write32(priv, REG_SW_GPIO_SHARE_CTRL_1, 0x1b0000); + + ledcfg = rtl8xxxu_read16(priv, REG_LEDCFG0); + + if (brightness == LED_OFF) { + /* Value obtained like above. */ + ledcfg = BIT(1) | BIT(7); + } else if (brightness == LED_ON) { + /* Value obtained like above. */ + ledcfg = BIT(1) | BIT(7) | BIT(11); + } else if (brightness == RTL8XXXU_HW_LED_CONTROL) { + /* Value obtained by brute force. */ + ledcfg = BIT(8) | BIT(9); + } + + rtl8xxxu_write16(priv, REG_LEDCFG0, ledcfg); + + return 0; +} + +struct rtl8xxxu_fileops rtl8192fu_fops = { + .identify_chip = rtl8192fu_identify_chip, + .parse_efuse = rtl8192fu_parse_efuse, + .load_firmware = rtl8192fu_load_firmware, + .power_on = rtl8192fu_power_on, + .power_off = rtl8192fu_power_off, + .read_efuse = rtl8xxxu_read_efuse, + .reset_8051 = rtl8192f_reset_8051, + .llt_init = rtl8xxxu_auto_llt_table, + .init_phy_bb = rtl8192fu_init_phy_bb, + .init_phy_rf = rtl8192fu_init_phy_rf, + .phy_lc_calibrate = rtl8192f_phy_lc_calibrate, + .phy_iq_calibrate = rtl8192fu_phy_iq_calibrate, + .config_channel = rtl8192fu_config_channel, + .parse_rx_desc = rtl8xxxu_parse_rxdesc24, + .parse_phystats = jaguar2_rx_parse_phystats, + .init_aggregation = rtl8192fu_init_aggregation, + .init_burst = rtl8xxxu_init_burst, + .enable_rf = rtl8192f_enable_rf, + .disable_rf = rtl8192f_disable_rf, + .usb_quirks = rtl8192f_usb_quirks, + .set_tx_power = rtl8192f_set_tx_power, + .update_rate_mask = rtl8xxxu_gen2_update_rate_mask, + .report_connect = rtl8xxxu_gen2_report_connect, + .report_rssi = rtl8xxxu_gen2_report_rssi, + .fill_txdesc = rtl8xxxu_fill_txdesc_v2, + .set_crystal_cap = rtl8192f_set_crystal_cap, + .cck_rssi = rtl8192f_cck_rssi, + .led_classdev_brightness_set = rtl8192fu_led_brightness_set, + .writeN_block_size = 254, + .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24), + .tx_desc_size = sizeof(struct rtl8xxxu_txdesc40), + .has_tx_report = 1, + .gen2_thermal_meter = 1, + .needs_full_init = 1, + .init_reg_rxfltmap = 1, + .init_reg_pkt_life_time = 1, + .init_reg_hmtfr = 1, + .ampdu_max_time = 0x5e, + .ustime_tsf_edca = 0x50, + .max_aggr_num = 0x1f1f, + .trxff_boundary = 0x3f3f, + .pbp_rx = PBP_PAGE_SIZE_256, + .pbp_tx = PBP_PAGE_SIZE_256, + .mactable = rtl8192f_mac_init_table, + .total_page_num = TX_TOTAL_PAGE_NUM_8192F, + .page_num_hi = TX_PAGE_NUM_HI_PQ_8192F, + .page_num_lo = TX_PAGE_NUM_LO_PQ_8192F, + .page_num_norm = TX_PAGE_NUM_NORM_PQ_8192F, +}; diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c index 22d4704dd31e18..f0d17b75c5f10b 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8710b.c @@ -1031,12 +1031,12 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7); /* PA,PAD gain adjust */ - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 |= BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG); u32p_replace_bits(&val32, 0x1ed, 0x00fff); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32); /* enter IQK mode */ val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK); @@ -1068,9 +1068,9 @@ static int rtl8710bu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result) u32p_replace_bits(&val32, 0, 0xffffff00); rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 &= ~BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); /* save LOK result */ *lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC); @@ -1113,12 +1113,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173); /* PA,PAD gain adjust */ - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 |= BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG); u32p_replace_bits(&val32, 0xf, 0x003e0); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32); /* * Enter IQK mode @@ -1170,9 +1170,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) u32p_replace_bits(&val32, 0, 0xffffff00); rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 &= ~BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); return result; } @@ -1197,12 +1197,12 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) /* * PA, PAD setting */ - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 |= BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_PAD_TXG); u32p_replace_bits(&val32, 0x2a, 0x00fff); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_56, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, val32); /* * Enter IQK mode @@ -1241,9 +1241,9 @@ static int rtl8710bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result) u32p_replace_bits(&val32, 0, 0xffffff00); rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32); - val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF); + val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA); val32 &= ~BIT(11); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, val32); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, val32); /* reload LOK value */ rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result); @@ -1874,6 +1874,7 @@ struct rtl8xxxu_fileops rtl8710bu_fops = { * but in rtl8xxxu 0x50 causes slow upload and random packet loss. Why? */ .ustime_tsf_edca = 0x28, + .max_aggr_num = 0x0c14, .adda_1t_init = 0x03c00016, .adda_1t_path_on = 0x03c00016, .trxff_boundary = 0x3f7f, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c index abc56c7de6f756..13ad5d5b73f4e6 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8723b.c @@ -824,7 +824,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) /* * PA, PAD setting */ - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0xf80); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0xf80); rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_55, 0x4021f); /* @@ -888,7 +888,7 @@ static int rtl8723bu_rx_iqk_path_a(struct rtl8xxxu_priv *priv) reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2); reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2); - rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_DF, 0x780); + rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x780); val32 = (reg_eac >> 16) & 0x3ff; if (val32 & 0x200) @@ -1741,6 +1741,7 @@ struct rtl8xxxu_fileops rtl8723bu_fops = { .init_reg_hmtfr = 1, .ampdu_max_time = 0x5e, .ustime_tsf_edca = 0x50, + .max_aggr_num = 0x0c14, .adda_1t_init = 0x01c00014, .adda_1t_path_on = 0x01c00014, .adda_2t_path_on_a = 0x01c00014, diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c index 1eb0d564262396..5d102a1246a301 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c @@ -56,6 +56,7 @@ MODULE_FIRMWARE("rtlwifi/rtl8723bu_bt.bin"); MODULE_FIRMWARE("rtlwifi/rtl8188fufw.bin"); MODULE_FIRMWARE("rtlwifi/rtl8710bufw_SMIC.bin"); MODULE_FIRMWARE("rtlwifi/rtl8710bufw_UMC.bin"); +MODULE_FIRMWARE("rtlwifi/rtl8192fufw.bin"); module_param_named(debug, rtl8xxxu_debug, int, 0600); MODULE_PARM_DESC(debug, "Set debug mask"); @@ -642,7 +643,7 @@ const u32 rtl8xxxu_iqk_phy_iq_bb_reg[RTL8XXXU_BB_REGS] = { REG_OFDM0_XA_RX_IQ_IMBALANCE, REG_OFDM0_XB_RX_IQ_IMBALANCE, REG_OFDM0_ENERGY_CCA_THRES, - REG_OFDM0_AGCR_SSI_TABLE, + REG_OFDM0_AGC_RSSI_TABLE, REG_OFDM0_XA_TX_IQ_IMBALANCE, REG_OFDM0_XB_TX_IQ_IMBALANCE, REG_OFDM0_XC_TX_AFE, @@ -2020,12 +2021,18 @@ static int rtl8xxxu_start_firmware(struct rtl8xxxu_priv *priv) static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) { int pages, remainder, i, ret; + u16 reg_fw_start_address; u16 reg_mcu_fw_dl; u8 val8; u16 val16; u32 val32; u8 *fwptr; + if (priv->rtl_chip == RTL8192F) + reg_fw_start_address = REG_FW_START_ADDRESS_8192F; + else + reg_fw_start_address = REG_FW_START_ADDRESS; + if (priv->rtl_chip == RTL8710B) { reg_mcu_fw_dl = REG_8051FW_CTRL_V1_8710B; } else { @@ -2081,7 +2088,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) val8 |= i; rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8); - ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + ret = rtl8xxxu_writeN(priv, reg_fw_start_address, fwptr, RTL_FW_PAGE_SIZE); if (ret != RTL_FW_PAGE_SIZE) { ret = -EAGAIN; @@ -2095,7 +2102,7 @@ static int rtl8xxxu_download_firmware(struct rtl8xxxu_priv *priv) val8 = rtl8xxxu_read8(priv, reg_mcu_fw_dl + 2) & 0xF8; val8 |= i; rtl8xxxu_write8(priv, reg_mcu_fw_dl + 2, val8); - ret = rtl8xxxu_writeN(priv, REG_FW_START_ADDRESS, + ret = rtl8xxxu_writeN(priv, reg_fw_start_address, fwptr, remainder); if (ret != remainder) { ret = -EAGAIN; @@ -2149,6 +2156,7 @@ int rtl8xxxu_load_firmware(struct rtl8xxxu_priv *priv, const char *fw_name) case 0x2300: case 0x88f0: case 0x10b0: + case 0x92f0: break; default: ret = -EINVAL; @@ -2595,6 +2603,7 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) u16 hiq, mgq, bkq, beq, viq, voq; int hip, mgp, bkp, bep, vip, vop; int ret = 0; + u32 val32; switch (priv->ep_tx_count) { case 1: @@ -2677,15 +2686,28 @@ static int rtl8xxxu_init_queue_priority(struct rtl8xxxu_priv *priv) * queue here .... why? */ if (!ret) { - val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); - val16 &= 0x7; - val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | - (viq << TRXDMA_CTRL_VIQ_SHIFT) | - (beq << TRXDMA_CTRL_BEQ_SHIFT) | - (bkq << TRXDMA_CTRL_BKQ_SHIFT) | - (mgq << TRXDMA_CTRL_MGQ_SHIFT) | - (hiq << TRXDMA_CTRL_HIQ_SHIFT); - rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16); + /* Only RTL8192F seems to do it like this. */ + if (priv->rtl_chip == RTL8192F) { + val32 = rtl8xxxu_read32(priv, REG_TRXDMA_CTRL); + val32 &= 0x7; + val32 |= (voq << TRXDMA_CTRL_VOQ_SHIFT_8192F) | + (viq << TRXDMA_CTRL_VIQ_SHIFT_8192F) | + (beq << TRXDMA_CTRL_BEQ_SHIFT_8192F) | + (bkq << TRXDMA_CTRL_BKQ_SHIFT_8192F) | + (mgq << TRXDMA_CTRL_MGQ_SHIFT_8192F) | + (hiq << TRXDMA_CTRL_HIQ_SHIFT_8192F); + rtl8xxxu_write32(priv, REG_TRXDMA_CTRL, val32); + } else { + val16 = rtl8xxxu_read16(priv, REG_TRXDMA_CTRL); + val16 &= 0x7; + val16 |= (voq << TRXDMA_CTRL_VOQ_SHIFT) | + (viq << TRXDMA_CTRL_VIQ_SHIFT) | + (beq << TRXDMA_CTRL_BEQ_SHIFT) | + (bkq << TRXDMA_CTRL_BKQ_SHIFT) | + (mgq << TRXDMA_CTRL_MGQ_SHIFT) | + (hiq << TRXDMA_CTRL_HIQ_SHIFT); + rtl8xxxu_write16(priv, REG_TRXDMA_CTRL, val16); + } priv->pipe_out[TXDESC_QUEUE_VO] = usb_sndbulkpipe(priv->udev, priv->out_ep[vop]); @@ -2856,10 +2878,14 @@ void rtl8xxxu_fill_iqk_matrix_b(struct rtl8xxxu_priv *priv, bool iqk_ok, reg = (result[candidate][7] >> 6) & 0xf; - val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGCR_SSI_TABLE); - val32 &= ~0x0000f000; - val32 |= (reg << 12); - rtl8xxxu_write32(priv, REG_OFDM0_AGCR_SSI_TABLE, val32); + if (priv->rtl_chip == RTL8192F) { + rtl8xxxu_write32_mask(priv, REG_RXIQB_EXT, 0x000000f0, reg); + } else { + val32 = rtl8xxxu_read32(priv, REG_OFDM0_AGC_RSSI_TABLE); + val32 &= ~0x0000f000; + val32 |= (reg << 12); + rtl8xxxu_write32(priv, REG_OFDM0_AGC_RSSI_TABLE, val32); + } } #define MAX_TOLERANCE 5 @@ -3958,13 +3984,14 @@ void rtl8xxxu_init_burst(struct rtl8xxxu_priv *priv) val8 |= HT_SINGLE_AMPDU_ENABLE; rtl8xxxu_write8(priv, REG_HT_SINGLE_AMPDU_8723B, val8); - rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, 0x0c14); + rtl8xxxu_write16(priv, REG_MAX_AGGR_NUM, priv->fops->max_aggr_num); rtl8xxxu_write8(priv, REG_AMPDU_MAX_TIME_8723B, priv->fops->ampdu_max_time); rtl8xxxu_write32(priv, REG_AGGLEN_LMT, 0xffffffff); rtl8xxxu_write8(priv, REG_RX_PKT_LIMIT, 0x18); rtl8xxxu_write8(priv, REG_PIFS, 0x00); - if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B) { + if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8710B || + priv->rtl_chip == RTL8192F) { rtl8xxxu_write8(priv, REG_FWHW_TXQ_CTRL, FWHW_TXQ_CTRL_AMPDU_RETRY); rtl8xxxu_write32(priv, REG_FAST_EDCA_CTRL, 0x03086666); } @@ -4078,9 +4105,14 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) if (ret) goto exit; + /* Mac APLL Setting */ + if (priv->rtl_chip == RTL8192F) + rtl8xxxu_write16_set(priv, REG_AFE_CTRL4, BIT(4) | BIT(15)); + /* RFSW Control - clear bit 14 ?? */ if (priv->rtl_chip != RTL8723B && priv->rtl_chip != RTL8192E && - priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B) + priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B && + priv->rtl_chip != RTL8192F) rtl8xxxu_write32(priv, REG_FPGA0_TX_INFO, 0x00000003); val32 = FPGA0_RF_TRSW | FPGA0_RF_TRSWB | FPGA0_RF_ANTSW | @@ -4094,7 +4126,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* 0x860[6:5]= 00 - why? - this sets antenna B */ if (priv->rtl_chip != RTL8192E && priv->rtl_chip != RTL8188E && - priv->rtl_chip != RTL8710B) + priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F) rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, 0x66f60210); if (!macpower) { @@ -4168,7 +4200,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, 0xa3, val8); } - if (priv->rtl_chip == RTL8710B) + if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F) rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8710B, 0); } @@ -4195,7 +4227,7 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, val8); } else if (priv->rtl_chip == RTL8710B) { rtl8xxxu_write32(priv, REG_HIMR0_8710B, 0); - } else { + } else if (priv->rtl_chip != RTL8192F) { /* * Enable all interrupts - not obvious USB needs to do this */ @@ -4284,7 +4316,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) val16 = BEACON_DISABLE_TSF_UPDATE | (BEACON_DISABLE_TSF_UPDATE << 8); rtl8xxxu_write16(priv, REG_BEACON_CTRL, val16); rtl8xxxu_write16(priv, REG_TBTT_PROHIBIT, 0x6404); - if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B) + if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8710B && + priv->rtl_chip != RTL8192F) /* Firmware will control REG_DRVERLYINT when power saving is enable, */ /* so don't set this register on STA mode. */ rtl8xxxu_write8(priv, REG_DRIVER_EARLY_INT, DRIVER_EARLY_INT_TIME); @@ -4335,7 +4368,8 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) /* Disable BAR - not sure if this has any effect on USB */ rtl8xxxu_write32(priv, REG_BAR_MODE_CTRL, 0x0201ffff); - if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && priv->rtl_chip != RTL8710B) + if (priv->rtl_chip != RTL8188F && priv->rtl_chip != RTL8188E && + priv->rtl_chip != RTL8710B && priv->rtl_chip != RTL8192F) rtl8xxxu_write16(priv, REG_FAST_EDCA_CTRL, 0); if (fops->init_statistics) @@ -4353,9 +4387,10 @@ static int rtl8xxxu_init_device(struct ieee80211_hw *hw) * Reset USB mode switch setting */ rtl8xxxu_write8(priv, REG_ACLK_MON, 0x00); - } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E) { + } else if (priv->rtl_chip == RTL8188F || priv->rtl_chip == RTL8188E || + priv->rtl_chip == RTL8192F) { /* - * Init GPIO settings for 8188f, 8188e + * Init GPIO settings for 8188f, 8188e, 8192f */ val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG); val8 &= ~GPIO_MUXCFG_IO_SEL_ENBT; @@ -5517,8 +5552,10 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, tx_desc->pkt_size = cpu_to_le16(pktlen); tx_desc->pkt_offset = tx_desc_size; - tx_desc->txdw0 = - TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; + /* These bits mean different things to the RTL8192F. */ + if (priv->rtl_chip != RTL8192F) + tx_desc->txdw0 = + TXDESC_OWN | TXDESC_FIRST_SEGMENT | TXDESC_LAST_SEGMENT; if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) || is_broadcast_ether_addr(ieee80211_get_DA(hdr))) tx_desc->txdw0 |= TXDESC_BROADMULTICAST; @@ -5588,7 +5625,7 @@ static void rtl8xxxu_tx(struct ieee80211_hw *hw, rtl8xxxu_calc_tx_desc_csum(tx_desc); /* avoid zero checksum make tx hang */ - if (priv->rtl_chip == RTL8710B) + if (priv->rtl_chip == RTL8710B || priv->rtl_chip == RTL8192F) tx_desc->csum = ~tx_desc->csum; usb_fill_bulk_urb(&tx_urb->urb, priv->udev, priv->pipe_out[queue], @@ -7462,6 +7499,7 @@ static int rtl8xxxu_probe(struct usb_interface *interface, case 0xf179: case 0x8179: case 0xb711: + case 0xf192: untested = 0; break; } @@ -7486,6 +7524,10 @@ static int rtl8xxxu_probe(struct usb_interface *interface, if (id->idProduct == 0x0109) untested = 0; break; + case 0x0b05: + if (id->idProduct == 0x18f1) + untested = 0; + break; default: break; } @@ -7752,6 +7794,16 @@ static const struct usb_device_id dev_table[] = { /* TOTOLINK N150UA V5 / N150UA-B */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x2005, 0xff, 0xff, 0xff), .driver_info = (unsigned long)&rtl8710bu_fops}, +/* Comfast CF-826F */ +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0xf192, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, +/* Asus USB-N13 rev C1 */ +{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x18f1, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb722, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, +{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x318b, 0xff, 0xff, 0xff), + .driver_info = (unsigned long)&rtl8192fu_fops}, #ifdef CONFIG_RTL8XXXU_UNTESTED /* Still supported by rtlwifi */ {USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8176, 0xff, 0xff, 0xff), diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h index 8571d5129f327b..920ee50e211536 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_regs.h @@ -67,6 +67,7 @@ #define REG_SPS0_CTRL 0x0011 #define REG_SPS_OCP_CFG 0x0018 #define REG_8192E_LDOV12_CTRL 0x0014 +#define REG_SYS_SWR_CTRL2 0x0014 #define REG_RSV_CTRL 0x001c #define RSV_CTRL_WLOCK_1C BIT(5) #define RSV_CTRL_DIS_PRST BIT(6) @@ -215,6 +216,8 @@ #define REG_HMBOX_EXT_2 0x008c #define REG_HMBOX_EXT_3 0x008e +#define REG_RSVD_1 0x0097 + /* Interrupt registers for 8192e/8723bu/8812 */ #define REG_HIMR0 0x00b0 #define IMR0_TXCCK BIT(30) /* TXRPT interrupt when CCX bit @@ -283,6 +286,7 @@ #define REG_BIST_SCAN 0x00d0 #define REG_BIST_RPT 0x00d4 #define REG_BIST_ROM_RPT 0x00d8 +#define REG_RSVD_4 0x00dc #define REG_USB_SIE_INTF 0x00e0 #define REG_PCIE_MIO_INTF 0x00e4 #define REG_PCIE_MIO_INTD 0x00e8 @@ -390,6 +394,12 @@ #define TRXDMA_CTRL_BKQ_SHIFT 10 #define TRXDMA_CTRL_MGQ_SHIFT 12 #define TRXDMA_CTRL_HIQ_SHIFT 14 +#define TRXDMA_CTRL_VOQ_SHIFT_8192F 4 +#define TRXDMA_CTRL_VIQ_SHIFT_8192F 7 +#define TRXDMA_CTRL_BEQ_SHIFT_8192F 10 +#define TRXDMA_CTRL_BKQ_SHIFT_8192F 13 +#define TRXDMA_CTRL_MGQ_SHIFT_8192F 16 +#define TRXDMA_CTRL_HIQ_SHIFT_8192F 19 #define TRXDMA_QUEUE_LOW 1 #define TRXDMA_QUEUE_NORMAL 2 #define TRXDMA_QUEUE_HIGH 3 @@ -439,7 +449,7 @@ #define LLT_OP_READ (0x2 << 30) #define LLT_OP_MASK (0x3 << 30) -#define REG_BB_ACCEESS_CTRL 0x01e8 +#define REG_BB_ACCESS_CTRL 0x01e8 #define REG_BB_ACCESS_DATA 0x01ec #define REG_HMBOX_EXT0_8723B 0x01f0 @@ -973,12 +983,18 @@ #define FPGA1_TX_OFDM_TXSC_MASK 0x30000000 #define REG_ANT_MAPPING1 0x0914 +#define REG_RFE_OPT 0x0920 #define REG_DPDT_CTRL 0x092c /* 8723BU */ #define REG_RFE_CTRL_ANTA_SRC 0x0930 /* 8723BU */ +#define REG_RFE_CTRL_ANT_SRC1 0x0934 +#define REG_RFE_CTRL_ANT_SRC2 0x0938 +#define REG_RFE_CTRL_ANT_SRC3 0x093c #define REG_RFE_PATH_SELECT 0x0940 /* 8723BU */ #define REG_RFE_BUFFER 0x0944 /* 8723BU */ #define REG_S0S1_PATH_SWITCH 0x0948 /* 8723BU */ +#define REG_RX_DFIR_MOD_97F 0x0948 #define REG_OFDM_RX_DFIR 0x954 +#define REG_RFE_OPT62 0x0968 #define REG_CCK0_SYSTEM 0x0a00 #define CCK0_SIDEBAND BIT(4) @@ -1038,6 +1054,8 @@ #define REG_OFDM0_FA_RSTC 0x0c0c +#define REG_DOWNSAM_FACTOR 0x0c10 + #define REG_OFDM0_XA_RX_AFE 0x0c10 #define REG_OFDM0_XA_RX_IQ_IMBALANCE 0x0c14 #define REG_OFDM0_XB_RX_IQ_IMBALANCE 0x0c1c @@ -1059,7 +1077,7 @@ #define REG_OFDM0_AGC_PARM1 0x0c70 -#define REG_OFDM0_AGCR_SSI_TABLE 0x0c78 +#define REG_OFDM0_AGC_RSSI_TABLE 0x0c78 #define REG_OFDM0_XA_TX_IQ_IMBALANCE 0x0c80 #define REG_OFDM0_XB_TX_IQ_IMBALANCE 0x0c88 @@ -1074,6 +1092,8 @@ /* 8188eu */ #define REG_ANTDIV_PARA1 0x0ca4 +#define REG_RXIQB_EXT 0x0ca8 + /* 8723bu */ #define REG_OFDM0_TX_PSDO_NOISE_WEIGHT 0x0ce4 @@ -1093,6 +1113,8 @@ #define REG_OFDM1_CSI_FIX_MASK1 0x0d40 #define REG_OFDM1_CSI_FIX_MASK2 0x0d44 +#define REG_ANAPWR1 0x0d94 + #define REG_TX_AGC_A_RATE18_06 0x0e00 #define REG_TX_AGC_A_RATE54_24 0x0e04 #define REG_TX_AGC_A_CCK1_MCS32 0x0e08 @@ -1101,6 +1123,10 @@ #define REG_TX_AGC_A_MCS11_MCS08 0x0e18 #define REG_TX_AGC_A_MCS15_MCS12 0x0e1c +#define REG_NP_ANTA 0x0e20 + +#define REG_TAP_UPD_97F 0x0e24 + #define REG_FPGA0_IQK 0x0e28 #define REG_TX_IQK_TONE_A 0x0e30 @@ -1129,19 +1155,23 @@ #define REG_RX_CCK 0x0e8c #define REG_TX_POWER_BEFORE_IQK_A 0x0e94 +#define REG_IQK_RPT_TXA 0x0e98 #define REG_TX_POWER_AFTER_IQK_A 0x0e9c #define REG_RX_POWER_BEFORE_IQK_A 0x0ea0 #define REG_RX_POWER_BEFORE_IQK_A_2 0x0ea4 #define REG_RX_POWER_AFTER_IQK_A 0x0ea8 +#define REG_IQK_RPT_RXA 0x0ea8 #define REG_RX_POWER_AFTER_IQK_A_2 0x0eac #define REG_TX_POWER_BEFORE_IQK_B 0x0eb4 +#define REG_IQK_RPT_TXB 0x0eb8 #define REG_TX_POWER_AFTER_IQK_B 0x0ebc #define REG_RX_POWER_BEFORE_IQK_B 0x0ec0 #define REG_RX_POWER_BEFORE_IQK_B_2 0x0ec4 #define REG_RX_POWER_AFTER_IQK_B 0x0ec8 +#define REG_IQK_RPT_RXB 0x0ec8 #define REG_RX_POWER_AFTER_IQK_B_2 0x0ecc #define REG_RX_OFDM 0x0ed0 @@ -1152,6 +1182,12 @@ #define REG_PMPD_ANAEN 0x0eec #define REG_FW_START_ADDRESS 0x1000 +#define REG_FW_START_ADDRESS_8192F 0x4000 + +#define REG_SW_GPIO_SHARE_CTRL_0 0x1038 +#define REG_SW_GPIO_SHARE_CTRL_1 0x103c +#define REG_GPIO_A0 0x1050 +#define REG_GPIO_B0 0x105b #define REG_USB_INFO 0xfe17 #define REG_USB_HIMR 0xfe38 @@ -1316,12 +1352,15 @@ /* * NextGen regs: 8723BU */ +#define RF6052_REG_GAIN_P1 0x35 #define RF6052_REG_T_METER_8723B 0x42 #define RF6052_REG_UNKNOWN_43 0x43 #define RF6052_REG_UNKNOWN_55 0x55 -#define RF6052_REG_UNKNOWN_56 0x56 +#define RF6052_REG_PAD_TXG 0x56 +#define RF6052_REG_TXMOD 0x58 #define RF6052_REG_RXG_MIX_SWBW 0x87 #define RF6052_REG_S0S1 0xb0 -#define RF6052_REG_UNKNOWN_DF 0xdf +#define RF6052_REG_GAIN_CCA 0xdf #define RF6052_REG_UNKNOWN_ED 0xed #define RF6052_REG_WE_LUT 0xef +#define RF6052_REG_GAIN_CTRL 0xf5 diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 9e7e98b55eff80..807a53a97325bf 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -452,8 +452,7 @@ static int _rtl_init_deferred_work(struct ieee80211_hw *hw) /* <1> timer */ timer_setup(&rtlpriv->works.watchdog_timer, rtl_watch_dog_timer_callback, 0); - timer_setup(&rtlpriv->works.dualmac_easyconcurrent_retrytimer, - rtl_easy_concurrent_retrytimer_callback, 0); + /* <2> work queue */ rtlpriv->works.hw = hw; rtlpriv->works.rtl_wq = wq; @@ -1905,7 +1904,7 @@ EXPORT_SYMBOL(rtl_rx_ampdu_apply); void rtl_beacon_statistic(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION) return; @@ -1991,7 +1990,7 @@ void rtl_scan_list_expire(struct ieee80211_hw *hw) void rtl_collect_scan_list(struct ieee80211_hw *hw, struct sk_buff *skb) { struct rtl_priv *rtlpriv = rtl_priv(hw); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); unsigned long flags; @@ -2366,19 +2365,6 @@ static void rtl_c2hcmd_wq_callback(struct work_struct *work) rtl_c2hcmd_launcher(hw, 1); } -void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t) -{ - struct rtl_priv *rtlpriv = - from_timer(rtlpriv, t, works.dualmac_easyconcurrent_retrytimer); - struct ieee80211_hw *hw = rtlpriv->hw; - struct rtl_priv *buddy_priv = rtlpriv->buddy_priv; - - if (buddy_priv == NULL) - return; - - rtlpriv->cfg->ops->dualmac_easy_concurrent(hw); -} - /********************************************************* * * frame process functions diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h index 0e4f8a8ae3a5fc..f081a9a90563f5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.h +++ b/drivers/net/wireless/realtek/rtlwifi/base.h @@ -124,7 +124,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw, u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie); void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len); u8 rtl_tid_to_ac(u8 tid); -void rtl_easy_concurrent_retrytimer_callback(struct timer_list *t); extern struct rtl_global_var rtl_global_var; void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation); diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c index ca79f652fef3c1..028a7c97bacf65 100644 --- a/drivers/net/wireless/realtek/rtlwifi/pci.c +++ b/drivers/net/wireless/realtek/rtlwifi/pci.c @@ -482,11 +482,6 @@ static void _rtl_pci_tx_chk_waitq(struct ieee80211_hw *hw) if (!rtlpriv->rtlhal.earlymode_enable) return; - if (rtlpriv->dm.supp_phymode_switch && - (rtlpriv->easy_concurrent_ctl.switch_in_process || - (rtlpriv->buddy_priv && - rtlpriv->buddy_priv->easy_concurrent_ctl.switch_in_process))) - return; /* we just use em for BE/BK/VI/VO */ for (tid = 7; tid >= 0; tid--) { u8 hw_queue = ac_to_hwq[rtl_tid_to_ac(tid)]; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c index 6e4741e9483f60..65ebe52883d3f5 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/trx.c @@ -674,7 +674,7 @@ void rtl88ee_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 fw_queue = QSLT_BEACON; __le32 *pdesc = (__le32 *)pdesc8; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c index 730c7e939bd2e0..5376bb34251f7c 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/trx.c @@ -527,7 +527,7 @@ void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 fw_queue = QSLT_BEACON; __le32 *pdesc = (__le32 *)pdesc8; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c index ae3c4f97637ebc..b70767e72f3d9b 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192cu/trx.c @@ -394,7 +394,7 @@ static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb) (struct rx_desc_92c *)rxdesc, p_drvinfo); } skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE)); - hdr = (struct ieee80211_hdr *)(skb->data); + hdr = rtl_get_hdr(skb); fc = hdr->frame_control; bv = ieee80211_is_probe_resp(fc); if (bv) @@ -632,7 +632,7 @@ void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw, { struct rtl_priv *rtlpriv = rtl_priv(hw); u8 fw_queue = QSLT_BEACON; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; __le32 *pdesc = (__le32 *)pdesc8; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c index 807b66c16e111e..c09c0c3126658a 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/trx.c @@ -665,7 +665,7 @@ void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw, struct rtl_hal *rtlhal = rtl_hal(rtlpriv); u8 fw_queue = QSLT_BEACON; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; __le32 *pdesc = (__le32 *)pdesc8; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c index a8b5bf45b1bba3..4ae8f69c64f9c3 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/hw.c @@ -1302,7 +1302,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); u8 u1btmp; - if (rtlhal->driver_going2unload) + if (rtlhal->driver_is_goingto_unload) rtl_write_byte(rtlpriv, 0x560, 0x0); /* Power save for BB/RF */ @@ -1323,7 +1323,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) rtl_write_word(rtlpriv, CMDR, 0x57FC); rtl_write_word(rtlpriv, CMDR, 0x0000); - if (rtlhal->driver_going2unload) { + if (rtlhal->driver_is_goingto_unload) { u1btmp = rtl_read_byte(rtlpriv, (REG_SYS_FUNC_EN + 1)); u1btmp &= ~(BIT(0)); rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, u1btmp); @@ -1345,7 +1345,7 @@ static void _rtl92s_phy_set_rfhalt(struct ieee80211_hw *hw) /* Power save for MAC */ if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS && - !rtlhal->driver_going2unload) { + !rtlhal->driver_is_goingto_unload) { /* enable LED function */ rtl_write_byte(rtlpriv, 0x03, 0xF9); /* SW/HW radio off or halt adapter!! For example S3/S4 */ diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c index 27fddbcade3258..7f294e69899479 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/trx.c @@ -528,7 +528,7 @@ void rtl8723e_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 fw_queue = QSLT_BEACON; __le32 *pdesc = (__le32 *)pdesc8; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; dma_addr_t mapping = dma_map_single(&rtlpci->pdev->dev, skb->data, diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c index a8eebafb9a7ee2..ab675703eaf507 100644 --- a/drivers/net/wireless/realtek/rtlwifi/usb.c +++ b/drivers/net/wireless/realtek/rtlwifi/usb.c @@ -433,7 +433,7 @@ static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw, skb_pull(skb, RTL_RX_DESC_SIZE); rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); - hdr = (struct ieee80211_hdr *)(skb->data); + hdr = rtl_get_hdr(skb); fc = hdr->frame_control; if (!stats.crc) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); @@ -475,7 +475,7 @@ static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw, skb_pull(skb, RTL_RX_DESC_SIZE); rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb); skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift)); - hdr = (struct ieee80211_hdr *)(skb->data); + hdr = rtl_get_hdr(skb); fc = hdr->frame_control; if (!stats.crc) { memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); @@ -926,7 +926,7 @@ static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct rtl_tx_desc *pdesc = NULL; struct rtl_tcb_desc tcb_desc; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; u8 *pda_addr = hdr->addr1; @@ -961,7 +961,7 @@ static int rtl_usb_tx(struct ieee80211_hw *hw, { struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw)); struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data); + struct ieee80211_hdr *hdr = rtl_get_hdr(skb); __le16 fc = hdr->frame_control; u16 hw_queue; diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h index 082af216760f8e..a16b779080cb75 100644 --- a/drivers/net/wireless/realtek/rtlwifi/wifi.h +++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h @@ -1673,8 +1673,6 @@ struct rtl_hal { bool fw_clk_change_in_progress; bool allow_sw_to_change_hwclc; u8 fw_ps_state; - /**/ - bool driver_going2unload; /*AMPDU init min space*/ u8 minspace_cfg; /*For Min spacing configurations */ @@ -2300,7 +2298,6 @@ struct rtl_hal_ops { u32 regaddr, u32 bitmask, u32 data); void (*linked_set_reg)(struct ieee80211_hw *hw); void (*chk_switch_dmdp)(struct ieee80211_hw *hw); - void (*dualmac_easy_concurrent)(struct ieee80211_hw *hw); void (*dualmac_switch_to_dmdp)(struct ieee80211_hw *hw); bool (*phy_rf6052_config)(struct ieee80211_hw *hw); void (*phy_rf6052_set_cck_txpower)(struct ieee80211_hw *hw, @@ -2465,7 +2462,6 @@ struct rtl_works { /*timer */ struct timer_list watchdog_timer; - struct timer_list dualmac_easyconcurrent_retrytimer; struct timer_list fw_clockoff_timer; struct timer_list fast_antenna_training_timer; /*task */ @@ -2498,14 +2494,6 @@ struct rtl_debug { #define MIMO_PS_DYNAMIC 1 #define MIMO_PS_NOLIMIT 3 -struct rtl_dualmac_easy_concurrent_ctl { - enum band_type currentbandtype_backfordmdp; - bool close_bbandrf_for_dmsp; - bool change_to_dmdp; - bool change_to_dmsp; - bool switch_in_process; -}; - struct rtl_dmsp_ctl { bool activescan_for_slaveofdmsp; bool scan_for_anothermac_fordmsp; @@ -2746,7 +2734,6 @@ struct rtl_priv { struct list_head list; struct rtl_priv *buddy_priv; struct rtl_global_var *glb_var; - struct rtl_dualmac_easy_concurrent_ctl easy_concurrent_ctl; struct rtl_dmsp_ctl dmsp_ctl; struct rtl_locks locks; struct rtl_works works; diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig index 29eb2f8e0eb798..cffad1c012499e 100644 --- a/drivers/net/wireless/realtek/rtw88/Kconfig +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -111,6 +111,17 @@ config RTW88_8723DE 802.11n PCIe wireless network adapter +config RTW88_8723DS + tristate "Realtek 8723DS SDIO wireless network adapter" + depends on MMC + select RTW88_CORE + select RTW88_SDIO + select RTW88_8723D + help + Select this option will enable support for 8723DS chipset + + 802.11n SDIO wireless network adapter + config RTW88_8723DU tristate "Realtek 8723DU USB wireless network adapter" depends on USB diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile index 82979b30ae8dd3..fd212c09d88a9e 100644 --- a/drivers/net/wireless/realtek/rtw88/Makefile +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -50,6 +50,9 @@ rtw88_8723d-objs := rtw8723d.o rtw8723d_table.o obj-$(CONFIG_RTW88_8723DE) += rtw88_8723de.o rtw88_8723de-objs := rtw8723de.o +obj-$(CONFIG_RTW88_8723DS) += rtw88_8723ds.o +rtw88_8723ds-objs := rtw8723ds.o + obj-$(CONFIG_RTW88_8723DU) += rtw88_8723du.o rtw88_8723du-objs := rtw8723du.o diff --git a/drivers/net/wireless/realtek/rtw88/mac80211.c b/drivers/net/wireless/realtek/rtw88/mac80211.c index e82e40cac60a19..09bcc2345bb052 100644 --- a/drivers/net/wireless/realtek/rtw88/mac80211.c +++ b/drivers/net/wireless/realtek/rtw88/mac80211.c @@ -88,15 +88,6 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed) } } - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (hw->conf.flags & IEEE80211_CONF_PS) { - rtwdev->ps_enabled = true; - } else { - rtwdev->ps_enabled = false; - rtw_leave_lps(rtwdev); - } - } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) rtw_set_channel(rtwdev); @@ -215,6 +206,7 @@ static int rtw_ops_add_interface(struct ieee80211_hw *hw, config |= PORT_SET_BCN_CTRL; rtw_vif_port_config(rtwdev, rtwvif, config); rtw_core_port_switch(rtwdev, vif); + rtw_recalc_lps(rtwdev, vif); mutex_unlock(&rtwdev->mutex); @@ -246,6 +238,7 @@ static void rtw_ops_remove_interface(struct ieee80211_hw *hw, config |= PORT_SET_BCN_CTRL; rtw_vif_port_config(rtwdev, rtwvif, config); clear_bit(rtwvif->port, rtwdev->hw_port); + rtw_recalc_lps(rtwdev, NULL); mutex_unlock(&rtwdev->mutex); } @@ -440,6 +433,9 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ERP_SLOT) rtw_conf_tx(rtwdev, rtwvif); + if (changed & BSS_CHANGED_PS) + rtw_recalc_lps(rtwdev, NULL); + rtw_vif_port_config(rtwdev, rtwvif, config); mutex_unlock(&rtwdev->mutex); diff --git a/drivers/net/wireless/realtek/rtw88/main.c b/drivers/net/wireless/realtek/rtw88/main.c index d30a191c9291dc..9447a3aae3b5e1 100644 --- a/drivers/net/wireless/realtek/rtw88/main.c +++ b/drivers/net/wireless/realtek/rtw88/main.c @@ -271,8 +271,8 @@ static void rtw_watch_dog_work(struct work_struct *work) * more than two stations associated to the AP, then we can not enter * lps, because fw does not handle the overlapped beacon interval * - * mac80211 should iterate vifs and determine if driver can enter - * ps by passing IEEE80211_CONF_PS to us, all we need to do is to + * rtw_recalc_lps() iterate vifs and determine if driver can enter + * ps by vif->type and vif->cfg.ps, all we need to do here is to * get that vif and check if device is having traffic more than the * threshold. */ diff --git a/drivers/net/wireless/realtek/rtw88/ps.c b/drivers/net/wireless/realtek/rtw88/ps.c index 996365575f44fe..53933fb38a3308 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.c +++ b/drivers/net/wireless/realtek/rtw88/ps.c @@ -299,3 +299,46 @@ void rtw_leave_lps_deep(struct rtw_dev *rtwdev) __rtw_leave_lps_deep(rtwdev); } + +struct rtw_vif_recalc_lps_iter_data { + struct rtw_dev *rtwdev; + struct ieee80211_vif *found_vif; + int count; +}; + +static void __rtw_vif_recalc_lps(struct rtw_vif_recalc_lps_iter_data *data, + struct ieee80211_vif *vif) +{ + if (data->count < 0) + return; + + if (vif->type != NL80211_IFTYPE_STATION) { + data->count = -1; + return; + } + + data->count++; + data->found_vif = vif; +} + +static void rtw_vif_recalc_lps_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + __rtw_vif_recalc_lps(data, vif); +} + +void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif) +{ + struct rtw_vif_recalc_lps_iter_data data = { .rtwdev = rtwdev }; + + if (new_vif) + __rtw_vif_recalc_lps(&data, new_vif); + rtw_iterate_vifs(rtwdev, rtw_vif_recalc_lps_iter, &data); + + if (data.count == 1 && data.found_vif->cfg.ps) { + rtwdev->ps_enabled = true; + } else { + rtwdev->ps_enabled = false; + rtw_leave_lps(rtwdev); + } +} diff --git a/drivers/net/wireless/realtek/rtw88/ps.h b/drivers/net/wireless/realtek/rtw88/ps.h index c194386f6db53a..5ae83d2526cfd2 100644 --- a/drivers/net/wireless/realtek/rtw88/ps.h +++ b/drivers/net/wireless/realtek/rtw88/ps.h @@ -23,4 +23,6 @@ void rtw_enter_lps(struct rtw_dev *rtwdev, u8 port_id); void rtw_leave_lps(struct rtw_dev *rtwdev); void rtw_leave_lps_deep(struct rtw_dev *rtwdev); enum rtw_lps_deep_mode rtw_get_lps_deep_mode(struct rtw_dev *rtwdev); +void rtw_recalc_lps(struct rtw_dev *rtwdev, struct ieee80211_vif *new_vif); + #endif diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 06e7454c9ca693..cadf66f4e85458 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -216,6 +216,12 @@ static void rtw8723du_efuse_parsing(struct rtw_efuse *efuse, ether_addr_copy(efuse->addr, map->u.mac_addr); } +static void rtw8723ds_efuse_parsing(struct rtw_efuse *efuse, + struct rtw8723d_efuse *map) +{ + ether_addr_copy(efuse->addr, map->s.mac_addr); +} + static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) { struct rtw_efuse *efuse = &rtwdev->efuse; @@ -248,6 +254,9 @@ static int rtw8723d_read_efuse(struct rtw_dev *rtwdev, u8 *log_map) case RTW_HCI_TYPE_USB: rtw8723du_efuse_parsing(efuse, map); break; + case RTW_HCI_TYPE_SDIO: + rtw8723ds_efuse_parsing(efuse, map); + break; default: /* unsupported now */ return -ENOTSUPP; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index a356318a5c15b2..3642a2c7f80c98 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -49,6 +49,11 @@ struct rtw8723du_efuse { u8 mac_addr[ETH_ALEN]; /* 0x107 */ }; +struct rtw8723ds_efuse { + u8 res4[0x4a]; /* 0xd0 */ + u8 mac_addr[ETH_ALEN]; /* 0x11a */ +}; + struct rtw8723d_efuse { __le16 rtl_id; u8 rsvd[2]; @@ -80,6 +85,7 @@ struct rtw8723d_efuse { union { struct rtw8723de_efuse e; struct rtw8723du_efuse u; + struct rtw8723ds_efuse s; }; }; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723ds.c b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c new file mode 100644 index 00000000000000..e5b6960ba0a02c --- /dev/null +++ b/drivers/net/wireless/realtek/rtw88/rtw8723ds.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright(c) Martin Blumenstingl + */ + +#include +#include +#include +#include "main.h" +#include "rtw8723d.h" +#include "sdio.h" + +static const struct sdio_device_id rtw_8723ds_id_table[] = { + { + SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, + SDIO_DEVICE_ID_REALTEK_RTW8723DS_1ANT), + .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec, + }, + { + SDIO_DEVICE(SDIO_VENDOR_ID_REALTEK, + SDIO_DEVICE_ID_REALTEK_RTW8723DS_2ANT), + .driver_data = (kernel_ulong_t)&rtw8723d_hw_spec, + }, + {} +}; +MODULE_DEVICE_TABLE(sdio, rtw_8723ds_id_table); + +static struct sdio_driver rtw_8723ds_driver = { + .name = "rtw_8723ds", + .probe = rtw_sdio_probe, + .remove = rtw_sdio_remove, + .id_table = rtw_8723ds_id_table, + .drv = { + .pm = &rtw_sdio_pm_ops, + .shutdown = rtw_sdio_shutdown, + } +}; +module_sdio_driver(rtw_8723ds_driver); + +MODULE_AUTHOR("Martin Blumenstingl "); +MODULE_DESCRIPTION("Realtek 802.11n wireless 8723ds driver"); +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/net/wireless/realtek/rtw88/sdio.c b/drivers/net/wireless/realtek/rtw88/sdio.c index 06fce7c3addaa3..2c1fb2dabd40a4 100644 --- a/drivers/net/wireless/realtek/rtw88/sdio.c +++ b/drivers/net/wireless/realtek/rtw88/sdio.c @@ -998,9 +998,9 @@ static void rtw_sdio_rxfifo_recv(struct rtw_dev *rtwdev, u32 rx_len) static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) { - u32 rx_len, total_rx_bytes = 0; + u32 rx_len, hisr, total_rx_bytes = 0; - while (total_rx_bytes < SZ_64K) { + do { if (rtw_chip_wcpu_11n(rtwdev)) rx_len = rtw_read16(rtwdev, REG_SDIO_RX0_REQ_LEN); else @@ -1012,7 +1012,25 @@ static void rtw_sdio_rx_isr(struct rtw_dev *rtwdev) rtw_sdio_rxfifo_recv(rtwdev, rx_len); total_rx_bytes += rx_len; - } + + if (rtw_chip_wcpu_11n(rtwdev)) { + /* Stop if no more RX requests are pending, even if + * rx_len could be greater than zero in the next + * iteration. This is needed because the RX buffer may + * already contain data while either HW or FW are not + * done filling that buffer yet. Still reading the + * buffer can result in packets where + * rtw_rx_pkt_stat.pkt_len is zero or points beyond the + * end of the buffer. + */ + hisr = rtw_read32(rtwdev, REG_SDIO_HISR); + } else { + /* RTW_WCPU_11AC chips have improved hardware or + * firmware and can use rx_len unconditionally. + */ + hisr = REG_SDIO_HISR_RX_REQUEST; + } + } while (total_rx_bytes < SZ_64K && hisr & REG_SDIO_HISR_RX_REQUEST); } static void rtw_sdio_handle_interrupt(struct sdio_func *sdio_func) diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c index 44a5fafb990551..976eafa739a2d6 100644 --- a/drivers/net/wireless/realtek/rtw88/usb.c +++ b/drivers/net/wireless/realtek/rtw88/usb.c @@ -535,7 +535,7 @@ static void rtw_usb_rx_handler(struct work_struct *work) } if (skb_queue_len(&rtwusb->rx_queue) >= RTW_USB_MAX_RXQ_LEN) { - rtw_err(rtwdev, "failed to get rx_queue, overflow\n"); + dev_dbg_ratelimited(rtwdev->dev, "failed to get rx_queue, overflow\n"); dev_kfree_skb_any(skb); continue; } diff --git a/drivers/net/wireless/realtek/rtw89/Kconfig b/drivers/net/wireless/realtek/rtw89/Kconfig index 2b20cf8bbf3aa3..90ffbab7cc4c6d 100644 --- a/drivers/net/wireless/realtek/rtw89/Kconfig +++ b/drivers/net/wireless/realtek/rtw89/Kconfig @@ -16,6 +16,9 @@ config RTW89_CORE config RTW89_PCI tristate +config RTW89_8851B + tristate + config RTW89_8852A tristate @@ -25,6 +28,17 @@ config RTW89_8852B config RTW89_8852C tristate +config RTW89_8851BE + tristate "Realtek 8851BE PCI wireless network (Wi-Fi 6) adapter" + depends on PCI + select RTW89_CORE + select RTW89_PCI + select RTW89_8851B + help + Select this option will enable support for 8851BE chipset + + 802.11ax PCIe wireless network (Wi-Fi 6) adapter + config RTW89_8852AE tristate "Realtek 8852AE PCI wireless network (Wi-Fi 6) adapter" depends on PCI diff --git a/drivers/net/wireless/realtek/rtw89/Makefile b/drivers/net/wireless/realtek/rtw89/Makefile index 99e870d6a7d7d8..41940099af1b69 100644 --- a/drivers/net/wireless/realtek/rtw89/Makefile +++ b/drivers/net/wireless/realtek/rtw89/Makefile @@ -18,6 +18,15 @@ rtw89_core-y += core.o \ rtw89_core-$(CONFIG_PM) += wow.o +obj-$(CONFIG_RTW89_8851B) += rtw89_8851b.o +rtw89_8851b-objs := rtw8851b.o \ + rtw8851b_table.o \ + rtw8851b_rfk.o \ + rtw8851b_rfk_table.o + +obj-$(CONFIG_RTW89_8851BE) += rtw89_8851be.o +rtw89_8851be-objs := rtw8851be.o + obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o rtw89_8852a-objs := rtw8852a.o \ rtw8852a_table.o \ diff --git a/drivers/net/wireless/realtek/rtw89/coex.c b/drivers/net/wireless/realtek/rtw89/coex.c index acb3fac0c96d4f..bda0e1e99a8c6b 100644 --- a/drivers/net/wireless/realtek/rtw89/coex.c +++ b/drivers/net/wireless/realtek/rtw89/coex.c @@ -127,6 +127,13 @@ static const u32 cxtbl[] = { static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { /* firmware version must be in decreasing order for each chip */ + {RTL8851B, RTW89_FW_VER_CODE(0, 29, 29, 0), + .fcxbtcrpt = 105, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 5, + .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 2, .fcxgpiodbg = 1, + .fcxbtver = 1, .fcxbtscan = 2, .fcxbtafh = 2, .fcxbtdevinfo = 1, + .fwlrole = 1, .frptmap = 3, .fcxctrl = 1, + .info_buf = 1800, .max_role_num = 6, + }, {RTL8852C, RTW89_FW_VER_CODE(0, 27, 57, 0), .fcxbtcrpt = 4, .fcxtdma = 3, .fcxslots = 1, .fcxcysta = 3, .fcxstep = 3, .fcxnullsta = 2, .fcxmreg = 1, .fcxgpiodbg = 1, @@ -199,7 +206,7 @@ static const struct rtw89_btc_ver rtw89_btc_ver_defs[] = { struct rtw89_btc_btf_tlv { u8 type; u8 len; - u8 val[1]; + u8 val[]; } __packed; enum btc_btf_set_report_en { diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c index fbcb9b6e6f754c..69b181fa296674 100644 --- a/drivers/net/wireless/realtek/rtw89/core.c +++ b/drivers/net/wireless/realtek/rtw89/core.c @@ -336,8 +336,7 @@ void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev) sub_entity_idx = RTW89_SUB_ENTITY_0; phy_idx = RTW89_PHY_0; chan = rtw89_chan_get(rtwdev, sub_entity_idx); - if (chip->ops->set_txpwr) - chip->ops->set_txpwr(rtwdev, chan, phy_idx); + chip->ops->set_txpwr(rtwdev, chan, phy_idx); } void rtw89_set_channel(struct rtw89_dev *rtwdev) @@ -373,7 +372,7 @@ void rtw89_set_channel(struct rtw89_dev *rtwdev) chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx); - rtw89_core_set_chip_txpwr(rtwdev); + chip->ops->set_txpwr(rtwdev, &chan, phy_idx); rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx); @@ -1213,14 +1212,15 @@ static int rtw89_core_rx_process_mac_ppdu(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct rtw89_rx_phy_ppdu *phy_ppdu) { + const struct rtw89_rxinfo *rxinfo = (const struct rtw89_rxinfo *)skb->data; bool rx_cnt_valid = false; u8 plcp_size = 0; u8 usr_num = 0; u8 *phy_sts; - rx_cnt_valid = RTW89_GET_RXINFO_RX_CNT_VLD(skb->data); - plcp_size = RTW89_GET_RXINFO_PLCP_LEN(skb->data) << 3; - usr_num = RTW89_GET_RXINFO_USR_NUM(skb->data); + rx_cnt_valid = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_RX_CNT_VLD); + plcp_size = le32_get_bits(rxinfo->w1, RTW89_RXINFO_W1_PLCP_LEN) << 3; + usr_num = le32_get_bits(rxinfo->w0, RTW89_RXINFO_W0_USR_NUM); if (usr_num > RTW89_PPDU_MAX_USR) { rtw89_warn(rtwdev, "Invalid user number in mac info\n"); return -EINVAL; @@ -1279,7 +1279,8 @@ static void rtw89_core_rx_process_phy_ppdu_iter(void *data, #define VAR_LEN 0xff #define VAR_LEN_UNIT 8 -static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr) +static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, + const struct rtw89_phy_sts_iehdr *iehdr) { static const u8 physts_ie_len_tab[32] = { 16, 32, 24, 24, 8, 8, 8, 8, VAR_LEN, 8, VAR_LEN, 176, VAR_LEN, @@ -1289,19 +1290,20 @@ static u16 rtw89_core_get_phy_status_ie_len(struct rtw89_dev *rtwdev, u8 *addr) u16 ie_len; u8 ie; - ie = RTW89_GET_PHY_STS_IE_TYPE(addr); + ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE); if (physts_ie_len_tab[ie] != VAR_LEN) ie_len = physts_ie_len_tab[ie]; else - ie_len = RTW89_GET_PHY_STS_IE_LEN(addr) * VAR_LEN_UNIT; + ie_len = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_LEN) * VAR_LEN_UNIT; return ie_len; } -static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, u8 *addr, +static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, + const struct rtw89_phy_sts_iehdr *iehdr, struct rtw89_rx_phy_ppdu *phy_ppdu) { - const struct rtw89_phy_sts_ie0 *ie = (const struct rtw89_phy_sts_ie0 *)addr; + const struct rtw89_phy_sts_ie0 *ie = (const struct rtw89_phy_sts_ie0 *)iehdr; s16 cfo; u32 t; @@ -1329,15 +1331,17 @@ static void rtw89_core_parse_phy_status_ie01(struct rtw89_dev *rtwdev, u8 *addr, rtw89_phy_cfo_parse(rtwdev, cfo, phy_ppdu); } -static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr, +static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, + const struct rtw89_phy_sts_iehdr *iehdr, struct rtw89_rx_phy_ppdu *phy_ppdu) { u8 ie; - ie = RTW89_GET_PHY_STS_IE_TYPE(addr); + ie = le32_get_bits(iehdr->w0, RTW89_PHY_STS_IEHDR_TYPE); + switch (ie) { case RTW89_PHYSTS_IE01_CMN_OFDM: - rtw89_core_parse_phy_status_ie01(rtwdev, addr, phy_ppdu); + rtw89_core_parse_phy_status_ie01(rtwdev, iehdr, phy_ppdu); break; default: break; @@ -1348,21 +1352,26 @@ static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev, u8 *addr, static void rtw89_core_update_phy_ppdu(struct rtw89_rx_phy_ppdu *phy_ppdu) { + const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf; u8 *rssi = phy_ppdu->rssi; - u8 *buf = phy_ppdu->buf; - phy_ppdu->ie = RTW89_GET_PHY_STS_IE_MAP(buf); - phy_ppdu->rssi_avg = RTW89_GET_PHY_STS_RSSI_AVG(buf); - rssi[RF_PATH_A] = RTW89_GET_PHY_STS_RSSI_A(buf); - rssi[RF_PATH_B] = RTW89_GET_PHY_STS_RSSI_B(buf); - rssi[RF_PATH_C] = RTW89_GET_PHY_STS_RSSI_C(buf); - rssi[RF_PATH_D] = RTW89_GET_PHY_STS_RSSI_D(buf); + phy_ppdu->ie = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_IE_MAP); + phy_ppdu->rssi_avg = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_RSSI_AVG); + rssi[RF_PATH_A] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_A); + rssi[RF_PATH_B] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_B); + rssi[RF_PATH_C] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_C); + rssi[RF_PATH_D] = le32_get_bits(hdr->w1, RTW89_PHY_STS_HDR_W1_RSSI_D); } static int rtw89_core_rx_process_phy_ppdu(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu) { - if (RTW89_GET_PHY_STS_LEN(phy_ppdu->buf) << 3 != phy_ppdu->len) { + const struct rtw89_phy_sts_hdr *hdr = phy_ppdu->buf; + u32 len_from_header; + + len_from_header = le32_get_bits(hdr->w0, RTW89_PHY_STS_HDR_W0_LEN) << 3; + + if (len_from_header != phy_ppdu->len) { rtw89_debug(rtwdev, RTW89_DBG_UNEXP, "phy ppdu len mismatch\n"); return -EINVAL; } @@ -1375,17 +1384,19 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev, struct rtw89_rx_phy_ppdu *phy_ppdu) { u16 ie_len; - u8 *pos, *end; + void *pos, *end; /* mark invalid reports and bypass them */ if (phy_ppdu->ie < RTW89_CCK_PKT) return -EINVAL; - pos = (u8 *)phy_ppdu->buf + PHY_STS_HDR_LEN; - end = (u8 *)phy_ppdu->buf + phy_ppdu->len; + pos = phy_ppdu->buf + PHY_STS_HDR_LEN; + end = phy_ppdu->buf + phy_ppdu->len; while (pos < end) { - ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, pos); - rtw89_core_process_phy_status_ie(rtwdev, pos, phy_ppdu); + const struct rtw89_phy_sts_iehdr *iehdr = pos; + + ie_len = rtw89_core_get_phy_status_ie_len(rtwdev, iehdr); + rtw89_core_process_phy_status_ie(rtwdev, iehdr, phy_ppdu); pos += ie_len; if (pos > end || ie_len == 0) { rtw89_debug(rtwdev, RTW89_DBG_TXRX, @@ -1794,43 +1805,47 @@ void rtw89_core_query_rxdesc(struct rtw89_dev *rtwdev, u8 shift_len, drv_info_len; rxd_s = (struct rtw89_rxdesc_short *)(data + data_offset); - desc_info->pkt_size = RTW89_GET_RXWD_PKT_SIZE(rxd_s); - desc_info->drv_info_size = RTW89_GET_RXWD_DRV_INFO_SIZE(rxd_s); - desc_info->long_rxdesc = RTW89_GET_RXWD_LONG_RXD(rxd_s); - desc_info->pkt_type = RTW89_GET_RXWD_RPKT_TYPE(rxd_s); - desc_info->mac_info_valid = RTW89_GET_RXWD_MAC_INFO_VALID(rxd_s); + desc_info->pkt_size = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_LEN_MASK); + desc_info->drv_info_size = le32_get_bits(rxd_s->dword0, AX_RXD_DRV_INFO_SIZE_MASK); + desc_info->long_rxdesc = le32_get_bits(rxd_s->dword0, AX_RXD_LONG_RXD); + desc_info->pkt_type = le32_get_bits(rxd_s->dword0, AX_RXD_RPKT_TYPE_MASK); + desc_info->mac_info_valid = le32_get_bits(rxd_s->dword0, AX_RXD_MAC_INFO_VLD); if (chip->chip_id == RTL8852C) - desc_info->bw = RTW89_GET_RXWD_BW_V1(rxd_s); + desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_v1_MASK); else - desc_info->bw = RTW89_GET_RXWD_BW(rxd_s); - desc_info->data_rate = RTW89_GET_RXWD_DATA_RATE(rxd_s); - desc_info->gi_ltf = RTW89_GET_RXWD_GI_LTF(rxd_s); - desc_info->user_id = RTW89_GET_RXWD_USER_ID(rxd_s); - desc_info->sr_en = RTW89_GET_RXWD_SR_EN(rxd_s); - desc_info->ppdu_cnt = RTW89_GET_RXWD_PPDU_CNT(rxd_s); - desc_info->ppdu_type = RTW89_GET_RXWD_PPDU_TYPE(rxd_s); - desc_info->free_run_cnt = RTW89_GET_RXWD_FREE_RUN_CNT(rxd_s); - desc_info->icv_err = RTW89_GET_RXWD_ICV_ERR(rxd_s); - desc_info->crc32_err = RTW89_GET_RXWD_CRC32_ERR(rxd_s); - desc_info->hw_dec = RTW89_GET_RXWD_HW_DEC(rxd_s); - desc_info->sw_dec = RTW89_GET_RXWD_SW_DEC(rxd_s); - desc_info->addr1_match = RTW89_GET_RXWD_A1_MATCH(rxd_s); + desc_info->bw = le32_get_bits(rxd_s->dword1, AX_RXD_BW_MASK); + desc_info->data_rate = le32_get_bits(rxd_s->dword1, AX_RXD_RX_DATARATE_MASK); + desc_info->gi_ltf = le32_get_bits(rxd_s->dword1, AX_RXD_RX_GI_LTF_MASK); + desc_info->user_id = le32_get_bits(rxd_s->dword1, AX_RXD_USER_ID_MASK); + desc_info->sr_en = le32_get_bits(rxd_s->dword1, AX_RXD_SR_EN); + desc_info->ppdu_cnt = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_CNT_MASK); + desc_info->ppdu_type = le32_get_bits(rxd_s->dword1, AX_RXD_PPDU_TYPE_MASK); + desc_info->free_run_cnt = le32_get_bits(rxd_s->dword2, AX_RXD_FREERUN_CNT_MASK); + desc_info->icv_err = le32_get_bits(rxd_s->dword3, AX_RXD_ICV_ERR); + desc_info->crc32_err = le32_get_bits(rxd_s->dword3, AX_RXD_CRC32_ERR); + desc_info->hw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_HW_DEC); + desc_info->sw_dec = le32_get_bits(rxd_s->dword3, AX_RXD_SW_DEC); + desc_info->addr1_match = le32_get_bits(rxd_s->dword3, AX_RXD_A1_MATCH); shift_len = desc_info->shift << 1; /* 2-byte unit */ drv_info_len = desc_info->drv_info_size << 3; /* 8-byte unit */ desc_info->offset = data_offset + shift_len + drv_info_len; + if (desc_info->long_rxdesc) + desc_info->rxd_len = sizeof(struct rtw89_rxdesc_long); + else + desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short); desc_info->ready = true; if (!desc_info->long_rxdesc) return; rxd_l = (struct rtw89_rxdesc_long *)(data + data_offset); - desc_info->frame_type = RTW89_GET_RXWD_TYPE(rxd_l); - desc_info->addr_cam_valid = RTW89_GET_RXWD_ADDR_CAM_VLD(rxd_l); - desc_info->addr_cam_id = RTW89_GET_RXWD_ADDR_CAM_ID(rxd_l); - desc_info->sec_cam_id = RTW89_GET_RXWD_SEC_CAM_ID(rxd_l); - desc_info->mac_id = RTW89_GET_RXWD_MAC_ID(rxd_l); - desc_info->rx_pl_id = RTW89_GET_RXWD_RX_PL_ID(rxd_l); + desc_info->frame_type = le32_get_bits(rxd_l->dword4, AX_RXD_TYPE_MASK); + desc_info->addr_cam_valid = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_VLD); + desc_info->addr_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_ADDR_CAM_MASK); + desc_info->sec_cam_id = le32_get_bits(rxd_l->dword5, AX_RXD_SEC_CAM_IDX_MASK); + desc_info->mac_id = le32_get_bits(rxd_l->dword5, AX_RXD_MAC_ID_MASK); + desc_info->rx_pl_id = le32_get_bits(rxd_l->dword5, AX_RXD_RX_PL_ID_MASK); } EXPORT_SYMBOL(rtw89_core_query_rxdesc); @@ -2603,9 +2618,6 @@ static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwv rtwvif->tdls_peer) return; - if (rtwdev->total_sta_assoc > 1) - return; - if (rtwvif->offchan) return; @@ -2857,6 +2869,8 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev, if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { /* for station mode, assign the mac_id from itself */ rtwsta->mac_id = rtwvif->mac_id; + /* must do rtw89_reg_6ghz_power_recalc() before rfk channel */ + rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, true); rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, BTC_ROLE_MSTS_STA_CONN_START); rtw89_chip_rfk_channel(rtwdev); @@ -3030,10 +3044,11 @@ int rtw89_core_sta_remove(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv; int ret; - if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) + if (vif->type == NL80211_IFTYPE_STATION && !sta->tdls) { + rtw89_reg_6ghz_power_recalc(rtwdev, rtwvif, false); rtw89_btc_ntfy_role_info(rtwdev, rtwvif, rtwsta, BTC_ROLE_MSTS_STA_DIS_CONN); - else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { + } else if (vif->type == NL80211_IFTYPE_AP || sta->tdls) { rtw89_core_release_bit_map(rtwdev->mac_id_map, rtwsta->mac_id); ret = rtw89_fw_h2c_role_maintain(rtwdev, rtwvif, rtwsta, @@ -3374,8 +3389,10 @@ static void rtw89_core_clr_supported_band(struct rtw89_dev *rtwdev) { struct ieee80211_hw *hw = rtwdev->hw; - kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); - kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); + if (hw->wiphy->bands[NL80211_BAND_2GHZ]) + kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]->iftype_data); + if (hw->wiphy->bands[NL80211_BAND_5GHZ]) + kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]->iftype_data); if (hw->wiphy->bands[NL80211_BAND_6GHZ]) kfree(hw->wiphy->bands[NL80211_BAND_6GHZ]->iftype_data); kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]); diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h index b60cd9852259ea..7e1e508956c897 100644 --- a/drivers/net/wireless/realtek/rtw89/core.h +++ b/drivers/net/wireless/realtek/rtw89/core.h @@ -488,6 +488,15 @@ enum rtw89_regulation_type { RTW89_REGD_NUM, }; +enum rtw89_reg_6ghz_power { + RTW89_REG_6GHZ_POWER_VLP = 0, + RTW89_REG_6GHZ_POWER_LPI = 1, + RTW89_REG_6GHZ_POWER_STD = 2, + + NUM_OF_RTW89_REG_6GHZ_POWER, + RTW89_REG_6GHZ_POWER_DFLT = RTW89_REG_6GHZ_POWER_VLP, +}; + enum rtw89_fw_pkt_ofld_type { RTW89_PKT_OFLD_TYPE_PROBE_RSP = 0, RTW89_PKT_OFLD_TYPE_PS_POLL = 1, @@ -550,7 +559,7 @@ struct rtw89_rate_desc { #define RF_PATH_MAX 4 #define RTW89_MAX_PPDU_CNT 8 struct rtw89_rx_phy_ppdu { - u8 *buf; + void *buf; u32 len; u8 rssi_avg; u8 rssi[RF_PATH_MAX]; @@ -776,6 +785,7 @@ struct rtw89_rx_desc_info { u8 sec_cam_id; u8 mac_id; u16 offset; + u16 rxd_len; bool ready; }; @@ -2681,6 +2691,7 @@ struct rtw89_vif { struct rtw89_dev *rtwdev; struct rtw89_roc roc; enum rtw89_sub_entity_idx sub_entity_idx; + enum rtw89_reg_6ghz_power reg_6ghz_power; u8 mac_id; u8 port; @@ -2799,6 +2810,7 @@ struct rtw89_chip_ops { int (*read_efuse)(struct rtw89_dev *rtwdev, u8 *log_map); int (*read_phycap)(struct rtw89_dev *rtwdev, u8 *phycap_map); void (*fem_setup)(struct rtw89_dev *rtwdev); + void (*rfe_gpio)(struct rtw89_dev *rtwdev); void (*rfk_init)(struct rtw89_dev *rtwdev); void (*rfk_channel)(struct rtw89_dev *rtwdev); void (*rfk_band_changed)(struct rtw89_dev *rtwdev, @@ -2823,6 +2835,9 @@ struct rtw89_chip_ops { s8 pw_ofst, enum rtw89_mac_idx mac_idx); int (*pwr_on_func)(struct rtw89_dev *rtwdev); int (*pwr_off_func)(struct rtw89_dev *rtwdev); + void (*query_rxdesc)(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + u8 *data, u32 data_offset); void (*fill_txdesc)(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, void *txdesc); @@ -3031,9 +3046,11 @@ struct rtw89_txpwr_rule_5ghz { struct rtw89_txpwr_rule_6ghz { const s8 (*lmt)[RTW89_6G_BW_NUM][RTW89_NTX_NUM] [RTW89_RS_LMT_NUM][RTW89_BF_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM]; + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM]; const s8 (*lmt_ru)[RTW89_RU_NUM][RTW89_NTX_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM]; + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM]; }; struct rtw89_rfe_parms { @@ -3504,6 +3521,7 @@ enum rtw89_flags { RTW89_FLAG_LOW_POWER_MODE, RTW89_FLAG_INACTIVE_PS, RTW89_FLAG_CRASH_SIMULATING, + RTW89_FLAG_SER_HANDLING, RTW89_FLAG_WOWLAN, RTW89_FLAG_FORBIDDEN_TRACK_WROK, RTW89_FLAG_CHANGING_INTERFACE, @@ -3801,11 +3819,16 @@ struct rtw89_power_trim_info { u8 pa_bias_trim[RF_PATH_MAX]; }; -struct rtw89_regulatory { +struct rtw89_regd { char alpha2[3]; u8 txpwr_regd[RTW89_BAND_MAX]; }; +struct rtw89_regulatory_info { + const struct rtw89_regd *regd; + enum rtw89_reg_6ghz_power reg_6ghz_power; +}; + enum rtw89_ifs_clm_application { RTW89_IFS_CLM_INIT = 0, RTW89_IFS_CLM_BACKGROUND = 1, @@ -4155,7 +4178,7 @@ struct rtw89_dev { u8 total_sta_assoc; bool scanning; - const struct rtw89_regulatory *regd; + struct rtw89_regulatory_info regulatory; struct rtw89_sar_info sar; struct rtw89_btc btc; @@ -4700,6 +4723,14 @@ static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev) chip->ops->fem_setup(rtwdev); } +static inline void rtw89_chip_rfe_gpio(struct rtw89_dev *rtwdev) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + if (chip->ops->rfe_gpio) + chip->ops->rfe_gpio(rtwdev); +} + static inline void rtw89_chip_bb_sethw(struct rtw89_dev *rtwdev) { const struct rtw89_chip_info *chip = rtwdev->chip; @@ -4834,7 +4865,9 @@ static inline void rtw89_load_txpwr_table(struct rtw89_dev *rtwdev, static inline u8 rtw89_regd_get(struct rtw89_dev *rtwdev, u8 band) { - return rtwdev->regd->txpwr_regd[band]; + const struct rtw89_regd *regd = rtwdev->regulatory.regd; + + return regd->txpwr_regd[band]; } static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) @@ -4845,6 +4878,16 @@ static inline void rtw89_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) chip->ops->ctrl_btg(rtwdev, btg); } +static inline +void rtw89_chip_query_rxdesc(struct rtw89_dev *rtwdev, + struct rtw89_rx_desc_info *desc_info, + u8 *data, u32 data_offset) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + + chip->ops->query_rxdesc(rtwdev, desc_info, data, data_offset); +} + static inline void rtw89_chip_fill_txdesc(struct rtw89_dev *rtwdev, struct rtw89_tx_desc_info *desc_info, @@ -5066,5 +5109,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif, const u8 *mac_addr, bool hw_scan); void rtw89_core_scan_complete(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif, bool hw_scan); +void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool active); #endif diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c index 6f418f14ec3fe7..1db2d59d33ff70 100644 --- a/drivers/net/wireless/realtek/rtw89/debug.c +++ b/drivers/net/wireless/realtek/rtw89/debug.c @@ -30,7 +30,7 @@ struct rtw89_debugfs_priv { u32 cb_data; struct { u32 addr; - u8 len; + u32 len; } read_reg; struct { u32 addr; @@ -164,12 +164,15 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v) { struct rtw89_debugfs_priv *debugfs_priv = m->private; struct rtw89_dev *rtwdev = debugfs_priv->rtwdev; - u32 addr, data; - u8 len; + u32 addr, end, data, k; + u32 len; len = debugfs_priv->read_reg.len; addr = debugfs_priv->read_reg.addr; + if (len > 4) + goto ndata; + switch (len) { case 1: data = rtw89_read8(rtwdev, addr); @@ -187,6 +190,20 @@ static int rtw89_debug_priv_read_reg_get(struct seq_file *m, void *v) seq_printf(m, "get %d bytes at 0x%08x=0x%08x\n", len, addr, data); + return 0; + +ndata: + end = addr + len; + + for (; addr < end; addr += 16) { + seq_printf(m, "%08xh : ", 0x18600000 + addr); + for (k = 0; k < 16; k += 4) { + data = rtw89_read32(rtwdev, addr + k); + seq_printf(m, "%08x ", data); + } + seq_puts(m, "\n"); + } + return 0; } @@ -359,6 +376,7 @@ struct txpwr_map { u8 size; u32 addr_from; u32 addr_to; + u32 addr_to_1ss; }; #define __GEN_TXPWR_ENT2(_t, _e0, _e1) \ @@ -396,6 +414,7 @@ static const struct txpwr_map __txpwr_map_byr = { .size = ARRAY_SIZE(__txpwr_ent_byr), .addr_from = R_AX_PWR_BY_RATE, .addr_to = R_AX_PWR_BY_RATE_MAX, + .addr_to_1ss = R_AX_PWR_BY_RATE_1SS_MAX, }; static const struct txpwr_ent __txpwr_ent_lmt[] = { @@ -451,6 +470,7 @@ static const struct txpwr_map __txpwr_map_lmt = { .size = ARRAY_SIZE(__txpwr_ent_lmt), .addr_from = R_AX_PWR_LMT, .addr_to = R_AX_PWR_LMT_MAX, + .addr_to_1ss = R_AX_PWR_LMT_1SS_MAX, }; static const struct txpwr_ent __txpwr_ent_lmt_ru[] = { @@ -478,6 +498,7 @@ static const struct txpwr_map __txpwr_map_lmt_ru = { .size = ARRAY_SIZE(__txpwr_ent_lmt_ru), .addr_from = R_AX_PWR_RU_LMT, .addr_to = R_AX_PWR_RU_LMT_MAX, + .addr_to_1ss = R_AX_PWR_RU_LMT_1SS_MAX, }; static u8 __print_txpwr_ent(struct seq_file *m, const struct txpwr_ent *ent, @@ -510,6 +531,8 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev, const struct txpwr_map *map) { u8 fct = rtwdev->chip->txpwr_factor_mac; + u8 path_num = rtwdev->chip->rf_path_num; + u32 max_valid_addr; u32 val, addr; s8 *buf, tmp; u8 cur, i; @@ -519,7 +542,12 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev, if (!buf) return -ENOMEM; - for (addr = map->addr_from; addr <= map->addr_to; addr += 4) { + if (path_num == 1) + max_valid_addr = map->addr_to_1ss; + else + max_valid_addr = map->addr_to; + + for (addr = map->addr_from; addr <= max_valid_addr; addr += 4) { ret = rtw89_mac_txpwr_read32(rtwdev, RTW89_PHY_0, addr, &val); if (ret) val = MASKDWORD; diff --git a/drivers/net/wireless/realtek/rtw89/efuse.c b/drivers/net/wireless/realtek/rtw89/efuse.c index 7bd4f8558e03b6..2aaf4d013e4645 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.c +++ b/drivers/net/wireless/realtek/rtw89/efuse.c @@ -7,6 +7,10 @@ #include "mac.h" #include "reg.h" +#define EF_FV_OFSET 0x5ea +#define EF_CV_MASK GENMASK(7, 4) +#define EF_CV_INV 15 + enum rtw89_efuse_bank { RTW89_EFUSE_BANK_WIFI, RTW89_EFUSE_BANK_BT, @@ -328,3 +332,20 @@ int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev) return ret; } + +int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *ecv) +{ + int ret; + u8 val; + + ret = rtw89_dump_physical_efuse_map(rtwdev, &val, EF_FV_OFSET, 1, false); + if (ret) + return ret; + + *ecv = u8_get_bits(val, EF_CV_MASK); + if (*ecv == EF_CV_INV) + return -ENOENT; + + return 0; +} +EXPORT_SYMBOL(rtw89_read_efuse_ver); diff --git a/drivers/net/wireless/realtek/rtw89/efuse.h b/drivers/net/wireless/realtek/rtw89/efuse.h index 622ff95e74763a..79071aff28de38 100644 --- a/drivers/net/wireless/realtek/rtw89/efuse.h +++ b/drivers/net/wireless/realtek/rtw89/efuse.h @@ -9,5 +9,6 @@ int rtw89_parse_efuse_map(struct rtw89_dev *rtwdev); int rtw89_parse_phycap_map(struct rtw89_dev *rtwdev); +int rtw89_read_efuse_ver(struct rtw89_dev *rtwdev, u8 *efv); #endif diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c index ad277f22b1973e..65202f82e3beaf 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.c +++ b/drivers/net/wireless/realtek/rtw89/fw.c @@ -256,6 +256,9 @@ struct __fw_feat_cfg { } static const struct __fw_feat_cfg fw_feat_tbl[] = { + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, TX_WAKE), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 37, 1, SCAN_OFFLOAD), + __CFG_FW_FEAT(RTL8851B, ge, 0, 29, 41, 0, CRASH_TRIGGER), __CFG_FW_FEAT(RTL8852A, le, 0, 13, 29, 0, OLD_HT_RA_FORMAT), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, SCAN_OFFLOAD), __CFG_FW_FEAT(RTL8852A, ge, 0, 13, 35, 0, TX_WAKE), @@ -2467,7 +2470,7 @@ int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id) cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(id, RTW89_PKT_OFLD_OP_DEL); ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond); - if (ret) { + if (ret < 0) { rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to del pkt ofld: id %d, ret %d\n", id, ret); @@ -2517,7 +2520,7 @@ int rtw89_fw_h2c_add_pkt_offload(struct rtw89_dev *rtwdev, u8 *id, cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(alloc_id, RTW89_PKT_OFLD_OP_ADD); ret = rtw89_h2c_tx_and_wait(rtwdev, skb, wait, cond); - if (ret) { + if (ret < 0) { rtw89_debug(rtwdev, RTW89_DBG_FW, "failed to add pkt ofld: id %d, ret %d\n", alloc_id, ret); @@ -2916,12 +2919,13 @@ static int rtw89_fw_write_h2c_reg(struct rtw89_dev *rtwdev, } len = DIV_ROUND_UP(info->content_len + RTW89_H2CREG_HDR_LEN, - sizeof(info->h2creg[0])); + sizeof(info->u.h2creg[0])); + + u32p_replace_bits(&info->u.hdr.w0, info->id, RTW89_H2CREG_HDR_FUNC_MASK); + u32p_replace_bits(&info->u.hdr.w0, len, RTW89_H2CREG_HDR_LEN_MASK); - RTW89_SET_H2CREG_HDR_FUNC(&info->h2creg[0], info->id); - RTW89_SET_H2CREG_HDR_LEN(&info->h2creg[0], len); for (i = 0; i < RTW89_H2CREG_MAX; i++) - rtw89_write32(rtwdev, h2c_reg[i], info->h2creg[i]); + rtw89_write32(rtwdev, h2c_reg[i], info->u.h2creg[i]); fw_info->h2c_counter++; rtw89_write8_mask(rtwdev, chip->h2c_counter_reg.addr, @@ -2951,13 +2955,14 @@ static int rtw89_fw_read_c2h_reg(struct rtw89_dev *rtwdev, } for (i = 0; i < RTW89_C2HREG_MAX; i++) - info->c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]); + info->u.c2hreg[i] = rtw89_read32(rtwdev, c2h_reg[i]); rtw89_write8(rtwdev, chip->c2h_ctrl_reg, 0); - info->id = RTW89_GET_C2H_HDR_FUNC(*info->c2hreg); - info->content_len = (RTW89_GET_C2H_HDR_LEN(*info->c2hreg) << 2) - - RTW89_C2HREG_HDR_LEN; + info->id = u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_FUNC_MASK); + info->content_len = + (u32_get_bits(info->u.hdr.w0, RTW89_C2HREG_HDR_LEN_MASK) << 2) - + RTW89_C2HREG_HDR_LEN; fw_info->c2h_counter++; rtw89_write8_mask(rtwdev, chip->c2h_counter_reg.addr, @@ -3792,6 +3797,11 @@ int rtw89_fw_wow_cam_update(struct rtw89_dev *rtwdev, return ret; } +/* Return < 0, if failures happen during waiting for the condition. + * Return 0, when waiting for the condition succeeds. + * Return > 0, if the wait is considered unreachable due to driver/FW design, + * where 1 means during SER. + */ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, struct rtw89_wait_info *wait, unsigned int cond) { @@ -3804,6 +3814,9 @@ static int rtw89_h2c_tx_and_wait(struct rtw89_dev *rtwdev, struct sk_buff *skb, return -EBUSY; } + if (test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags)) + return 1; + return rtw89_wait_for_cond(wait, cond); } diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h index 048283750a2d2e..78d808f1e8c849 100644 --- a/drivers/net/wireless/realtek/rtw89/fw.h +++ b/drivers/net/wireless/realtek/rtw89/fw.h @@ -18,15 +18,51 @@ enum rtw89_fw_dl_status { RTW89_FWDL_WCPU_FW_INIT_RDY = 7 }; -#define RTW89_GET_C2H_HDR_FUNC(info) \ - u32_get_bits(info, GENMASK(6, 0)) -#define RTW89_GET_C2H_HDR_LEN(info) \ - u32_get_bits(info, GENMASK(11, 8)) +struct rtw89_c2hreg_hdr { + u32 w0; +}; + +#define RTW89_C2HREG_HDR_FUNC_MASK GENMASK(6, 0) +#define RTW89_C2HREG_HDR_ACK BIT(7) +#define RTW89_C2HREG_HDR_LEN_MASK GENMASK(11, 8) +#define RTW89_C2HREG_HDR_SEQ_MASK GENMASK(15, 12) + +struct rtw89_c2hreg_phycap { + u32 w0; + u32 w1; + u32 w2; + u32 w3; +} __packed; + +#define RTW89_C2HREG_PHYCAP_W0_FUNC GENMASK(6, 0) +#define RTW89_C2HREG_PHYCAP_W0_ACK BIT(7) +#define RTW89_C2HREG_PHYCAP_W0_LEN GENMASK(11, 8) +#define RTW89_C2HREG_PHYCAP_W0_SEQ GENMASK(15, 12) +#define RTW89_C2HREG_PHYCAP_W0_RX_NSS GENMASK(23, 16) +#define RTW89_C2HREG_PHYCAP_W0_BW GENMASK(31, 24) +#define RTW89_C2HREG_PHYCAP_W1_TX_NSS GENMASK(7, 0) +#define RTW89_C2HREG_PHYCAP_W1_PROT GENMASK(15, 8) +#define RTW89_C2HREG_PHYCAP_W1_NIC GENMASK(23, 16) +#define RTW89_C2HREG_PHYCAP_W1_WL_FUNC GENMASK(31, 24) +#define RTW89_C2HREG_PHYCAP_W2_HW_TYPE GENMASK(7, 0) +#define RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM GENMASK(15, 8) +#define RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM GENMASK(23, 16) + +struct rtw89_h2creg_hdr { + u32 w0; +}; + +#define RTW89_H2CREG_HDR_FUNC_MASK GENMASK(6, 0) +#define RTW89_H2CREG_HDR_LEN_MASK GENMASK(11, 8) -#define RTW89_SET_H2CREG_HDR_FUNC(info, val) \ - u32p_replace_bits(info, val, GENMASK(6, 0)) -#define RTW89_SET_H2CREG_HDR_LEN(info, val) \ - u32p_replace_bits(info, val, GENMASK(11, 8)) +struct rtw89_h2creg_sch_tx_en { + u32 w0; + u32 w1; +} __packed; + +#define RTW89_H2CREG_SCH_TX_EN_W0_EN GENMASK(31, 16) +#define RTW89_H2CREG_SCH_TX_EN_W1_MASK GENMASK(15, 0) +#define RTW89_H2CREG_SCH_TX_EN_W1_BAND BIT(16) #define RTW89_H2CREG_MAX 4 #define RTW89_C2HREG_MAX 4 @@ -36,13 +72,21 @@ enum rtw89_fw_dl_status { struct rtw89_mac_c2h_info { u8 id; u8 content_len; - u32 c2hreg[RTW89_C2HREG_MAX]; + union { + u32 c2hreg[RTW89_C2HREG_MAX]; + struct rtw89_c2hreg_hdr hdr; + struct rtw89_c2hreg_phycap phycap; + } u; }; struct rtw89_mac_h2c_info { u8 id; u8 content_len; - u32 h2creg[RTW89_H2CREG_MAX]; + union { + u32 h2creg[RTW89_H2CREG_MAX]; + struct rtw89_h2creg_hdr hdr; + struct rtw89_h2creg_sch_tx_en sch_tx_en; + } u; }; enum rtw89_mac_h2c_type { @@ -63,33 +107,6 @@ enum rtw89_mac_c2h_type { RTW89_FWCMD_C2HREG_FUNC_NULL = 0xFF }; -#define RTW89_GET_C2H_PHYCAP_FUNC(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(6, 0)) -#define RTW89_GET_C2H_PHYCAP_ACK(info) \ - u32_get_bits(*((const u32 *)(info)), BIT(7)) -#define RTW89_GET_C2H_PHYCAP_LEN(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(11, 8)) -#define RTW89_GET_C2H_PHYCAP_SEQ(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(15, 12)) -#define RTW89_GET_C2H_PHYCAP_RX_NSS(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(23, 16)) -#define RTW89_GET_C2H_PHYCAP_BW(info) \ - u32_get_bits(*((const u32 *)(info)), GENMASK(31, 24)) -#define RTW89_GET_C2H_PHYCAP_TX_NSS(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(7, 0)) -#define RTW89_GET_C2H_PHYCAP_PROT(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(15, 8)) -#define RTW89_GET_C2H_PHYCAP_NIC(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(23, 16)) -#define RTW89_GET_C2H_PHYCAP_WL_FUNC(info) \ - u32_get_bits(*((const u32 *)(info) + 1), GENMASK(31, 24)) -#define RTW89_GET_C2H_PHYCAP_HW_TYPE(info) \ - u32_get_bits(*((const u32 *)(info) + 2), GENMASK(7, 0)) -#define RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(info) \ - u32_get_bits(*((const u32 *)(info) + 3), GENMASK(15, 8)) -#define RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(info) \ - u32_get_bits(*((const u32 *)(info) + 3), GENMASK(23, 16)) - enum rtw89_fw_c2h_category { RTW89_C2H_CAT_TEST, RTW89_C2H_CAT_MAC, @@ -214,17 +231,6 @@ struct rtw89_fw_macid_pause_grp { __le32 mask_grp[4]; } __packed; -struct rtw89_h2creg_sch_tx_en { - u8 func:7; - u8 ack:1; - u8 total_len:4; - u8 seq_num:4; - u16 tx_en:16; - u16 mask:16; - u8 band:1; - u16 rsvd:15; -} __packed; - #define RTW89_H2C_MAX_SIZE 2048 #define RTW89_CHANNEL_TIME 45 #define RTW89_CHANNEL_TIME_6G 20 @@ -237,7 +243,7 @@ struct rtw89_h2creg_sch_tx_en { #define RTW89_SCANOFLD_MAX_IE_LEN 512 #define RTW89_SCANOFLD_PKT_NONE 0xFF #define RTW89_SCANOFLD_DEBUG_MASK 0x1F -#define RTW89_MAC_CHINFO_SIZE 24 +#define RTW89_MAC_CHINFO_SIZE 28 #define RTW89_SCAN_LIST_GUARD 4 #define RTW89_SCAN_LIST_LIMIT \ ((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD) diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c index 0833a9eb88f37d..49d59346826566 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.c +++ b/drivers/net/wireless/realtek/rtw89/mac.c @@ -2650,6 +2650,7 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) struct rtw89_hal *hal = &rtwdev->hal; const struct rtw89_chip_info *chip = rtwdev->chip; struct rtw89_mac_c2h_info c2h_info = {0}; + const struct rtw89_c2hreg_phycap *phycap; u8 tx_nss; u8 rx_nss; u8 tx_ant; @@ -2660,10 +2661,12 @@ int rtw89_mac_setup_phycap(struct rtw89_dev *rtwdev) if (ret) return ret; - tx_nss = RTW89_GET_C2H_PHYCAP_TX_NSS(c2h_info.c2hreg); - rx_nss = RTW89_GET_C2H_PHYCAP_RX_NSS(c2h_info.c2hreg); - tx_ant = RTW89_GET_C2H_PHYCAP_ANT_TX_NUM(c2h_info.c2hreg); - rx_ant = RTW89_GET_C2H_PHYCAP_ANT_RX_NUM(c2h_info.c2hreg); + phycap = &c2h_info.u.phycap; + + tx_nss = u32_get_bits(phycap->w1, RTW89_C2HREG_PHYCAP_W1_TX_NSS); + rx_nss = u32_get_bits(phycap->w0, RTW89_C2HREG_PHYCAP_W0_RX_NSS); + tx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_TX_NUM); + rx_ant = u32_get_bits(phycap->w3, RTW89_C2HREG_PHYCAP_W3_ANT_RX_NUM); hal->tx_nss = tx_nss ? min_t(u8, tx_nss, chip->tx_nss) : chip->tx_nss; hal->rx_nss = rx_nss ? min_t(u8, rx_nss, chip->rx_nss) : chip->rx_nss; @@ -2704,14 +2707,14 @@ static int rtw89_hw_sch_tx_en_h2c(struct rtw89_dev *rtwdev, u8 band, u32 ret; struct rtw89_mac_c2h_info c2h_info = {0}; struct rtw89_mac_h2c_info h2c_info = {0}; - struct rtw89_h2creg_sch_tx_en *h2creg = - (struct rtw89_h2creg_sch_tx_en *)h2c_info.h2creg; + struct rtw89_h2creg_sch_tx_en *sch_tx_en = &h2c_info.u.sch_tx_en; h2c_info.id = RTW89_FWCMD_H2CREG_FUNC_SCH_TX_EN; - h2c_info.content_len = sizeof(*h2creg) - RTW89_H2CREG_HDR_LEN; - h2creg->tx_en = tx_en_u16; - h2creg->mask = mask_u16; - h2creg->band = band; + h2c_info.content_len = sizeof(*sch_tx_en) - RTW89_H2CREG_HDR_LEN; + + u32p_replace_bits(&sch_tx_en->w0, tx_en_u16, RTW89_H2CREG_SCH_TX_EN_W0_EN); + u32p_replace_bits(&sch_tx_en->w1, mask_u16, RTW89_H2CREG_SCH_TX_EN_W1_MASK); + u32p_replace_bits(&sch_tx_en->w1, band, RTW89_H2CREG_SCH_TX_EN_W1_BAND); ret = rtw89_fw_msg_reg(rtwdev, &h2c_info, &c2h_info); if (ret) @@ -4460,6 +4463,9 @@ rtw89_mac_c2h_pkt_ofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb_c2h, struct rtw89_completion_data data = {}; unsigned int cond; + rtw89_debug(rtwdev, RTW89_DBG_FW, "pkt ofld rsp: id %d op %d len %d\n", + pkt_id, pkt_op, pkt_len); + data.err = !pkt_len; cond = RTW89_FW_OFLD_WAIT_COND_PKT_OFLD(pkt_id, pkt_op); diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h index 0f380b6fb97ba8..0e1570451c2c5f 100644 --- a/drivers/net/wireless/realtek/rtw89/mac.h +++ b/drivers/net/wireless/realtek/rtw89/mac.h @@ -1118,6 +1118,8 @@ enum rtw89_mac_xtal_si_offset { XTAL_SI_PWR_CUT = 0x10, #define XTAL_SI_SMALL_PWR_CUT BIT(0) #define XTAL_SI_BIG_PWR_CUT BIT(1) + XTAL_SI_XTAL_DRV = 0x15, +#define XTAL_SI_DRV_LATCH BIT(4) XTAL_SI_XTAL_XMD_2 = 0x24, #define XTAL_SI_LDO_LPS GENMASK(6, 4) XTAL_SI_XTAL_XMD_4 = 0x26, diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c index f40d70f016e4cd..a66503eb35b807 100644 --- a/drivers/net/wireless/realtek/rtw89/mac80211.c +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c @@ -89,15 +89,6 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed) !(hw->conf.flags & IEEE80211_CONF_IDLE)) rtw89_leave_ips(rtwdev); - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (hw->conf.flags & IEEE80211_CONF_PS) { - rtwdev->lps_enabled = true; - } else { - rtw89_leave_lps(rtwdev); - rtwdev->lps_enabled = false; - } - } - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &hw->conf.chandef); @@ -155,6 +146,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, rtwvif->phy_idx = RTW89_PHY_0; rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0; rtwvif->hit_rule = 0; + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; ether_addr_copy(rtwvif->mac_addr, vif->addr); INIT_LIST_HEAD(&rtwvif->general_pkt_list); @@ -168,6 +160,8 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw, rtw89_core_txq_init(rtwdev, vif->txq); rtw89_btc_ntfy_role_info(rtwdev, rtwvif, NULL, BTC_ROLE_START); + + rtw89_recalc_lps(rtwdev); out: mutex_unlock(&rtwdev->mutex); @@ -192,6 +186,7 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw, rtw89_mac_remove_vif(rtwdev, rtwvif); rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); list_del_init(&rtwvif->list); + rtw89_recalc_lps(rtwdev); rtw89_enter_ips_by_hwflags(rtwdev); mutex_unlock(&rtwdev->mutex); @@ -451,6 +446,9 @@ static void rtw89_ops_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_CQM) rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, vif, true); + if (changed & BSS_CHANGED_PS) + rtw89_recalc_lps(rtwdev); + mutex_unlock(&rtwdev->mutex); } @@ -460,8 +458,16 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw, { struct rtw89_dev *rtwdev = hw->priv; struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv; + const struct rtw89_chan *chan; mutex_lock(&rtwdev->mutex); + + chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); + if (chan->band_type == RTW89_BAND_6G) { + mutex_unlock(&rtwdev->mutex); + return -EOPNOTSUPP; + } + ether_addr_copy(rtwvif->bssid, vif->bss_conf.bssid); rtw89_cam_bssid_changed(rtwdev, rtwvif); rtw89_mac_port_update(rtwdev, rtwvif); diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c index 92bfef942d3a93..9402f1a0caea8a 100644 --- a/drivers/net/wireless/realtek/rtw89/pci.c +++ b/drivers/net/wireless/realtek/rtw89/pci.c @@ -265,7 +265,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev, goto err_sync_device; } - rtw89_core_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size); + rtw89_chip_query_rxdesc(rtwdev, desc_info, skb->data, rxinfo_size); new = rtw89_alloc_skb_for_rx(rtwdev, desc_info->pkt_size); if (!new) @@ -274,9 +274,7 @@ static u32 rtw89_pci_rxbd_deliver_skbs(struct rtw89_dev *rtwdev, rx_ring->diliver_skb = new; /* first segment has RX desc */ - offset = desc_info->offset; - offset += desc_info->long_rxdesc ? sizeof(struct rtw89_rxdesc_long) : - sizeof(struct rtw89_rxdesc_short); + offset = desc_info->offset + desc_info->rxd_len; } else { offset = sizeof(struct rtw89_pci_rxbd_info); if (!new) { @@ -546,12 +544,10 @@ static u32 rtw89_pci_release_tx_skbs(struct rtw89_dev *rtwdev, return cnt; } - rtw89_core_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size); + rtw89_chip_query_rxdesc(rtwdev, &desc_info, skb->data, rxinfo_size); /* first segment has RX desc */ - offset = desc_info.offset; - offset += desc_info.long_rxdesc ? sizeof(struct rtw89_rxdesc_long) : - sizeof(struct rtw89_rxdesc_short); + offset = desc_info.offset + desc_info.rxd_len; for (; offset + rpp_size <= rx_info->len; offset += rpp_size) { rpp = (struct rtw89_pci_rpp_fmt *)(skb->data + offset); rtw89_pci_release_rpp(rtwdev, rpp); diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c index 568488da3ff15d..e2eb9422a6bb72 100644 --- a/drivers/net/wireless/realtek/rtw89/phy.c +++ b/drivers/net/wireless/realtek/rtw89/phy.c @@ -1626,8 +1626,10 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz; const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz; const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz; + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); + u8 reg6 = regulatory->reg_6ghz_power; s8 lmt = 0, sar; switch (band) { @@ -1646,11 +1648,13 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band, lmt = (*rule_5ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx]; break; case RTW89_BAND_6G: - lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][ch_idx]; + lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][regd][reg6][ch_idx]; if (lmt) break; - lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW][ch_idx]; + lmt = (*rule_6ghz->lmt)[bw][ntx][rs][bf][RTW89_WW] + [RTW89_REG_6GHZ_POWER_DFLT] + [ch_idx]; break; default: rtw89_warn(rtwdev, "unknown band type: %d\n", band); @@ -1877,8 +1881,10 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, const struct rtw89_txpwr_rule_2ghz *rule_2ghz = &rfe_parms->rule_2ghz; const struct rtw89_txpwr_rule_5ghz *rule_5ghz = &rfe_parms->rule_5ghz; const struct rtw89_txpwr_rule_6ghz *rule_6ghz = &rfe_parms->rule_6ghz; + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch); u8 regd = rtw89_regd_get(rtwdev, band); + u8 reg6 = regulatory->reg_6ghz_power; s8 lmt_ru = 0, sar; switch (band) { @@ -1897,11 +1903,13 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band, lmt_ru = (*rule_5ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx]; break; case RTW89_BAND_6G: - lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][ch_idx]; + lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][regd][reg6][ch_idx]; if (lmt_ru) break; - lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW][ch_idx]; + lmt_ru = (*rule_6ghz->lmt_ru)[ru][ntx][RTW89_WW] + [RTW89_REG_6GHZ_POWER_DFLT] + [ch_idx]; break; default: rtw89_warn(rtwdev, "unknown band type: %d\n", band); @@ -4399,6 +4407,7 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev) rtw89_phy_cfo_init(rtwdev); rtw89_phy_ul_tb_info_init(rtwdev); rtw89_phy_antdiv_init(rtwdev); + rtw89_chip_rfe_gpio(rtwdev); rtw89_phy_antdiv_set_ant(rtwdev); rtw89_phy_init_rf_nctl(rtwdev); diff --git a/drivers/net/wireless/realtek/rtw89/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c index fa94335f699aa4..84201ef19c176c 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.c +++ b/drivers/net/wireless/realtek/rtw89/ps.c @@ -252,3 +252,29 @@ void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif) rtw89_p2p_disable_all_noa(rtwdev, vif); rtw89_p2p_update_noa(rtwdev, vif); } + +void rtw89_recalc_lps(struct rtw89_dev *rtwdev) +{ + struct ieee80211_vif *vif, *found_vif = NULL; + struct rtw89_vif *rtwvif; + int count = 0; + + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + vif = rtwvif_to_vif(rtwvif); + + if (vif->type != NL80211_IFTYPE_STATION) { + count = 0; + break; + } + + count++; + found_vif = vif; + } + + if (count == 1 && found_vif->cfg.ps) { + rtwdev->lps_enabled = true; + } else { + rtw89_leave_lps(rtwdev); + rtwdev->lps_enabled = false; + } +} diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h index 73c008db042643..4c18f49204b285 100644 --- a/drivers/net/wireless/realtek/rtw89/ps.h +++ b/drivers/net/wireless/realtek/rtw89/ps.h @@ -15,6 +15,7 @@ void rtw89_enter_ips(struct rtw89_dev *rtwdev); void rtw89_leave_ips(struct rtw89_dev *rtwdev); void rtw89_set_coex_ctrl_lps(struct rtw89_dev *rtwdev, bool btc_ctrl); void rtw89_process_p2p_ps(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif); +void rtw89_recalc_lps(struct rtw89_dev *rtwdev); static inline void rtw89_leave_ips_by_hwflags(struct rtw89_dev *rtwdev) { diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h index 21f68787ff1095..b6ffa923133d4e 100644 --- a/drivers/net/wireless/realtek/rtw89/reg.h +++ b/drivers/net/wireless/realtek/rtw89/reg.h @@ -19,6 +19,8 @@ #define B_AX_FEN_BBRSTB BIT(0) #define R_AX_SYS_PW_CTRL 0x0004 +#define B_AX_SOP_ASWRM BIT(31) +#define B_AX_SOP_PWMM_DSWR BIT(29) #define B_AX_XTAL_OFF_A_DIE BIT(22) #define B_AX_DIS_WLBT_PDNSUSEN_SOPC BIT(18) #define B_AX_RDY_SYSPWR BIT(17) @@ -134,6 +136,8 @@ #define B_AX_PLATFORM_EN BIT(0) #define R_AX_WLLPS_CTRL 0x0090 +#define B_AX_LPSOP_ASWRM BIT(17) +#define B_AX_LPSOP_DSWRM BIT(9) #define B_AX_DIS_WLBT_LPSEN_LOPC BIT(1) #define SW_LPS_OPTION 0x0001A0B2 @@ -222,9 +226,14 @@ #define B_AX_OCP_L1_MASK GENMASK(15, 13) #define B_AX_VOL_L1_MASK GENMASK(3, 0) +#define R_AX_SPSLDO_ON_CTRL1 0x0204 +#define B_AX_FPWMDELAY BIT(3) + #define R_AX_LDO_AON_CTRL0 0x0218 #define B_AX_PD_REGU_L BIT(16) +#define R_AX_SPSANA_ON_CTRL1 0x0224 + #define R_AX_WLAN_XTAL_SI_CTRL 0x0270 #define B_AX_WL_XTAL_SI_CMD_POLL BIT(31) #define B_AX_BT_XTAL_SI_ERR_FLAG BIT(30) @@ -237,6 +246,9 @@ #define B_AX_WL_XTAL_SI_DATA_MASK GENMASK(15, 8) #define B_AX_WL_XTAL_SI_ADDR_MASK GENMASK(7, 0) +#define R_AX_WLAN_XTAL_SI_CONFIG 0x0274 +#define B_AX_XTAL_SI_ADDR_NOT_CHK BIT(0) + #define R_AX_XTAL_ON_CTRL0 0x0280 #define B_AX_XTAL_SC_LPS BIT(31) #define B_AX_XTAL_SC_XO_MASK GENMASK(23, 17) @@ -254,6 +266,10 @@ #define R_AX_EECS_EESK_FUNC_SEL 0x02D8 #define B_AX_PINMUX_EESK_FUNC_SEL_MASK GENMASK(7, 4) +#define R_AX_GPIO16_23_FUNC_SEL 0x02D8 +#define B_AX_PINMUX_GPIO17_FUNC_SEL_MASK GENMASK(7, 4) +#define B_AX_PINMUX_GPIO16_FUNC_SEL_MASK GENMASK(3, 0) + #define R_AX_LED1_FUNC_SEL 0x02DC #define B_AX_PINMUX_EESK_FUNC_SEL_V1_MASK GENMASK(27, 24) #define PINMUX_EESK_FUNC_SEL_BT_LOG 0x1 @@ -263,6 +279,10 @@ #define B_AX_EESK_PULL_LOW_EN BIT(17) #define B_AX_EECS_PULL_LOW_EN BIT(16) +#define R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN 0x02E4 +#define B_AX_GPIO16_PULL_LOW_EN_V1 BIT(19) +#define B_AX_GPIO10_PULL_LOW_EN BIT(10) + #define R_AX_WLRF_CTRL 0x02F0 #define B_AX_AFC_AFEDIG BIT(17) #define B_AX_WLRF1_CTRL_7 BIT(15) @@ -3305,6 +3325,10 @@ #define B_AX_TXAGC_BT_EN BIT(1) #define B_AX_TXAGC_BT_MASK GENMASK(11, 3) +#define R_AX_PWR_SWING_OTHER_CTRL0 0xD230 +#define R_AX_PWR_SWING_OTHER_CTRL0_C1 0xF230 +#define B_AX_CFIR_BY_RATE_OFF_MASK GENMASK(17, 0) + #define R_AX_PWR_UL_CTRL0 0xD240 #define R_AX_PWR_UL_CTRL2 0xD248 #define B_AX_PWR_UL_CFO_MASK GENMASK(2, 0) @@ -3318,16 +3342,22 @@ #define B_AX_PWR_UL_TB_2T_MASK GENMASK(4, 0) #define B_AX_PWR_UL_TB_2T_V1_MASK GENMASK(7, 0) #define R_AX_PWR_BY_RATE_TABLE0 0xD2C0 +#define R_AX_PWR_BY_RATE_TABLE6 0xD2D8 #define R_AX_PWR_BY_RATE_TABLE10 0xD2E8 #define R_AX_PWR_BY_RATE R_AX_PWR_BY_RATE_TABLE0 +#define R_AX_PWR_BY_RATE_1SS_MAX R_AX_PWR_BY_RATE_TABLE6 #define R_AX_PWR_BY_RATE_MAX R_AX_PWR_BY_RATE_TABLE10 #define R_AX_PWR_LMT_TABLE0 0xD2EC +#define R_AX_PWR_LMT_TABLE9 0xD310 #define R_AX_PWR_LMT_TABLE19 0xD338 #define R_AX_PWR_LMT R_AX_PWR_LMT_TABLE0 +#define R_AX_PWR_LMT_1SS_MAX R_AX_PWR_LMT_TABLE9 #define R_AX_PWR_LMT_MAX R_AX_PWR_LMT_TABLE19 #define R_AX_PWR_RU_LMT_TABLE0 0xD33C +#define R_AX_PWR_RU_LMT_TABLE5 0xD350 #define R_AX_PWR_RU_LMT_TABLE11 0xD368 #define R_AX_PWR_RU_LMT R_AX_PWR_RU_LMT_TABLE0 +#define R_AX_PWR_RU_LMT_1SS_MAX R_AX_PWR_RU_LMT_TABLE5 #define R_AX_PWR_RU_LMT_MAX R_AX_PWR_RU_LMT_TABLE11 #define R_AX_PWR_MACID_LMT_TABLE0 0xD36C #define R_AX_PWR_MACID_LMT_TABLE127 0xD568 @@ -3735,6 +3765,7 @@ #define RR_RXA_DPK GENMASK(9, 8) #define RR_RXA_LNA 0x8b #define RR_RXA2 0x8c +#define RR_RAA2_SATT GENMASK(15, 13) #define RR_RAA2_SWATT GENMASK(15, 9) #define RR_RXA2_C1 GENMASK(12, 10) #define RR_RXA2_C2 GENMASK(9, 3) @@ -3821,6 +3852,7 @@ #define RR_CAL_RW BIT(19) #define RR_LUTWE2 0xee #define RR_LUTWE2_RTXBW BIT(2) +#define RR_LUTWE2_DIS BIT(6) #define RR_LUTWE 0xef #define RR_LUTWE_LOK BIT(2) #define RR_RFC 0xf0 @@ -3846,6 +3878,7 @@ #define R_RFE_E_A2 0x0334 #define R_RFE_O_SEL_A2 0x0338 #define R_RFE_SEL0_A2 0x033C +#define B_RFE_SEL0_MASK GENMASK(1, 0) #define R_RFE_SEL32_A2 0x0340 #define R_CIRST 0x035c #define B_CIRST_SYN GENMASK(11, 10) @@ -3978,6 +4011,7 @@ #define R_S0_HW_SI_DIS 0x1200 #define B_S0_HW_SI_DIS_W_R_TRIG GENMASK(30, 28) #define R_P0_RXCK 0x12A0 +#define B_P0_RXCK_ADJ GENMASK(31, 23) #define B_P0_RXCK_BW3 BIT(30) #define B_P0_TXCK_ALL GENMASK(19, 12) #define B_P0_RXCK_ON BIT(19) @@ -4051,6 +4085,7 @@ #define R_TXAGC_BB 0x1C60 #define B_TXAGC_BB_OFT GENMASK(31, 16) #define B_TXAGC_BB GENMASK(31, 24) +#define B_TXAGC_RF GENMASK(5, 0) #define R_S0_ADDCK 0x1E00 #define B_S0_ADDCK_I GENMASK(9, 0) #define B_S0_ADDCK_Q GENMASK(19, 10) @@ -4134,8 +4169,10 @@ #define R_DCFO 0x4264 #define B_DCFO GENMASK(7, 0) #define R_SEG0CSI 0x42AC +#define R_SEG0CSI_V1 0x42B0 #define B_SEG0CSI_IDX GENMASK(10, 0) #define R_SEG0CSI_EN 0x42C4 +#define R_SEG0CSI_EN_V1 0x42C8 #define B_SEG0CSI_EN BIT(23) #define R_BSS_CLR_MAP 0x43ac #define R_BSS_CLR_MAP_V1 0x43B0 @@ -4367,6 +4404,14 @@ #define B_PATH0_BT_BACKOFF_V1 GENMASK(23, 0) #define R_PATH1_BT_BACKOFF_V1 0x4AEC #define B_PATH1_BT_BACKOFF_V1 GENMASK(23, 0) +#define R_DCFO_COMP_S0_V2 0x4B20 +#define B_DCFO_COMP_S0_MSK_V2 GENMASK(13, 0) +#define R_PATH0_TX_CFR 0x4B30 +#define B_PATH0_TX_CFR_LGC1 GENMASK(19, 10) +#define B_PATH0_TX_CFR_LGC0 GENMASK(9, 0) +#define R_PATH0_TX_POLAR_CLIPPING 0x4B3C +#define B_PATH0_TX_POLAR_CLIPPING_LGC1 GENMASK(19, 16) +#define B_PATH0_TX_POLAR_CLIPPING_LGC0 GENMASK(15, 12) #define R_PATH0_FRC_FIR_TYPE_V1 0x4C00 #define B_PATH0_FRC_FIR_TYPE_MSK_V1 GENMASK(1, 0) #define R_PATH0_NOTCH 0x4C14 @@ -4490,6 +4535,11 @@ #define B_P0_ANTSEL_RX_ORI GENMASK(7, 4) #define R_RFSW_CTRL_ANT0_BASE 0x5870 #define B_RFSW_CTRL_ANT_MAPPING GENMASK(15, 0) +#define R_RFE_SEL0_BASE 0x5880 +#define B_RFE_SEL0_SRC_MASK GENMASK(3, 0) +#define R_RFE_SEL32_BASE 0x5884 +#define RFE_SEL0_SRC_ANTSEL_0 8 +#define R_RFE_INV0 0x5890 #define R_P0_RFM 0x5894 #define B_P0_RFM_DIS_WL BIT(7) #define B_P0_RFM_TX_OPT BIT(6) @@ -4611,6 +4661,7 @@ #define R_MDPK_SYNC 0x8070 #define B_MDPK_SYNC_SEL BIT(31) #define B_MDPK_SYNC_MAN GENMASK(31, 28) +#define B_MDPK_SYNC_DMAN GENMASK(30, 28) #define R_MDPK_RX_DCK 0x8074 #define B_MDPK_RX_DCK_EN BIT(31) #define R_KIP_MOD 0x8078 @@ -4619,6 +4670,7 @@ #define R_KIP_SYSCFG 0x8088 #define R_KIP_CLK 0x808C #define R_DPK_IDL 0x809C +#define B_DPK_IDL_SEL GENMASK(10, 9) #define B_DPK_IDL BIT(8) #define R_LDL_NORM 0x80A0 #define B_LDL_NORM_MA BIT(16) @@ -4637,6 +4689,10 @@ #define B_KIP_RPT1_SEL GENMASK(21, 16) #define B_KIP_RPT1_SEL_V1 GENMASK(19, 16) #define R_SRAM_IQRX 0x80D8 +#define R_IDL_MPA 0x80DC +#define B_IDL_DN BIT(31) +#define B_IDL_MD530 BIT(1) +#define B_IDL_MD500 BIT(0) #define R_GAPK 0x80E0 #define B_GAPK_ADR BIT(0) #define R_SRAM_IQRX2 0x80E8 @@ -4724,6 +4780,7 @@ #define B_DPK_GL_A0 GENMASK(31, 28) #define B_DPK_GL_A1 GENMASK(17, 0) #define R_RPT_PER 0x81FC +#define B_RPT_PER_KSET GENMASK(31, 29) #define B_RPT_PER_TSSI GENMASK(28, 16) #define B_RPT_PER_OF GENMASK(15, 8) #define B_RPT_PER_TH GENMASK(5, 0) @@ -4817,11 +4874,16 @@ #define R_P0_CFCH_BW1 0xC0D8 #define B_P0_CFCH_EX BIT(13) #define B_P0_CFCH_BW1 GENMASK(8, 5) +#define R_WDADC 0xC0E4 +#define B_WDADC_SEL GENMASK(5, 4) #define R_ADCMOD 0xC0E8 #define B_ADCMOD_LP GENMASK(31, 16) +#define R_DCIM 0xC0EC +#define B_DCIM_FR GENMASK(14, 13) #define R_ADDCK0D 0xC0F0 #define B_ADDCK0D_VAL2 GENMASK(31, 26) #define B_ADDCK0D_VAL GENMASK(25, 16) +#define B_ADDCK_DS BIT(16) #define R_ADDCK0 0xC0F4 #define B_ADDCK0_TRG BIT(11) #define B_ADDCK0_IQ BIT(10) diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c index 377a7a1c560b73..34c4d40cfa022c 100644 --- a/drivers/net/wireless/realtek/rtw89/regd.c +++ b/drivers/net/wireless/realtek/rtw89/regd.c @@ -5,31 +5,32 @@ #include "acpi.h" #include "debug.h" #include "ps.h" +#include "util.h" #define COUNTRY_REGD(_alpha2, _txpwr_regd...) \ {.alpha2 = (_alpha2), \ .txpwr_regd = {_txpwr_regd}, \ } -static const struct rtw89_regulatory rtw89_ww_regd = +static const struct rtw89_regd rtw89_ww_regd = COUNTRY_REGD("00", RTW89_WW, RTW89_WW); -static const struct rtw89_regulatory rtw89_regd_map[] = { +static const struct rtw89_regd rtw89_regd_map[] = { COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA), - COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE), - COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("EC", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("SV", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("GT", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("HN", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("MX", RTW89_MEXICO, RTW89_MEXICO, RTW89_NA), COUNTRY_REGD("NI", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PA", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PY", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("PE", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("US", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA), @@ -66,37 +67,37 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("CH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GB", RTW89_UK, RTW89_UK, RTW89_UK), COUNTRY_REGD("AL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("AZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("BH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("JO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("KZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("KE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR), - COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("SA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("SN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("RS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("ME", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ZA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE), COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -104,11 +105,11 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN), - COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("HK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("IN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC), - COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -116,55 +117,55 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), + COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA), + COUNTRY_REGD("PG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CA", RTW89_IC, RTW89_IC, RTW89_IC), - COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_NA), - COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("JP", RTW89_MKK, RTW89_MKK, RTW89_MKK), + COUNTRY_REGD("JM", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("AN", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("TT", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("TN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("AF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("DZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("AS", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("AD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("AO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("AI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("AQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("AG", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("AM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("AW", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("BS", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("BB", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("BZ", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("BJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("BM", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("BV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("IO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("VG", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("BN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("BF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("BI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("KY", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("CF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA), - COUNTRY_REGD("CC", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA), + COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), + COUNTRY_REGD("DM", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("GQ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("ER", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ET", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("FK", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -174,17 +175,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("PF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("GY", RTW89_NCC, RTW89_NCC, RTW89_NA), + COUNTRY_REGD("GY", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("HT", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("HM", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("VA", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -195,17 +196,17 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("NR", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -219,26 +220,26 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC), + COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA), COUNTRY_REGD("SM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("ST", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("ST", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SC", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("SL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("SB", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_NA), + COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC), COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), - COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA), COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("TM", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -246,7 +247,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA), COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA), - COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA), + COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI), COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA), COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA), @@ -255,7 +256,7 @@ static const struct rtw89_regulatory rtw89_regd_map[] = { COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA), }; -static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2) +static const struct rtw89_regd *rtw89_regd_find_reg_by_name(char *alpha2) { u32 i; @@ -267,7 +268,7 @@ static const struct rtw89_regulatory *rtw89_regd_find_reg_by_name(char *alpha2) return &rtw89_ww_regd; } -static bool rtw89_regd_is_ww(const struct rtw89_regulatory *regd) +static bool rtw89_regd_is_ww(const struct rtw89_regd *regd) { return regd == &rtw89_ww_regd; } @@ -330,6 +331,55 @@ static void rtw89_regd_setup_unii4(struct rtw89_dev *rtwdev, sband->n_channels -= 3; } +static void rtw89_regd_setup_6ghz(struct rtw89_dev *rtwdev, struct wiphy *wiphy) +{ + const struct rtw89_chip_info *chip = rtwdev->chip; + bool chip_support_6ghz = chip->support_bands & BIT(NL80211_BAND_6GHZ); + bool regd_allow_6ghz = chip_support_6ghz; + struct ieee80211_supported_band *sband; + int ret; + u8 val; + + if (!chip_support_6ghz) + goto bottom; + + ret = rtw89_acpi_evaluate_dsm(rtwdev, RTW89_ACPI_DSM_FUNC_6G_DIS, &val); + if (ret) { + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: cannot eval 6ghz: %d\n", ret); + goto bottom; + } + + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "acpi: eval if disallow 6ghz: %d\n", val); + + switch (val) { + case 0: + regd_allow_6ghz = true; + break; + case 1: + regd_allow_6ghz = false; + break; + default: + break; + } + +bottom: + rtw89_debug(rtwdev, RTW89_DBG_REGD, "regd: allow 6ghz: %d\n", + regd_allow_6ghz); + + if (regd_allow_6ghz) + return; + + sband = wiphy->bands[NL80211_BAND_6GHZ]; + if (!sband) + return; + + wiphy->bands[NL80211_BAND_6GHZ] = NULL; + kfree(sband->iftype_data); + kfree(sband); +} + int rtw89_regd_setup(struct rtw89_dev *rtwdev) { struct wiphy *wiphy = rtwdev->hw->wiphy; @@ -338,6 +388,7 @@ int rtw89_regd_setup(struct rtw89_dev *rtwdev) return -EINVAL; rtw89_regd_setup_unii4(rtwdev, wiphy); + rtw89_regd_setup_6ghz(rtwdev, wiphy); wiphy->reg_notifier = rtw89_regd_notifier; return 0; @@ -347,21 +398,25 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev, void (*reg_notifier)(struct wiphy *wiphy, struct regulatory_request *request)) { - const struct rtw89_regulatory *chip_regd; + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + const struct rtw89_regd *chip_regd; struct wiphy *wiphy = rtwdev->hw->wiphy; int ret; + regulatory->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + if (!wiphy) return -EINVAL; chip_regd = rtw89_regd_find_reg_by_name(rtwdev->efuse.country_code); if (!rtw89_regd_is_ww(chip_regd)) { - rtwdev->regd = chip_regd; + rtwdev->regulatory.regd = chip_regd; /* Ignore country ie if there is a country domain programmed in chip */ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; wiphy->regulatory_flags |= REGULATORY_STRICT_REG; - ret = regulatory_hint(rtwdev->hw->wiphy, rtwdev->regd->alpha2); + ret = regulatory_hint(rtwdev->hw->wiphy, + rtwdev->regulatory.regd->alpha2); if (ret) rtw89_warn(rtwdev, "failed to hint regulatory:%d\n", ret); @@ -369,7 +424,7 @@ int rtw89_regd_init(struct rtw89_dev *rtwdev, return 0; } - rtw89_debug_regd(rtwdev, rtwdev->regd, + rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, "worldwide roaming chip, follow the setting of stack"); return 0; } @@ -378,13 +433,13 @@ static void rtw89_regd_notifier_apply(struct rtw89_dev *rtwdev, struct wiphy *wiphy, struct regulatory_request *request) { - rtwdev->regd = rtw89_regd_find_reg_by_name(request->alpha2); + rtwdev->regulatory.regd = rtw89_regd_find_reg_by_name(request->alpha2); /* This notification might be set from the system of distros, * and it does not expect the regulatory will be modified by * connecting to an AP (i.e. country ie). */ if (request->initiator == NL80211_REGDOM_SET_BY_USER && - !rtw89_regd_is_ww(rtwdev->regd)) + !rtw89_regd_is_ww(rtwdev->regulatory.regd)) wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE; else wiphy->regulatory_flags &= ~REGULATORY_COUNTRY_IE_IGNORE; @@ -404,7 +459,8 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request goto exit; } rtw89_regd_notifier_apply(rtwdev, wiphy, request); - rtw89_debug_regd(rtwdev, rtwdev->regd, "get from initiator %d, alpha2", + rtw89_debug_regd(rtwdev, rtwdev->regulatory.regd, + "get from initiator %d, alpha2", request->initiator); rtw89_core_set_chip_txpwr(rtwdev); @@ -412,3 +468,66 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request exit: mutex_unlock(&rtwdev->mutex); } + +static void __rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev) +{ + struct rtw89_regulatory_info *regulatory = &rtwdev->regulatory; + enum rtw89_reg_6ghz_power sel; + const struct rtw89_chan *chan; + struct rtw89_vif *rtwvif; + int count = 0; + + rtw89_for_each_rtwvif(rtwdev, rtwvif) { + chan = rtw89_chan_get(rtwdev, rtwvif->sub_entity_idx); + if (chan->band_type != RTW89_BAND_6G) + continue; + + if (count != 0 && rtwvif->reg_6ghz_power == sel) + continue; + + sel = rtwvif->reg_6ghz_power; + count++; + } + + if (count != 1) + sel = RTW89_REG_6GHZ_POWER_DFLT; + + if (regulatory->reg_6ghz_power == sel) + return; + + rtw89_debug(rtwdev, RTW89_DBG_REGD, + "recalc 6 GHz reg power type to %d\n", sel); + + regulatory->reg_6ghz_power = sel; + + rtw89_core_set_chip_txpwr(rtwdev); +} + +void rtw89_reg_6ghz_power_recalc(struct rtw89_dev *rtwdev, + struct rtw89_vif *rtwvif, bool active) +{ + struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif); + + lockdep_assert_held(&rtwdev->mutex); + + if (active) { + switch (vif->bss_conf.power_type) { + case IEEE80211_REG_VLP_AP: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_VLP; + break; + case IEEE80211_REG_LPI_AP: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_LPI; + break; + case IEEE80211_REG_SP_AP: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_STD; + break; + default: + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + break; + } + } else { + rtwvif->reg_6ghz_power = RTW89_REG_6GHZ_POWER_DFLT; + } + + __rtw89_reg_6ghz_power_recalc(rtwdev); +} diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c index 00cabf92c5a999..c4254e051be05f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c @@ -3,11 +3,13 @@ */ #include "coex.h" +#include "efuse.h" #include "fw.h" #include "mac.h" #include "phy.h" #include "reg.h" #include "rtw8851b.h" +#include "rtw8851b_rfk.h" #include "rtw8851b_rfk_table.h" #include "rtw8851b_table.h" #include "txrx.h" @@ -66,17 +68,2254 @@ static const struct rtw89_dle_mem rtw8851b_dle_mem_pcie[] = { NULL}, }; +static const struct rtw89_reg3_def rtw8851b_btc_preagc_en_defs[] = { + {0x46D0, GENMASK(1, 0), 0x3}, + {0x4AD4, GENMASK(31, 0), 0xf}, + {0x4688, GENMASK(23, 16), 0x80}, + {0x4688, GENMASK(31, 24), 0x80}, + {0x4694, GENMASK(7, 0), 0x80}, + {0x4694, GENMASK(15, 8), 0x80}, + {0x4AE4, GENMASK(11, 6), 0x34}, + {0x4AE4, GENMASK(17, 12), 0x0}, + {0x469C, GENMASK(31, 26), 0x34}, +}; + +static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_en_defs); + +static const struct rtw89_reg3_def rtw8851b_btc_preagc_dis_defs[] = { + {0x46D0, GENMASK(1, 0), 0x0}, + {0x4AD4, GENMASK(31, 0), 0x60}, + {0x4688, GENMASK(23, 16), 0x10}, + {0x4690, GENMASK(31, 24), 0x2a}, + {0x4694, GENMASK(15, 8), 0x2a}, + {0x4AE4, GENMASK(11, 6), 0x26}, + {0x4AE4, GENMASK(17, 12), 0x1e}, + {0x469C, GENMASK(31, 26), 0x26}, +}; + +static DECLARE_PHY_REG3_TBL(rtw8851b_btc_preagc_dis_defs); + +static const u32 rtw8851b_h2c_regs[RTW89_H2CREG_MAX] = { + R_AX_H2CREG_DATA0, R_AX_H2CREG_DATA1, R_AX_H2CREG_DATA2, + R_AX_H2CREG_DATA3 +}; + +static const u32 rtw8851b_c2h_regs[RTW89_C2HREG_MAX] = { + R_AX_C2HREG_DATA0, R_AX_C2HREG_DATA1, R_AX_C2HREG_DATA2, + R_AX_C2HREG_DATA3 +}; + +static const struct rtw89_page_regs rtw8851b_page_regs = { + .hci_fc_ctrl = R_AX_HCI_FC_CTRL, + .ch_page_ctrl = R_AX_CH_PAGE_CTRL, + .ach_page_ctrl = R_AX_ACH0_PAGE_CTRL, + .ach_page_info = R_AX_ACH0_PAGE_INFO, + .pub_page_info3 = R_AX_PUB_PAGE_INFO3, + .pub_page_ctrl1 = R_AX_PUB_PAGE_CTRL1, + .pub_page_ctrl2 = R_AX_PUB_PAGE_CTRL2, + .pub_page_info1 = R_AX_PUB_PAGE_INFO1, + .pub_page_info2 = R_AX_PUB_PAGE_INFO2, + .wp_page_ctrl1 = R_AX_WP_PAGE_CTRL1, + .wp_page_ctrl2 = R_AX_WP_PAGE_CTRL2, + .wp_page_info1 = R_AX_WP_PAGE_INFO1, +}; + +static const struct rtw89_reg_def rtw8851b_dcfo_comp = { + R_DCFO_COMP_S0_V2, B_DCFO_COMP_S0_MSK_V2 +}; + +static const struct rtw89_imr_info rtw8851b_imr_info = { + .wdrls_imr_set = B_AX_WDRLS_IMR_SET, + .wsec_imr_reg = R_AX_SEC_DEBUG, + .wsec_imr_set = B_AX_IMR_ERROR, + .mpdu_tx_imr_set = 0, + .mpdu_rx_imr_set = 0, + .sta_sch_imr_set = B_AX_STA_SCHEDULER_IMR_SET, + .txpktctl_imr_b0_reg = R_AX_TXPKTCTL_ERR_IMR_ISR, + .txpktctl_imr_b0_clr = B_AX_TXPKTCTL_IMR_B0_CLR, + .txpktctl_imr_b0_set = B_AX_TXPKTCTL_IMR_B0_SET, + .txpktctl_imr_b1_reg = R_AX_TXPKTCTL_ERR_IMR_ISR_B1, + .txpktctl_imr_b1_clr = B_AX_TXPKTCTL_IMR_B1_CLR, + .txpktctl_imr_b1_set = B_AX_TXPKTCTL_IMR_B1_SET, + .wde_imr_clr = B_AX_WDE_IMR_CLR, + .wde_imr_set = B_AX_WDE_IMR_SET, + .ple_imr_clr = B_AX_PLE_IMR_CLR, + .ple_imr_set = B_AX_PLE_IMR_SET, + .host_disp_imr_clr = B_AX_HOST_DISP_IMR_CLR, + .host_disp_imr_set = B_AX_HOST_DISP_IMR_SET, + .cpu_disp_imr_clr = B_AX_CPU_DISP_IMR_CLR, + .cpu_disp_imr_set = B_AX_CPU_DISP_IMR_SET, + .other_disp_imr_clr = B_AX_OTHER_DISP_IMR_CLR, + .other_disp_imr_set = 0, + .bbrpt_com_err_imr_reg = R_AX_BBRPT_COM_ERR_IMR_ISR, + .bbrpt_chinfo_err_imr_reg = R_AX_BBRPT_CHINFO_ERR_IMR_ISR, + .bbrpt_err_imr_set = 0, + .bbrpt_dfs_err_imr_reg = R_AX_BBRPT_DFS_ERR_IMR_ISR, + .ptcl_imr_clr = B_AX_PTCL_IMR_CLR_ALL, + .ptcl_imr_set = B_AX_PTCL_IMR_SET, + .cdma_imr_0_reg = R_AX_DLE_CTRL, + .cdma_imr_0_clr = B_AX_DLE_IMR_CLR, + .cdma_imr_0_set = B_AX_DLE_IMR_SET, + .cdma_imr_1_reg = 0, + .cdma_imr_1_clr = 0, + .cdma_imr_1_set = 0, + .phy_intf_imr_reg = R_AX_PHYINFO_ERR_IMR, + .phy_intf_imr_clr = 0, + .phy_intf_imr_set = 0, + .rmac_imr_reg = R_AX_RMAC_ERR_ISR, + .rmac_imr_clr = B_AX_RMAC_IMR_CLR, + .rmac_imr_set = B_AX_RMAC_IMR_SET, + .tmac_imr_reg = R_AX_TMAC_ERR_IMR_ISR, + .tmac_imr_clr = B_AX_TMAC_IMR_CLR, + .tmac_imr_set = B_AX_TMAC_IMR_SET, +}; + static const struct rtw89_xtal_info rtw8851b_xtal_info = { .xcap_reg = R_AX_XTAL_ON_CTRL3, .sc_xo_mask = B_AX_XTAL_SC_XO_A_BLOCK_MASK, .sc_xi_mask = B_AX_XTAL_SC_XI_A_BLOCK_MASK, }; +static const struct rtw89_rrsr_cfgs rtw8851b_rrsr_cfgs = { + .ref_rate = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_REF_RATE_SEL, 0}, + .rsc = {R_AX_TRXPTCL_RRSR_CTL_0, B_AX_WMAC_RESP_RSC_MASK, 2}, +}; + +static const struct rtw89_dig_regs rtw8851b_dig_regs = { + .seg0_pd_reg = R_SEG0R_PD_V1, + .pd_lower_bound_mask = B_SEG0R_PD_LOWER_BOUND_MSK, + .pd_spatial_reuse_en = B_SEG0R_PD_SPATIAL_REUSE_EN_MSK_V1, + .p0_lna_init = {R_PATH0_LNA_INIT_V1, B_PATH0_LNA_INIT_IDX_MSK}, + .p1_lna_init = {R_PATH1_LNA_INIT_V1, B_PATH1_LNA_INIT_IDX_MSK}, + .p0_tia_init = {R_PATH0_TIA_INIT_V1, B_PATH0_TIA_INIT_IDX_MSK_V1}, + .p1_tia_init = {R_PATH1_TIA_INIT_V1, B_PATH1_TIA_INIT_IDX_MSK_V1}, + .p0_rxb_init = {R_PATH0_RXB_INIT_V1, B_PATH0_RXB_INIT_IDX_MSK_V1}, + .p1_rxb_init = {R_PATH1_RXB_INIT_V1, B_PATH1_RXB_INIT_IDX_MSK_V1}, + .p0_p20_pagcugc_en = {R_PATH0_P20_FOLLOW_BY_PAGCUGC_V2, + B_PATH0_P20_FOLLOW_BY_PAGCUGC_EN_MSK}, + .p0_s20_pagcugc_en = {R_PATH0_S20_FOLLOW_BY_PAGCUGC_V2, + B_PATH0_S20_FOLLOW_BY_PAGCUGC_EN_MSK}, + .p1_p20_pagcugc_en = {R_PATH1_P20_FOLLOW_BY_PAGCUGC_V2, + B_PATH1_P20_FOLLOW_BY_PAGCUGC_EN_MSK}, + .p1_s20_pagcugc_en = {R_PATH1_S20_FOLLOW_BY_PAGCUGC_V2, + B_PATH1_S20_FOLLOW_BY_PAGCUGC_EN_MSK}, +}; + +static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_ul[] = { + {255, 0, 0, 7}, /* 0 -> original */ + {255, 2, 0, 7}, /* 1 -> for BT-connected ACI issue && BTG co-rx */ + {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ + {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ + {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {6, 1, 0, 7}, + {13, 1, 0, 7}, + {13, 1, 0, 7} +}; + +static const struct rtw89_btc_rf_trx_para rtw89_btc_8851b_rf_dl[] = { + {255, 0, 0, 7}, /* 0 -> original */ + {255, 2, 0, 7}, /* 1 -> reserved for shared-antenna */ + {255, 0, 0, 7}, /* 2 ->reserved for shared-antenna */ + {255, 0, 0, 7}, /* 3- >reserved for shared-antenna */ + {255, 0, 0, 7}, /* 4 ->reserved for shared-antenna */ + {255, 1, 0, 7}, /* the below id is for non-shared-antenna free-run */ + {255, 1, 0, 7}, + {255, 1, 0, 7}, + {255, 1, 0, 7} +}; + +static const struct rtw89_btc_fbtc_mreg rtw89_btc_8851b_mon_reg[] = { + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda24), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda28), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda2c), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda30), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda4c), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda10), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda20), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xda34), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xcef4), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0x8424), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd200), + RTW89_DEF_FBTC_MREG(REG_MAC, 4, 0xd220), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x980), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4738), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4688), + RTW89_DEF_FBTC_MREG(REG_BB, 4, 0x4694), +}; + +static const u8 rtw89_btc_8851b_wl_rssi_thres[BTC_WL_RSSI_THMAX] = {70, 60, 50, 40}; +static const u8 rtw89_btc_8851b_bt_rssi_thres[BTC_BT_RSSI_THMAX] = {50, 40, 30, 20}; + +static int rtw8851b_pwr_on_func(struct rtw89_dev *rtwdev) +{ + u32 val32; + u8 val8; + u32 ret; + + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_AFSM_WLSUS_EN | + B_AX_AFSM_PCIE_SUS_EN); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_DIS_WLBT_PDNSUSEN_SOPC); + rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_DIS_WLBT_LPSEN_LOPC); + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APDM_HPDN); + rtw89_write32_clr(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + + ret = read_poll_timeout(rtw89_read32, val32, val32 & B_AX_RDY_SYSPWR, + 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); + if (ret) + return ret; + + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFN_ONMAC); + + ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFN_ONMAC), + 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); + if (ret) + return ret; + + rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write8_clr(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + + rtw89_write8_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_PLATFORM_EN); + rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL, B_AX_PCIE_CALIB_EN_V1); + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_WEI, + XTAL_SI_OFF_WEI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_OFF_EI, + XTAL_SI_OFF_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_RFC2RF); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_WEI, + XTAL_SI_PON_WEI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_PON_EI, + XTAL_SI_PON_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_SRAM2RFC); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_SRAM_CTRL, 0, XTAL_SI_SRAM_DIS); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, XTAL_SI_LDO_LPS); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_4, 0, XTAL_SI_LPS_CAP); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_DRV, 0, XTAL_SI_DRV_LATCH); + if (ret) + return ret; + + rtw89_write32_set(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); + rtw89_write32_set(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_ISO_EB2CORE); + rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B15); + + fsleep(1000); + + rtw89_write32_clr(rtwdev, R_AX_SYS_ISO_CTRL, B_AX_PWC_EV2EF_B14); + rtw89_write32_clr(rtwdev, R_AX_PMC_DBG_CTRL2, B_AX_SYSON_DIS_PMCR_AX_WRMSK); + rtw89_write32_set(rtwdev, R_AX_GPIO0_16_EECS_EESK_LED1_PULL_LOW_EN, + B_AX_GPIO10_PULL_LOW_EN | B_AX_GPIO16_PULL_LOW_EN_V1); + + if (rtwdev->hal.cv == CHIP_CAV) { + ret = rtw89_read_efuse_ver(rtwdev, &val8); + if (!ret) + rtwdev->hal.cv = val8; + } + + rtw89_write32_clr(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG, + B_AX_XTAL_SI_ADDR_NOT_CHK); + if (rtwdev->hal.cv != CHIP_CAV) { + rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY); + rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY); + } + + rtw89_write32_set(rtwdev, R_AX_DMAC_FUNC_EN, + B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_MPDU_PROC_EN | + B_AX_WD_RLS_EN | B_AX_DLE_WDE_EN | B_AX_TXPKT_CTRL_EN | + B_AX_STA_SCH_EN | B_AX_DLE_PLE_EN | B_AX_PKT_BUF_EN | + B_AX_DMAC_TBL_EN | B_AX_PKT_IN_EN | B_AX_DLE_CPUIO_EN | + B_AX_DISPATCHER_EN | B_AX_BBRPT_EN | B_AX_MAC_SEC_EN | + B_AX_DMACREG_GCKEN); + rtw89_write32_set(rtwdev, R_AX_CMAC_FUNC_EN, + B_AX_CMAC_EN | B_AX_CMAC_TXEN | B_AX_CMAC_RXEN | + B_AX_FORCE_CMACREG_GCKEN | B_AX_PHYINTF_EN | B_AX_CMAC_DMA_EN | + B_AX_PTCLTOP_EN | B_AX_SCHEDULER_EN | B_AX_TMAC_EN | + B_AX_RMAC_EN); + + rtw89_write32_mask(rtwdev, R_AX_EECS_EESK_FUNC_SEL, B_AX_PINMUX_EESK_FUNC_SEL_MASK, + PINMUX_EESK_FUNC_SEL_BT_LOG); + + return 0; +} + +static void rtw8851b_patch_swr_pfm2pwm(struct rtw89_dev *rtwdev) +{ + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_PWMM_DSWR); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_SOP_ASWRM); + rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_DSWRM); + rtw89_write32_set(rtwdev, R_AX_WLLPS_CTRL, B_AX_LPSOP_ASWRM); +} + +static int rtw8851b_pwr_off_func(struct rtw89_dev *rtwdev) +{ + u32 val32; + u32 ret; + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_RFC2RF, + XTAL_SI_RFC2RF); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_OFF_WEI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0, XTAL_SI_RF00); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, XTAL_SI_SRAM2RFC, + XTAL_SI_SRAM2RFC); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_EI); + if (ret) + return ret; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, XTAL_SI_PON_WEI); + if (ret) + return ret; + + rtw89_write32_set(rtwdev, R_AX_WLAN_XTAL_SI_CONFIG, + B_AX_XTAL_SI_ADDR_NOT_CHK); + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_EN_WLON); + rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, B_AX_FEN_BB_GLB_RSTN | B_AX_FEN_BBRSTB); + + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_OFFMAC); + + ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_AX_APFM_OFFMAC), + 1000, 20000, false, rtwdev, R_AX_SYS_PW_CTRL); + if (ret) + return ret; + + rtw89_write32(rtwdev, R_AX_WLLPS_CTRL, SW_LPS_OPTION); + + if (rtwdev->hal.cv == CHIP_CAV) { + rtw8851b_patch_swr_pfm2pwm(rtwdev); + } else { + rtw89_write32_set(rtwdev, R_AX_SPSLDO_ON_CTRL1, B_AX_FPWMDELAY); + rtw89_write32_set(rtwdev, R_AX_SPSANA_ON_CTRL1, B_AX_FPWMDELAY); + } + + rtw89_write32_set(rtwdev, R_AX_SYS_PW_CTRL, B_AX_APFM_SWLPS); + + return 0; +} + +static void rtw8851b_efuse_parsing(struct rtw89_efuse *efuse, + struct rtw8851b_efuse *map) +{ + ether_addr_copy(efuse->addr, map->e.mac_addr); + efuse->rfe_type = map->rfe_type; + efuse->xtal_cap = map->xtal_k; +} + +static void rtw8851b_efuse_parsing_tssi(struct rtw89_dev *rtwdev, + struct rtw8851b_efuse *map) +{ + struct rtw89_tssi_info *tssi = &rtwdev->tssi; + struct rtw8851b_tssi_offset *ofst[] = {&map->path_a_tssi}; + u8 i, j; + + tssi->thermal[RF_PATH_A] = map->path_a_therm; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + memcpy(tssi->tssi_cck[i], ofst[i]->cck_tssi, + sizeof(ofst[i]->cck_tssi)); + + for (j = 0; j < TSSI_CCK_CH_GROUP_NUM; j++) + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][EFUSE] path=%d cck[%d]=0x%x\n", + i, j, tssi->tssi_cck[i][j]); + + memcpy(tssi->tssi_mcs[i], ofst[i]->bw40_tssi, + sizeof(ofst[i]->bw40_tssi)); + memcpy(tssi->tssi_mcs[i] + TSSI_MCS_2G_CH_GROUP_NUM, + ofst[i]->bw40_1s_tssi_5g, sizeof(ofst[i]->bw40_1s_tssi_5g)); + + for (j = 0; j < TSSI_MCS_CH_GROUP_NUM; j++) + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][EFUSE] path=%d mcs[%d]=0x%x\n", + i, j, tssi->tssi_mcs[i][j]); + } +} + +static bool _decode_efuse_gain(u8 data, s8 *high, s8 *low) +{ + if (high) + *high = sign_extend32(u8_get_bits(data, GENMASK(7, 4)), 3); + if (low) + *low = sign_extend32(u8_get_bits(data, GENMASK(3, 0)), 3); + + return data != 0xff; +} + +static void rtw8851b_efuse_parsing_gain_offset(struct rtw89_dev *rtwdev, + struct rtw8851b_efuse *map) +{ + struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; + bool valid = false; + + valid |= _decode_efuse_gain(map->rx_gain_2g_cck, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_CCK], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_2g_ofdm, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_2G_OFDM], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_5g_low, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_LOW], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_5g_mid, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_MID], + NULL); + valid |= _decode_efuse_gain(map->rx_gain_5g_high, + &gain->offset[RF_PATH_A][RTW89_GAIN_OFFSET_5G_HIGH], + NULL); + + gain->offset_valid = valid; +} + +static int rtw8851b_read_efuse(struct rtw89_dev *rtwdev, u8 *log_map) +{ + struct rtw89_efuse *efuse = &rtwdev->efuse; + struct rtw8851b_efuse *map; + + map = (struct rtw8851b_efuse *)log_map; + + efuse->country_code[0] = map->country_code[0]; + efuse->country_code[1] = map->country_code[1]; + rtw8851b_efuse_parsing_tssi(rtwdev, map); + rtw8851b_efuse_parsing_gain_offset(rtwdev, map); + + switch (rtwdev->hci.type) { + case RTW89_HCI_TYPE_PCIE: + rtw8851b_efuse_parsing(efuse, map); + break; + default: + return -EOPNOTSUPP; + } + + rtw89_info(rtwdev, "chip rfe_type is %d\n", efuse->rfe_type); + + return 0; +} + +static void rtw8851b_phycap_parsing_tssi(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + struct rtw89_tssi_info *tssi = &rtwdev->tssi; + static const u32 tssi_trim_addr[RF_PATH_NUM_8851B] = {0x5D6}; + u32 addr = rtwdev->chip->phycap_addr; + bool pg = false; + u32 ofst; + u8 i, j; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) { + /* addrs are in decreasing order */ + ofst = tssi_trim_addr[i] - addr - j; + tssi->tssi_trim[i][j] = phycap_map[ofst]; + + if (phycap_map[ofst] != 0xff) + pg = true; + } + } + + if (!pg) { + memset(tssi->tssi_trim, 0, sizeof(tssi->tssi_trim)); + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM] no PG, set all trim info to 0\n"); + } + + for (i = 0; i < RF_PATH_NUM_8851B; i++) + for (j = 0; j < TSSI_TRIM_CH_GROUP_NUM; j++) + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] path=%d idx=%d trim=0x%x addr=0x%x\n", + i, j, tssi->tssi_trim[i][j], + tssi_trim_addr[i] - j); +} + +static void rtw8851b_phycap_parsing_thermal_trim(struct rtw89_dev *rtwdev, + u8 *phycap_map) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + static const u32 thm_trim_addr[RF_PATH_NUM_8851B] = {0x5DF}; + u32 addr = rtwdev->chip->phycap_addr; + u8 i; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + info->thermal_trim[i] = phycap_map[thm_trim_addr[i] - addr]; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[THERMAL][TRIM] path=%d thermal_trim=0x%x\n", + i, info->thermal_trim[i]); + + if (info->thermal_trim[i] != 0xff) + info->pg_thermal_trim = true; + } +} + +static void rtw8851b_thermal_trim(struct rtw89_dev *rtwdev) +{ +#define __thm_setting(raw) \ +({ \ + u8 __v = (raw); \ + ((__v & 0x1) << 3) | ((__v & 0x1f) >> 1); \ +}) + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + u8 i, val; + + if (!info->pg_thermal_trim) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[THERMAL][TRIM] no PG, do nothing\n"); + + return; + } + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + val = __thm_setting(info->thermal_trim[i]); + rtw89_write_rf(rtwdev, i, RR_TM2, RR_TM2_OFF, val); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[THERMAL][TRIM] path=%d thermal_setting=0x%x\n", + i, val); + } +#undef __thm_setting +} + +static void rtw8851b_phycap_parsing_pa_bias_trim(struct rtw89_dev *rtwdev, + u8 *phycap_map) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + static const u32 pabias_trim_addr[] = {0x5DE}; + u32 addr = rtwdev->chip->phycap_addr; + u8 i; + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + info->pa_bias_trim[i] = phycap_map[pabias_trim_addr[i] - addr]; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[PA_BIAS][TRIM] path=%d pa_bias_trim=0x%x\n", + i, info->pa_bias_trim[i]); + + if (info->pa_bias_trim[i] != 0xff) + info->pg_pa_bias_trim = true; + } +} + +static void rtw8851b_pa_bias_trim(struct rtw89_dev *rtwdev) +{ + struct rtw89_power_trim_info *info = &rtwdev->pwr_trim; + u8 pabias_2g, pabias_5g; + u8 i; + + if (!info->pg_pa_bias_trim) { + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[PA_BIAS][TRIM] no PG, do nothing\n"); + + return; + } + + for (i = 0; i < RF_PATH_NUM_8851B; i++) { + pabias_2g = u8_get_bits(info->pa_bias_trim[i], GENMASK(3, 0)); + pabias_5g = u8_get_bits(info->pa_bias_trim[i], GENMASK(7, 4)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[PA_BIAS][TRIM] path=%d 2G=0x%x 5G=0x%x\n", + i, pabias_2g, pabias_5g); + + rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXG, pabias_2g); + rtw89_write_rf(rtwdev, i, RR_BIASA, RR_BIASA_TXA, pabias_5g); + } +} + +static void rtw8851b_phycap_parsing_gain_comp(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + static const u32 comp_addrs[][RTW89_SUBBAND_2GHZ_5GHZ_NR] = { + {0x5BB, 0x5BA, 0, 0x5B9, 0x5B8}, + }; + struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; + u32 phycap_addr = rtwdev->chip->phycap_addr; + bool valid = false; + int path, i; + u8 data; + + for (path = 0; path < BB_PATH_NUM_8851B; path++) + for (i = 0; i < RTW89_SUBBAND_2GHZ_5GHZ_NR; i++) { + if (comp_addrs[path][i] == 0) + continue; + + data = phycap_map[comp_addrs[path][i] - phycap_addr]; + valid |= _decode_efuse_gain(data, NULL, + &gain->comp[path][i]); + } + + gain->comp_valid = valid; +} + +static int rtw8851b_read_phycap(struct rtw89_dev *rtwdev, u8 *phycap_map) +{ + rtw8851b_phycap_parsing_tssi(rtwdev, phycap_map); + rtw8851b_phycap_parsing_thermal_trim(rtwdev, phycap_map); + rtw8851b_phycap_parsing_pa_bias_trim(rtwdev, phycap_map); + rtw8851b_phycap_parsing_gain_comp(rtwdev, phycap_map); + + return 0; +} + +static void rtw8851b_set_bb_gpio(struct rtw89_dev *rtwdev, u8 gpio_idx, bool inv, + u8 src_sel) +{ + u32 addr, mask; + + if (gpio_idx >= 32) + return; + + /* 2 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 2 bits */ + addr = R_RFE_SEL0_A2 + (gpio_idx / 16) * sizeof(u32); + mask = B_RFE_SEL0_MASK << (gpio_idx % 16) * 2; + + rtw89_phy_write32_mask(rtwdev, addr, mask, RF_PATH_A); + rtw89_phy_write32_mask(rtwdev, R_RFE_INV0, BIT(gpio_idx), inv); + + /* 4 continual 32-bit registers for 32 GPIOs, and each GPIO occupies 4 bits */ + addr = R_RFE_SEL0_BASE + (gpio_idx / 8) * sizeof(u32); + mask = B_RFE_SEL0_SRC_MASK << (gpio_idx % 8) * 4; + + rtw89_phy_write32_mask(rtwdev, addr, mask, src_sel); +} + +static void rtw8851b_set_mac_gpio(struct rtw89_dev *rtwdev, u8 func) +{ + static const struct rtw89_reg3_def func16 = { + R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO16_FUNC_SEL_MASK, BIT(3) + }; + static const struct rtw89_reg3_def func17 = { + R_AX_GPIO16_23_FUNC_SEL, B_AX_PINMUX_GPIO17_FUNC_SEL_MASK, BIT(7) >> 4, + }; + const struct rtw89_reg3_def *def; + + switch (func) { + case 16: + def = &func16; + break; + case 17: + def = &func17; + break; + default: + rtw89_warn(rtwdev, "undefined gpio func %d\n", func); + return; + } + + rtw89_write8_mask(rtwdev, def->addr, def->mask, def->data); +} + +static void rtw8851b_rfe_gpio(struct rtw89_dev *rtwdev) +{ + u8 rfe_type = rtwdev->efuse.rfe_type; + + if (rfe_type > 50) + return; + + if (rfe_type % 3 == 2) { + rtw8851b_set_bb_gpio(rtwdev, 16, true, RFE_SEL0_SRC_ANTSEL_0); + rtw8851b_set_bb_gpio(rtwdev, 17, false, RFE_SEL0_SRC_ANTSEL_0); + + rtw8851b_set_mac_gpio(rtwdev, 16); + rtw8851b_set_mac_gpio(rtwdev, 17); + } +} + +static void rtw8851b_power_trim(struct rtw89_dev *rtwdev) +{ + rtw8851b_thermal_trim(rtwdev); + rtw8851b_pa_bias_trim(rtwdev); +} + +static void rtw8851b_set_channel_mac(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + u8 mac_idx) +{ + u32 sub_carr = rtw89_mac_reg_by_idx(R_AX_TX_SUB_CARRIER_VALUE, mac_idx); + u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx); + u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx); + u8 txsc20 = 0, txsc40 = 0; + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_80: + txsc40 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_40); + fallthrough; + case RTW89_CHANNEL_WIDTH_40: + txsc20 = rtw89_phy_get_txsc(rtwdev, chan, RTW89_CHANNEL_WIDTH_20); + break; + default: + break; + } + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_80: + rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(1)); + rtw89_write32(rtwdev, sub_carr, txsc20 | (txsc40 << 4)); + break; + case RTW89_CHANNEL_WIDTH_40: + rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, BIT(0)); + rtw89_write32(rtwdev, sub_carr, txsc20); + break; + case RTW89_CHANNEL_WIDTH_20: + rtw89_write8_clr(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK); + rtw89_write32(rtwdev, sub_carr, 0); + break; + default: + break; + } + + if (chan->channel > 14) { + rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE); + rtw89_write8_set(rtwdev, chk_rate, + B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6); + } else { + rtw89_write8_set(rtwdev, chk_rate, B_AX_BAND_MODE); + rtw89_write8_clr(rtwdev, chk_rate, + B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6); + } +} + +static const u32 rtw8851b_sco_barker_threshold[14] = { + 0x1cfea, 0x1d0e1, 0x1d1d7, 0x1d2cd, 0x1d3c3, 0x1d4b9, 0x1d5b0, 0x1d6a6, + 0x1d79c, 0x1d892, 0x1d988, 0x1da7f, 0x1db75, 0x1ddc4 +}; + +static const u32 rtw8851b_sco_cck_threshold[14] = { + 0x27de3, 0x27f35, 0x28088, 0x281da, 0x2832d, 0x2847f, 0x285d2, 0x28724, + 0x28877, 0x289c9, 0x28b1c, 0x28c6e, 0x28dc1, 0x290ed +}; + +static void rtw8851b_ctrl_sco_cck(struct rtw89_dev *rtwdev, u8 primary_ch) +{ + u8 ch_element = primary_ch - 1; + + rtw89_phy_write32_mask(rtwdev, R_RXSCOBC, B_RXSCOBC_TH, + rtw8851b_sco_barker_threshold[ch_element]); + rtw89_phy_write32_mask(rtwdev, R_RXSCOCCK, B_RXSCOCCK_TH, + rtw8851b_sco_cck_threshold[ch_element]); +} + +static u8 rtw8851b_sco_mapping(u8 central_ch) +{ + if (central_ch == 1) + return 109; + else if (central_ch >= 2 && central_ch <= 6) + return 108; + else if (central_ch >= 7 && central_ch <= 10) + return 107; + else if (central_ch >= 11 && central_ch <= 14) + return 106; + else if (central_ch == 36 || central_ch == 38) + return 51; + else if (central_ch >= 40 && central_ch <= 58) + return 50; + else if (central_ch >= 60 && central_ch <= 64) + return 49; + else if (central_ch == 100 || central_ch == 102) + return 48; + else if (central_ch >= 104 && central_ch <= 126) + return 47; + else if (central_ch >= 128 && central_ch <= 151) + return 46; + else if (central_ch >= 153 && central_ch <= 177) + return 45; + else + return 0; +} + +struct rtw8851b_bb_gain { + u32 gain_g[BB_PATH_NUM_8851B]; + u32 gain_a[BB_PATH_NUM_8851B]; + u32 gain_mask; +}; + +static const struct rtw8851b_bb_gain bb_gain_lna[LNA_GAIN_NUM] = { + { .gain_g = {0x4678}, .gain_a = {0x45DC}, + .gain_mask = 0x00ff0000 }, + { .gain_g = {0x4678}, .gain_a = {0x45DC}, + .gain_mask = 0xff000000 }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0x000000ff }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0x0000ff00 }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0x00ff0000 }, + { .gain_g = {0x467C}, .gain_a = {0x4660}, + .gain_mask = 0xff000000 }, + { .gain_g = {0x4680}, .gain_a = {0x4664}, + .gain_mask = 0x000000ff }, +}; + +static const struct rtw8851b_bb_gain bb_gain_tia[TIA_GAIN_NUM] = { + { .gain_g = {0x4680}, .gain_a = {0x4664}, + .gain_mask = 0x00ff0000 }, + { .gain_g = {0x4680}, .gain_a = {0x4664}, + .gain_mask = 0xff000000 }, +}; + +static void rtw8851b_set_gain_error(struct rtw89_dev *rtwdev, + enum rtw89_subband subband, + enum rtw89_rf_path path) +{ + const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain; + u8 gain_band = rtw89_subband_to_bb_gain_band(subband); + s32 val; + u32 reg; + u32 mask; + int i; + + for (i = 0; i < LNA_GAIN_NUM; i++) { + if (subband == RTW89_CH_2G) + reg = bb_gain_lna[i].gain_g[path]; + else + reg = bb_gain_lna[i].gain_a[path]; + + mask = bb_gain_lna[i].gain_mask; + val = gain->lna_gain[gain_band][path][i]; + rtw89_phy_write32_mask(rtwdev, reg, mask, val); + } + + for (i = 0; i < TIA_GAIN_NUM; i++) { + if (subband == RTW89_CH_2G) + reg = bb_gain_tia[i].gain_g[path]; + else + reg = bb_gain_tia[i].gain_a[path]; + + mask = bb_gain_tia[i].gain_mask; + val = gain->tia_gain[gain_band][path][i]; + rtw89_phy_write32_mask(rtwdev, reg, mask, val); + } +} + +static void rtw8851b_set_gain_offset(struct rtw89_dev *rtwdev, + enum rtw89_subband subband, + enum rtw89_phy_idx phy_idx) +{ + static const u32 rssi_ofst_addr[] = {R_PATH0_G_TIA1_LNA6_OP1DB_V1}; + static const u32 gain_err_addr[] = {R_P0_AGC_RSVD}; + struct rtw89_phy_efuse_gain *efuse_gain = &rtwdev->efuse_gain; + enum rtw89_gain_offset gain_ofdm_band; + s32 offset_ofdm, offset_cck; + s32 offset_a; + s32 tmp; + u8 path; + + if (!efuse_gain->comp_valid) + goto next; + + for (path = RF_PATH_A; path < BB_PATH_NUM_8851B; path++) { + tmp = efuse_gain->comp[path][subband]; + tmp = clamp_t(s32, tmp << 2, S8_MIN, S8_MAX); + rtw89_phy_write32_mask(rtwdev, gain_err_addr[path], MASKBYTE0, tmp); + } + +next: + if (!efuse_gain->offset_valid) + return; + + gain_ofdm_band = rtw89_subband_to_gain_offset_band_of_ofdm(subband); + + offset_a = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band]; + + tmp = -((offset_a << 2) + (efuse_gain->offset_base[RTW89_PHY_0] >> 2)); + tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX); + rtw89_phy_write32_mask(rtwdev, rssi_ofst_addr[RF_PATH_A], B_PATH0_R_G_OFST_MASK, tmp); + + offset_ofdm = -efuse_gain->offset[RF_PATH_A][gain_ofdm_band]; + offset_cck = -efuse_gain->offset[RF_PATH_A][0]; + + tmp = (offset_ofdm << 4) + efuse_gain->offset_base[RTW89_PHY_0]; + tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX); + rtw89_phy_write32_idx(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx); + + tmp = (offset_ofdm << 4) + efuse_gain->rssi_base[RTW89_PHY_0]; + tmp = clamp_t(s32, tmp, S8_MIN, S8_MAX); + rtw89_phy_write32_idx(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK, tmp, phy_idx); + + if (subband == RTW89_CH_2G) { + tmp = (offset_cck << 3) + (efuse_gain->offset_base[RTW89_PHY_0] >> 1); + tmp = clamp_t(s32, tmp, S8_MIN >> 1, S8_MAX >> 1); + rtw89_phy_write32_mask(rtwdev, R_RX_RPL_OFST, + B_RX_RPL_OFST_CCK_MASK, tmp); + } +} + +static +void rtw8851b_set_rxsc_rpl_comp(struct rtw89_dev *rtwdev, enum rtw89_subband subband) +{ + const struct rtw89_phy_bb_gain_info *gain = &rtwdev->bb_gain; + u8 band = rtw89_subband_to_bb_gain_band(subband); + u32 val; + + val = u32_encode_bits(gain->rpl_ofst_20[band][RF_PATH_A], B_P0_RPL1_20_MASK) | + u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][0], B_P0_RPL1_40_MASK) | + u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][1], B_P0_RPL1_41_MASK); + val >>= B_P0_RPL1_SHIFT; + rtw89_phy_write32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_MASK, val); + rtw89_phy_write32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_MASK, val); + + val = u32_encode_bits(gain->rpl_ofst_40[band][RF_PATH_A][2], B_P0_RTL2_42_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][0], B_P0_RTL2_80_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][1], B_P0_RTL2_81_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][10], B_P0_RTL2_8A_MASK); + rtw89_phy_write32(rtwdev, R_P0_RPL2, val); + rtw89_phy_write32(rtwdev, R_P1_RPL2, val); + + val = u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][2], B_P0_RTL3_82_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][3], B_P0_RTL3_83_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][4], B_P0_RTL3_84_MASK) | + u32_encode_bits(gain->rpl_ofst_80[band][RF_PATH_A][9], B_P0_RTL3_89_MASK); + rtw89_phy_write32(rtwdev, R_P0_RPL3, val); + rtw89_phy_write32(rtwdev, R_P1_RPL3, val); +} + +static void rtw8851b_ctrl_ch(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 subband = chan->subband_type; + u8 central_ch = chan->channel; + bool is_2g = central_ch <= 14; + u8 sco_comp; + + if (is_2g) + rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1, + B_PATH0_BAND_SEL_MSK_V1, 1, phy_idx); + else + rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1, + B_PATH0_BAND_SEL_MSK_V1, 0, phy_idx); + /* SCO compensate FC setting */ + sco_comp = rtw8851b_sco_mapping(central_ch); + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_INV, sco_comp, phy_idx); + + if (chan->band_type == RTW89_BAND_6G) + return; + + /* CCK parameters */ + if (central_ch == 14) { + rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3b13ff); + rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x1c42de); + rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfdb0ad); + rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xf60f6e); + rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xfd8f92); + rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0x2d011); + rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0x1c02c); + rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xfff00a); + } else { + rtw89_phy_write32_mask(rtwdev, R_TXFIR0, B_TXFIR_C01, 0x3d23ff); + rtw89_phy_write32_mask(rtwdev, R_TXFIR2, B_TXFIR_C23, 0x29b354); + rtw89_phy_write32_mask(rtwdev, R_TXFIR4, B_TXFIR_C45, 0xfc1c8); + rtw89_phy_write32_mask(rtwdev, R_TXFIR6, B_TXFIR_C67, 0xfdb053); + rtw89_phy_write32_mask(rtwdev, R_TXFIR8, B_TXFIR_C89, 0xf86f9a); + rtw89_phy_write32_mask(rtwdev, R_TXFIRA, B_TXFIR_CAB, 0xfaef92); + rtw89_phy_write32_mask(rtwdev, R_TXFIRC, B_TXFIR_CCD, 0xfe5fcc); + rtw89_phy_write32_mask(rtwdev, R_TXFIRE, B_TXFIR_CEF, 0xffdff5); + } + + rtw8851b_set_gain_error(rtwdev, subband, RF_PATH_A); + rtw8851b_set_gain_offset(rtwdev, subband, phy_idx); + rtw8851b_set_rxsc_rpl_comp(rtwdev, subband); +} + +static void rtw8851b_bw_setting(struct rtw89_dev *rtwdev, u8 bw) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_CTL, 0x8); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_EN, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW0, B_P0_CFCH_BW0, 0x2); + rtw89_phy_write32_mask(rtwdev, R_P0_CFCH_BW1, B_P0_CFCH_BW1, 0x4); + rtw89_phy_write32_mask(rtwdev, R_DRCK, B_DRCK_MUL, 0xf); + rtw89_phy_write32_mask(rtwdev, R_ADCMOD, B_ADCMOD_LP, 0xa); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK, B_P0_RXCK_ADJ, 0x92); + + switch (bw) { + case RTW89_CHANNEL_WIDTH_5: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x1); + break; + case RTW89_CHANNEL_WIDTH_10: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x1); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + case RTW89_CHANNEL_WIDTH_20: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + case RTW89_CHANNEL_WIDTH_40: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x2); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + case RTW89_CHANNEL_WIDTH_80: + rtw89_phy_write32_mask(rtwdev, R_DCIM, B_DCIM_FR, 0x0); + rtw89_phy_write32_mask(rtwdev, R_WDADC, B_WDADC_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_ADDCK0D, B_ADDCK_DS, 0x0); + break; + default: + rtw89_warn(rtwdev, "Fail to set ADC\n"); + } +} + +static void rtw8851b_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw, + enum rtw89_phy_idx phy_idx) +{ + switch (bw) { + case RTW89_CHANNEL_WIDTH_5: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x1, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx); + break; + case RTW89_CHANNEL_WIDTH_10: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x2, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx); + break; + case RTW89_CHANNEL_WIDTH_20: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, 0x0, phy_idx); + break; + case RTW89_CHANNEL_WIDTH_40: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x1, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, + pri_ch, phy_idx); + /* CCK primary channel */ + if (pri_ch == RTW89_SC_20_UPPER) + rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 1); + else + rtw89_phy_write32_mask(rtwdev, R_RXSC, B_RXSC_EN, 0); + + break; + case RTW89_CHANNEL_WIDTH_80: + rtw89_phy_write32_idx(rtwdev, R_FC0_BW_V1, B_FC0_BW_SET, 0x2, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_SBW, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_CHBW_MOD_V1, B_CHBW_MOD_PRICH, + pri_ch, phy_idx); + break; + default: + rtw89_warn(rtwdev, "Fail to switch bw (bw:%d, pri ch:%d)\n", bw, + pri_ch); + } + + rtw8851b_bw_setting(rtwdev, bw); +} + +static void rtw8851b_ctrl_cck_en(struct rtw89_dev *rtwdev, bool cck_en) +{ + if (cck_en) { + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0); + rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF, + B_PD_ARBITER_OFF, 0); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1); + } else { + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1); + rtw89_phy_write32_mask(rtwdev, R_PD_ARBITER_OFF, + B_PD_ARBITER_OFF, 1); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 0); + } +} + +static u32 rtw8851b_spur_freq(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + u8 center_chan = chan->channel; + + switch (chan->band_type) { + case RTW89_BAND_5G: + if (center_chan == 151 || center_chan == 153 || + center_chan == 155 || center_chan == 163) + return 5760; + else if (center_chan == 54 || center_chan == 58) + return 5280; + break; + default: + break; + } + + return 0; +} + +#define CARRIER_SPACING_312_5 312500 /* 312.5 kHz */ +#define CARRIER_SPACING_78_125 78125 /* 78.125 kHz */ +#define MAX_TONE_NUM 2048 + +static void rtw8851b_set_csi_tone_idx(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u32 spur_freq; + s32 freq_diff, csi_idx, csi_tone_idx; + + spur_freq = rtw8851b_spur_freq(rtwdev, chan); + if (spur_freq == 0) { + rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN, + 0, phy_idx); + return; + } + + freq_diff = (spur_freq - chan->freq) * 1000000; + csi_idx = s32_div_u32_round_closest(freq_diff, CARRIER_SPACING_78_125); + s32_div_u32_round_down(csi_idx, MAX_TONE_NUM, &csi_tone_idx); + + rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_V1, B_SEG0CSI_IDX, + csi_tone_idx, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN_V1, B_SEG0CSI_EN, 1, phy_idx); +} + +static const struct rtw89_nbi_reg_def rtw8851b_nbi_reg_def = { + .notch1_idx = {0x46E4, 0xFF}, + .notch1_frac_idx = {0x46E4, 0xC00}, + .notch1_en = {0x46E4, 0x1000}, + .notch2_idx = {0x47A4, 0xFF}, + .notch2_frac_idx = {0x47A4, 0xC00}, + .notch2_en = {0x47A4, 0x1000}, +}; + +static void rtw8851b_set_nbi_tone_idx(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan) +{ + const struct rtw89_nbi_reg_def *nbi = &rtw8851b_nbi_reg_def; + s32 nbi_frac_idx, nbi_frac_tone_idx; + s32 nbi_idx, nbi_tone_idx; + bool notch2_chk = false; + u32 spur_freq, fc; + s32 freq_diff; + + spur_freq = rtw8851b_spur_freq(rtwdev, chan); + if (spur_freq == 0) { + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 0); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 0); + return; + } + + fc = chan->freq; + if (chan->band_width == RTW89_CHANNEL_WIDTH_160) { + fc = (spur_freq > fc) ? fc + 40 : fc - 40; + if ((fc > spur_freq && + chan->channel < chan->primary_channel) || + (fc < spur_freq && + chan->channel > chan->primary_channel)) + notch2_chk = true; + } + + freq_diff = (spur_freq - fc) * 1000000; + nbi_idx = s32_div_u32_round_down(freq_diff, CARRIER_SPACING_312_5, + &nbi_frac_idx); + + if (chan->band_width == RTW89_CHANNEL_WIDTH_20) { + s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx); + } else { + u16 tone_para = (chan->band_width == RTW89_CHANNEL_WIDTH_40) ? + 128 : 256; + + s32_div_u32_round_down(nbi_idx, tone_para, &nbi_tone_idx); + } + nbi_frac_tone_idx = s32_div_u32_round_closest(nbi_frac_idx, + CARRIER_SPACING_78_125); + + if (chan->band_width == RTW89_CHANNEL_WIDTH_160 && notch2_chk) { + rtw89_phy_write32_mask(rtwdev, nbi->notch2_idx.addr, + nbi->notch2_idx.mask, nbi_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_frac_idx.addr, + nbi->notch2_frac_idx.mask, nbi_frac_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 0); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 1); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 0); + } else { + rtw89_phy_write32_mask(rtwdev, nbi->notch1_idx.addr, + nbi->notch1_idx.mask, nbi_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_frac_idx.addr, + nbi->notch1_frac_idx.mask, nbi_frac_tone_idx); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 0); + rtw89_phy_write32_mask(rtwdev, nbi->notch1_en.addr, + nbi->notch1_en.mask, 1); + rtw89_phy_write32_mask(rtwdev, nbi->notch2_en.addr, + nbi->notch2_en.mask, 0); + } +} + +static void rtw8851b_set_cfr(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan) +{ + if (chan->band_type == RTW89_BAND_2G && + chan->band_width == RTW89_CHANNEL_WIDTH_20 && + (chan->channel == 1 || chan->channel == 13)) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC0, 0xf8); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC1, 0x120); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x3); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC0, 0x120); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_CFR, + B_PATH0_TX_CFR_LGC1, 0x3ff); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC0, 0x3); + rtw89_phy_write32_mask(rtwdev, R_PATH0_TX_POLAR_CLIPPING, + B_PATH0_TX_POLAR_CLIPPING_LGC1, 0x7); + } +} + +static void rtw8851b_5m_mask(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 pri_ch = chan->pri_ch_idx; + bool mask_5m_low; + bool mask_5m_en; + + switch (chan->band_width) { + case RTW89_CHANNEL_WIDTH_40: + /* Prich=1: Mask 5M High, Prich=2: Mask 5M Low */ + mask_5m_en = true; + mask_5m_low = pri_ch == RTW89_SC_20_LOWER; + break; + case RTW89_CHANNEL_WIDTH_80: + /* Prich=3: Mask 5M High, Prich=4: Mask 5M Low, Else: Disable */ + mask_5m_en = pri_ch == RTW89_SC_20_UPMOST || + pri_ch == RTW89_SC_20_LOWEST; + mask_5m_low = pri_ch == RTW89_SC_20_LOWEST; + break; + default: + mask_5m_en = false; + break; + } + + if (!mask_5m_en) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x0); + rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1, + B_ASSIGN_SBD_OPT_EN_V1, 0x0, phy_idx); + return; + } + + if (mask_5m_low) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x1); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_TH, 0x5); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB2, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_5MDET_V1, B_PATH0_5MDET_SB0, 0x0); + } + rtw89_phy_write32_idx(rtwdev, R_ASSIGN_SBD_OPT_V1, + B_ASSIGN_SBD_OPT_EN_V1, 0x1, phy_idx); +} + +static void rtw8851b_bb_reset_all(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx); + fsleep(1); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx); +} + +static void rtw8851b_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band, + enum rtw89_phy_idx phy_idx, bool en) +{ + if (en) { + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, + B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 1, phy_idx); + if (band == RTW89_BAND_2G) + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0); + } else { + rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x1); + rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS, + B_S0_HW_SI_DIS_W_R_TRIG, 0x7, phy_idx); + fsleep(1); + rtw89_phy_write32_idx(rtwdev, R_RSTB_ASYNC, B_RSTB_ASYNC_ALL, 0, phy_idx); + } +} + +static void rtw8851b_bb_reset(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, + B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x1); + rtw89_phy_write32_set(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN); + rtw8851b_bb_reset_all(rtwdev, phy_idx); + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, + B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI, 0x3); + rtw89_phy_write32_clr(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN); +} + +static +void rtw8851b_bb_gpio_trsw(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + u8 tx_path_en, u8 trsw_tx, + u8 trsw_rx, u8 trsw_a, u8 trsw_b) +{ + u32 mask_ofst = 16; + u32 val; + + if (path != RF_PATH_A) + return; + + mask_ofst += (tx_path_en * 4 + trsw_tx * 2 + trsw_rx) * 2; + val = u32_encode_bits(trsw_a, B_P0_TRSW_A) | + u32_encode_bits(trsw_b, B_P0_TRSW_B); + + rtw89_phy_write32_mask(rtwdev, R_P0_TRSW, + (B_P0_TRSW_A | B_P0_TRSW_B) << mask_ofst, val); +} + +static void rtw8851b_bb_gpio_init(struct rtw89_dev *rtwdev) +{ + rtw89_phy_write32_set(rtwdev, R_P0_TRSW, B_P0_TRSW_A); + rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_X); + rtw89_phy_write32_clr(rtwdev, R_P0_TRSW, B_P0_TRSW_SO_A2); + rtw89_phy_write32(rtwdev, R_RFE_SEL0_BASE, 0x77777777); + rtw89_phy_write32(rtwdev, R_RFE_SEL32_BASE, 0x77777777); + + rtw89_phy_write32(rtwdev, R_RFE_E_A2, 0xffffffff); + rtw89_phy_write32(rtwdev, R_RFE_O_SEL_A2, 0); + rtw89_phy_write32(rtwdev, R_RFE_SEL0_A2, 0); + rtw89_phy_write32(rtwdev, R_RFE_SEL32_A2, 0); + + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 0, 0, 1); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 0, 1, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 0, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 0, 1, 1, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 0, 0, 1); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 0, 1, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 0, 1, 0); + rtw8851b_bb_gpio_trsw(rtwdev, RF_PATH_A, 1, 1, 1, 1, 0); +} + +static void rtw8851b_bb_macid_ctrl_init(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + u32 addr; + + for (addr = R_AX_PWR_MACID_LMT_TABLE0; + addr <= R_AX_PWR_MACID_LMT_TABLE127; addr += 4) + rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, 0); +} + +static void rtw8851b_bb_sethw(struct rtw89_dev *rtwdev) +{ + struct rtw89_phy_efuse_gain *gain = &rtwdev->efuse_gain; + + rtw89_phy_write32_clr(rtwdev, R_P0_EN_SOUND_WO_NDP, B_P0_EN_SOUND_WO_NDP); + + rtw8851b_bb_macid_ctrl_init(rtwdev, RTW89_PHY_0); + rtw8851b_bb_gpio_init(rtwdev); + + /* read these registers after loading BB parameters */ + gain->offset_base[RTW89_PHY_0] = + rtw89_phy_read32_mask(rtwdev, R_P0_RPL1, B_P0_RPL1_BIAS_MASK); + gain->rssi_base[RTW89_PHY_0] = + rtw89_phy_read32_mask(rtwdev, R_P1_RPL1, B_P0_RPL1_BIAS_MASK); +} + +static void rtw8851b_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 band = chan->band_type, chan_idx; + bool cck_en = chan->channel <= 14; + u8 pri_ch_idx = chan->pri_ch_idx; + + if (cck_en) + rtw8851b_ctrl_sco_cck(rtwdev, chan->primary_channel); + + rtw8851b_ctrl_ch(rtwdev, chan, phy_idx); + rtw8851b_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx); + rtw8851b_ctrl_cck_en(rtwdev, cck_en); + rtw8851b_set_nbi_tone_idx(rtwdev, chan); + rtw8851b_set_csi_tone_idx(rtwdev, chan, phy_idx); + + if (chan->band_type == RTW89_BAND_5G) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, + B_PATH0_BT_SHARE_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, + B_PATH0_BTG_PATH_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0); + rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1, + B_BT_DYN_DC_EST_EN_MSK, 0x0); + rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0); + } + + chan_idx = rtw89_encode_chan_idx(rtwdev, chan->primary_channel, band); + rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx); + rtw8851b_5m_mask(rtwdev, chan, phy_idx); + rtw8851b_set_cfr(rtwdev, chan); + rtw8851b_bb_reset_all(rtwdev, phy_idx); +} + +static void rtw8851b_set_channel(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_mac_idx mac_idx, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_set_channel_mac(rtwdev, chan, mac_idx); + rtw8851b_set_channel_bb(rtwdev, chan, phy_idx); + rtw8851b_set_channel_rf(rtwdev, chan, phy_idx); +} + +static void rtw8851b_tssi_cont_en(struct rtw89_dev *rtwdev, bool en, + enum rtw89_rf_path path) +{ + if (en) { + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x0); + } else { + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_TRK_EN, 0x1); + } +} + +static void rtw8851b_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, + u8 phy_idx) +{ + rtw8851b_tssi_cont_en(rtwdev, en, RF_PATH_A); +} + +static void rtw8851b_adc_en(struct rtw89_dev *rtwdev, bool en) +{ + if (en) + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0x0); + else + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RST, 0xf); +} + +static void rtw8851b_set_channel_help(struct rtw89_dev *rtwdev, bool enter, + struct rtw89_channel_help_params *p, + const struct rtw89_chan *chan, + enum rtw89_mac_idx mac_idx, + enum rtw89_phy_idx phy_idx) +{ + if (enter) { + rtw89_chip_stop_sch_tx(rtwdev, RTW89_MAC_0, &p->tx_en, RTW89_SCH_TX_SEL_ALL); + rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, false); + rtw8851b_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0); + rtw8851b_adc_en(rtwdev, false); + fsleep(40); + rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, false); + } else { + rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true); + rtw8851b_adc_en(rtwdev, true); + rtw8851b_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0); + rtw8851b_bb_reset_en(rtwdev, chan->band_type, phy_idx, true); + rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en); + } +} + +static void rtw8851b_rfk_init(struct rtw89_dev *rtwdev) +{ + rtwdev->is_tssi_mode[RF_PATH_A] = false; + rtwdev->is_tssi_mode[RF_PATH_B] = false; + + rtw8851b_dpk_init(rtwdev); + rtw8851b_aack(rtwdev); + rtw8851b_rck(rtwdev); + rtw8851b_dack(rtwdev); + rtw8851b_rx_dck(rtwdev, RTW89_PHY_0); +} + +static void rtw8851b_rfk_channel(struct rtw89_dev *rtwdev) +{ + enum rtw89_phy_idx phy_idx = RTW89_PHY_0; + + rtw8851b_rx_dck(rtwdev, phy_idx); + rtw8851b_iqk(rtwdev, phy_idx); + rtw8851b_tssi(rtwdev, phy_idx, true); + rtw8851b_dpk(rtwdev, phy_idx); +} + +static void rtw8851b_rfk_band_changed(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_tssi_scan(rtwdev, phy_idx); +} + +static void rtw8851b_rfk_scan(struct rtw89_dev *rtwdev, bool start) +{ + rtw8851b_wifi_scan_notify(rtwdev, start, RTW89_PHY_0); +} + +static void rtw8851b_rfk_track(struct rtw89_dev *rtwdev) +{ + rtw8851b_dpk_track(rtwdev); +} + +static u32 rtw8851b_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx, s16 ref) +{ + const u16 tssi_16dbm_cw = 0x12c; + const u8 base_cw_0db = 0x27; + const s8 ofst_int = 0; + s16 pwr_s10_3; + s16 rf_pwr_cw; + u16 bb_pwr_cw; + u32 pwr_cw; + u32 tssi_ofst_cw; + + pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3); + bb_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(2, 0)); + rf_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(8, 3)); + rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63); + pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw; + + tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n", + tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw); + + return u32_encode_bits(tssi_ofst_cw, B_DPD_TSSI_CW) | + u32_encode_bits(pwr_cw, B_DPD_PWR_CW) | + u32_encode_bits(ref, B_DPD_REF); +} + +static void rtw8851b_set_txpwr_ref(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + static const u32 addr[RF_PATH_NUM_8851B] = {0x5800}; + const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF; + const u8 ofst_ofdm = 0x4; + const u8 ofst_cck = 0x8; + const s16 ref_ofdm = 0; + const s16 ref_cck = 0; + u32 val; + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr reference\n"); + + rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL, + B_AX_PWR_REF, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n"); + val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm); + + for (i = 0; i < RF_PATH_NUM_8851B; i++) + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, + phy_idx); + + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n"); + val = rtw8851b_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck); + + for (i = 0; i < RF_PATH_NUM_8851B; i++) + rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, + phy_idx); +} + +static void rtw8851b_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + u8 tx_shape_idx, + enum rtw89_phy_idx phy_idx) +{ +#define __DFIR_CFG_ADDR(i) (R_TXFIR0 + ((i) << 2)) +#define __DFIR_CFG_MASK 0xffffffff +#define __DFIR_CFG_NR 8 +#define __DECL_DFIR_PARAM(_name, _val...) \ + static const u32 param_ ## _name[] = {_val}; \ + static_assert(ARRAY_SIZE(param_ ## _name) == __DFIR_CFG_NR) + + __DECL_DFIR_PARAM(flat, + 0x023D23FF, 0x0029B354, 0x000FC1C8, 0x00FDB053, + 0x00F86F9A, 0x06FAEF92, 0x00FE5FCC, 0x00FFDFF5); + __DECL_DFIR_PARAM(sharp, + 0x023D83FF, 0x002C636A, 0x0013F204, 0x00008090, + 0x00F87FB0, 0x06F99F83, 0x00FDBFBA, 0x00003FF5); + __DECL_DFIR_PARAM(sharp_14, + 0x023B13FF, 0x001C42DE, 0x00FDB0AD, 0x00F60F6E, + 0x00FD8F92, 0x0602D011, 0x0001C02C, 0x00FFF00A); + u8 ch = chan->channel; + const u32 *param; + u32 addr; + int i; + + if (ch > 14) { + rtw89_warn(rtwdev, + "set tx shape dfir by unknown ch: %d on 2G\n", ch); + return; + } + + if (ch == 14) + param = param_sharp_14; + else + param = tx_shape_idx == 0 ? param_flat : param_sharp; + + for (i = 0; i < __DFIR_CFG_NR; i++) { + addr = __DFIR_CFG_ADDR(i); + rtw89_debug(rtwdev, RTW89_DBG_TXPWR, + "set tx shape dfir: 0x%x: 0x%x\n", addr, param[i]); + rtw89_phy_write32_idx(rtwdev, addr, __DFIR_CFG_MASK, param[i], + phy_idx); + } + +#undef __DECL_DFIR_PARAM +#undef __DFIR_CFG_NR +#undef __DFIR_CFG_MASK +#undef __DECL_CFG_ADDR +} + +static void rtw8851b_set_tx_shape(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + u8 band = chan->band_type; + u8 regd = rtw89_regd_get(rtwdev, band); + u8 tx_shape_cck = rtw89_8851b_tx_shape[band][RTW89_RS_CCK][regd]; + u8 tx_shape_ofdm = rtw89_8851b_tx_shape[band][RTW89_RS_OFDM][regd]; + + if (band == RTW89_BAND_2G) + rtw8851b_bb_set_tx_shape_dfir(rtwdev, chan, tx_shape_cck, phy_idx); + + rtw89_phy_write32_mask(rtwdev, R_DCFO_OPT, B_TXSHAPE_TRIANGULAR_CFG, + tx_shape_ofdm); +} + +static void rtw8851b_set_txpwr(struct rtw89_dev *rtwdev, + const struct rtw89_chan *chan, + enum rtw89_phy_idx phy_idx) +{ + rtw89_phy_set_txpwr_byrate(rtwdev, chan, phy_idx); + rtw89_phy_set_txpwr_offset(rtwdev, chan, phy_idx); + rtw8851b_set_tx_shape(rtwdev, chan, phy_idx); + rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx); + rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx); +} + +static void rtw8851b_set_txpwr_ctrl(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy_idx) +{ + rtw8851b_set_txpwr_ref(rtwdev, phy_idx); +} + +static +void rtw8851b_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev, + s8 pw_ofst, enum rtw89_mac_idx mac_idx) +{ + u32 reg; + + if (pw_ofst < -16 || pw_ofst > 15) { + rtw89_warn(rtwdev, "[ULTB] Err pwr_offset=%d\n", pw_ofst); + return; + } + + reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_CTRL, mac_idx); + rtw89_write32_set(rtwdev, reg, B_AX_PWR_UL_TB_CTRL_EN); + + reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_1T, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_1T_MASK, pw_ofst); + + pw_ofst = max_t(s8, pw_ofst - 3, -16); + reg = rtw89_mac_reg_by_idx(R_AX_PWR_UL_TB_2T, mac_idx); + rtw89_write32_mask(rtwdev, reg, B_AX_PWR_UL_TB_2T_MASK, pw_ofst); +} + +static int +rtw8851b_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + int ret; + + ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL2, 0x07763333); + if (ret) + return ret; + + ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_COEXT_CTRL, 0x01ebf000); + if (ret) + return ret; + + ret = rtw89_mac_txpwr_write32(rtwdev, phy_idx, R_AX_PWR_UL_CTRL0, 0x0002f8ff); + if (ret) + return ret; + + rtw8851b_set_txpwr_ul_tb_offset(rtwdev, 0, phy_idx == RTW89_PHY_1 ? + RTW89_MAC_1 : RTW89_MAC_0); + + return 0; +} + +static void rtw8851b_bb_ctrl_btc_preagc(struct rtw89_dev *rtwdev, bool bt_en) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + + rtw89_phy_write_reg3_tbl(rtwdev, bt_en ? &rtw8851b_btc_preagc_en_defs_tbl : + &rtw8851b_btc_preagc_dis_defs_tbl); + + if (!bt_en) { + if (chan->band_type == RTW89_BAND_2G) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x20); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x1a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a); + } + } +} + +static void rtw8851b_ctrl_btg(struct rtw89_dev *rtwdev, bool btg) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + + if (btg) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, + B_PATH0_BT_SHARE_V1, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, + B_PATH0_BTG_PATH_V1, 0x1); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x20); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x30); + rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x1); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x1); + rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1, + B_BT_DYN_DC_EST_EN_MSK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x1); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_BT_SHARE_V1, + B_PATH0_BT_SHARE_V1, 0x0); + rtw89_phy_write32_mask(rtwdev, R_PATH0_BTG_PATH_V1, + B_PATH0_BTG_PATH_V1, 0x0); + if (chan->band_type == RTW89_BAND_2G) { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x80); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x80); + } else { + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_LNA6_OP1DB_V1, + B_PATH0_G_LNA6_OP1DB_V1, 0x1a); + rtw89_phy_write32_mask(rtwdev, R_PATH0_G_TIA0_LNA6_OP1DB_V1, + B_PATH0_G_TIA0_LNA6_OP1DB_V1, 0x2a); + } + rtw89_phy_write32_mask(rtwdev, R_PMAC_GNT, B_PMAC_GNT_P1, 0xc); + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_BT_SHARE, 0x0); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_BT_SEG0, 0x0); + rtw89_phy_write32_mask(rtwdev, R_BT_DYN_DC_EST_EN_V1, + B_BT_DYN_DC_EST_EN_MSK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_GNT_BT_WGT_EN, B_GNT_BT_WGT_EN, 0x0); + } +} + +static void rtw8851b_bb_ctrl_rx_path(struct rtw89_dev *rtwdev, + enum rtw89_rf_path_bit rx_path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u32 rst_mask0; + + if (rx_path == RF_A) { + rtw89_phy_write32_mask(rtwdev, R_CHBW_MOD_V1, B_ANT_RX_SEG0, 1); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG0, 1); + rtw89_phy_write32_mask(rtwdev, R_FC0_BW_V1, B_ANT_RX_1RCCA_SEG1, 1); + rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_USER_MAX, 4); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0); + } + + rtw8851b_set_gain_offset(rtwdev, chan->subband_type, RTW89_PHY_0); + + rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI; + if (rx_path == RF_A) { + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 1); + rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB, rst_mask0, 3); + } +} + +static void rtw8851b_bb_cfg_txrx_path(struct rtw89_dev *rtwdev) +{ + rtw8851b_bb_ctrl_rx_path(rtwdev, RF_A); + + if (rtwdev->hal.rx_nss == 1) { + rtw89_phy_write32_mask(rtwdev, R_RXHT_MCS_LIMIT, B_RXHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXVHT_MCS_LIMIT, B_RXVHT_MCS_LIMIT, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHE_MAX_NSS, 0); + rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS, 0); + } + + rtw89_phy_write32_idx(rtwdev, R_MAC_SEL, B_MAC_SEL_MOD, 0x0, RTW89_PHY_0); +} + +static u8 rtw8851b_get_thermal(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path) +{ + if (rtwdev->is_tssi_mode[rf_path]) { + u32 addr = R_TSSI_THER + (rf_path << 13); + + return rtw89_phy_read32_mask(rtwdev, addr, B_TSSI_THER); + } + + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x0); + rtw89_write_rf(rtwdev, rf_path, RR_TM, RR_TM_TRI, 0x1); + + fsleep(200); + + return rtw89_read_rf(rtwdev, rf_path, RR_TM, RR_TM_VAL); +} + +static void rtw8851b_btc_set_rfe(struct rtw89_dev *rtwdev) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_module *module = &btc->mdinfo; + + module->rfe_type = rtwdev->efuse.rfe_type; + module->cv = rtwdev->hal.cv; + module->bt_solo = 0; + module->switch_type = BTC_SWITCH_INTERNAL; + module->ant.isolation = 10; + module->kt_ver_adie = rtwdev->hal.acv; + + if (module->rfe_type == 0) + return; + + /* rfe_type 3*n+1: 1-Ant(shared), + * 3*n+2: 2-Ant+Div(non-shared), + * 3*n+3: 2-Ant+no-Div(non-shared) + */ + module->ant.num = (module->rfe_type % 3 == 1) ? 1 : 2; + /* WL-1ss at S0, btg at s0 (On 1 WL RF) */ + module->ant.single_pos = RF_PATH_A; + module->ant.btg_pos = RF_PATH_A; + module->ant.stream_cnt = 1; + + if (module->ant.num == 1) { + module->ant.type = BTC_ANT_SHARED; + module->bt_pos = BTC_BT_BTG; + module->wa_type = 1; + module->ant.diversity = 0; + } else { /* ant.num == 2 */ + module->ant.type = BTC_ANT_DEDICATED; + module->bt_pos = BTC_BT_ALONE; + module->switch_type = BTC_SWITCH_EXTERNAL; + module->wa_type = 0; + if (module->rfe_type % 3 == 2) + module->ant.diversity = 1; + } +} + +static +void rtw8851b_set_trx_mask(struct rtw89_dev *rtwdev, u8 path, u8 group, u32 val) +{ + if (group > BTC_BT_SS_GROUP) + group--; /* Tx-group=1, Rx-group=2 */ + + if (rtwdev->btc.mdinfo.ant.type == BTC_ANT_SHARED) /* 1-Ant */ + group += 3; + + rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, group); + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val); +} + +static void rtw8851b_btc_init_cfg(struct rtw89_dev *rtwdev) +{ + static const struct rtw89_mac_ax_coex coex_params = { + .pta_mode = RTW89_MAC_AX_COEX_RTK_MODE, + .direction = RTW89_MAC_AX_COEX_INNER, + }; + const struct rtw89_chip_info *chip = rtwdev->chip; + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_module *module = &btc->mdinfo; + struct rtw89_btc_ant_info *ant = &module->ant; + u8 path, path_min, path_max; + + /* PTA init */ + rtw89_mac_coex_init(rtwdev, &coex_params); + + /* set WL Tx response = Hi-Pri */ + chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_TX_RESP, true); + chip->ops->btc_set_wl_pri(rtwdev, BTC_PRI_MASK_BEACON, true); + + /* for 1-Ant && 1-ss case: only 1-path */ + if (ant->stream_cnt == 1) { + path_min = ant->single_pos; + path_max = path_min; + } else { + path_min = RF_PATH_A; + path_max = RF_PATH_B; + } + + for (path = path_min; path <= path_max; path++) { + /* set rf gnt-debug off */ + rtw89_write_rf(rtwdev, path, RR_WLSEL, RFREG_MASK, 0x0); + + /* set DEBUG_LUT_RFMODE_MASK = 1 to start trx-mask-setup */ + rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, BIT(17)); + + /* if GNT_WL=0 && BT=SS_group --> WL Tx/Rx = THRU */ + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_SS_GROUP, 0x5ff); + + /* if GNT_WL=0 && BT=Rx_group --> WL-Rx = THRU + WL-Tx = MASK */ + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_RX_GROUP, 0x5df); + + /* if GNT_WL = 0 && BT = Tx_group --> + * Shared-Ant && BTG-path:WL mask(0x55f), others:WL THRU(0x5ff) + */ + if (ant->type == BTC_ANT_SHARED && ant->btg_pos == path) + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x55f); + else + rtw8851b_set_trx_mask(rtwdev, path, BTC_BT_TX_GROUP, 0x5ff); + + /* set DEBUG_LUT_RFMODE_MASK = 0 to stop trx-mask-setup */ + rtw89_write_rf(rtwdev, path, RR_LUTWE, RFREG_MASK, 0); + } + + /* set PTA break table */ + rtw89_write32(rtwdev, R_BTC_BREAK_TABLE, BTC_BREAK_PARAM); + + /* enable BT counter 0xda40[16,2] = 2b'11 */ + rtw89_write32_set(rtwdev, R_AX_CSR_MODE, B_AX_BT_CNT_RST | B_AX_STATIS_BT_EN); + + btc->cx.wl.status.map.init_ok = true; +} + +static +void rtw8851b_btc_set_wl_pri(struct rtw89_dev *rtwdev, u8 map, bool state) +{ + u32 bitmap; + u32 reg; + + switch (map) { + case BTC_PRI_MASK_TX_RESP: + reg = R_BTC_BT_COEX_MSK_TABLE; + bitmap = B_BTC_PRI_MASK_TX_RESP_V1; + break; + case BTC_PRI_MASK_BEACON: + reg = R_AX_WL_PRI_MSK; + bitmap = B_AX_PTA_WL_PRI_MASK_BCNQ; + break; + case BTC_PRI_MASK_RX_CCK: + reg = R_BTC_BT_COEX_MSK_TABLE; + bitmap = B_BTC_PRI_MASK_RXCCK_V1; + break; + default: + return; + } + + if (state) + rtw89_write32_set(rtwdev, reg, bitmap); + else + rtw89_write32_clr(rtwdev, reg, bitmap); +} + +union rtw8851b_btc_wl_txpwr_ctrl { + u32 txpwr_val; + struct { + union { + u16 ctrl_all_time; + struct { + s16 data:9; + u16 rsvd:6; + u16 flag:1; + } all_time; + }; + union { + u16 ctrl_gnt_bt; + struct { + s16 data:9; + u16 rsvd:7; + } gnt_bt; + }; + }; +} __packed; + +static void +rtw8851b_btc_set_wl_txpwr_ctrl(struct rtw89_dev *rtwdev, u32 txpwr_val) +{ + union rtw8851b_btc_wl_txpwr_ctrl arg = { .txpwr_val = txpwr_val }; + s32 val; + +#define __write_ctrl(_reg, _msk, _val, _en, _cond) \ +do { \ + u32 _wrt = FIELD_PREP(_msk, _val); \ + BUILD_BUG_ON(!!(_msk & _en)); \ + if (_cond) \ + _wrt |= _en; \ + else \ + _wrt &= ~_en; \ + rtw89_mac_txpwr_write32_mask(rtwdev, RTW89_PHY_0, _reg, \ + _msk | _en, _wrt); \ +} while (0) + + switch (arg.ctrl_all_time) { + case 0xffff: + val = 0; + break; + default: + val = arg.all_time.data; + break; + } + + __write_ctrl(R_AX_PWR_RATE_CTRL, B_AX_FORCE_PWR_BY_RATE_VALUE_MASK, + val, B_AX_FORCE_PWR_BY_RATE_EN, + arg.ctrl_all_time != 0xffff); + + switch (arg.ctrl_gnt_bt) { + case 0xffff: + val = 0; + break; + default: + val = arg.gnt_bt.data; + break; + } + + __write_ctrl(R_AX_PWR_COEXT_CTRL, B_AX_TXAGC_BT_MASK, val, + B_AX_TXAGC_BT_EN, arg.ctrl_gnt_bt != 0xffff); + +#undef __write_ctrl +} + +static +s8 rtw8851b_btc_get_bt_rssi(struct rtw89_dev *rtwdev, s8 val) +{ + val = clamp_t(s8, val, -100, 0) + 100; + val = min(val + 6, 100); /* compensate offset */ + + return val; +} + +static +void rtw8851b_btc_update_bt_cnt(struct rtw89_dev *rtwdev) +{ + /* Feature move to firmware */ +} + +static void rtw8851b_btc_wl_s1_standby(struct rtw89_dev *rtwdev, bool state) +{ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant; + + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x80000); + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWA, RFREG_MASK, 0x1); + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD1, RFREG_MASK, 0x110); + + /* set WL standby = Rx for GNT_BT_Tx = 1->0 settle issue */ + if (state) + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x179c); + else + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWD0, RFREG_MASK, 0x208); + + rtw89_write_rf(rtwdev, ant->btg_pos, RR_LUTWE, RFREG_MASK, 0x0); +} + +#define LNA2_51B_MA 0x700 + +static const struct rtw89_reg2_def btc_8851b_rf_0[] = {{0x2, 0x0}}; +static const struct rtw89_reg2_def btc_8851b_rf_1[] = {{0x2, 0x1}}; + +static void rtw8851b_btc_set_wl_rx_gain(struct rtw89_dev *rtwdev, u32 level) +{ + /* To improve BT ACI in co-rx + * level=0 Default: TIA 1/0= (LNA2,TIAN6) = (7,1)/(5,1) = 21dB/12dB + * level=1 Fix LNA2=5: TIA 1/0= (LNA2,TIAN6) = (5,0)/(5,1) = 18dB/12dB + */ + struct rtw89_btc *btc = &rtwdev->btc; + struct rtw89_btc_ant_info *ant = &btc->mdinfo.ant; + const struct rtw89_reg2_def *rf; + u32 n, i, val; + + switch (level) { + case 0: /* original */ + default: + btc->dm.wl_lna2 = 0; + break; + case 1: /* for FDD free-run */ + btc->dm.wl_lna2 = 0; + break; + case 2: /* for BTG Co-Rx*/ + btc->dm.wl_lna2 = 1; + break; + } + + if (btc->dm.wl_lna2 == 0) { + rf = btc_8851b_rf_0; + n = ARRAY_SIZE(btc_8851b_rf_0); + } else { + rf = btc_8851b_rf_1; + n = ARRAY_SIZE(btc_8851b_rf_1); + } + + for (i = 0; i < n; i++, rf++) { + val = rf->data; + /* bit[10] = 1 if non-shared-ant for 8851b */ + if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) + val |= 0x4; + + rtw89_write_rf(rtwdev, ant->btg_pos, rf->addr, LNA2_51B_MA, val); + } +} + +static void rtw8851b_fill_freq_with_ppdu(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu, + struct ieee80211_rx_status *status) +{ + u16 chan = phy_ppdu->chan_idx; + enum nl80211_band band; + u8 ch; + + if (chan == 0) + return; + + rtw89_decode_chan_idx(rtwdev, chan, &ch, &band); + status->freq = ieee80211_channel_to_frequency(ch, band); + status->band = band; +} + +static void rtw8851b_query_ppdu(struct rtw89_dev *rtwdev, + struct rtw89_rx_phy_ppdu *phy_ppdu, + struct ieee80211_rx_status *status) +{ + u8 path; + u8 *rx_power = phy_ppdu->rssi; + + status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]); + + for (path = 0; path < rtwdev->chip->rf_path_num; path++) { + status->chains |= BIT(path); + status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]); + } + if (phy_ppdu->valid) + rtw8851b_fill_freq_with_ppdu(rtwdev, phy_ppdu, status); +} + +static int rtw8851b_mac_enable_bb_rf(struct rtw89_dev *rtwdev) +{ + int ret; + + rtw89_write8_set(rtwdev, R_AX_SYS_FUNC_EN, + B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); + rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + rtw89_write32_clr(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + rtw89_write32_set(rtwdev, R_AX_WLRF_CTRL, B_AX_AFC_AFEDIG); + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xC7, + FULL_BIT_MASK); + if (ret) + return ret; + + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xC7, + FULL_BIT_MASK); + if (ret) + return ret; + + rtw89_write8(rtwdev, R_AX_PHYREG_SET, PHYREG_SET_XYN_CYCLE); + + return 0; +} + +static int rtw8851b_mac_disable_bb_rf(struct rtw89_dev *rtwdev) +{ + u8 wl_rfc_s0; + u8 wl_rfc_s1; + int ret; + + rtw89_write8_clr(rtwdev, R_AX_SYS_FUNC_EN, + B_AX_FEN_BBRSTB | B_AX_FEN_BB_GLB_RSTN); + + ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, &wl_rfc_s0); + if (ret) + return ret; + wl_rfc_s0 &= ~XTAL_SI_RF00S_EN; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, wl_rfc_s0, + FULL_BIT_MASK); + if (ret) + return ret; + + ret = rtw89_mac_read_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, &wl_rfc_s1); + if (ret) + return ret; + wl_rfc_s1 &= ~XTAL_SI_RF10S_EN; + ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, wl_rfc_s1, + FULL_BIT_MASK); + return ret; +} + static const struct rtw89_chip_ops rtw8851b_chip_ops = { + .enable_bb_rf = rtw8851b_mac_enable_bb_rf, + .disable_bb_rf = rtw8851b_mac_disable_bb_rf, + .bb_reset = rtw8851b_bb_reset, + .bb_sethw = rtw8851b_bb_sethw, + .read_rf = rtw89_phy_read_rf_v1, + .write_rf = rtw89_phy_write_rf_v1, + .set_channel = rtw8851b_set_channel, + .set_channel_help = rtw8851b_set_channel_help, + .read_efuse = rtw8851b_read_efuse, + .read_phycap = rtw8851b_read_phycap, .fem_setup = NULL, + .rfe_gpio = rtw8851b_rfe_gpio, + .rfk_init = rtw8851b_rfk_init, + .rfk_channel = rtw8851b_rfk_channel, + .rfk_band_changed = rtw8851b_rfk_band_changed, + .rfk_scan = rtw8851b_rfk_scan, + .rfk_track = rtw8851b_rfk_track, + .power_trim = rtw8851b_power_trim, + .set_txpwr = rtw8851b_set_txpwr, + .set_txpwr_ctrl = rtw8851b_set_txpwr_ctrl, + .init_txpwr_unit = rtw8851b_init_txpwr_unit, + .get_thermal = rtw8851b_get_thermal, + .ctrl_btg = rtw8851b_ctrl_btg, + .query_ppdu = rtw8851b_query_ppdu, + .bb_ctrl_btc_preagc = rtw8851b_bb_ctrl_btc_preagc, + .cfg_txrx_path = rtw8851b_bb_cfg_txrx_path, + .set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset, + .pwr_on_func = rtw8851b_pwr_on_func, + .pwr_off_func = rtw8851b_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, + .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, + .mac_cfg_gnt = rtw89_mac_cfg_gnt, + .stop_sch_tx = rtw89_mac_stop_sch_tx, + .resume_sch_tx = rtw89_mac_resume_sch_tx, .h2c_dctl_sec_cam = NULL, + + .btc_set_rfe = rtw8851b_btc_set_rfe, + .btc_init_cfg = rtw8851b_btc_init_cfg, + .btc_set_wl_pri = rtw8851b_btc_set_wl_pri, + .btc_set_wl_txpwr_ctrl = rtw8851b_btc_set_wl_txpwr_ctrl, + .btc_get_bt_rssi = rtw8851b_btc_get_bt_rssi, + .btc_update_bt_cnt = rtw8851b_btc_update_bt_cnt, + .btc_wl_s1_standby = rtw8851b_btc_wl_s1_standby, + .btc_set_wl_rx_gain = rtw8851b_btc_set_wl_rx_gain, + .btc_set_policy = rtw89_btc_set_policy_v1, }; #ifdef CONFIG_PM @@ -118,6 +2357,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .txpwr_factor_rf = 2, .txpwr_factor_mac = 1, .dig_table = NULL, + .dig_regs = &rtw8851b_dig_regs, .tssi_dbw_table = NULL, .support_chanctx_num = 0, .support_bands = BIT(NL80211_BAND_2GHZ) | @@ -149,6 +2389,16 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .scbd = 0x1, .mailbox = 0x1, + .afh_guard_ch = 6, + .wl_rssi_thres = rtw89_btc_8851b_wl_rssi_thres, + .bt_rssi_thres = rtw89_btc_8851b_bt_rssi_thres, + .rssi_tol = 2, + .mon_reg_num = ARRAY_SIZE(rtw89_btc_8851b_mon_reg), + .mon_reg = rtw89_btc_8851b_mon_reg, + .rf_para_ulink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_ul), + .rf_para_ulink = rtw89_btc_8851b_rf_ul, + .rf_para_dlink_num = ARRAY_SIZE(rtw89_btc_8851b_rf_dl), + .rf_para_dlink = rtw89_btc_8851b_rf_dl, .ps_mode_supported = BIT(RTW89_PS_MODE_RFOFF) | BIT(RTW89_PS_MODE_CLK_GATED), .low_power_hci_modes = 0, @@ -156,6 +2406,19 @@ const struct rtw89_chip_info rtw8851b_chip_info = { .hci_func_en_addr = R_AX_HCI_FUNC_EN, .h2c_desc_size = sizeof(struct rtw89_txwd_body), .txwd_body_size = sizeof(struct rtw89_txwd_body), + .h2c_ctrl_reg = R_AX_H2CREG_CTRL, + .h2c_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_H2C_DEQ_CNT_MASK >> 8}, + .h2c_regs = rtw8851b_h2c_regs, + .c2h_ctrl_reg = R_AX_C2HREG_CTRL, + .c2h_counter_reg = {R_AX_UDM1 + 1, B_AX_UDM1_HALMAC_C2H_ENQ_CNT_MASK >> 8}, + .c2h_regs = rtw8851b_c2h_regs, + .page_regs = &rtw8851b_page_regs, + .cfo_src_fd = true, + .cfo_hw_comp = true, + .dcfo_comp = &rtw8851b_dcfo_comp, + .dcfo_comp_sft = 12, + .imr_info = &rtw8851b_imr_info, + .rrsr_cfgs = &rtw8851b_rrsr_cfgs, .bss_clr_map_reg = R_BSS_CLR_MAP_V1, .dma_ch_mask = BIT(RTW89_DMA_ACH4) | BIT(RTW89_DMA_ACH5) | BIT(RTW89_DMA_ACH6) | BIT(RTW89_DMA_ACH7) | diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.h b/drivers/net/wireless/realtek/rtw89/rtw8851b.h index e34b7d09ad6df3..1a5c52654d8a44 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.h @@ -10,6 +10,67 @@ #define RF_PATH_NUM_8851B 1 #define BB_PATH_NUM_8851B 1 +struct rtw8851bu_efuse { + u8 rsvd[0x88]; + u8 mac_addr[ETH_ALEN]; +}; + +struct rtw8851be_efuse { + u8 mac_addr[ETH_ALEN]; +}; + +struct rtw8851b_tssi_offset { + u8 cck_tssi[TSSI_CCK_CH_GROUP_NUM]; + u8 bw40_tssi[TSSI_MCS_2G_CH_GROUP_NUM]; + u8 rsvd[7]; + u8 bw40_1s_tssi_5g[TSSI_MCS_5G_CH_GROUP_NUM]; +} __packed; + +struct rtw8851b_efuse { + u8 rsvd[0x210]; + struct rtw8851b_tssi_offset path_a_tssi; + u8 rsvd1[136]; + u8 channel_plan; + u8 xtal_k; + u8 rsvd2; + u8 iqk_lck; + u8 rsvd3[8]; + u8 eeprom_version; + u8 customer_id; + u8 tx_bb_swing_2g; + u8 tx_bb_swing_5g; + u8 tx_cali_pwr_trk_mode; + u8 trx_path_selection; + u8 rfe_type; + u8 country_code[2]; + u8 rsvd4[3]; + u8 path_a_therm; + u8 rsvd5[3]; + u8 rx_gain_2g_ofdm; + u8 rsvd6; + u8 rx_gain_2g_cck; + u8 rsvd7; + u8 rx_gain_5g_low; + u8 rsvd8; + u8 rx_gain_5g_mid; + u8 rsvd9; + u8 rx_gain_5g_high; + u8 rsvd10[35]; + u8 path_a_cck_pwr_idx[6]; + u8 path_a_bw40_1tx_pwr_idx[5]; + u8 path_a_ofdm_1tx_pwr_idx_diff:4; + u8 path_a_bw20_1tx_pwr_idx_diff:4; + u8 path_a_bw20_2tx_pwr_idx_diff:4; + u8 path_a_bw40_2tx_pwr_idx_diff:4; + u8 path_a_cck_2tx_pwr_idx_diff:4; + u8 path_a_ofdm_2tx_pwr_idx_diff:4; + u8 rsvd11[0xf2]; + union { + struct rtw8851bu_efuse u; + struct rtw8851be_efuse e; + }; +} __packed; + extern const struct rtw89_chip_info rtw8851b_chip_info; #endif diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c index 6eb47ed820102b..1899a5d69a810f 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c @@ -12,11 +12,49 @@ #include "rtw8851b_rfk_table.h" #include "rtw8851b_table.h" +#define DPK_VER_8851B 0x5 +#define DPK_KIP_REG_NUM_8851B 7 +#define DPK_RF_REG_NUM_8851B 4 +#define DPK_KSET_NUM 4 #define RTW8851B_RXK_GROUP_NR 4 #define RTW8851B_TXK_GROUP_NR 1 #define RTW8851B_IQK_VER 0x2a #define RTW8851B_IQK_SS 1 #define RTW8851B_LOK_GRAM 10 +#define RTW8851B_TSSI_PATH_NR 1 + +#define _TSSI_DE_MASK GENMASK(21, 12) + +enum dpk_id { + LBK_RXIQK = 0x06, + SYNC = 0x10, + MDPK_IDL = 0x11, + MDPK_MPA = 0x12, + GAIN_LOSS = 0x13, + GAIN_CAL = 0x14, + DPK_RXAGC = 0x15, + KIP_PRESET = 0x16, + KIP_RESTORE = 0x17, + DPK_TXAGC = 0x19, + D_KIP_PRESET = 0x28, + D_TXAGC = 0x29, + D_RXAGC = 0x2a, + D_SYNC = 0x2b, + D_GAIN_LOSS = 0x2c, + D_MDPK_IDL = 0x2d, + D_MDPK_LDL = 0x2e, + D_GAIN_NORM = 0x2f, + D_KIP_THERMAL = 0x30, + D_KIP_RESTORE = 0x31 +}; + +enum dpk_agc_step { + DPK_AGC_STEP_SYNC_DGAIN, + DPK_AGC_STEP_GAIN_LOSS_IDX, + DPK_AGC_STEP_GL_GT_CRITERION, + DPK_AGC_STEP_GL_LT_CRITERION, + DPK_AGC_STEP_SET_TX_GAIN, +}; enum rtw8851b_iqk_type { ID_TXAGC = 0x0, @@ -35,6 +73,25 @@ enum rtw8851b_iqk_type { ID_IQK_RESTORE = 0x10, }; +enum rf_mode { + RF_SHUT_DOWN = 0x0, + RF_STANDBY = 0x1, + RF_TX = 0x2, + RF_RX = 0x3, + RF_TXIQK = 0x4, + RF_DPK = 0x5, + RF_RXK1 = 0x6, + RF_RXK2 = 0x7, +}; + +static const u32 _tssi_de_cck_long[RF_PATH_NUM_8851B] = {0x5858}; +static const u32 _tssi_de_cck_short[RF_PATH_NUM_8851B] = {0x5860}; +static const u32 _tssi_de_mcs_20m[RF_PATH_NUM_8851B] = {0x5838}; +static const u32 _tssi_de_mcs_40m[RF_PATH_NUM_8851B] = {0x5840}; +static const u32 _tssi_de_mcs_80m[RF_PATH_NUM_8851B] = {0x5848}; +static const u32 _tssi_de_mcs_80m_80m[RF_PATH_NUM_8851B] = {0x5850}; +static const u32 _tssi_de_mcs_5m[RF_PATH_NUM_8851B] = {0x5828}; +static const u32 _tssi_de_mcs_10m[RF_PATH_NUM_8851B] = {0x5830}; static const u32 g_idxrxgain[RTW8851B_RXK_GROUP_NR] = {0x10e, 0x116, 0x28e, 0x296}; static const u32 g_idxattc2[RTW8851B_RXK_GROUP_NR] = {0x0, 0xf, 0x0, 0xf}; static const u32 g_idxrxagc[RTW8851B_RXK_GROUP_NR] = {0x0, 0x1, 0x2, 0x3}; @@ -57,6 +114,10 @@ static const u32 rtw8851b_backup_rf_regs[] = { #define BACKUP_BB_REGS_NR ARRAY_SIZE(rtw8851b_backup_bb_regs) #define BACKUP_RF_REGS_NR ARRAY_SIZE(rtw8851b_backup_rf_regs) +static const u32 dpk_kip_reg[DPK_KIP_REG_NUM_8851B] = { + 0x813c, 0x8124, 0xc0ec, 0xc0e8, 0xc0c4, 0xc0d4, 0xc0d8}; +static const u32 dpk_rf_reg[DPK_RF_REG_NUM_8851B] = {0xde, 0x8f, 0x5, 0x10005}; + static u8 _kpath(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) { return RF_A; @@ -70,6 +131,24 @@ static void _adc_fifo_rst(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, B_ADC_FIFO_RXK, 0x1111); } +static void _rfk_rf_direct_cntrl(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool is_bybb) +{ + if (is_bybb) + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x1); + else + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); +} + +static void _rfk_drf_direct_cntrl(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool is_bybb) +{ + if (is_bybb) + rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x1); + else + rtw89_write_rf(rtwdev, path, RR_BBDC, RR_BBDC_SEL, 0x0); +} + static void _wait_rx_mode(struct rtw89_dev *rtwdev, u8 kpath) { u32 rf_mode; @@ -427,6 +506,91 @@ static void _dac_cal(struct rtw89_dev *rtwdev, bool force) rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DACK]DACK finish!!!\n"); } +static void _rx_dck_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, bool is_afe) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RX_DCK] ==== S%d RX DCK (%s / CH%d / %s / by %s)====\n", path, + chan->band_type == RTW89_BAND_2G ? "2G" : + chan->band_type == RTW89_BAND_5G ? "5G" : "6G", + chan->channel, + chan->band_width == RTW89_CHANNEL_WIDTH_20 ? "20M" : + chan->band_width == RTW89_CHANNEL_WIDTH_40 ? "40M" : "80M", + is_afe ? "AFE" : "RFC"); +} + +static void _rxbb_ofst_swap(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode) +{ + u32 val, val_i, val_q; + + val_i = rtw89_read_rf(rtwdev, path, RR_DCK, RR_DCK_S1); + val_q = rtw89_read_rf(rtwdev, path, RR_DCK1, RR_DCK1_S1); + + val = val_q << 4 | val_i; + + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x1); + rtw89_write_rf(rtwdev, path, RR_LUTWA, RFREG_MASK, rf_mode); + rtw89_write_rf(rtwdev, path, RR_LUTWD0, RFREG_MASK, val); + rtw89_write_rf(rtwdev, path, RR_LUTWE2, RR_LUTWE2_DIS, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RX_DCK] val_i = 0x%x, val_q = 0x%x, 0x3F = 0x%x\n", + val_i, val_q, val); +} + +static void _set_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 rf_mode) +{ + u32 val; + int ret; + + rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0); + rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x1); + + ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, + 2, 2000, false, + rtwdev, path, RR_DCK, BIT(8)); + + rtw89_write_rf(rtwdev, path, RR_DCK, RR_DCK_LV, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RX_DCK] S%d RXDCK finish (ret = %d)\n", + path, ret); + + _rxbb_ofst_swap(rtwdev, path, rf_mode); +} + +static void _rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool is_afe) +{ + u32 rf_reg5; + u8 path; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[RX_DCK] ****** RXDCK Start (Ver: 0x%x, Cv: %d) ******\n", + 0x2, rtwdev->hal.cv); + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + _rx_dck_info(rtwdev, phy, path, is_afe); + + rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK); + + if (rtwdev->is_tssi_mode[path]) + rtw89_phy_write32_mask(rtwdev, + R_P0_TSSI_TRK + (path << 13), + B_P0_TSSI_TRK_EN, 0x1); + + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX); + _set_rx_dck(rtwdev, path, RF_RX); + rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5); + + if (rtwdev->is_tssi_mode[path]) + rtw89_phy_write32_mask(rtwdev, + R_P0_TSSI_TRK + (path << 13), + B_P0_TSSI_TRK_EN, 0x0); + } +} + static void _iqk_sram(struct rtw89_dev *rtwdev, u8 path) { u32 i; @@ -1450,107 +1614,1719 @@ static void _iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, bool forc _doiqk(rtwdev, force, phy_idx, RF_PATH_A); } -static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +static void _dpk_bkup_kip(struct rtw89_dev *rtwdev, const u32 *reg, + u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path) { - u32 rf_reg5; - u32 rck_val; + u8 i; + + for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) { + reg_bkup[path][i] = + rtw89_phy_read32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup 0x%x = %x\n", + reg[i] + (path << 8), reg_bkup[path][i]); + } +} + +static void _dpk_bkup_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg, + u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) { + rf_bkup[path][i] = rtw89_read_rf(rtwdev, path, rf_reg[i], RFREG_MASK); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Backup RF S%d 0x%x = %x\n", + path, rf_reg[i], rf_bkup[path][i]); + } +} + +static void _dpk_reload_kip(struct rtw89_dev *rtwdev, const u32 *reg, + u32 reg_bkup[][DPK_KIP_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_KIP_REG_NUM_8851B; i++) { + rtw89_phy_write32_mask(rtwdev, reg[i] + (path << 8), MASKDWORD, + reg_bkup[path][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Reload 0x%x = %x\n", + reg[i] + (path << 8), reg_bkup[path][i]); + } +} + +static void _dpk_reload_rf(struct rtw89_dev *rtwdev, const u32 *rf_reg, + u32 rf_bkup[][DPK_RF_REG_NUM_8851B], u8 path) +{ + u8 i; + + for (i = 0; i < DPK_RF_REG_NUM_8851B; i++) { + rtw89_write_rf(rtwdev, path, rf_reg[i], RFREG_MASK, rf_bkup[path][i]); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Reload RF S%d 0x%x = %x\n", path, + rf_reg[i], rf_bkup[path][i]); + } +} + +static void _dpk_one_shot(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, enum dpk_id id) +{ + u16 dpk_cmd; u32 val; int ret; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] ====== S%d RCK ======\n", path); + dpk_cmd = ((id << 8) | (0x19 + path * 0x12)); + rtw89_phy_write32_mask(rtwdev, R_NCTL_CFG, MASKDWORD, dpk_cmd); - rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK); + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x55, + 10, 20000, false, + rtwdev, 0xbff8, MASKBYTE0); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 1 timeout\n"); - rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); - rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX); + udelay(1); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF0x00 = 0x%05x\n", - rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + ret = read_poll_timeout_atomic(rtw89_phy_read32_mask, val, val == 0x8000, + 1, 2000, false, + rtwdev, R_RPT_COM, MASKLWORD); + if (ret) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] one-shot 2 timeout\n"); - /* RCK trigger */ - rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, 0x00240); + rtw89_phy_write32_mask(rtwdev, R_NCTL_N1, MASKBYTE0, 0x0); - ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, 2, 30, - false, rtwdev, path, RR_RCKS, BIT(3)); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] one-shot for %s = 0x%04x\n", + id == 0x28 ? "KIP_PRESET" : + id == 0x29 ? "DPK_TXAGC" : + id == 0x2a ? "DPK_RXAGC" : + id == 0x2b ? "SYNC" : + id == 0x2c ? "GAIN_LOSS" : + id == 0x2d ? "MDPK_IDL" : + id == 0x2f ? "DPK_GAIN_NORM" : + id == 0x31 ? "KIP_RESTORE" : + id == 0x6 ? "LBK_RXIQK" : "Unknown id", + dpk_cmd); +} - rck_val = rtw89_read_rf(rtwdev, path, RR_RCKC, RR_RCKC_CA); +static void _dpk_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool off) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 kidx = dpk->cur_idx[path]; + u8 off_reverse = off ? 0 : 1; + u8 val; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] rck_val = 0x%x, ret = %d\n", - rck_val, ret); + val = dpk->is_dpk_enable * off_reverse * dpk->bp[path][kidx].path_ok; - rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, rck_val); - rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5); + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + 0xf0000000, val); - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF 0x1b = 0x%x\n", - rtw89_read_rf(rtwdev, path, RR_RCKC, RFREG_MASK)); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] DPK %s !!!\n", path, + kidx, val == 0 ? "disable" : "enable"); } -void rtw8851b_aack(struct rtw89_dev *rtwdev) +static void _dpk_init(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) { - u32 tmp05, ib[4]; - u32 tmp; - int ret; - int rek; - int i; + struct rtw89_dpk_info *dpk = &rtwdev->dpk; - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO AACK\n"); + u8 kidx = dpk->cur_idx[path]; - tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0); + dpk->bp[path][kidx].path_ok = 0; +} - for (rek = 0; rek < 4; rek++) { - rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201e); - rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201f); - fsleep(100); +static void _dpk_information(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + struct rtw89_dpk_info *dpk = &rtwdev->dpk; - ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp, - 1, 1000, false, - rtwdev, RF_PATH_A, 0xd0, BIT(16)); - if (ret) - rtw89_warn(rtwdev, "[LCK]AACK timeout\n"); + u8 kidx = dpk->cur_idx[path]; - rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x1); - for (i = 0; i < 4; i++) { - rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCO, RR_VCO_SEL, i); - ib[i] = rtw89_read_rf(rtwdev, RF_PATH_A, RR_IBD, RR_IBD_VAL); - } - rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x0); + dpk->bp[path][kidx].band = chan->band_type; + dpk->bp[path][kidx].ch = chan->band_width; + dpk->bp[path][kidx].bw = chan->channel; - if (ib[0] != 0 && ib[1] != 0 && ib[2] != 0 && ib[3] != 0) - break; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n", + path, dpk->cur_idx[path], phy, + rtwdev->is_tssi_mode[path] ? "on" : "off", + rtwdev->dbcc_en ? "on" : "off", + dpk->bp[path][kidx].band == 0 ? "2G" : + dpk->bp[path][kidx].band == 1 ? "5G" : "6G", + dpk->bp[path][kidx].ch, + dpk->bp[path][kidx].bw == 0 ? "20M" : + dpk->bp[path][kidx].bw == 1 ? "40M" : + dpk->bp[path][kidx].bw == 2 ? "80M" : "160M"); +} + +static void _dpk_rxagc_onoff(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool turn_on) +{ + if (path == RF_PATH_A) + rtw89_phy_write32_mask(rtwdev, R_P0_AGC_CTL, B_P0_AGC_EN, turn_on); + else + rtw89_phy_write32_mask(rtwdev, R_P1_AGC_CTL, B_P1_AGC_EN, turn_on); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d RXAGC is %s\n", path, + turn_on ? "turn_on" : "turn_off"); +} + +static void _dpk_bb_afe_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0xd801dffd); + + rtw89_rfk_parser(rtwdev, &rtw8851b_iqk_bb_afe_defs_tbl); + + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x1); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE setting\n", path); +} + +static void _dpk_bb_afe_restore(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_NRBW + (path << 13), B_P0_NRBW_DBG, 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(20 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x1); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(28 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), MASKDWORD, 0x00000000); + rtw89_phy_write32_mask(rtwdev, R_P0_RXCK + (path << 13), B_P0_TXCK_ALL, 0x00); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(16 + path), 0x0); + rtw89_phy_write32_mask(rtwdev, R_ADC_FIFO, BIT(24 + path), 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d BB/AFE restore\n", path); +} + +static void _dpk_tssi_pause(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, + bool is_pause) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK + (path << 13), + B_P0_TSSI_TRK_EN, is_pause); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d TSSI %s\n", path, + is_pause ? "pause" : "resume"); +} + +static void _dpk_tpg_sel(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80) { + rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x0); + rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xffe0fa00); + } else if (dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40) { + rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x2); + rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xff4009e0); + } else { + rtw89_phy_write32_mask(rtwdev, R_TPG_MOD, B_TPG_MOD_F, 0x1); + rtw89_phy_write32_mask(rtwdev, R_TPG_SEL, MASKDWORD, 0xf9f007d0); } - if (rek != 0) - rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]AACK rek = %d\n", rek); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] TPG Select for %s\n", + dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_80 ? "80M" : + dpk->bp[path][kidx].bw == RTW89_CHANNEL_WIDTH_40 ? "40M" : "20M"); +} - rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05); +static void _dpk_txpwr_bb_force(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool force) +{ + rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13), B_TXPWRB_ON, force); + rtw89_phy_write32_mask(rtwdev, R_TXPWRB_H + (path << 13), B_TXPWRB_RDY, force); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d txpwr_bb_force %s\n", + path, force ? "on" : "off"); } -void rtw8851b_rck(struct rtw89_dev *rtwdev) +static void _dpk_kip_pwr_clk_onoff(struct rtw89_dev *rtwdev, bool turn_on) { - _rck(rtwdev, RF_PATH_A); + if (turn_on) { + rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000080); + rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x807f030a); + } else { + rtw89_phy_write32_mask(rtwdev, R_NCTL_RPT, MASKDWORD, 0x00000000); + rtw89_phy_write32_mask(rtwdev, R_KIP_SYSCFG, MASKDWORD, 0x80000000); + rtw89_phy_write32_mask(rtwdev, R_DPK_WR, BIT(18), 0x1); + } } -void rtw8851b_dack(struct rtw89_dev *rtwdev) +static void _dpk_kip_control_rfc(struct rtw89_dev *rtwdev, + enum rtw89_rf_path path, bool ctrl_by_kip) { - _dac_cal(rtwdev, false); + rtw89_phy_write32_mask(rtwdev, R_UPD_CLK + (path << 13), + B_IQK_RFC_ON, ctrl_by_kip); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] RFC is controlled by %s\n", + ctrl_by_kip ? "KIP" : "BB"); } -void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +static void _dpk_kip_preset(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) { - u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); - u32 tx_en; + rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD, + rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + B_DPD_SEL, 0x01); - rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_START); - rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); - _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + _dpk_kip_control_rfc(rtwdev, path, true); + _dpk_one_shot(rtwdev, phy, path, D_KIP_PRESET); +} - _iqk_init(rtwdev); - _iqk(rtwdev, phy_idx, false); +static void _dpk_kip_restore(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + _dpk_one_shot(rtwdev, phy, path, D_KIP_RESTORE); + _dpk_kip_control_rfc(rtwdev, path, false); + _dpk_txpwr_bb_force(rtwdev, path, false); - rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); - rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP); + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d restore KIP\n", path); +} + +static void _dpk_kset_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), B_KIP_RPT_SEL, 0x10); + + dpk->cur_k_set = + rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), B_RPT_PER_KSET) - 1; +} + +static void _dpk_para_query(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = { + {0x8190, 0x8194, 0x8198, 0x81a4}, + {0x81a8, 0x81c4, 0x81c8, 0x81e8} + }; + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 cur_k_set = dpk->cur_k_set; + u32 para; + + if (cur_k_set >= DPK_KSET_NUM) { + rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set); + cur_k_set = 2; + } + + para = rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8), + MASKDWORD); + + dpk->bp[path][kidx].txagc_dpk = (para >> 10) & 0x3f; + dpk->bp[path][kidx].ther_dpk = (para >> 26) & 0x3f; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] thermal/ txagc_RF (K%d) = 0x%x/ 0x%x\n", + dpk->cur_k_set, dpk->bp[path][kidx].ther_dpk, + dpk->bp[path][kidx].txagc_dpk); +} + +static bool _dpk_sync_check(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 corr_val, corr_idx, rxbb; + u16 dc_i, dc_q; + u8 rxbb_ov; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0); + + corr_idx = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORI); + corr_val = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_CORV); + dpk->corr_idx[path][kidx] = corr_idx; + dpk->corr_val[path][kidx] = corr_val; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x9); + + dc_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI); + dc_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCQ); + + dc_i = abs(sign_extend32(dc_i, 11)); + dc_q = abs(sign_extend32(dc_q, 11)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] S%d Corr_idx/ Corr_val /DC I/Q, = %d / %d / %d / %d\n", + path, corr_idx, corr_val, dc_i, dc_q); + + dpk->dc_i[path][kidx] = dc_i; + dpk->dc_q[path][kidx] = dc_q; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x8); + rxbb = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXBB); + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x31); + rxbb_ov = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_RXOV); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] S%d RXBB/ RXAGC_done /RXBB_ovlmt = %d / %d / %d\n", + path, rxbb, + rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DONE), + rxbb_ov); + + if (dc_i > 200 || dc_q > 200 || corr_val < 170) + return true; + else + return false; +} + +static void _dpk_kip_set_txagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 dbm, + bool set_from_bb) +{ + if (set_from_bb) { + dbm = clamp_t(u8, dbm, 7, 24); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] set S%d txagc to %ddBm\n", path, dbm); + rtw89_phy_write32_mask(rtwdev, R_TXPWRB + (path << 13), + B_TXPWRB_VAL, dbm << 2); + } + + _dpk_one_shot(rtwdev, phy, path, D_TXAGC); + _dpk_kset_query(rtwdev, path); +} + +static bool _dpk_kip_set_rxagc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + _dpk_kip_control_rfc(rtwdev, path, false); + rtw89_phy_write32_mask(rtwdev, R_KIP_MOD, B_KIP_MOD, + rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + _dpk_kip_control_rfc(rtwdev, path, true); + + _dpk_one_shot(rtwdev, phy, path, D_RXAGC); + return _dpk_sync_check(rtwdev, path, kidx); +} + +static void _dpk_lbk_rxiqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + u32 rf_11, reg_81cc; + u8 cur_rxbb; + + rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x1); + + _dpk_kip_control_rfc(rtwdev, path, false); + + cur_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB); + rf_11 = rtw89_read_rf(rtwdev, path, RR_TXIG, RFREG_MASK); + reg_81cc = rtw89_phy_read32_mask(rtwdev, R_KIP_IQP + (path << 8), + B_KIP_IQP_SW); + + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR0, 0x0); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_GR1, 0x3); + rtw89_write_rf(rtwdev, path, RR_TXIG, RR_TXIG_TG, 0xd); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, 0x1f); + + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_IQSW, 0x12); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, 0x3); + + _dpk_kip_control_rfc(rtwdev, path, true); + + rtw89_phy_write32_mask(rtwdev, R_IQK_DIF4, MASKDWORD, 0x00250025); + + _dpk_one_shot(rtwdev, phy, path, LBK_RXIQK); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d LBK RXIQC = 0x%x\n", path, + rtw89_phy_read32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD)); + + _dpk_kip_control_rfc(rtwdev, path, false); + + rtw89_write_rf(rtwdev, path, RR_TXIG, RFREG_MASK, rf_11); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, cur_rxbb); + rtw89_phy_write32_mask(rtwdev, R_KIP_IQP + (path << 8), B_KIP_IQP_SW, reg_81cc); + + rtw89_phy_write32_mask(rtwdev, R_MDPK_RX_DCK, B_MDPK_RX_DCK_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_KPATH_CFG, B_KPATH_CFG_ED, 0x0); + rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_DI, 0x1); + + _dpk_kip_control_rfc(rtwdev, path, true); +} + +static void _dpk_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + if (dpk->bp[path][kidx].band == RTW89_BAND_2G) { + rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK, 0x50521); + rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK); + rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTC, 0x0); + rtw89_write_rf(rtwdev, path, RR_RXBB, RR_RXBB_ATTR, 0x7); + } else { + rtw89_write_rf(rtwdev, path, RR_MOD, RFREG_MASK, + 0x50521 | BIT(rtwdev->dbcc_en)); + rtw89_write_rf(rtwdev, path, RR_MOD_V1, RR_MOD_MASK, RF_DPK); + rtw89_write_rf(rtwdev, path, RR_RXA2, RR_RAA2_SATT, 0x3); + } + + rtw89_write_rf(rtwdev, path, RR_RCKD, RR_RCKD_BW, 0x1); + rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_TXBB, dpk->bp[path][kidx].bw + 1); + rtw89_write_rf(rtwdev, path, RR_BTC, RR_BTC_RXBB, 0x0); + rtw89_write_rf(rtwdev, path, RR_RXBB2, RR_RXBB2_EBW, 0x0); +} + +static void _dpk_bypass_rxiqc(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_phy_write32_mask(rtwdev, R_DPD_V1 + (path << 8), B_DPD_LBK, 0x1); + rtw89_phy_write32_mask(rtwdev, R_RXIQC + (path << 8), MASKDWORD, 0x40000002); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Bypass RXIQC\n"); +} + +static u16 _dpk_dgain_read(struct rtw89_dev *rtwdev) +{ + u16 dgain; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x0); + dgain = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_DCI); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] DGain = 0x%x\n", dgain); + + return dgain; +} + +static u8 _dpk_gainloss_read(struct rtw89_dev *rtwdev) +{ + u8 result; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, B_KIP_RPT1_SEL, 0x6); + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x1); + result = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, B_PRT_COM_GL); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] tmp GL = %d\n", result); + + return result; +} + +static u8 _dpk_gainloss(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + _dpk_one_shot(rtwdev, phy, path, D_GAIN_LOSS); + _dpk_kip_set_txagc(rtwdev, phy, path, 0xff, false); + + rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A1, 0xf078); + rtw89_phy_write32_mask(rtwdev, R_DPK_GL + (path << 8), B_DPK_GL_A0, 0x0); + + return _dpk_gainloss_read(rtwdev); +} + +static u8 _dpk_pas_read(struct rtw89_dev *rtwdev, u8 is_check) +{ + u32 val1_i = 0, val1_q = 0, val2_i = 0, val2_q = 0; + u32 val1_sqrt_sum, val2_sqrt_sum; + u8 i; + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT1, MASKBYTE2, 0x06); + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG2, B_DPK_CFG2_ST, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE2, 0x08); + + if (is_check) { + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x00); + val1_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD); + val1_i = abs(sign_extend32(val1_i, 11)); + val1_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD); + val1_q = abs(sign_extend32(val1_q, 11)); + + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, 0x1f); + val2_i = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKHWORD); + val2_i = abs(sign_extend32(val2_i, 11)); + val2_q = rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKLWORD); + val2_q = abs(sign_extend32(val2_q, 11)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] PAS_delta = 0x%x\n", + phy_div(val1_i * val1_i + val1_q * val1_q, + val2_i * val2_i + val2_q * val2_q)); + } else { + for (i = 0; i < 32; i++) { + rtw89_phy_write32_mask(rtwdev, R_DPK_CFG3, MASKBYTE3, i); + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] PAS_Read[%02d]= 0x%08x\n", i, + rtw89_phy_read32_mask(rtwdev, R_RPT_COM, MASKDWORD)); + } + } + + val1_sqrt_sum = val1_i * val1_i + val1_q * val1_q; + val2_sqrt_sum = val2_i * val2_i + val2_q * val2_q; + + if (val1_sqrt_sum < val2_sqrt_sum) + return 2; + else if (val1_sqrt_sum >= val2_sqrt_sum * 8 / 5) + return 1; + else + return 0; +} + +static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx, u8 init_xdbm, u8 loss_only) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 tmp_dbm = init_xdbm, tmp_gl_idx = 0; + u8 step = DPK_AGC_STEP_SYNC_DGAIN; + u8 goout = 0, agc_cnt = 0; + bool is_fail = false; + int limit = 200; + u8 tmp_rxbb; + u16 dgain; + + do { + switch (step) { + case DPK_AGC_STEP_SYNC_DGAIN: + is_fail = _dpk_kip_set_rxagc(rtwdev, phy, path, kidx); + + if (is_fail) { + goout = 1; + break; + } + + dgain = _dpk_dgain_read(rtwdev); + + if (dgain > 0x5fc || dgain < 0x556) { + _dpk_one_shot(rtwdev, phy, path, D_SYNC); + dgain = _dpk_dgain_read(rtwdev); + } + + if (agc_cnt == 0) { + if (dpk->bp[path][kidx].band == RTW89_BAND_2G) + _dpk_bypass_rxiqc(rtwdev, path); + else + _dpk_lbk_rxiqk(rtwdev, phy, path); + } + step = DPK_AGC_STEP_GAIN_LOSS_IDX; + break; + + case DPK_AGC_STEP_GAIN_LOSS_IDX: + tmp_gl_idx = _dpk_gainloss(rtwdev, phy, path, kidx); + + if (_dpk_pas_read(rtwdev, true) == 2 && tmp_gl_idx > 0) + step = DPK_AGC_STEP_GL_LT_CRITERION; + else if ((tmp_gl_idx == 0 && _dpk_pas_read(rtwdev, true) == 1) || + tmp_gl_idx >= 7) + step = DPK_AGC_STEP_GL_GT_CRITERION; + else if (tmp_gl_idx == 0) + step = DPK_AGC_STEP_GL_LT_CRITERION; + else + step = DPK_AGC_STEP_SET_TX_GAIN; + break; + + case DPK_AGC_STEP_GL_GT_CRITERION: + if (tmp_dbm <= 7) { + goout = 1; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Txagc@lower bound!!\n"); + } else { + tmp_dbm = max_t(u8, tmp_dbm - 3, 7); + _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true); + } + step = DPK_AGC_STEP_SYNC_DGAIN; + agc_cnt++; + break; + + case DPK_AGC_STEP_GL_LT_CRITERION: + if (tmp_dbm >= 24) { + goout = 1; + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Txagc@upper bound!!\n"); + } else { + tmp_dbm = min_t(u8, tmp_dbm + 2, 24); + _dpk_kip_set_txagc(rtwdev, phy, path, tmp_dbm, true); + } + step = DPK_AGC_STEP_SYNC_DGAIN; + agc_cnt++; + break; + + case DPK_AGC_STEP_SET_TX_GAIN: + _dpk_kip_control_rfc(rtwdev, path, false); + tmp_rxbb = rtw89_read_rf(rtwdev, path, RR_MOD, RR_MOD_RXB); + tmp_rxbb = min_t(u8, tmp_rxbb + tmp_gl_idx, 0x1f); + + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_RXB, tmp_rxbb); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Adjust RXBB (%+d) = 0x%x\n", + tmp_gl_idx, tmp_rxbb); + _dpk_kip_control_rfc(rtwdev, path, true); + goout = 1; + break; + default: + goout = 1; + break; + } + } while (!goout && agc_cnt < 6 && limit-- > 0); + + return is_fail; +} + +static void _dpk_set_mdpd_para(struct rtw89_dev *rtwdev, u8 order) +{ + switch (order) { + case 0: /* (5,3,1) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x2); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1); + break; + case 1: /* (5,3,0) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x1); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x1); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0); + break; + case 2: /* (5,0,0) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x2); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x0); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x0); + break; + case 3: /* (7,3,1) */ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP, 0x3); + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL_SEL, 0x3); + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_PN, 0x4); + rtw89_phy_write32_mask(rtwdev, R_MDPK_SYNC, B_MDPK_SYNC_DMAN, 0x1); + break; + default: + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] Wrong MDPD order!!(0x%x)\n", order); + break; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Set %s for IDL\n", + order == 0x0 ? "(5,3,1)" : + order == 0x1 ? "(5,3,0)" : + order == 0x2 ? "(5,0,0)" : "(7,3,1)"); +} + +static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + rtw89_phy_write32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_MA, 0x1); + + if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD500) == 0x1) + _dpk_set_mdpd_para(rtwdev, 0x2); + else if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_MD530) == 0x1) + _dpk_set_mdpd_para(rtwdev, 0x1); + else + _dpk_set_mdpd_para(rtwdev, 0x0); + + rtw89_phy_write32_mask(rtwdev, R_DPK_IDL, B_DPK_IDL, 0x0); + fsleep(1000); + + _dpk_one_shot(rtwdev, phy, path, D_MDPK_IDL); +} + +static u8 _dpk_order_convert(struct rtw89_dev *rtwdev) +{ + u32 order; + u8 val; + + order = rtw89_phy_read32_mask(rtwdev, R_LDL_NORM, B_LDL_NORM_OP); + + switch (order) { + case 0: /* (5,3,1) */ + val = 0x6; + break; + case 1: /* (5,3,0) */ + val = 0x2; + break; + case 2: /* (5,0,0) */ + val = 0x0; + break; + default: + val = 0xff; + break; + } + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] convert MDPD order to 0x%x\n", val); + + return val; +} + +static void _dpk_gain_normalize(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx, bool is_execute) +{ + static const u32 reg[RTW89_DPK_BKUP_NUM][DPK_KSET_NUM] = { + {0x8190, 0x8194, 0x8198, 0x81a4}, + {0x81a8, 0x81c4, 0x81c8, 0x81e8} + }; + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 cur_k_set = dpk->cur_k_set; + + if (cur_k_set >= DPK_KSET_NUM) { + rtw89_warn(rtwdev, "DPK cur_k_set = %d\n", cur_k_set); + cur_k_set = 2; + } + + if (is_execute) { + rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8), + B_DPK_GN_AG, 0x200); + rtw89_phy_write32_mask(rtwdev, R_DPK_GN + (path << 8), + B_DPK_GN_EN, 0x3); + + _dpk_one_shot(rtwdev, phy, path, D_GAIN_NORM); + } else { + rtw89_phy_write32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8), + 0x0000007F, 0x5b); + } + + dpk->bp[path][kidx].gs = + rtw89_phy_read32_mask(rtwdev, reg[kidx][cur_k_set] + (path << 8), + 0x0000007F); +} + +static void _dpk_on(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, u8 kidx) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + + rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x1); + rtw89_phy_write32_mask(rtwdev, R_LOAD_COEF + (path << 8), B_LOAD_COEF_MDPD, 0x0); + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + B_DPD_ORDER, _dpk_order_convert(rtwdev)); + + dpk->bp[path][kidx].path_ok = + dpk->bp[path][kidx].path_ok | BIT(dpk->cur_k_set); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d] path_ok = 0x%x\n", + path, kidx, dpk->bp[path][kidx].path_ok); + + rtw89_phy_write32_mask(rtwdev, R_DPD_CH0A + (path << 8) + (kidx << 2), + B_DPD_MEN, dpk->bp[path][kidx].path_ok); + + _dpk_gain_normalize(rtwdev, phy, path, kidx, false); +} + +static bool _dpk_main(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u8 kidx = dpk->cur_idx[path]; + u8 init_xdbm = 17; + bool is_fail; + + if (dpk->bp[path][kidx].band != RTW89_BAND_2G) + init_xdbm = 15; + + _dpk_kip_control_rfc(rtwdev, path, false); + _rfk_rf_direct_cntrl(rtwdev, path, false); + rtw89_write_rf(rtwdev, path, RR_BBDC, RFREG_MASK, 0x03ffd); + + _dpk_rf_setting(rtwdev, path, kidx); + _set_rx_dck(rtwdev, path, RF_DPK); + + _dpk_kip_pwr_clk_onoff(rtwdev, true); + _dpk_kip_preset(rtwdev, phy, path, kidx); + _dpk_txpwr_bb_force(rtwdev, path, true); + _dpk_kip_set_txagc(rtwdev, phy, path, init_xdbm, true); + _dpk_tpg_sel(rtwdev, path, kidx); + is_fail = _dpk_agc(rtwdev, phy, path, kidx, init_xdbm, false); + if (is_fail) + goto _error; + + _dpk_idl_mpa(rtwdev, phy, path, kidx); + _dpk_para_query(rtwdev, path, kidx); + + _dpk_on(rtwdev, phy, path, kidx); +_error: + _dpk_kip_control_rfc(rtwdev, path, false); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RF_RX); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] S%d[%d]_K%d %s\n", path, kidx, + dpk->cur_k_set, is_fail ? "need Check" : "is Success"); + + return is_fail; +} + +static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force, + enum rtw89_phy_idx phy, u8 kpath) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + u32 kip_bkup[RF_PATH_NUM_8851B][DPK_KIP_REG_NUM_8851B] = {}; + u32 rf_bkup[RF_PATH_NUM_8851B][DPK_RF_REG_NUM_8851B] = {}; + bool is_fail; + u8 path; + + for (path = 0; path < RF_PATH_NUM_8851B; path++) + dpk->cur_idx[path] = 0; + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + _dpk_bkup_kip(rtwdev, dpk_kip_reg, kip_bkup, path); + _dpk_bkup_rf(rtwdev, dpk_rf_reg, rf_bkup, path); + _dpk_information(rtwdev, phy, path); + _dpk_init(rtwdev, path); + + if (rtwdev->is_tssi_mode[path]) + _dpk_tssi_pause(rtwdev, path, true); + } + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] ========= S%d[%d] DPK Start =========\n", + path, dpk->cur_idx[path]); + + _dpk_rxagc_onoff(rtwdev, path, false); + _rfk_drf_direct_cntrl(rtwdev, path, false); + _dpk_bb_afe_setting(rtwdev, path); + + is_fail = _dpk_main(rtwdev, phy, path); + _dpk_onoff(rtwdev, path, is_fail); + } + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + if (!(kpath & BIT(path))) + continue; + + _dpk_kip_restore(rtwdev, phy, path); + _dpk_reload_kip(rtwdev, dpk_kip_reg, kip_bkup, path); + _dpk_reload_rf(rtwdev, dpk_rf_reg, rf_bkup, path); + _dpk_bb_afe_restore(rtwdev, path); + _dpk_rxagc_onoff(rtwdev, path, true); + + if (rtwdev->is_tssi_mode[path]) + _dpk_tssi_pause(rtwdev, path, false); + } + + _dpk_kip_pwr_clk_onoff(rtwdev, false); +} + +static void _dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool force) +{ + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[DPK] ****** 8851B DPK Start (Ver: 0x%x, Cv: %d) ******\n", + DPK_VER_8851B, rtwdev->hal.cv); + + _dpk_cal_select(rtwdev, force, phy, _kpath(rtwdev, phy)); +} + +static void _dpk_track(struct rtw89_dev *rtwdev) +{ + struct rtw89_dpk_info *dpk = &rtwdev->dpk; + s8 txagc_bb, txagc_bb_tp, txagc_ofst; + s16 pwsf_tssi_ofst; + s8 delta_ther = 0; + u8 path, kidx; + u8 txagc_rf; + u8 cur_ther; + + for (path = 0; path < RF_PATH_NUM_8851B; path++) { + kidx = dpk->cur_idx[path]; + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] ================[S%d[%d] (CH %d)]================\n", + path, kidx, dpk->bp[path][kidx].ch); + + txagc_rf = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13), + B_TXAGC_RF); + txagc_bb = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BB + (path << 13), + MASKBYTE2); + txagc_bb_tp = rtw89_phy_read32_mask(rtwdev, R_TXAGC_BTP + (path << 13), + B_TXAGC_BTP); + + rtw89_phy_write32_mask(rtwdev, R_KIP_RPT + (path << 8), + B_KIP_RPT_SEL, 0xf); + cur_ther = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), + B_RPT_PER_TH); + txagc_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), + B_RPT_PER_OF); + pwsf_tssi_ofst = rtw89_phy_read32_mask(rtwdev, R_RPT_PER + (path << 8), + B_RPT_PER_TSSI); + pwsf_tssi_ofst = sign_extend32(pwsf_tssi_ofst, 12); + + delta_ther = cur_ther - dpk->bp[path][kidx].ther_dpk; + + delta_ther = delta_ther * 2 / 3; + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] extra delta_ther = %d (0x%x / 0x%x@k)\n", + delta_ther, cur_ther, dpk->bp[path][kidx].ther_dpk); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] delta_txagc = %d (0x%x / 0x%x@k)\n", + txagc_rf - dpk->bp[path][kidx].txagc_dpk, + txagc_rf, dpk->bp[path][kidx].txagc_dpk); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] txagc_offset / pwsf_tssi_ofst = 0x%x / %+d\n", + txagc_ofst, pwsf_tssi_ofst); + + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] txagc_bb_tp / txagc_bb = 0x%x / 0x%x\n", + txagc_bb_tp, txagc_bb); + + if (rtw89_phy_read32_mask(rtwdev, R_IDL_MPA, B_IDL_DN) == 0x0 && + txagc_rf != 0) { + rtw89_debug(rtwdev, RTW89_DBG_RFK_TRACK, + "[DPK_TRK] New pwsf = 0x%x\n", 0x78 - delta_ther); + + rtw89_phy_write32_mask(rtwdev, + R_DPD_BND + (path << 8) + (kidx << 2), + 0x07FC0000, 0x78 - delta_ther); + } + } +} + +static void _rck(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + u32 rf_reg5; + u32 rck_val; + u32 val; + int ret; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] ====== S%d RCK ======\n", path); + + rf_reg5 = rtw89_read_rf(rtwdev, path, RR_RSV1, RFREG_MASK); + + rtw89_write_rf(rtwdev, path, RR_RSV1, RR_RSV1_RST, 0x0); + rtw89_write_rf(rtwdev, path, RR_MOD, RR_MOD_MASK, RR_MOD_V_RX); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF0x00 = 0x%05x\n", + rtw89_read_rf(rtwdev, path, RR_MOD, RFREG_MASK)); + + /* RCK trigger */ + rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, 0x00240); + + ret = read_poll_timeout_atomic(rtw89_read_rf, val, val, 2, 30, + false, rtwdev, path, RR_RCKS, BIT(3)); + + rck_val = rtw89_read_rf(rtwdev, path, RR_RCKC, RR_RCKC_CA); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] rck_val = 0x%x, ret = %d\n", + rck_val, ret); + + rtw89_write_rf(rtwdev, path, RR_RCKC, RFREG_MASK, rck_val); + rtw89_write_rf(rtwdev, path, RR_RSV1, RFREG_MASK, rf_reg5); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[RCK] RF 0x1b = 0x%x\n", + rtw89_read_rf(rtwdev, path, RR_RCKC, RFREG_MASK)); +} + +static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + enum rtw89_band band = chan->band_type; + + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_sys_defs_tbl); + + rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G, + &rtw8851b_tssi_sys_a_defs_2g_tbl, + &rtw8851b_tssi_sys_a_defs_5g_tbl); +} + +static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_defs_a_tbl); +} + +static void _tssi_ini_txpwr_ctrl_bb_he_tb(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_init_txpwr_he_tb_defs_a_tbl); +} + +static void _tssi_set_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dck_defs_a_tbl); +} + +static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ +#define RTW8851B_TSSI_GET_VAL(ptr, idx) \ +({ \ + s8 *__ptr = (ptr); \ + u8 __idx = (idx), __i, __v; \ + u32 __val = 0; \ + for (__i = 0; __i < 4; __i++) { \ + __v = (__ptr[__idx + __i]); \ + __val |= (__v << (8 * __i)); \ + } \ + __val; \ +}) + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 ch = chan->channel; + u8 subband = chan->subband_type; + const s8 *thm_up_a = NULL; + const s8 *thm_down_a = NULL; + u8 thermal = 0xff; + s8 thm_ofst[64] = {0}; + u32 tmp = 0; + u8 i, j; + + switch (subband) { + default: + case RTW89_CH_2G: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_p; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_2ga_n; + break; + case RTW89_CH_5G_BAND_1: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[0]; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[0]; + break; + case RTW89_CH_5G_BAND_3: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[1]; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[1]; + break; + case RTW89_CH_5G_BAND_4: + thm_up_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_p[2]; + thm_down_a = rtw89_8851b_trk_cfg.delta_swingidx_5ga_n[2]; + break; + } + + if (path == RF_PATH_A) { + thermal = tssi_info->thermal[RF_PATH_A]; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] ch=%d thermal_pathA=0x%x\n", ch, thermal); + + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_DIS, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER_TRK, 0x1); + + if (thermal == 0xff) { + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER, 32); + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL, 32); + + for (i = 0; i < 64; i += 4) { + rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, 0x0); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] write 0x%x val=0x%08x\n", + R_P0_TSSI_BASE + i, 0x0); + } + + } else { + rtw89_phy_write32_mask(rtwdev, R_P0_TMETER, B_P0_TMETER, + thermal); + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, B_P0_RFCTM_VAL, + thermal); + + i = 0; + for (j = 0; j < 32; j++) + thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ? + -thm_down_a[i++] : + -thm_down_a[DELTA_SWINGIDX_SIZE - 1]; + + i = 1; + for (j = 63; j >= 32; j--) + thm_ofst[j] = i < DELTA_SWINGIDX_SIZE ? + thm_up_a[i++] : + thm_up_a[DELTA_SWINGIDX_SIZE - 1]; + + for (i = 0; i < 64; i += 4) { + tmp = RTW8851B_TSSI_GET_VAL(thm_ofst, i); + rtw89_phy_write32(rtwdev, R_P0_TSSI_BASE + i, tmp); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] write 0x%x val=0x%08x\n", + 0x5c00 + i, tmp); + } + } + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_RFCTM, R_P0_RFCTM_RDY, 0x0); + } +#undef RTW8851B_TSSI_GET_VAL +} + +static void _tssi_set_dac_gain_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_dac_gain_defs_a_tbl); +} + +static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + enum rtw89_band band = chan->band_type; + + rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G, + &rtw8851b_tssi_slope_a_defs_2g_tbl, + &rtw8851b_tssi_slope_a_defs_5g_tbl); +} + +static void _tssi_alignment_default(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path, bool all) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + enum rtw89_band band = chan->band_type; + + rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G, + &rtw8851b_tssi_align_a_2g_defs_tbl, + &rtw8851b_tssi_align_a_5g_defs_tbl); +} + +static void _tssi_set_tssi_slope(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_slope_defs_a_tbl); +} + +static void _tssi_set_tssi_track(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_track_defs_a_tbl); +} + +static void _tssi_set_txagc_offset_mv_avg(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + rtw89_rfk_parser(rtwdev, &rtw8851b_tssi_mv_avg_defs_a_tbl); +} + +static void _tssi_enable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + _tssi_set_tssi_track(rtwdev, phy, RF_PATH_A); + _tssi_set_txagc_offset_mv_avg(rtwdev, phy, RF_PATH_A); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x1); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_TXGA_V1, RR_TXGA_V1_TRK_EN, 0x1); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_RFC, 0x3); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + + rtwdev->is_tssi_mode[RF_PATH_A] = true; +} + +static void _tssi_disable(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_AVG, B_P0_TSSI_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_MV_AVG, B_P0_TSSI_MV_CLR, 0x1); + + rtwdev->is_tssi_mode[RF_PATH_A] = false; +} + +static u32 _tssi_get_cck_group(struct rtw89_dev *rtwdev, u8 ch) +{ + switch (ch) { + case 1 ... 2: + return 0; + case 3 ... 5: + return 1; + case 6 ... 8: + return 2; + case 9 ... 11: + return 3; + case 12 ... 13: + return 4; + case 14: + return 5; + } + + return 0; +} + +#define TSSI_EXTRA_GROUP_BIT (BIT(31)) +#define TSSI_EXTRA_GROUP(idx) (TSSI_EXTRA_GROUP_BIT | (idx)) +#define IS_TSSI_EXTRA_GROUP(group) ((group) & TSSI_EXTRA_GROUP_BIT) +#define TSSI_EXTRA_GET_GROUP_IDX1(group) ((group) & ~TSSI_EXTRA_GROUP_BIT) +#define TSSI_EXTRA_GET_GROUP_IDX2(group) (TSSI_EXTRA_GET_GROUP_IDX1(group) + 1) + +static u32 _tssi_get_ofdm_group(struct rtw89_dev *rtwdev, u8 ch) +{ + switch (ch) { + case 1 ... 2: + return 0; + case 3 ... 5: + return 1; + case 6 ... 8: + return 2; + case 9 ... 11: + return 3; + case 12 ... 14: + return 4; + case 36 ... 40: + return 5; + case 41 ... 43: + return TSSI_EXTRA_GROUP(5); + case 44 ... 48: + return 6; + case 49 ... 51: + return TSSI_EXTRA_GROUP(6); + case 52 ... 56: + return 7; + case 57 ... 59: + return TSSI_EXTRA_GROUP(7); + case 60 ... 64: + return 8; + case 100 ... 104: + return 9; + case 105 ... 107: + return TSSI_EXTRA_GROUP(9); + case 108 ... 112: + return 10; + case 113 ... 115: + return TSSI_EXTRA_GROUP(10); + case 116 ... 120: + return 11; + case 121 ... 123: + return TSSI_EXTRA_GROUP(11); + case 124 ... 128: + return 12; + case 129 ... 131: + return TSSI_EXTRA_GROUP(12); + case 132 ... 136: + return 13; + case 137 ... 139: + return TSSI_EXTRA_GROUP(13); + case 140 ... 144: + return 14; + case 149 ... 153: + return 15; + case 154 ... 156: + return TSSI_EXTRA_GROUP(15); + case 157 ... 161: + return 16; + case 162 ... 164: + return TSSI_EXTRA_GROUP(16); + case 165 ... 169: + return 17; + case 170 ... 172: + return TSSI_EXTRA_GROUP(17); + case 173 ... 177: + return 18; + } + + return 0; +} + +static u32 _tssi_get_trim_group(struct rtw89_dev *rtwdev, u8 ch) +{ + switch (ch) { + case 1 ... 8: + return 0; + case 9 ... 14: + return 1; + case 36 ... 48: + return 2; + case 52 ... 64: + return 3; + case 100 ... 112: + return 4; + case 116 ... 128: + return 5; + case 132 ... 144: + return 6; + case 149 ... 177: + return 7; + } + + return 0; +} + +static s8 _tssi_get_ofdm_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u32 gidx, gidx_1st, gidx_2nd; + u8 ch = chan->channel; + s8 de_1st; + s8 de_2nd; + s8 val; + + gidx = _tssi_get_ofdm_group(rtwdev, ch); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs group_idx=0x%x\n", path, gidx); + + if (IS_TSSI_EXTRA_GROUP(gidx)) { + gidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(gidx); + gidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(gidx); + de_1st = tssi_info->tssi_mcs[path][gidx_1st]; + de_2nd = tssi_info->tssi_mcs[path][gidx_2nd]; + val = (de_1st + de_2nd) / 2; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs de=%d 1st=%d 2nd=%d\n", + path, val, de_1st, de_2nd); + } else { + val = tssi_info->tssi_mcs[path][gidx]; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs de=%d\n", path, val); + } + + return val; +} + +static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, + enum rtw89_rf_path path) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u32 tgidx, tgidx_1st, tgidx_2nd; + u8 ch = chan->channel; + s8 tde_1st; + s8 tde_2nd; + s8 val; + + tgidx = _tssi_get_trim_group(rtwdev, ch); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs trim_group_idx=0x%x\n", + path, tgidx); + + if (IS_TSSI_EXTRA_GROUP(tgidx)) { + tgidx_1st = TSSI_EXTRA_GET_GROUP_IDX1(tgidx); + tgidx_2nd = TSSI_EXTRA_GET_GROUP_IDX2(tgidx); + tde_1st = tssi_info->tssi_trim[path][tgidx_1st]; + tde_2nd = tssi_info->tssi_trim[path][tgidx_2nd]; + val = (tde_1st + tde_2nd) / 2; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs trim_de=%d 1st=%d 2nd=%d\n", + path, val, tde_1st, tde_2nd); + } else { + val = tssi_info->tssi_trim[path][tgidx]; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs trim_de=%d\n", + path, val); + } + + return val; +} + +static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 ch = chan->channel; + u8 gidx; + s8 ofdm_de; + s8 trim_de; + s32 val; + u32 i; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI][TRIM]: phy=%d ch=%d\n", + phy, ch); + + for (i = RF_PATH_A; i < RTW8851B_TSSI_PATH_NR; i++) { + gidx = _tssi_get_cck_group(rtwdev, ch); + trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i); + val = tssi_info->tssi_cck[i][gidx] + trim_de; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d cck[%d]=0x%x trim=0x%x\n", + i, gidx, tssi_info->tssi_cck[i][gidx], trim_de); + + rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_long[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_cck_short[i], _TSSI_DE_MASK, val); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] Set TSSI CCK DE 0x%x[21:12]=0x%x\n", + _tssi_de_cck_long[i], + rtw89_phy_read32_mask(rtwdev, _tssi_de_cck_long[i], + _TSSI_DE_MASK)); + + ofdm_de = _tssi_get_ofdm_de(rtwdev, phy, i); + trim_de = _tssi_get_ofdm_trim_de(rtwdev, phy, i); + val = ofdm_de + trim_de; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI][TRIM]: path=%d mcs=0x%x trim=0x%x\n", + i, ofdm_de, trim_de); + + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_20m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_40m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_80m_80m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_5m[i], _TSSI_DE_MASK, val); + rtw89_phy_write32_mask(rtwdev, _tssi_de_mcs_10m[i], _TSSI_DE_MASK, val); + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, + "[TSSI] Set TSSI MCS DE 0x%x[21:12]=0x%x\n", + _tssi_de_mcs_20m[i], + rtw89_phy_read32_mask(rtwdev, _tssi_de_mcs_20m[i], + _TSSI_DE_MASK)); + } +} + +static void _tssi_alimentk_dump_result(struct rtw89_dev *rtwdev, enum rtw89_rf_path path) +{ + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "[TSSI PA K]\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n" + "0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n0x%x = 0x%08x\n", + R_TSSI_PA_K1 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K1 + (path << 13), MASKDWORD), + R_TSSI_PA_K2 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K2 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM1 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM3 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD), + R_TSSI_PA_K5 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K5 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM2 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD), + R_P0_TSSI_ALIM4 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD), + R_TSSI_PA_K8 + (path << 13), + rtw89_phy_read32_mask(rtwdev, R_TSSI_PA_K8 + (path << 13), MASKDWORD)); +} + +static void _tssi_alimentk_done(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, enum rtw89_rf_path path) +{ + struct rtw89_tssi_info *tssi_info = &rtwdev->tssi; + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 channel = chan->channel; + u8 band; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s phy=%d path=%d\n", __func__, phy, path); + + if (channel >= 1 && channel <= 14) + band = TSSI_ALIMK_2G; + else if (channel >= 36 && channel <= 64) + band = TSSI_ALIMK_5GL; + else if (channel >= 100 && channel <= 144) + band = TSSI_ALIMK_5GM; + else if (channel >= 149 && channel <= 177) + band = TSSI_ALIMK_5GH; + else + band = TSSI_ALIMK_2G; + + if (tssi_info->alignment_done[path][band]) { + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM1 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][0]); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM3 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][1]); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM2 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][2]); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_ALIM4 + (path << 13), MASKDWORD, + tssi_info->alignment_value[path][band][3]); + } + + _tssi_alimentk_dump_result(rtwdev, path); +} + +static void rtw8851b_by_rate_dpd(struct rtw89_dev *rtwdev) +{ + rtw89_write32_mask(rtwdev, R_AX_PWR_SWING_OTHER_CTRL0, + B_AX_CFIR_BY_RATE_OFF_MASK, 0x21861); +} + +void rtw8851b_dpk_init(struct rtw89_dev *rtwdev) +{ + rtw8851b_by_rate_dpd(rtwdev); +} + +void rtw8851b_aack(struct rtw89_dev *rtwdev) +{ + u32 tmp05, ib[4]; + u32 tmp; + int ret; + int rek; + int i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]DO AACK\n"); + + tmp05 = rtw89_read_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_MOD, RR_MOD_MASK, 0x3); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, 0x0); + + for (rek = 0; rek < 4; rek++) { + rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201e); + rtw89_write_rf(rtwdev, RF_PATH_A, RR_AACK, RFREG_MASK, 0x8201f); + fsleep(100); + + ret = read_poll_timeout_atomic(rtw89_read_rf, tmp, tmp, + 1, 1000, false, + rtwdev, RF_PATH_A, 0xd0, BIT(16)); + if (ret) + rtw89_warn(rtwdev, "[LCK]AACK timeout\n"); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x1); + for (i = 0; i < 4; i++) { + rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCO, RR_VCO_SEL, i); + ib[i] = rtw89_read_rf(rtwdev, RF_PATH_A, RR_IBD, RR_IBD_VAL); + } + rtw89_write_rf(rtwdev, RF_PATH_A, RR_VCI, RR_VCI_ON, 0x0); + + if (ib[0] != 0 && ib[1] != 0 && ib[2] != 0 && ib[3] != 0) + break; + } + + if (rek != 0) + rtw89_debug(rtwdev, RTW89_DBG_RFK, "[LCK]AACK rek = %d\n", rek); + + rtw89_write_rf(rtwdev, RF_PATH_A, RR_RSV1, RFREG_MASK, tmp05); +} + +void rtw8851b_rck(struct rtw89_dev *rtwdev) +{ + _rck(rtwdev, RF_PATH_A); +} + +void rtw8851b_dack(struct rtw89_dev *rtwdev) +{ + _dac_cal(rtwdev, false); +} + +void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); + u32 tx_en; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_START); + rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); + _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + + _iqk_init(rtwdev); + _iqk(rtwdev, phy_idx, false); + + rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_STOP); +} + +void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); + u32 tx_en; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_START); + rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); + _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + + _rx_dck(rtwdev, phy_idx, false); + + rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_RXDCK, BTC_WRFK_STOP); +} + +void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy_idx, 0); + u32 tx_en; + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_START); + rtw89_chip_stop_sch_tx(rtwdev, phy_idx, &tx_en, RTW89_SCH_TX_SEL_ALL); + _wait_rx_mode(rtwdev, _kpath(rtwdev, phy_idx)); + + rtwdev->dpk.is_dpk_enable = true; + rtwdev->dpk.is_dpk_reload_en = false; + _dpk(rtwdev, phy_idx, false); + + rtw89_chip_resume_sch_tx(rtwdev, phy_idx, tx_en); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_DPK, BTC_WRFK_STOP); +} + +void rtw8851b_dpk_track(struct rtw89_dev *rtwdev) +{ + _dpk_track(rtwdev); +} + +void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en) +{ + u8 phy_map = rtw89_btc_phymap(rtwdev, phy, RF_A); + u8 i; + + rtw89_debug(rtwdev, RTW89_DBG_TSSI, "[TSSI] %s: phy=%d\n", __func__, phy); + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_START); + + _tssi_disable(rtwdev, phy); + + for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) { + _tssi_set_sys(rtwdev, phy, i); + _tssi_ini_txpwr_ctrl_bb(rtwdev, phy, i); + _tssi_ini_txpwr_ctrl_bb_he_tb(rtwdev, phy, i); + _tssi_set_dck(rtwdev, phy, i); + _tssi_set_tmeter_tbl(rtwdev, phy, i); + _tssi_set_dac_gain_tbl(rtwdev, phy, i); + _tssi_slope_cal_org(rtwdev, phy, i); + _tssi_alignment_default(rtwdev, phy, i, true); + _tssi_set_tssi_slope(rtwdev, phy, i); + } + + _tssi_enable(rtwdev, phy); + _tssi_set_efuse_to_de(rtwdev, phy); + + rtw89_btc_ntfy_wl_rfk(rtwdev, phy_map, BTC_WRFKT_IQK, BTC_WRFK_ONESHOT_STOP); +} + +void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 channel = chan->channel; + u32 i; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s phy=%d channel=%d\n", __func__, phy, channel); + + _tssi_disable(rtwdev, phy); + + for (i = RF_PATH_A; i < RF_PATH_NUM_8851B; i++) { + _tssi_set_sys(rtwdev, phy, i); + _tssi_set_tmeter_tbl(rtwdev, phy, i); + _tssi_slope_cal_org(rtwdev, phy, i); + _tssi_alignment_default(rtwdev, phy, i, true); + } + + _tssi_enable(rtwdev, phy); + _tssi_set_efuse_to_de(rtwdev, phy); +} + +static void rtw8851b_tssi_default_txagc(struct rtw89_dev *rtwdev, + enum rtw89_phy_idx phy, bool enable) +{ + const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0); + u8 channel = chan->channel; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, "======> %s ch=%d\n", + __func__, channel); + + if (enable) + return; + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s 1 SCAN_END Set 0x5818[7:0]=0x%x\n", + __func__, + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT)); + + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT, 0xc0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x0); + rtw89_phy_write32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT_EN, 0x1); + + _tssi_alimentk_done(rtwdev, phy, RF_PATH_A); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======>%s 2 SCAN_END Set 0x5818[7:0]=0x%x\n", + __func__, + rtw89_phy_read32_mask(rtwdev, R_P0_TSSI_TRK, B_P0_TSSI_OFT)); + + rtw89_debug(rtwdev, RTW89_DBG_RFK, + "======> %s SCAN_END\n", __func__); +} + +void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, + enum rtw89_phy_idx phy_idx) +{ + if (scan_start) + rtw8851b_tssi_default_txagc(rtwdev, phy_idx, true); + else + rtw8851b_tssi_default_txagc(rtwdev, phy_idx, false); } static void _bw_setting(struct rtw89_dev *rtwdev, enum rtw89_rf_path path, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h index d86c630ff47ec9..bf0c79d58a71d4 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h +++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.h @@ -11,6 +11,14 @@ void rtw8851b_aack(struct rtw89_dev *rtwdev); void rtw8851b_rck(struct rtw89_dev *rtwdev); void rtw8851b_dack(struct rtw89_dev *rtwdev); void rtw8851b_iqk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw8851b_rx_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx); +void rtw8851b_dpk_init(struct rtw89_dev *rtwdev); +void rtw8851b_dpk(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); +void rtw8851b_dpk_track(struct rtw89_dev *rtwdev); +void rtw8851b_tssi(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy, bool hwtx_en); +void rtw8851b_tssi_scan(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy); +void rtw8851b_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start, + enum rtw89_phy_idx phy_idx); void rtw8851b_set_channel_rf(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan, enum rtw89_phy_idx phy_idx); diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c index 4e6f3bbdc2d8f0..559835ce86bb6a 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c @@ -2032,6 +2032,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .read_efuse = rtw8852a_read_efuse, .read_phycap = rtw8852a_read_phycap, .fem_setup = rtw8852a_fem_setup, + .rfe_gpio = NULL, .rfk_init = rtw8852a_rfk_init, .rfk_channel = rtw8852a_rfk_channel, .rfk_band_changed = rtw8852a_rfk_band_changed, @@ -2049,6 +2050,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = { .set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset, .pwr_on_func = NULL, .pwr_off_func = NULL, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c index 9ed4ade08813e1..718f993da62afb 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c @@ -2454,6 +2454,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .read_efuse = rtw8852b_read_efuse, .read_phycap = rtw8852b_read_phycap, .fem_setup = NULL, + .rfe_gpio = NULL, .rfk_init = rtw8852b_rfk_init, .rfk_channel = rtw8852b_rfk_channel, .rfk_band_changed = rtw8852b_rfk_band_changed, @@ -2471,6 +2472,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = { .set_txpwr_ul_tb_offset = rtw8852b_set_txpwr_ul_tb_offset, .pwr_on_func = rtw8852b_pwr_on_func, .pwr_off_func = rtw8852b_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c index f2e70bda8e480d..9c7c9812d4f456 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c @@ -2762,6 +2762,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .read_efuse = rtw8852c_read_efuse, .read_phycap = rtw8852c_read_phycap, .fem_setup = NULL, + .rfe_gpio = NULL, .rfk_init = rtw8852c_rfk_init, .rfk_channel = rtw8852c_rfk_channel, .rfk_band_changed = rtw8852c_rfk_band_changed, @@ -2779,6 +2780,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = { .set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset, .pwr_on_func = rtw8852c_pwr_on_func, .pwr_off_func = rtw8852c_pwr_off_func, + .query_rxdesc = rtw89_core_query_rxdesc, .fill_txdesc = rtw89_core_fill_txdesc_v1, .fill_txdesc_fwcmd = rtw89_core_fill_txdesc_fwcmd_v1, .cfg_ctrl_path = rtw89_mac_cfg_ctrl_path_v1, diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c index 7011e5a6f8fdac..8fda2c2e9833d7 100644 --- a/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c +++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_table.c @@ -2551,19 +2551,27 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0xF0040001, 0x0000000A}, {0xF0050001, 0x0000000B}, {0xF0070001, 0x0000000C}, - {0xF0320001, 0x0000000D}, - {0xF0330001, 0x0000000E}, - {0xF0340001, 0x0000000F}, - {0xF0350001, 0x00000010}, - {0xF0360001, 0x00000011}, - {0xF03F0001, 0x00000012}, - {0xF0400001, 0x00000013}, + {0xF0150001, 0x0000000D}, + {0xF0160001, 0x0000000E}, + {0xF0320001, 0x0000000F}, + {0xF0330001, 0x00000010}, + {0xF0340001, 0x00000011}, + {0xF0350001, 0x00000012}, + {0xF0360001, 0x00000013}, + {0xF03F0001, 0x00000014}, + {0xF0400001, 0x00000015}, {0x005, 0x00000000}, {0x10005, 0x00000000}, {0x000, 0x00030001}, {0x10000, 0x00030000}, {0x018, 0x00011124}, {0x10018, 0x00011124}, + {0x0A3, 0x000B9204}, + {0x0AD, 0x00091E0F}, + {0x05D, 0x00001012}, + {0x05C, 0x00061C5C}, + {0x062, 0x00055220}, + {0x0D3, 0x00000103}, {0x0EF, 0x00080000}, {0x033, 0x00000001}, {0x03E, 0x00000620}, @@ -2636,6 +2644,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, @@ -2716,6 +2730,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000CC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000CC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000CC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000CC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000CC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2760,6 +2778,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000C4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000C4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000C4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000C4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000C4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2804,6 +2826,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000BC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2848,6 +2874,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000B4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2892,6 +2922,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000AC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2936,6 +2970,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -2980,6 +3018,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000009C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3024,6 +3066,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000094}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3068,6 +3114,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000008C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3112,6 +3162,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000084}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3156,6 +3210,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000BC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000BC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000BC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3200,6 +3258,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000B4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000B4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000B4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3244,6 +3306,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000AC}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000AC}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000AC}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3288,6 +3354,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000000A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000000A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000000A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3332,6 +3402,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000009C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000009C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000009C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3376,6 +3450,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000094}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000094}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000094}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3420,6 +3498,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000008C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000008C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000008C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3464,6 +3546,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000084}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000084}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000084}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3508,6 +3594,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000003C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000003C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000003C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000003C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000003C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3552,6 +3642,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000034}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000034}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000034}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000034}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000034}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3596,6 +3690,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000002C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000002C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000002C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000002C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000002C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3640,6 +3738,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000024}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000024}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000024}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000024}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000024}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3684,6 +3786,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000001C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000001C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000001C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000001C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000001C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3728,6 +3834,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000014}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000014}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000014}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000014}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000014}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3772,6 +3882,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000000C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000000C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000000C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000000C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000000C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3816,6 +3930,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000004}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000004}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000004}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000004}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000004}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3873,6 +3991,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x08F, 0x000D1352}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -3936,6 +4058,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000007}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -4472,6 +4598,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000EFFF}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -4810,6 +4940,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x030, 0x00050112}, {0x030, 0x00058101}, {0x030, 0x00060001}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000085ED}, {0x030, 0x000105CC}, @@ -5157,6 +5313,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x030, 0x000300FF}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000300FF}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000300FF}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000300FF}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000300FF}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5178,152 +5338,632 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x0EF, 0x00000000}, {0x06E, 0x00077A18}, {0x06D, 0x00000C31}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, {0x06A, 0x000E0F8A}, {0x06B, 0x000018A0}, {0x06F, 0x000F81FC}, {0x05E, 0x0000001F}, - {0x0EF, 0x00000200}, - {0x030, 0x0003D407}, - {0x030, 0x00035A87}, - {0x030, 0x0002CF07}, - {0x030, 0x00024F07}, - {0x030, 0x0001CF07}, - {0x030, 0x00014F07}, - {0x030, 0x0000CF07}, - {0x030, 0x00004F07}, - {0x0EF, 0x00000000}, - {0x0EB, 0x00080000}, - {0x030, 0x00008038}, - {0x030, 0x00010038}, - {0x030, 0x00018038}, - {0x030, 0x00020038}, - {0x030, 0x00028038}, - {0x030, 0x00030038}, - {0x030, 0x0003803C}, - {0x030, 0x0004003C}, - {0x030, 0x0004803C}, - {0x030, 0x0005003C}, - {0x030, 0x0005803C}, - {0x030, 0x0006003C}, - {0x030, 0x0006803C}, - {0x030, 0x0007003C}, - {0x0EB, 0x00000000}, - {0x094, 0x000000FC}, - {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x05E, 0x0000001F}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x05E, 0x0000001F}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x095, 0x00000008}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0xA0000000, 0x00000000}, - {0x095, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x05E, 0x0000001F}, {0xB0000000, 0x00000000}, - {0x0EE, 0x00001000}, - {0x033, 0x00000020}, + {0x0EF, 0x00000200}, {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, - {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, - {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, - {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000152}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0xA0000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, {0xB0000000, 0x00000000}, - {0x033, 0x00000024}, + {0x0EF, 0x00000000}, + {0x0EB, 0x00080000}, {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000015A}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xA0000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xB0000000, 0x00000000}, + {0x030, 0x0003803C}, + {0x030, 0x0004003C}, + {0x030, 0x0004803C}, + {0x030, 0x0005003C}, + {0x030, 0x0005803C}, + {0x030, 0x0006003C}, + {0x030, 0x0006803C}, + {0x030, 0x0007003C}, + {0x0EB, 0x00000000}, + {0x094, 0x000000FC}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000000}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0xA0000000, 0x00000000}, + {0x095, 0x00000000}, + {0xB0000000, 0x00000000}, + {0x0EE, 0x00001000}, + {0x033, 0x00000020}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000052}, + {0xA0000000, 0x00000000}, + {0x03F, 0x00000052}, + {0xB0000000, 0x00000000}, + {0x033, 0x00000024}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000005A}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5368,6 +6008,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5412,6 +6056,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5456,6 +6104,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5500,6 +6152,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5548,6 +6204,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5592,6 +6252,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5636,6 +6300,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5680,6 +6348,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5724,6 +6396,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5768,6 +6444,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5812,6 +6492,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5856,6 +6540,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5900,6 +6588,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5944,6 +6636,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -5988,6 +6684,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6032,6 +6732,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6076,6 +6780,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6120,6 +6828,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6164,6 +6876,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6208,6 +6924,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -6252,20 +6972,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -6296,20 +7020,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -6340,20 +7068,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -6384,20 +7116,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -6428,20 +7164,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -6472,20 +7212,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -6516,20 +7260,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -6560,20 +7308,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -6604,20 +7356,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -6648,20 +7404,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -6692,20 +7452,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -6736,20 +7500,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -6780,20 +7548,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -6824,20 +7596,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -6868,20 +7644,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -6912,20 +7692,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -6956,20 +7740,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -7000,20 +7788,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -7044,20 +7836,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -7088,20 +7884,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -7132,20 +7932,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -7176,20 +7980,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -7220,20 +8028,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -7264,20 +8076,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -7308,20 +8124,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -7352,20 +8172,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -7396,20 +8220,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -7440,20 +8268,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -7484,20 +8316,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -7528,20 +8364,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -9436,7 +10276,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9581,7 +10421,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9600,60 +10440,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00003C5F}, {0x10030, 0x00004059}, {0x10030, 0x00004453}, - {0x10030, 0x000201A7}, - {0x10030, 0x000205A1}, - {0x10030, 0x0002099B}, - {0x10030, 0x00020D95}, - {0x10030, 0x0002115B}, - {0x10030, 0x00021555}, - {0x10030, 0x00021921}, - {0x10030, 0x00021D1B}, - {0x10030, 0x000220E3}, - {0x10030, 0x000224DD}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, {0x10030, 0x000228A3}, {0x10030, 0x00022C9D}, {0x10030, 0x00023063}, {0x10030, 0x0002345D}, {0x10030, 0x00023823}, - {0x10030, 0x00023C1D}, - {0x10030, 0x00024017}, - {0x10030, 0x00024411}, - {0x10030, 0x000281A9}, - {0x10030, 0x000285A3}, - {0x10030, 0x0002899D}, - {0x10030, 0x00028D97}, - {0x10030, 0x0002915D}, - {0x10030, 0x00029557}, - {0x10030, 0x0002991F}, - {0x10030, 0x00029D19}, - {0x10030, 0x0002A0E1}, - {0x10030, 0x0002A4DB}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, {0x10030, 0x0002A8A1}, - {0x10030, 0x0002AC9B}, + {0x10030, 0x0002AC67}, {0x10030, 0x0002B061}, - {0x10030, 0x0002B45B}, + {0x10030, 0x0002B427}, {0x10030, 0x0002B821}, - {0x10030, 0x0002BC1B}, - {0x10030, 0x0002C015}, - {0x10030, 0x0002C40F}, - {0x10030, 0x000301A9}, - {0x10030, 0x000305A3}, - {0x10030, 0x0003099D}, - {0x10030, 0x00030D97}, - {0x10030, 0x0003115D}, - {0x10030, 0x00031557}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, {0x10030, 0x0003191F}, - {0x10030, 0x00031D19}, + {0x10030, 0x00031CE7}, {0x10030, 0x000320E1}, - {0x10030, 0x000324DB}, - {0x10030, 0x000328A1}, - {0x10030, 0x00032C9B}, - {0x10030, 0x00033061}, - {0x10030, 0x0003345B}, - {0x10030, 0x00033821}, - {0x10030, 0x00033C1B}, - {0x10030, 0x00034015}, - {0x10030, 0x0003440F}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, {0x10030, 0x000601F1}, {0x10030, 0x000605E9}, {0x10030, 0x000609A9}, @@ -9697,7 +10537,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007115B}, {0x10030, 0x00071523}, {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, + {0x10030, 0x00071D17}, {0x10030, 0x000720DF}, {0x10030, 0x000724D9}, {0x10030, 0x000728A1}, @@ -9726,7 +10566,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9745,60 +10585,60 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00003C5F}, {0x10030, 0x00004059}, {0x10030, 0x00004453}, - {0x10030, 0x000201A7}, - {0x10030, 0x000205A1}, - {0x10030, 0x0002099B}, - {0x10030, 0x00020D95}, - {0x10030, 0x0002115B}, - {0x10030, 0x00021555}, - {0x10030, 0x00021921}, - {0x10030, 0x00021D1B}, - {0x10030, 0x000220E3}, - {0x10030, 0x000224DD}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, {0x10030, 0x000228A3}, {0x10030, 0x00022C9D}, {0x10030, 0x00023063}, {0x10030, 0x0002345D}, {0x10030, 0x00023823}, - {0x10030, 0x00023C1D}, - {0x10030, 0x00024017}, - {0x10030, 0x00024411}, - {0x10030, 0x000281A9}, - {0x10030, 0x000285A3}, - {0x10030, 0x0002899D}, - {0x10030, 0x00028D97}, - {0x10030, 0x0002915D}, - {0x10030, 0x00029557}, - {0x10030, 0x0002991F}, - {0x10030, 0x00029D19}, - {0x10030, 0x0002A0E1}, - {0x10030, 0x0002A4DB}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, {0x10030, 0x0002A8A1}, - {0x10030, 0x0002AC9B}, + {0x10030, 0x0002AC67}, {0x10030, 0x0002B061}, - {0x10030, 0x0002B45B}, + {0x10030, 0x0002B427}, {0x10030, 0x0002B821}, - {0x10030, 0x0002BC1B}, - {0x10030, 0x0002C015}, - {0x10030, 0x0002C40F}, - {0x10030, 0x000301A9}, - {0x10030, 0x000305A3}, - {0x10030, 0x0003099D}, - {0x10030, 0x00030D97}, - {0x10030, 0x0003115D}, - {0x10030, 0x00031557}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, {0x10030, 0x0003191F}, - {0x10030, 0x00031D19}, + {0x10030, 0x00031CE7}, {0x10030, 0x000320E1}, - {0x10030, 0x000324DB}, - {0x10030, 0x000328A1}, - {0x10030, 0x00032C9B}, - {0x10030, 0x00033061}, - {0x10030, 0x0003345B}, - {0x10030, 0x00033821}, - {0x10030, 0x00033C1B}, - {0x10030, 0x00034015}, - {0x10030, 0x0003440F}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, {0x10030, 0x000601F1}, {0x10030, 0x000605E9}, {0x10030, 0x000609A9}, @@ -9842,7 +10682,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007115B}, {0x10030, 0x00071523}, {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, + {0x10030, 0x00071D17}, {0x10030, 0x000720DF}, {0x10030, 0x000724D9}, {0x10030, 0x000728A1}, @@ -9871,7 +10711,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -9949,74 +10789,74 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, - {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -10094,74 +10934,74 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, - {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -10239,74 +11079,74 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, - {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -10384,73 +11224,363 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, + {0x10030, 0x0006C411}, {0x10030, 0x000701EF}, - {0x10030, 0x000705E7}, - {0x10030, 0x000709A7}, - {0x10030, 0x00070D61}, - {0x10030, 0x0007115B}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071CE5}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728A1}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, {0x10030, 0x000781EF}, {0x10030, 0x000785E9}, {0x10030, 0x000789E3}, {0x10030, 0x00078DA1}, {0x10030, 0x0007915F}, {0x10030, 0x00079559}, - {0x10030, 0x00079921}, - {0x10030, 0x00079D1B}, - {0x10030, 0x0007A0E3}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B823}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201A7}, + {0x10030, 0x000205A1}, + {0x10030, 0x0002099B}, + {0x10030, 0x00020D95}, + {0x10030, 0x0002115B}, + {0x10030, 0x00021555}, + {0x10030, 0x00021921}, + {0x10030, 0x00021D1B}, + {0x10030, 0x000220E3}, + {0x10030, 0x000224DD}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1D}, + {0x10030, 0x00024017}, + {0x10030, 0x00024411}, + {0x10030, 0x000281A9}, + {0x10030, 0x000285A3}, + {0x10030, 0x0002899D}, + {0x10030, 0x00028D97}, + {0x10030, 0x0002915D}, + {0x10030, 0x00029557}, + {0x10030, 0x0002991F}, + {0x10030, 0x00029D19}, + {0x10030, 0x0002A0E1}, + {0x10030, 0x0002A4DB}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC9B}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B45B}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC1B}, + {0x10030, 0x0002C015}, + {0x10030, 0x0002C40F}, + {0x10030, 0x000301A9}, + {0x10030, 0x000305A3}, + {0x10030, 0x0003099D}, + {0x10030, 0x00030D97}, + {0x10030, 0x0003115D}, + {0x10030, 0x00031557}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031D19}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324DB}, + {0x10030, 0x000328A1}, + {0x10030, 0x00032C9B}, + {0x10030, 0x00033061}, + {0x10030, 0x0003345B}, + {0x10030, 0x00033821}, + {0x10030, 0x00033C1B}, + {0x10030, 0x00034015}, + {0x10030, 0x0003440F}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201A7}, + {0x10030, 0x000205A1}, + {0x10030, 0x0002099B}, + {0x10030, 0x00020D95}, + {0x10030, 0x0002115B}, + {0x10030, 0x00021555}, + {0x10030, 0x00021921}, + {0x10030, 0x00021D1B}, + {0x10030, 0x000220E3}, + {0x10030, 0x000224DD}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1D}, + {0x10030, 0x00024017}, + {0x10030, 0x00024411}, + {0x10030, 0x000281A9}, + {0x10030, 0x000285A3}, + {0x10030, 0x0002899D}, + {0x10030, 0x00028D97}, + {0x10030, 0x0002915D}, + {0x10030, 0x00029557}, + {0x10030, 0x0002991F}, + {0x10030, 0x00029D19}, + {0x10030, 0x0002A0E1}, + {0x10030, 0x0002A4DB}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC9B}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B45B}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC1B}, + {0x10030, 0x0002C015}, + {0x10030, 0x0002C40F}, + {0x10030, 0x000301A9}, + {0x10030, 0x000305A3}, + {0x10030, 0x0003099D}, + {0x10030, 0x00030D97}, + {0x10030, 0x0003115D}, + {0x10030, 0x00031557}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031D19}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324DB}, + {0x10030, 0x000328A1}, + {0x10030, 0x00032C9B}, + {0x10030, 0x00033061}, + {0x10030, 0x0003345B}, + {0x10030, 0x00033821}, + {0x10030, 0x00033C1B}, + {0x10030, 0x00034015}, + {0x10030, 0x0003440F}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0xA0000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -11294,12 +12424,116 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x000338CC}, {0x10030, 0x00033C09}, {0x10030, 0x00034006}, - {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, - {0x10030, 0x000200FA}, - {0x10030, 0x000204F7}, - {0x10030, 0x000208F4}, - {0x10030, 0x00020CF1}, - {0x10030, 0x000210EE}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280ED}, + {0x10030, 0x000284EA}, + {0x10030, 0x000288E7}, + {0x10030, 0x00028CE4}, + {0x10030, 0x000290E1}, + {0x10030, 0x000294DE}, + {0x10030, 0x000298DB}, + {0x10030, 0x00029CD8}, + {0x10030, 0x0002A0D5}, + {0x10030, 0x0002A4D2}, + {0x10030, 0x0002A8CF}, + {0x10030, 0x0002AC0C}, + {0x10030, 0x0002B009}, + {0x10030, 0x0002B406}, + {0x10030, 0x0002B803}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300EE}, + {0x10030, 0x000304EB}, + {0x10030, 0x000308E8}, + {0x10030, 0x00030CE5}, + {0x10030, 0x000310E2}, + {0x10030, 0x000314DF}, + {0x10030, 0x000318DC}, + {0x10030, 0x00031CD9}, + {0x10030, 0x000320D6}, + {0x10030, 0x000324D3}, + {0x10030, 0x000328D0}, + {0x10030, 0x00032CCD}, + {0x10030, 0x0003300A}, + {0x10030, 0x00033407}, + {0x10030, 0x00033804}, + {0x10030, 0x00033C01}, + {0x10030, 0x00034000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280ED}, + {0x10030, 0x000284EA}, + {0x10030, 0x000288E7}, + {0x10030, 0x00028CE4}, + {0x10030, 0x000290E1}, + {0x10030, 0x000294DE}, + {0x10030, 0x000298DB}, + {0x10030, 0x00029CD8}, + {0x10030, 0x0002A0D5}, + {0x10030, 0x0002A4D2}, + {0x10030, 0x0002A8CF}, + {0x10030, 0x0002AC0C}, + {0x10030, 0x0002B009}, + {0x10030, 0x0002B406}, + {0x10030, 0x0002B803}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300EE}, + {0x10030, 0x000304EB}, + {0x10030, 0x000308E8}, + {0x10030, 0x00030CE5}, + {0x10030, 0x000310E2}, + {0x10030, 0x000314DF}, + {0x10030, 0x000318DC}, + {0x10030, 0x00031CD9}, + {0x10030, 0x000320D6}, + {0x10030, 0x000324D3}, + {0x10030, 0x000328D0}, + {0x10030, 0x00032CCD}, + {0x10030, 0x0003300A}, + {0x10030, 0x00033407}, + {0x10030, 0x00033804}, + {0x10030, 0x00033C01}, + {0x10030, 0x00034000}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200FA}, + {0x10030, 0x000204F7}, + {0x10030, 0x000208F4}, + {0x10030, 0x00020CF1}, + {0x10030, 0x000210EE}, {0x10030, 0x000214EB}, {0x10030, 0x000218E8}, {0x10030, 0x00021CE5}, @@ -11841,6 +13075,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -11885,6 +13123,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -11941,6 +13183,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -11985,6 +13231,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12041,6 +13291,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12085,6 +13339,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12141,6 +13399,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12185,6 +13447,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12241,6 +13507,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12285,6 +13555,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12305,7 +13579,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x033, 0x00000070}, {0x03F, 0x00050002}, {0x033, 0x00000071}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0xA0000000, 0x00000000}, {0x03F, 0x00060032}, + {0xB0000000, 0x00000000}, {0x033, 0x00000072}, {0x03F, 0x00050042}, {0x033, 0x00000073}, @@ -12341,6 +13661,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12385,6 +13709,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12405,7 +13733,53 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x033, 0x00000078}, {0x03F, 0x00050002}, {0x033, 0x00000079}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00060032}, + {0xA0000000, 0x00000000}, {0x03F, 0x00060032}, + {0xB0000000, 0x00000000}, {0x033, 0x0000007A}, {0x03F, 0x00050042}, {0x033, 0x0000007B}, @@ -12441,6 +13815,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12485,6 +13863,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12541,6 +13923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12585,6 +13971,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12641,6 +14031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12685,6 +14079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12741,6 +14139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12785,6 +14187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12841,6 +14247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12885,6 +14295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12941,6 +14355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -12985,6 +14403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13041,6 +14463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13085,6 +14511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13141,6 +14571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13185,6 +14619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13241,6 +14679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13285,6 +14727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13341,6 +14787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13385,6 +14835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13441,6 +14895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13485,6 +14943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13541,6 +15003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13585,6 +15051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13641,6 +15111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13685,6 +15159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13741,6 +15219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13785,6 +15267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13841,6 +15327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13885,6 +15375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13941,6 +15435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -13985,6 +15483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14041,6 +15543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14085,6 +15591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14141,6 +15651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14185,6 +15699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14241,6 +15759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14285,6 +15807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14341,6 +15867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14385,6 +15915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14441,6 +15975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14485,6 +16023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14541,6 +16083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14585,6 +16131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14669,6 +16219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00025003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14719,6 +16273,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0002D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14769,6 +16327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x00035003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14819,6 +16381,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x10030, 0x0003D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -14882,6 +16448,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, @@ -14952,6 +16524,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, @@ -15022,6 +16600,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, @@ -15092,6 +16676,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, @@ -15119,7 +16709,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = { {0xB0000000, 0x00000000}, {0x10030, 0x0007F003}, {0x100EE, 0x00000000}, - {0x0FE, 0x00000048}, + {0x0FE, 0x00000063}, }; static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { @@ -15136,13 +16726,15 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0xF0040001, 0x0000000A}, {0xF0050001, 0x0000000B}, {0xF0070001, 0x0000000C}, - {0xF0320001, 0x0000000D}, - {0xF0330001, 0x0000000E}, - {0xF0340001, 0x0000000F}, - {0xF0350001, 0x00000010}, - {0xF0360001, 0x00000011}, - {0xF03F0001, 0x00000012}, - {0xF0400001, 0x00000013}, + {0xF0150001, 0x0000000D}, + {0xF0160001, 0x0000000E}, + {0xF0320001, 0x0000000F}, + {0xF0330001, 0x00000010}, + {0xF0340001, 0x00000011}, + {0xF0350001, 0x00000012}, + {0xF0360001, 0x00000013}, + {0xF03F0001, 0x00000014}, + {0xF0400001, 0x00000015}, {0x005, 0x00000000}, {0x10005, 0x00000000}, {0x0B9, 0x00020440}, @@ -15150,6 +16742,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10000, 0x00030000}, {0x018, 0x00011124}, {0x10018, 0x00011124}, + {0x0A3, 0x000B9204}, + {0x0AD, 0x00091E0F}, + {0x05D, 0x00001012}, + {0x05C, 0x00079C5C}, + {0x062, 0x00055220}, + {0x0D3, 0x00000103}, {0x05F, 0x00000038}, {0x097, 0x00043200}, {0x0A6, 0x00066DB7}, @@ -15253,6 +16851,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x067, 0x0000D300}, + {0x0DA, 0x000D4000}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x067, 0x0000D300}, {0x0DA, 0x000D4000}, @@ -15319,6 +16923,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x08F, 0x000D1352}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x08F, 0x000D1352}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x08F, 0x000D1352}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -15382,6 +16990,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000007}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000017}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000007}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -15918,6 +17530,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000EFFF}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000EFFF}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000EFFF}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16256,6 +17872,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x030, 0x00050112}, {0x030, 0x00058101}, {0x030, 0x00060001}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x000085ED}, + {0x030, 0x000105CC}, + {0x030, 0x000184AA}, + {0x030, 0x00020388}, + {0x030, 0x00028377}, + {0x030, 0x00030377}, + {0x030, 0x00038255}, + {0x030, 0x00040244}, + {0x030, 0x00048133}, + {0x030, 0x00050112}, + {0x030, 0x00058101}, + {0x030, 0x00060001}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x000085ED}, {0x030, 0x000105CC}, @@ -16582,11 +18224,255 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x0EF, 0x00000000}, {0x06E, 0x00077A18}, {0x06D, 0x00000C31}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, {0x06A, 0x000E0F8A}, {0x06B, 0x000018A0}, {0x06F, 0x000F81FC}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0380}, + {0x06B, 0x00003CA0}, + {0x06F, 0x000C01FC}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0xA0000000, 0x00000000}, + {0x06A, 0x000E0F8A}, + {0x06B, 0x000018A0}, + {0x06F, 0x000F81FC}, + {0xB0000000, 0x00000000}, {0x05E, 0x0000001F}, {0x0EF, 0x00000200}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x030, 0x0003E207}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x0003D407}, {0x030, 0x00035A87}, {0x030, 0x0002CF07}, @@ -16595,14 +18481,216 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x030, 0x00014F07}, {0x030, 0x0000CF07}, {0x030, 0x00004F07}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0xA0000000, 0x00000000}, + {0x030, 0x0003D407}, + {0x030, 0x00035A87}, + {0x030, 0x0002CF07}, + {0x030, 0x00024F07}, + {0x030, 0x0001CF07}, + {0x030, 0x00014F07}, + {0x030, 0x0000CF07}, + {0x030, 0x00004F07}, + {0xB0000000, 0x00000000}, {0x0EF, 0x00000000}, {0x0EB, 0x00080000}, + {0x80010000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90020000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90320000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90330000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90340000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90350000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90360000, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90010001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x0000803C}, + {0x030, 0x0001003C}, + {0x030, 0x0001803C}, + {0x030, 0x0002003C}, + {0x030, 0x0002803C}, + {0x030, 0x0003003C}, + {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x030, 0x00008038}, {0x030, 0x00010038}, {0x030, 0x00018038}, {0x030, 0x00020038}, {0x030, 0x00028038}, {0x030, 0x00030038}, + {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xA0000000, 0x00000000}, + {0x030, 0x00008038}, + {0x030, 0x00010038}, + {0x030, 0x00018038}, + {0x030, 0x00020038}, + {0x030, 0x00028038}, + {0x030, 0x00030038}, + {0xB0000000, 0x00000000}, {0x030, 0x0003803C}, {0x030, 0x0004003C}, {0x030, 0x0004803C}, @@ -16639,6 +18727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x095, 0x00000008}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x095, 0x00000008}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x095, 0x00000008}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x095, 0x00000008}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16684,6 +18776,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16728,6 +18824,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16772,6 +18872,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16816,6 +18920,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16860,6 +18968,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16904,6 +19016,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16948,6 +19064,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -16992,6 +19112,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17036,6 +19160,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17080,6 +19208,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17124,6 +19256,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17168,6 +19304,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17212,6 +19352,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17256,6 +19400,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17300,6 +19448,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17344,6 +19496,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17388,6 +19544,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17432,6 +19592,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17476,6 +19640,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17520,6 +19688,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17564,6 +19736,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17608,6 +19784,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17652,6 +19832,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17696,6 +19880,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -17740,20 +19928,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -17784,20 +19976,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -17828,20 +20024,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -17872,20 +20072,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -17916,20 +20120,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -17960,20 +20168,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -18004,20 +20216,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -18048,20 +20264,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -18092,20 +20312,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -18136,20 +20360,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -18180,20 +20408,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -18224,20 +20456,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -18268,20 +20504,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -18312,20 +20552,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -18356,20 +20600,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -18400,20 +20648,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -18444,20 +20696,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -18488,20 +20744,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -18532,20 +20792,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -18576,20 +20840,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -18620,20 +20888,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -18664,20 +20936,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -18708,20 +20984,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000002E6}, + {0x03F, 0x000002E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000002E6}, {0xB0000000, 0x00000000}, @@ -18752,20 +21032,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000003E7}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000003E7}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000003E7}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000003E6}, + {0x03F, 0x000003E7}, {0xA0000000, 0x00000000}, {0x03F, 0x000003E6}, {0xB0000000, 0x00000000}, @@ -18796,20 +21080,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000152}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00000152}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000152}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x00000052}, + {0x03F, 0x00000152}, {0xA0000000, 0x00000000}, {0x03F, 0x00000052}, {0xB0000000, 0x00000000}, @@ -18840,20 +21128,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000015A}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000015A}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000015A}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000005A}, + {0x03F, 0x0000015A}, {0xA0000000, 0x00000000}, {0x03F, 0x0000005A}, {0xB0000000, 0x00000000}, @@ -18884,20 +21176,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000019C}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x0000019C}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x0000019C}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000009C}, + {0x03F, 0x0000019C}, {0xA0000000, 0x00000000}, {0x03F, 0x0000009C}, {0xB0000000, 0x00000000}, @@ -18928,20 +21224,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001A4}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001A4}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001A4}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x0000019C}, + {0x03F, 0x000001A4}, {0xA0000000, 0x00000000}, {0x03F, 0x0000019C}, {0xB0000000, 0x00000000}, @@ -18972,20 +21272,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000001E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000001E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000001E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001A4}, + {0x03F, 0x000001E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001A4}, {0xB0000000, 0x00000000}, @@ -19016,20 +21320,24 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x000002E6}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x000002E6}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x000002E6}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, - {0x03F, 0x000001E6}, + {0x03F, 0x000002E6}, {0xA0000000, 0x00000000}, {0x03F, 0x000001E6}, {0xB0000000, 0x00000000}, @@ -20199,7 +22507,297 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90020001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC67}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B427}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031CE7}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061525}, + {0x10030, 0x0006191F}, + {0x10030, 0x00061CE7}, + {0x10030, 0x000620E1}, + {0x10030, 0x000624DB}, + {0x10030, 0x000628A3}, + {0x10030, 0x00062C69}, + {0x10030, 0x00063063}, + {0x10030, 0x00063429}, + {0x10030, 0x00063823}, + {0x10030, 0x00063C1D}, + {0x10030, 0x00064013}, + {0x10030, 0x0006440D}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069523}, + {0x10030, 0x0006991D}, + {0x10030, 0x00069CE5}, + {0x10030, 0x0006A0DF}, + {0x10030, 0x0006A4A7}, + {0x10030, 0x0006A8A1}, + {0x10030, 0x0006AC67}, + {0x10030, 0x0006B061}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C40D}, + {0x10030, 0x000701F1}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071523}, + {0x10030, 0x0007191D}, + {0x10030, 0x00071D17}, + {0x10030, 0x00072111}, + {0x10030, 0x000724D9}, + {0x10030, 0x000728D3}, + {0x10030, 0x00072C67}, + {0x10030, 0x00073061}, + {0x10030, 0x00073427}, + {0x10030, 0x00073821}, + {0x10030, 0x00073C1B}, + {0x10030, 0x00074015}, + {0x10030, 0x0007440D}, + {0x10030, 0x000781F1}, + {0x10030, 0x000785EB}, + {0x10030, 0x000789E5}, + {0x10030, 0x00078DA3}, + {0x10030, 0x00079161}, + {0x10030, 0x0007955B}, + {0x10030, 0x00079923}, + {0x10030, 0x00079D1D}, + {0x10030, 0x0007A117}, + {0x10030, 0x0007A4DD}, + {0x10030, 0x0007A8D7}, + {0x10030, 0x0007AC9D}, + {0x10030, 0x0007B063}, + {0x10030, 0x0007B45D}, + {0x10030, 0x0007B857}, + {0x10030, 0x0007BC1D}, + {0x10030, 0x0007C017}, + {0x10030, 0x0007C40F}, + {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000001EF}, + {0x10030, 0x000005E9}, + {0x10030, 0x000009E3}, + {0x10030, 0x00000DDD}, + {0x10030, 0x000011D7}, + {0x10030, 0x0000159F}, + {0x10030, 0x00001999}, + {0x10030, 0x00001D5F}, + {0x10030, 0x00002159}, + {0x10030, 0x0000251F}, + {0x10030, 0x00002919}, + {0x10030, 0x00002CDF}, + {0x10030, 0x000030D9}, + {0x10030, 0x0000349F}, + {0x10030, 0x00003899}, + {0x10030, 0x00003C5F}, + {0x10030, 0x00004059}, + {0x10030, 0x00004453}, + {0x10030, 0x000201EF}, + {0x10030, 0x000205E9}, + {0x10030, 0x000209E3}, + {0x10030, 0x00020DA3}, + {0x10030, 0x00021161}, + {0x10030, 0x0002155B}, + {0x10030, 0x0002191F}, + {0x10030, 0x00021D19}, + {0x10030, 0x000220E1}, + {0x10030, 0x000224DB}, + {0x10030, 0x000228A3}, + {0x10030, 0x00022C9D}, + {0x10030, 0x00023063}, + {0x10030, 0x0002345D}, + {0x10030, 0x00023823}, + {0x10030, 0x00023C1B}, + {0x10030, 0x00024015}, + {0x10030, 0x0002440F}, + {0x10030, 0x000281EF}, + {0x10030, 0x000285E7}, + {0x10030, 0x000289A7}, + {0x10030, 0x00028D65}, + {0x10030, 0x0002915F}, + {0x10030, 0x00029523}, + {0x10030, 0x0002991D}, + {0x10030, 0x00029CE5}, + {0x10030, 0x0002A0DF}, + {0x10030, 0x0002A4A7}, + {0x10030, 0x0002A8A1}, + {0x10030, 0x0002AC67}, + {0x10030, 0x0002B061}, + {0x10030, 0x0002B427}, + {0x10030, 0x0002B821}, + {0x10030, 0x0002BC19}, + {0x10030, 0x0002C013}, + {0x10030, 0x0002C40D}, + {0x10030, 0x000301EF}, + {0x10030, 0x000305E7}, + {0x10030, 0x000309A7}, + {0x10030, 0x00030D65}, + {0x10030, 0x0003115F}, + {0x10030, 0x00031525}, + {0x10030, 0x0003191F}, + {0x10030, 0x00031CE7}, + {0x10030, 0x000320E1}, + {0x10030, 0x000324A9}, + {0x10030, 0x000328A3}, + {0x10030, 0x00032C69}, + {0x10030, 0x00033063}, + {0x10030, 0x00033429}, + {0x10030, 0x00033823}, + {0x10030, 0x00033C1D}, + {0x10030, 0x00034013}, + {0x10030, 0x0003440D}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061525}, + {0x10030, 0x0006191F}, + {0x10030, 0x00061CE7}, + {0x10030, 0x000620E1}, + {0x10030, 0x000624DB}, + {0x10030, 0x000628A3}, + {0x10030, 0x00062C69}, + {0x10030, 0x00063063}, + {0x10030, 0x00063429}, + {0x10030, 0x00063823}, + {0x10030, 0x00063C1D}, + {0x10030, 0x00064013}, + {0x10030, 0x0006440D}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069523}, + {0x10030, 0x0006991D}, + {0x10030, 0x00069CE5}, + {0x10030, 0x0006A0DF}, + {0x10030, 0x0006A4A7}, + {0x10030, 0x0006A8A1}, + {0x10030, 0x0006AC67}, + {0x10030, 0x0006B061}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C40D}, + {0x10030, 0x000701F1}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071523}, + {0x10030, 0x0007191D}, + {0x10030, 0x00071D17}, + {0x10030, 0x00072111}, + {0x10030, 0x000724D9}, + {0x10030, 0x000728D3}, + {0x10030, 0x00072C67}, + {0x10030, 0x00073061}, + {0x10030, 0x00073427}, + {0x10030, 0x00073821}, + {0x10030, 0x00073C1B}, + {0x10030, 0x00074015}, + {0x10030, 0x0007440D}, + {0x10030, 0x000781F1}, + {0x10030, 0x000785EB}, + {0x10030, 0x000789E5}, + {0x10030, 0x00078DA3}, + {0x10030, 0x00079161}, + {0x10030, 0x0007955B}, + {0x10030, 0x00079923}, + {0x10030, 0x00079D1D}, + {0x10030, 0x0007A117}, + {0x10030, 0x0007A4DD}, + {0x10030, 0x0007A8D7}, + {0x10030, 0x0007AC9D}, + {0x10030, 0x0007B063}, + {0x10030, 0x0007B45D}, + {0x10030, 0x0007B857}, + {0x10030, 0x0007BC1D}, + {0x10030, 0x0007C017}, + {0x10030, 0x0007C40F}, + {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20344,7 +22942,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90030001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20489,7 +23087,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90040001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20634,7 +23232,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90050001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -20779,7 +23377,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0007BC1D}, {0x10030, 0x0007C017}, {0x10030, 0x0007C40F}, - {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, {0x10030, 0x000009E3}, @@ -21147,73 +23745,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90340001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21292,73 +23890,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90350001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21428,82 +24026,82 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x00032C9B}, {0x10030, 0x00033061}, {0x10030, 0x0003345B}, - {0x10030, 0x00033821}, - {0x10030, 0x00033C1B}, - {0x10030, 0x00034015}, - {0x10030, 0x0003440F}, - {0x10030, 0x000601F1}, - {0x10030, 0x000605E9}, - {0x10030, 0x000609A9}, - {0x10030, 0x00060D65}, - {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, - {0x10030, 0x000681EF}, - {0x10030, 0x000685E7}, - {0x10030, 0x000689A7}, - {0x10030, 0x00068D61}, - {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, - {0x10030, 0x0006B429}, - {0x10030, 0x0006B823}, - {0x10030, 0x0006BC1D}, - {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, - {0x10030, 0x000705E9}, - {0x10030, 0x000709A9}, - {0x10030, 0x00070D63}, - {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00033821}, + {0x10030, 0x00033C1B}, + {0x10030, 0x00034015}, + {0x10030, 0x0003440F}, + {0x10030, 0x000601F1}, + {0x10030, 0x000605E9}, + {0x10030, 0x000609A9}, + {0x10030, 0x00060D65}, + {0x10030, 0x0006115F}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, + {0x10030, 0x000681EF}, + {0x10030, 0x000685E7}, + {0x10030, 0x000689A7}, + {0x10030, 0x00068D61}, + {0x10030, 0x0006915B}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, + {0x10030, 0x0006B429}, + {0x10030, 0x0006B823}, + {0x10030, 0x0006BC1D}, + {0x10030, 0x0006C017}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, + {0x10030, 0x000705E9}, + {0x10030, 0x000709A9}, + {0x10030, 0x00070D63}, + {0x10030, 0x0007115D}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90360001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21582,73 +24180,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x903f0001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21727,73 +24325,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0x90400001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -21872,73 +24470,73 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000609A9}, {0x10030, 0x00060D65}, {0x10030, 0x0006115F}, - {0x10030, 0x00061525}, - {0x10030, 0x0006191F}, - {0x10030, 0x00061CE7}, - {0x10030, 0x000620E1}, - {0x10030, 0x000624DB}, - {0x10030, 0x000628A3}, - {0x10030, 0x00062C69}, - {0x10030, 0x00063063}, - {0x10030, 0x00063429}, - {0x10030, 0x00063823}, - {0x10030, 0x00063C1D}, - {0x10030, 0x00064013}, - {0x10030, 0x0006440D}, + {0x10030, 0x00061527}, + {0x10030, 0x00061921}, + {0x10030, 0x00061CE9}, + {0x10030, 0x000620E3}, + {0x10030, 0x000624DD}, + {0x10030, 0x000628A5}, + {0x10030, 0x00062C6B}, + {0x10030, 0x00063065}, + {0x10030, 0x0006342B}, + {0x10030, 0x00063825}, + {0x10030, 0x00063C1F}, + {0x10030, 0x00064019}, + {0x10030, 0x00064413}, {0x10030, 0x000681EF}, {0x10030, 0x000685E7}, {0x10030, 0x000689A7}, {0x10030, 0x00068D61}, {0x10030, 0x0006915B}, - {0x10030, 0x00069523}, - {0x10030, 0x0006991D}, - {0x10030, 0x00069CE5}, - {0x10030, 0x0006A0DF}, - {0x10030, 0x0006A4A7}, - {0x10030, 0x0006A8A1}, - {0x10030, 0x0006AC67}, - {0x10030, 0x0006B061}, + {0x10030, 0x00069525}, + {0x10030, 0x0006991F}, + {0x10030, 0x00069CE7}, + {0x10030, 0x0006A0E1}, + {0x10030, 0x0006A4A9}, + {0x10030, 0x0006A8A3}, + {0x10030, 0x0006AC69}, + {0x10030, 0x0006B063}, {0x10030, 0x0006B429}, {0x10030, 0x0006B823}, {0x10030, 0x0006BC1D}, {0x10030, 0x0006C017}, - {0x10030, 0x0006C40D}, - {0x10030, 0x000701F1}, + {0x10030, 0x0006C411}, + {0x10030, 0x000701EF}, {0x10030, 0x000705E9}, {0x10030, 0x000709A9}, {0x10030, 0x00070D63}, {0x10030, 0x0007115D}, - {0x10030, 0x00071523}, - {0x10030, 0x0007191D}, - {0x10030, 0x00071D17}, - {0x10030, 0x000720DF}, - {0x10030, 0x000724D9}, - {0x10030, 0x000728D3}, - {0x10030, 0x00072C67}, - {0x10030, 0x00073061}, - {0x10030, 0x00073427}, - {0x10030, 0x00073821}, - {0x10030, 0x00073C1B}, - {0x10030, 0x00074015}, - {0x10030, 0x0007440D}, - {0x10030, 0x000781F1}, - {0x10030, 0x000785EB}, - {0x10030, 0x000789E5}, - {0x10030, 0x00078DA3}, - {0x10030, 0x00079161}, - {0x10030, 0x0007955B}, - {0x10030, 0x00079923}, - {0x10030, 0x00079D1D}, - {0x10030, 0x0007A117}, - {0x10030, 0x0007A4DD}, - {0x10030, 0x0007A8D7}, - {0x10030, 0x0007AC9D}, - {0x10030, 0x0007B063}, - {0x10030, 0x0007B45D}, - {0x10030, 0x0007B857}, - {0x10030, 0x0007BC1D}, - {0x10030, 0x0007C017}, - {0x10030, 0x0007C40F}, + {0x10030, 0x00071525}, + {0x10030, 0x0007191F}, + {0x10030, 0x00071D19}, + {0x10030, 0x000720E1}, + {0x10030, 0x000724DB}, + {0x10030, 0x000728A3}, + {0x10030, 0x00072C69}, + {0x10030, 0x00073063}, + {0x10030, 0x00073429}, + {0x10030, 0x00073823}, + {0x10030, 0x00073C1D}, + {0x10030, 0x00074017}, + {0x10030, 0x00074411}, + {0x10030, 0x000781EF}, + {0x10030, 0x000785E9}, + {0x10030, 0x000789E3}, + {0x10030, 0x00078DA1}, + {0x10030, 0x0007915F}, + {0x10030, 0x00079559}, + {0x10030, 0x0007991F}, + {0x10030, 0x00079D19}, + {0x10030, 0x0007A0DF}, + {0x10030, 0x0007A4D9}, + {0x10030, 0x0007A8D3}, + {0x10030, 0x0007AC99}, + {0x10030, 0x0007B05F}, + {0x10030, 0x0007B459}, + {0x10030, 0x0007B81F}, + {0x10030, 0x0007BC19}, + {0x10030, 0x0007C013}, + {0x10030, 0x0007C40D}, {0xA0000000, 0x00000000}, {0x10030, 0x000001EF}, {0x10030, 0x000005E9}, @@ -22782,6 +25380,110 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x000338CC}, {0x10030, 0x00033C09}, {0x10030, 0x00034006}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280E7}, + {0x10030, 0x000284E4}, + {0x10030, 0x000288E1}, + {0x10030, 0x00028CDE}, + {0x10030, 0x000290DB}, + {0x10030, 0x000294D8}, + {0x10030, 0x000298D5}, + {0x10030, 0x00029CD2}, + {0x10030, 0x0002A0CF}, + {0x10030, 0x0002A40C}, + {0x10030, 0x0002A809}, + {0x10030, 0x0002AC06}, + {0x10030, 0x0002B003}, + {0x10030, 0x0002B400}, + {0x10030, 0x0002B800}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300E7}, + {0x10030, 0x000304E4}, + {0x10030, 0x000308E1}, + {0x10030, 0x00030CDE}, + {0x10030, 0x000310DB}, + {0x10030, 0x000314D8}, + {0x10030, 0x000318D5}, + {0x10030, 0x00031CD2}, + {0x10030, 0x000320CF}, + {0x10030, 0x000324CC}, + {0x10030, 0x00032809}, + {0x10030, 0x00032C06}, + {0x10030, 0x00033003}, + {0x10030, 0x00033400}, + {0x10030, 0x00033800}, + {0x10030, 0x00033C00}, + {0x10030, 0x00034000}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x000200E8}, + {0x10030, 0x000204E5}, + {0x10030, 0x000208E2}, + {0x10030, 0x00020CDF}, + {0x10030, 0x000210DC}, + {0x10030, 0x000214D9}, + {0x10030, 0x000218D6}, + {0x10030, 0x00021CD3}, + {0x10030, 0x000220D0}, + {0x10030, 0x0002240D}, + {0x10030, 0x0002280A}, + {0x10030, 0x00022C07}, + {0x10030, 0x00023004}, + {0x10030, 0x00023401}, + {0x10030, 0x00023800}, + {0x10030, 0x00023C00}, + {0x10030, 0x00024000}, + {0x10030, 0x000280E7}, + {0x10030, 0x000284E4}, + {0x10030, 0x000288E1}, + {0x10030, 0x00028CDE}, + {0x10030, 0x000290DB}, + {0x10030, 0x000294D8}, + {0x10030, 0x000298D5}, + {0x10030, 0x00029CD2}, + {0x10030, 0x0002A0CF}, + {0x10030, 0x0002A40C}, + {0x10030, 0x0002A809}, + {0x10030, 0x0002AC06}, + {0x10030, 0x0002B003}, + {0x10030, 0x0002B400}, + {0x10030, 0x0002B800}, + {0x10030, 0x0002BC00}, + {0x10030, 0x0002C000}, + {0x10030, 0x000300E7}, + {0x10030, 0x000304E4}, + {0x10030, 0x000308E1}, + {0x10030, 0x00030CDE}, + {0x10030, 0x000310DB}, + {0x10030, 0x000314D8}, + {0x10030, 0x000318D5}, + {0x10030, 0x00031CD2}, + {0x10030, 0x000320CF}, + {0x10030, 0x000324CC}, + {0x10030, 0x00032809}, + {0x10030, 0x00032C06}, + {0x10030, 0x00033003}, + {0x10030, 0x00033400}, + {0x10030, 0x00033800}, + {0x10030, 0x00033C00}, + {0x10030, 0x00034000}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x000200FA}, {0x10030, 0x000204F7}, @@ -23329,6 +26031,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23373,6 +26079,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23429,6 +26139,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23473,6 +26187,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23529,6 +26247,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23573,6 +26295,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23629,6 +26355,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23673,6 +26403,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23729,6 +26463,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23773,6 +26511,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23829,6 +26571,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23873,6 +26619,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23929,6 +26679,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -23973,6 +26727,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24029,6 +26787,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24073,6 +26835,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24129,6 +26895,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24173,6 +26943,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24229,6 +27003,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24273,6 +27051,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24329,6 +27111,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24373,6 +27159,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24429,6 +27219,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24473,6 +27267,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24529,6 +27327,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24573,6 +27375,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24629,6 +27435,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24673,6 +27483,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24729,6 +27543,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24773,6 +27591,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24829,6 +27651,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24873,6 +27699,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24929,6 +27759,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -24973,6 +27807,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25029,6 +27867,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25073,6 +27915,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25129,6 +27975,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25173,6 +28023,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25229,6 +28083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25273,6 +28131,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25329,6 +28191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25373,6 +28239,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25429,6 +28299,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25473,6 +28347,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25529,6 +28407,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25573,6 +28455,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25629,6 +28515,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25673,6 +28563,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25729,6 +28623,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25773,6 +28671,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25829,6 +28731,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25873,6 +28779,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25929,6 +28839,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -25973,6 +28887,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26029,6 +28947,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26073,6 +28995,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x00000003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x03F, 0x00008002}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x03F, 0x00000003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26157,6 +29083,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x00025003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00025003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00025003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26207,6 +29137,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0002D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0002D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0002D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26257,6 +29191,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x00035003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00035003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00035003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26307,6 +29245,10 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x10030, 0x0003D003}, {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0003D003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0003D003}, {0x90330001, 0x00000000}, {0x40000000, 0x00000000}, @@ -26370,6 +29312,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00065003}, + {0x10030, 0x00066003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00065003}, {0x10030, 0x00066003}, @@ -26440,6 +29388,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0006D003}, + {0x10030, 0x0006E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0006D003}, {0x10030, 0x0006E003}, @@ -26510,6 +29464,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x00075003}, + {0x10030, 0x00076003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x00075003}, {0x10030, 0x00076003}, @@ -26580,6 +29540,12 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x90070001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, + {0x90150001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, + {0x90160001, 0x00000000}, {0x40000000, 0x00000000}, + {0x10030, 0x0007D003}, + {0x10030, 0x0007E003}, {0x90320001, 0x00000000}, {0x40000000, 0x00000000}, {0x10030, 0x0007D003}, {0x10030, 0x0007E003}, @@ -26621,7 +29587,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = { {0x03F, 0x0000000A}, {0x0ED, 0x00000000}, {0x100EE, 0x00000000}, - {0x0FE, 0x00000048}, + {0x0FE, 0x00000063}, }; static const struct rtw89_reg2_def rtw89_8852c_phy_nctl_regs[] = { @@ -28430,11 +31396,11 @@ static const struct rtw89_txpwr_byrate_cfg rtw89_8852c_txpwr_byrate[] = { { 2, 0, 1, 4, 4, 0x383c4040, }, { 2, 0, 2, 0, 4, 0x40404040, }, { 2, 0, 2, 4, 4, 0x34383c40, }, - { 2, 0, 2, 8, 4, 0x24282c30, }, + { 2, 0, 2, 8, 4, 0x20282c30, }, { 2, 0, 3, 0, 4, 0x40404040, }, { 2, 1, 2, 0, 4, 0x40404040, }, { 2, 1, 2, 4, 4, 0x34383c40, }, - { 2, 1, 2, 8, 4, 0x24282c30, }, + { 2, 1, 2, 8, 4, 0x20282c30, }, { 2, 1, 3, 0, 4, 0x40404040, }, { 2, 0, 4, 0, 4, 0x00000000, }, }; @@ -28562,32 +31528,50 @@ static const s8 _txpwr_track_delta_swingidx_2g_cck_a_p[] = { const u8 rtw89_8852c_tx_shape[RTW89_BAND_MAX][RTW89_RS_TX_SHAPE_NUM] [RTW89_REGD_NUM] = { [0][0][RTW89_ACMA] = 0, + [0][0][RTW89_CHILE] = 0, [0][0][RTW89_CN] = 0, [0][0][RTW89_ETSI] = 0, [0][0][RTW89_FCC] = 1, [0][0][RTW89_IC] = 1, [0][0][RTW89_KCC] = 0, + [0][0][RTW89_MEXICO] = 1, [0][0][RTW89_MKK] = 0, + [0][0][RTW89_QATAR] = 0, [0][0][RTW89_UK] = 0, + [0][0][RTW89_UKRAINE] = 0, [0][1][RTW89_ACMA] = 0, + [0][1][RTW89_CHILE] = 0, [0][1][RTW89_CN] = 0, [0][1][RTW89_ETSI] = 0, [0][1][RTW89_FCC] = 3, [0][1][RTW89_IC] = 3, [0][1][RTW89_KCC] = 0, + [0][1][RTW89_MEXICO] = 3, [0][1][RTW89_MKK] = 0, + [0][1][RTW89_QATAR] = 0, [0][1][RTW89_UK] = 0, + [0][1][RTW89_UKRAINE] = 0, [1][1][RTW89_ACMA] = 0, + [1][1][RTW89_CHILE] = 0, [1][1][RTW89_CN] = 0, [1][1][RTW89_ETSI] = 0, [1][1][RTW89_FCC] = 3, [1][1][RTW89_IC] = 3, [1][1][RTW89_KCC] = 0, + [1][1][RTW89_MEXICO] = 3, [1][1][RTW89_MKK] = 0, + [1][1][RTW89_QATAR] = 0, [1][1][RTW89_UK] = 0, + [1][1][RTW89_UKRAINE] = 0, + [2][1][RTW89_ACMA] = 0, + [2][1][RTW89_CHILE] = 0, [2][1][RTW89_ETSI] = 0, [2][1][RTW89_FCC] = 0, + [2][1][RTW89_IC] = 0, [2][1][RTW89_KCC] = 0, + [2][1][RTW89_MKK] = 0, + [2][1][RTW89_QATAR] = 0, + [2][1][RTW89_UK] = 0, }; static @@ -28770,6 +31754,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][0] = 60, [0][0][0][0][RTW89_CN][0] = 58, [0][0][0][0][RTW89_UK][0] = 60, + [0][0][0][0][RTW89_MEXICO][0] = 76, + [0][0][0][0][RTW89_UKRAINE][0] = 60, + [0][0][0][0][RTW89_CHILE][0] = 76, + [0][0][0][0][RTW89_QATAR][0] = 60, [0][0][0][0][RTW89_FCC][1] = 76, [0][0][0][0][RTW89_ETSI][1] = 60, [0][0][0][0][RTW89_MKK][1] = 68, @@ -28778,6 +31766,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][1] = 60, [0][0][0][0][RTW89_CN][1] = 58, [0][0][0][0][RTW89_UK][1] = 60, + [0][0][0][0][RTW89_MEXICO][1] = 76, + [0][0][0][0][RTW89_UKRAINE][1] = 60, + [0][0][0][0][RTW89_CHILE][1] = 68, + [0][0][0][0][RTW89_QATAR][1] = 60, [0][0][0][0][RTW89_FCC][2] = 76, [0][0][0][0][RTW89_ETSI][2] = 60, [0][0][0][0][RTW89_MKK][2] = 68, @@ -28786,6 +31778,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][2] = 60, [0][0][0][0][RTW89_CN][2] = 58, [0][0][0][0][RTW89_UK][2] = 60, + [0][0][0][0][RTW89_MEXICO][2] = 76, + [0][0][0][0][RTW89_UKRAINE][2] = 60, + [0][0][0][0][RTW89_CHILE][2] = 68, + [0][0][0][0][RTW89_QATAR][2] = 60, [0][0][0][0][RTW89_FCC][3] = 76, [0][0][0][0][RTW89_ETSI][3] = 60, [0][0][0][0][RTW89_MKK][3] = 68, @@ -28794,6 +31790,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][3] = 60, [0][0][0][0][RTW89_CN][3] = 58, [0][0][0][0][RTW89_UK][3] = 60, + [0][0][0][0][RTW89_MEXICO][3] = 76, + [0][0][0][0][RTW89_UKRAINE][3] = 60, + [0][0][0][0][RTW89_CHILE][3] = 68, + [0][0][0][0][RTW89_QATAR][3] = 60, [0][0][0][0][RTW89_FCC][4] = 76, [0][0][0][0][RTW89_ETSI][4] = 60, [0][0][0][0][RTW89_MKK][4] = 68, @@ -28802,6 +31802,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][4] = 60, [0][0][0][0][RTW89_CN][4] = 58, [0][0][0][0][RTW89_UK][4] = 60, + [0][0][0][0][RTW89_MEXICO][4] = 76, + [0][0][0][0][RTW89_UKRAINE][4] = 60, + [0][0][0][0][RTW89_CHILE][4] = 68, + [0][0][0][0][RTW89_QATAR][4] = 60, [0][0][0][0][RTW89_FCC][5] = 76, [0][0][0][0][RTW89_ETSI][5] = 60, [0][0][0][0][RTW89_MKK][5] = 68, @@ -28810,6 +31814,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][5] = 60, [0][0][0][0][RTW89_CN][5] = 58, [0][0][0][0][RTW89_UK][5] = 60, + [0][0][0][0][RTW89_MEXICO][5] = 76, + [0][0][0][0][RTW89_UKRAINE][5] = 60, + [0][0][0][0][RTW89_CHILE][5] = 76, + [0][0][0][0][RTW89_QATAR][5] = 60, [0][0][0][0][RTW89_FCC][6] = 76, [0][0][0][0][RTW89_ETSI][6] = 60, [0][0][0][0][RTW89_MKK][6] = 68, @@ -28818,6 +31826,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][6] = 60, [0][0][0][0][RTW89_CN][6] = 58, [0][0][0][0][RTW89_UK][6] = 60, + [0][0][0][0][RTW89_MEXICO][6] = 76, + [0][0][0][0][RTW89_UKRAINE][6] = 60, + [0][0][0][0][RTW89_CHILE][6] = 76, + [0][0][0][0][RTW89_QATAR][6] = 60, [0][0][0][0][RTW89_FCC][7] = 76, [0][0][0][0][RTW89_ETSI][7] = 60, [0][0][0][0][RTW89_MKK][7] = 68, @@ -28826,6 +31838,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][7] = 60, [0][0][0][0][RTW89_CN][7] = 58, [0][0][0][0][RTW89_UK][7] = 60, + [0][0][0][0][RTW89_MEXICO][7] = 76, + [0][0][0][0][RTW89_UKRAINE][7] = 60, + [0][0][0][0][RTW89_CHILE][7] = 76, + [0][0][0][0][RTW89_QATAR][7] = 60, [0][0][0][0][RTW89_FCC][8] = 76, [0][0][0][0][RTW89_ETSI][8] = 60, [0][0][0][0][RTW89_MKK][8] = 68, @@ -28834,6 +31850,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][8] = 60, [0][0][0][0][RTW89_CN][8] = 58, [0][0][0][0][RTW89_UK][8] = 60, + [0][0][0][0][RTW89_MEXICO][8] = 76, + [0][0][0][0][RTW89_UKRAINE][8] = 60, + [0][0][0][0][RTW89_CHILE][8] = 76, + [0][0][0][0][RTW89_QATAR][8] = 60, [0][0][0][0][RTW89_FCC][9] = 76, [0][0][0][0][RTW89_ETSI][9] = 60, [0][0][0][0][RTW89_MKK][9] = 68, @@ -28842,6 +31862,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][9] = 60, [0][0][0][0][RTW89_CN][9] = 58, [0][0][0][0][RTW89_UK][9] = 60, + [0][0][0][0][RTW89_MEXICO][9] = 76, + [0][0][0][0][RTW89_UKRAINE][9] = 60, + [0][0][0][0][RTW89_CHILE][9] = 76, + [0][0][0][0][RTW89_QATAR][9] = 60, [0][0][0][0][RTW89_FCC][10] = 76, [0][0][0][0][RTW89_ETSI][10] = 60, [0][0][0][0][RTW89_MKK][10] = 68, @@ -28850,6 +31874,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][10] = 60, [0][0][0][0][RTW89_CN][10] = 58, [0][0][0][0][RTW89_UK][10] = 60, + [0][0][0][0][RTW89_MEXICO][10] = 76, + [0][0][0][0][RTW89_UKRAINE][10] = 60, + [0][0][0][0][RTW89_CHILE][10] = 76, + [0][0][0][0][RTW89_QATAR][10] = 60, [0][0][0][0][RTW89_FCC][11] = 58, [0][0][0][0][RTW89_ETSI][11] = 60, [0][0][0][0][RTW89_MKK][11] = 68, @@ -28858,6 +31886,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][11] = 60, [0][0][0][0][RTW89_CN][11] = 58, [0][0][0][0][RTW89_UK][11] = 60, + [0][0][0][0][RTW89_MEXICO][11] = 58, + [0][0][0][0][RTW89_UKRAINE][11] = 60, + [0][0][0][0][RTW89_CHILE][11] = 58, + [0][0][0][0][RTW89_QATAR][11] = 60, [0][0][0][0][RTW89_FCC][12] = 46, [0][0][0][0][RTW89_ETSI][12] = 60, [0][0][0][0][RTW89_MKK][12] = 68, @@ -28866,6 +31898,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][12] = 60, [0][0][0][0][RTW89_CN][12] = 58, [0][0][0][0][RTW89_UK][12] = 60, + [0][0][0][0][RTW89_MEXICO][12] = 46, + [0][0][0][0][RTW89_UKRAINE][12] = 60, + [0][0][0][0][RTW89_CHILE][12] = 46, + [0][0][0][0][RTW89_QATAR][12] = 60, [0][0][0][0][RTW89_FCC][13] = 127, [0][0][0][0][RTW89_ETSI][13] = 127, [0][0][0][0][RTW89_MKK][13] = 72, @@ -28874,6 +31910,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][0][0][RTW89_ACMA][13] = 127, [0][0][0][0][RTW89_CN][13] = 127, [0][0][0][0][RTW89_UK][13] = 127, + [0][0][0][0][RTW89_MEXICO][13] = 127, + [0][0][0][0][RTW89_UKRAINE][13] = 127, + [0][0][0][0][RTW89_CHILE][13] = 127, + [0][0][0][0][RTW89_QATAR][13] = 127, [0][1][0][0][RTW89_FCC][0] = 76, [0][1][0][0][RTW89_ETSI][0] = 48, [0][1][0][0][RTW89_MKK][0] = 58, @@ -28882,6 +31922,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][0] = 48, [0][1][0][0][RTW89_CN][0] = 42, [0][1][0][0][RTW89_UK][0] = 48, + [0][1][0][0][RTW89_MEXICO][0] = 76, + [0][1][0][0][RTW89_UKRAINE][0] = 48, + [0][1][0][0][RTW89_CHILE][0] = 76, + [0][1][0][0][RTW89_QATAR][0] = 48, [0][1][0][0][RTW89_FCC][1] = 76, [0][1][0][0][RTW89_ETSI][1] = 48, [0][1][0][0][RTW89_MKK][1] = 58, @@ -28890,6 +31934,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][1] = 48, [0][1][0][0][RTW89_CN][1] = 42, [0][1][0][0][RTW89_UK][1] = 48, + [0][1][0][0][RTW89_MEXICO][1] = 76, + [0][1][0][0][RTW89_UKRAINE][1] = 48, + [0][1][0][0][RTW89_CHILE][1] = 54, + [0][1][0][0][RTW89_QATAR][1] = 48, [0][1][0][0][RTW89_FCC][2] = 76, [0][1][0][0][RTW89_ETSI][2] = 48, [0][1][0][0][RTW89_MKK][2] = 58, @@ -28898,6 +31946,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][2] = 48, [0][1][0][0][RTW89_CN][2] = 42, [0][1][0][0][RTW89_UK][2] = 48, + [0][1][0][0][RTW89_MEXICO][2] = 76, + [0][1][0][0][RTW89_UKRAINE][2] = 48, + [0][1][0][0][RTW89_CHILE][2] = 54, + [0][1][0][0][RTW89_QATAR][2] = 48, [0][1][0][0][RTW89_FCC][3] = 76, [0][1][0][0][RTW89_ETSI][3] = 48, [0][1][0][0][RTW89_MKK][3] = 58, @@ -28906,6 +31958,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][3] = 48, [0][1][0][0][RTW89_CN][3] = 42, [0][1][0][0][RTW89_UK][3] = 48, + [0][1][0][0][RTW89_MEXICO][3] = 76, + [0][1][0][0][RTW89_UKRAINE][3] = 48, + [0][1][0][0][RTW89_CHILE][3] = 54, + [0][1][0][0][RTW89_QATAR][3] = 48, [0][1][0][0][RTW89_FCC][4] = 76, [0][1][0][0][RTW89_ETSI][4] = 48, [0][1][0][0][RTW89_MKK][4] = 58, @@ -28914,6 +31970,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][4] = 48, [0][1][0][0][RTW89_CN][4] = 42, [0][1][0][0][RTW89_UK][4] = 48, + [0][1][0][0][RTW89_MEXICO][4] = 76, + [0][1][0][0][RTW89_UKRAINE][4] = 48, + [0][1][0][0][RTW89_CHILE][4] = 54, + [0][1][0][0][RTW89_QATAR][4] = 48, [0][1][0][0][RTW89_FCC][5] = 76, [0][1][0][0][RTW89_ETSI][5] = 48, [0][1][0][0][RTW89_MKK][5] = 58, @@ -28922,6 +31982,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][5] = 48, [0][1][0][0][RTW89_CN][5] = 42, [0][1][0][0][RTW89_UK][5] = 48, + [0][1][0][0][RTW89_MEXICO][5] = 76, + [0][1][0][0][RTW89_UKRAINE][5] = 48, + [0][1][0][0][RTW89_CHILE][5] = 76, + [0][1][0][0][RTW89_QATAR][5] = 48, [0][1][0][0][RTW89_FCC][6] = 76, [0][1][0][0][RTW89_ETSI][6] = 48, [0][1][0][0][RTW89_MKK][6] = 58, @@ -28930,6 +31994,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][6] = 48, [0][1][0][0][RTW89_CN][6] = 42, [0][1][0][0][RTW89_UK][6] = 48, + [0][1][0][0][RTW89_MEXICO][6] = 76, + [0][1][0][0][RTW89_UKRAINE][6] = 48, + [0][1][0][0][RTW89_CHILE][6] = 76, + [0][1][0][0][RTW89_QATAR][6] = 48, [0][1][0][0][RTW89_FCC][7] = 76, [0][1][0][0][RTW89_ETSI][7] = 48, [0][1][0][0][RTW89_MKK][7] = 58, @@ -28938,6 +32006,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][7] = 48, [0][1][0][0][RTW89_CN][7] = 42, [0][1][0][0][RTW89_UK][7] = 48, + [0][1][0][0][RTW89_MEXICO][7] = 76, + [0][1][0][0][RTW89_UKRAINE][7] = 48, + [0][1][0][0][RTW89_CHILE][7] = 76, + [0][1][0][0][RTW89_QATAR][7] = 48, [0][1][0][0][RTW89_FCC][8] = 76, [0][1][0][0][RTW89_ETSI][8] = 48, [0][1][0][0][RTW89_MKK][8] = 58, @@ -28946,6 +32018,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][8] = 48, [0][1][0][0][RTW89_CN][8] = 42, [0][1][0][0][RTW89_UK][8] = 48, + [0][1][0][0][RTW89_MEXICO][8] = 76, + [0][1][0][0][RTW89_UKRAINE][8] = 48, + [0][1][0][0][RTW89_CHILE][8] = 76, + [0][1][0][0][RTW89_QATAR][8] = 48, [0][1][0][0][RTW89_FCC][9] = 70, [0][1][0][0][RTW89_ETSI][9] = 48, [0][1][0][0][RTW89_MKK][9] = 58, @@ -28954,6 +32030,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][9] = 48, [0][1][0][0][RTW89_CN][9] = 42, [0][1][0][0][RTW89_UK][9] = 48, + [0][1][0][0][RTW89_MEXICO][9] = 70, + [0][1][0][0][RTW89_UKRAINE][9] = 48, + [0][1][0][0][RTW89_CHILE][9] = 70, + [0][1][0][0][RTW89_QATAR][9] = 48, [0][1][0][0][RTW89_FCC][10] = 72, [0][1][0][0][RTW89_ETSI][10] = 48, [0][1][0][0][RTW89_MKK][10] = 58, @@ -28962,6 +32042,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][10] = 48, [0][1][0][0][RTW89_CN][10] = 42, [0][1][0][0][RTW89_UK][10] = 48, + [0][1][0][0][RTW89_MEXICO][10] = 72, + [0][1][0][0][RTW89_UKRAINE][10] = 48, + [0][1][0][0][RTW89_CHILE][10] = 72, + [0][1][0][0][RTW89_QATAR][10] = 48, [0][1][0][0][RTW89_FCC][11] = 44, [0][1][0][0][RTW89_ETSI][11] = 48, [0][1][0][0][RTW89_MKK][11] = 58, @@ -28970,6 +32054,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][11] = 48, [0][1][0][0][RTW89_CN][11] = 42, [0][1][0][0][RTW89_UK][11] = 48, + [0][1][0][0][RTW89_MEXICO][11] = 44, + [0][1][0][0][RTW89_UKRAINE][11] = 48, + [0][1][0][0][RTW89_CHILE][11] = 44, + [0][1][0][0][RTW89_QATAR][11] = 48, [0][1][0][0][RTW89_FCC][12] = 18, [0][1][0][0][RTW89_ETSI][12] = 48, [0][1][0][0][RTW89_MKK][12] = 58, @@ -28978,6 +32066,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][12] = 48, [0][1][0][0][RTW89_CN][12] = 42, [0][1][0][0][RTW89_UK][12] = 48, + [0][1][0][0][RTW89_MEXICO][12] = 18, + [0][1][0][0][RTW89_UKRAINE][12] = 48, + [0][1][0][0][RTW89_CHILE][12] = 18, + [0][1][0][0][RTW89_QATAR][12] = 48, [0][1][0][0][RTW89_FCC][13] = 127, [0][1][0][0][RTW89_ETSI][13] = 127, [0][1][0][0][RTW89_MKK][13] = 60, @@ -28986,6 +32078,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][0][0][RTW89_ACMA][13] = 127, [0][1][0][0][RTW89_CN][13] = 127, [0][1][0][0][RTW89_UK][13] = 127, + [0][1][0][0][RTW89_MEXICO][13] = 127, + [0][1][0][0][RTW89_UKRAINE][13] = 127, + [0][1][0][0][RTW89_CHILE][13] = 127, + [0][1][0][0][RTW89_QATAR][13] = 127, [1][0][0][0][RTW89_FCC][0] = 127, [1][0][0][0][RTW89_ETSI][0] = 127, [1][0][0][0][RTW89_MKK][0] = 127, @@ -28994,6 +32090,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][0] = 127, [1][0][0][0][RTW89_CN][0] = 127, [1][0][0][0][RTW89_UK][0] = 127, + [1][0][0][0][RTW89_MEXICO][0] = 127, + [1][0][0][0][RTW89_UKRAINE][0] = 127, + [1][0][0][0][RTW89_CHILE][0] = 127, + [1][0][0][0][RTW89_QATAR][0] = 127, [1][0][0][0][RTW89_FCC][1] = 127, [1][0][0][0][RTW89_ETSI][1] = 127, [1][0][0][0][RTW89_MKK][1] = 127, @@ -29002,6 +32102,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][1] = 127, [1][0][0][0][RTW89_CN][1] = 127, [1][0][0][0][RTW89_UK][1] = 127, + [1][0][0][0][RTW89_MEXICO][1] = 127, + [1][0][0][0][RTW89_UKRAINE][1] = 127, + [1][0][0][0][RTW89_CHILE][1] = 127, + [1][0][0][0][RTW89_QATAR][1] = 127, [1][0][0][0][RTW89_FCC][2] = 44, [1][0][0][0][RTW89_ETSI][2] = 60, [1][0][0][0][RTW89_MKK][2] = 66, @@ -29010,6 +32114,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][2] = 60, [1][0][0][0][RTW89_CN][2] = 58, [1][0][0][0][RTW89_UK][2] = 60, + [1][0][0][0][RTW89_MEXICO][2] = 44, + [1][0][0][0][RTW89_UKRAINE][2] = 60, + [1][0][0][0][RTW89_CHILE][2] = 44, + [1][0][0][0][RTW89_QATAR][2] = 60, [1][0][0][0][RTW89_FCC][3] = 60, [1][0][0][0][RTW89_ETSI][3] = 60, [1][0][0][0][RTW89_MKK][3] = 66, @@ -29018,6 +32126,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][3] = 60, [1][0][0][0][RTW89_CN][3] = 58, [1][0][0][0][RTW89_UK][3] = 60, + [1][0][0][0][RTW89_MEXICO][3] = 60, + [1][0][0][0][RTW89_UKRAINE][3] = 60, + [1][0][0][0][RTW89_CHILE][3] = 60, + [1][0][0][0][RTW89_QATAR][3] = 60, [1][0][0][0][RTW89_FCC][4] = 60, [1][0][0][0][RTW89_ETSI][4] = 60, [1][0][0][0][RTW89_MKK][4] = 66, @@ -29026,6 +32138,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][4] = 60, [1][0][0][0][RTW89_CN][4] = 58, [1][0][0][0][RTW89_UK][4] = 60, + [1][0][0][0][RTW89_MEXICO][4] = 60, + [1][0][0][0][RTW89_UKRAINE][4] = 60, + [1][0][0][0][RTW89_CHILE][4] = 60, + [1][0][0][0][RTW89_QATAR][4] = 60, [1][0][0][0][RTW89_FCC][5] = 62, [1][0][0][0][RTW89_ETSI][5] = 60, [1][0][0][0][RTW89_MKK][5] = 66, @@ -29034,6 +32150,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][5] = 60, [1][0][0][0][RTW89_CN][5] = 58, [1][0][0][0][RTW89_UK][5] = 60, + [1][0][0][0][RTW89_MEXICO][5] = 62, + [1][0][0][0][RTW89_UKRAINE][5] = 60, + [1][0][0][0][RTW89_CHILE][5] = 62, + [1][0][0][0][RTW89_QATAR][5] = 60, [1][0][0][0][RTW89_FCC][6] = 46, [1][0][0][0][RTW89_ETSI][6] = 60, [1][0][0][0][RTW89_MKK][6] = 66, @@ -29042,6 +32162,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][6] = 60, [1][0][0][0][RTW89_CN][6] = 58, [1][0][0][0][RTW89_UK][6] = 60, + [1][0][0][0][RTW89_MEXICO][6] = 46, + [1][0][0][0][RTW89_UKRAINE][6] = 60, + [1][0][0][0][RTW89_CHILE][6] = 46, + [1][0][0][0][RTW89_QATAR][6] = 60, [1][0][0][0][RTW89_FCC][7] = 46, [1][0][0][0][RTW89_ETSI][7] = 60, [1][0][0][0][RTW89_MKK][7] = 66, @@ -29050,6 +32174,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][7] = 60, [1][0][0][0][RTW89_CN][7] = 58, [1][0][0][0][RTW89_UK][7] = 60, + [1][0][0][0][RTW89_MEXICO][7] = 46, + [1][0][0][0][RTW89_UKRAINE][7] = 60, + [1][0][0][0][RTW89_CHILE][7] = 46, + [1][0][0][0][RTW89_QATAR][7] = 60, [1][0][0][0][RTW89_FCC][8] = 28, [1][0][0][0][RTW89_ETSI][8] = 60, [1][0][0][0][RTW89_MKK][8] = 66, @@ -29058,6 +32186,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][8] = 60, [1][0][0][0][RTW89_CN][8] = 58, [1][0][0][0][RTW89_UK][8] = 60, + [1][0][0][0][RTW89_MEXICO][8] = 28, + [1][0][0][0][RTW89_UKRAINE][8] = 60, + [1][0][0][0][RTW89_CHILE][8] = 28, + [1][0][0][0][RTW89_QATAR][8] = 60, [1][0][0][0][RTW89_FCC][9] = 26, [1][0][0][0][RTW89_ETSI][9] = 60, [1][0][0][0][RTW89_MKK][9] = 66, @@ -29066,6 +32198,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][9] = 60, [1][0][0][0][RTW89_CN][9] = 58, [1][0][0][0][RTW89_UK][9] = 60, + [1][0][0][0][RTW89_MEXICO][9] = 26, + [1][0][0][0][RTW89_UKRAINE][9] = 60, + [1][0][0][0][RTW89_CHILE][9] = 26, + [1][0][0][0][RTW89_QATAR][9] = 60, [1][0][0][0][RTW89_FCC][10] = 26, [1][0][0][0][RTW89_ETSI][10] = 60, [1][0][0][0][RTW89_MKK][10] = 66, @@ -29074,6 +32210,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][10] = 60, [1][0][0][0][RTW89_CN][10] = 58, [1][0][0][0][RTW89_UK][10] = 60, + [1][0][0][0][RTW89_MEXICO][10] = 26, + [1][0][0][0][RTW89_UKRAINE][10] = 60, + [1][0][0][0][RTW89_CHILE][10] = 26, + [1][0][0][0][RTW89_QATAR][10] = 60, [1][0][0][0][RTW89_FCC][11] = 127, [1][0][0][0][RTW89_ETSI][11] = 127, [1][0][0][0][RTW89_MKK][11] = 127, @@ -29082,6 +32222,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][11] = 127, [1][0][0][0][RTW89_CN][11] = 127, [1][0][0][0][RTW89_UK][11] = 127, + [1][0][0][0][RTW89_MEXICO][11] = 127, + [1][0][0][0][RTW89_UKRAINE][11] = 127, + [1][0][0][0][RTW89_CHILE][11] = 127, + [1][0][0][0][RTW89_QATAR][11] = 127, [1][0][0][0][RTW89_FCC][12] = 127, [1][0][0][0][RTW89_ETSI][12] = 127, [1][0][0][0][RTW89_MKK][12] = 127, @@ -29090,6 +32234,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][12] = 127, [1][0][0][0][RTW89_CN][12] = 127, [1][0][0][0][RTW89_UK][12] = 127, + [1][0][0][0][RTW89_MEXICO][12] = 127, + [1][0][0][0][RTW89_UKRAINE][12] = 127, + [1][0][0][0][RTW89_CHILE][12] = 127, + [1][0][0][0][RTW89_QATAR][12] = 127, [1][0][0][0][RTW89_FCC][13] = 127, [1][0][0][0][RTW89_ETSI][13] = 127, [1][0][0][0][RTW89_MKK][13] = 127, @@ -29098,6 +32246,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][0][0][RTW89_ACMA][13] = 127, [1][0][0][0][RTW89_CN][13] = 127, [1][0][0][0][RTW89_UK][13] = 127, + [1][0][0][0][RTW89_MEXICO][13] = 127, + [1][0][0][0][RTW89_UKRAINE][13] = 127, + [1][0][0][0][RTW89_CHILE][13] = 127, + [1][0][0][0][RTW89_QATAR][13] = 127, [1][1][0][0][RTW89_FCC][0] = 127, [1][1][0][0][RTW89_ETSI][0] = 127, [1][1][0][0][RTW89_MKK][0] = 127, @@ -29106,6 +32258,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][0] = 127, [1][1][0][0][RTW89_CN][0] = 127, [1][1][0][0][RTW89_UK][0] = 127, + [1][1][0][0][RTW89_MEXICO][0] = 127, + [1][1][0][0][RTW89_UKRAINE][0] = 127, + [1][1][0][0][RTW89_CHILE][0] = 127, + [1][1][0][0][RTW89_QATAR][0] = 127, [1][1][0][0][RTW89_FCC][1] = 127, [1][1][0][0][RTW89_ETSI][1] = 127, [1][1][0][0][RTW89_MKK][1] = 127, @@ -29114,6 +32270,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][1] = 127, [1][1][0][0][RTW89_CN][1] = 127, [1][1][0][0][RTW89_UK][1] = 127, + [1][1][0][0][RTW89_MEXICO][1] = 127, + [1][1][0][0][RTW89_UKRAINE][1] = 127, + [1][1][0][0][RTW89_CHILE][1] = 127, + [1][1][0][0][RTW89_QATAR][1] = 127, [1][1][0][0][RTW89_FCC][2] = 46, [1][1][0][0][RTW89_ETSI][2] = 48, [1][1][0][0][RTW89_MKK][2] = 58, @@ -29122,6 +32282,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][2] = 48, [1][1][0][0][RTW89_CN][2] = 46, [1][1][0][0][RTW89_UK][2] = 48, + [1][1][0][0][RTW89_MEXICO][2] = 46, + [1][1][0][0][RTW89_UKRAINE][2] = 48, + [1][1][0][0][RTW89_CHILE][2] = 46, + [1][1][0][0][RTW89_QATAR][2] = 48, [1][1][0][0][RTW89_FCC][3] = 46, [1][1][0][0][RTW89_ETSI][3] = 48, [1][1][0][0][RTW89_MKK][3] = 58, @@ -29130,6 +32294,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][3] = 48, [1][1][0][0][RTW89_CN][3] = 46, [1][1][0][0][RTW89_UK][3] = 48, + [1][1][0][0][RTW89_MEXICO][3] = 46, + [1][1][0][0][RTW89_UKRAINE][3] = 48, + [1][1][0][0][RTW89_CHILE][3] = 46, + [1][1][0][0][RTW89_QATAR][3] = 48, [1][1][0][0][RTW89_FCC][4] = 46, [1][1][0][0][RTW89_ETSI][4] = 48, [1][1][0][0][RTW89_MKK][4] = 58, @@ -29138,6 +32306,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][4] = 48, [1][1][0][0][RTW89_CN][4] = 46, [1][1][0][0][RTW89_UK][4] = 48, + [1][1][0][0][RTW89_MEXICO][4] = 46, + [1][1][0][0][RTW89_UKRAINE][4] = 48, + [1][1][0][0][RTW89_CHILE][4] = 46, + [1][1][0][0][RTW89_QATAR][4] = 48, [1][1][0][0][RTW89_FCC][5] = 48, [1][1][0][0][RTW89_ETSI][5] = 48, [1][1][0][0][RTW89_MKK][5] = 58, @@ -29146,6 +32318,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][5] = 48, [1][1][0][0][RTW89_CN][5] = 46, [1][1][0][0][RTW89_UK][5] = 48, + [1][1][0][0][RTW89_MEXICO][5] = 48, + [1][1][0][0][RTW89_UKRAINE][5] = 48, + [1][1][0][0][RTW89_CHILE][5] = 48, + [1][1][0][0][RTW89_QATAR][5] = 48, [1][1][0][0][RTW89_FCC][6] = 40, [1][1][0][0][RTW89_ETSI][6] = 48, [1][1][0][0][RTW89_MKK][6] = 58, @@ -29154,6 +32330,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][6] = 48, [1][1][0][0][RTW89_CN][6] = 46, [1][1][0][0][RTW89_UK][6] = 48, + [1][1][0][0][RTW89_MEXICO][6] = 40, + [1][1][0][0][RTW89_UKRAINE][6] = 48, + [1][1][0][0][RTW89_CHILE][6] = 40, + [1][1][0][0][RTW89_QATAR][6] = 48, [1][1][0][0][RTW89_FCC][7] = 40, [1][1][0][0][RTW89_ETSI][7] = 48, [1][1][0][0][RTW89_MKK][7] = 58, @@ -29162,6 +32342,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][7] = 48, [1][1][0][0][RTW89_CN][7] = 46, [1][1][0][0][RTW89_UK][7] = 48, + [1][1][0][0][RTW89_MEXICO][7] = 40, + [1][1][0][0][RTW89_UKRAINE][7] = 48, + [1][1][0][0][RTW89_CHILE][7] = 40, + [1][1][0][0][RTW89_QATAR][7] = 48, [1][1][0][0][RTW89_FCC][8] = 14, [1][1][0][0][RTW89_ETSI][8] = 48, [1][1][0][0][RTW89_MKK][8] = 58, @@ -29170,6 +32354,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][8] = 48, [1][1][0][0][RTW89_CN][8] = 46, [1][1][0][0][RTW89_UK][8] = 48, + [1][1][0][0][RTW89_MEXICO][8] = 14, + [1][1][0][0][RTW89_UKRAINE][8] = 48, + [1][1][0][0][RTW89_CHILE][8] = 14, + [1][1][0][0][RTW89_QATAR][8] = 48, [1][1][0][0][RTW89_FCC][9] = 14, [1][1][0][0][RTW89_ETSI][9] = 48, [1][1][0][0][RTW89_MKK][9] = 58, @@ -29178,6 +32366,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][9] = 48, [1][1][0][0][RTW89_CN][9] = 46, [1][1][0][0][RTW89_UK][9] = 48, + [1][1][0][0][RTW89_MEXICO][9] = 14, + [1][1][0][0][RTW89_UKRAINE][9] = 48, + [1][1][0][0][RTW89_CHILE][9] = 14, + [1][1][0][0][RTW89_QATAR][9] = 48, [1][1][0][0][RTW89_FCC][10] = 12, [1][1][0][0][RTW89_ETSI][10] = 48, [1][1][0][0][RTW89_MKK][10] = 56, @@ -29186,6 +32378,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][10] = 48, [1][1][0][0][RTW89_CN][10] = 46, [1][1][0][0][RTW89_UK][10] = 48, + [1][1][0][0][RTW89_MEXICO][10] = 12, + [1][1][0][0][RTW89_UKRAINE][10] = 48, + [1][1][0][0][RTW89_CHILE][10] = 12, + [1][1][0][0][RTW89_QATAR][10] = 48, [1][1][0][0][RTW89_FCC][11] = 127, [1][1][0][0][RTW89_ETSI][11] = 127, [1][1][0][0][RTW89_MKK][11] = 127, @@ -29194,6 +32390,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][11] = 127, [1][1][0][0][RTW89_CN][11] = 127, [1][1][0][0][RTW89_UK][11] = 127, + [1][1][0][0][RTW89_MEXICO][11] = 127, + [1][1][0][0][RTW89_UKRAINE][11] = 127, + [1][1][0][0][RTW89_CHILE][11] = 127, + [1][1][0][0][RTW89_QATAR][11] = 127, [1][1][0][0][RTW89_FCC][12] = 127, [1][1][0][0][RTW89_ETSI][12] = 127, [1][1][0][0][RTW89_MKK][12] = 127, @@ -29202,6 +32402,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][12] = 127, [1][1][0][0][RTW89_CN][12] = 127, [1][1][0][0][RTW89_UK][12] = 127, + [1][1][0][0][RTW89_MEXICO][12] = 127, + [1][1][0][0][RTW89_UKRAINE][12] = 127, + [1][1][0][0][RTW89_CHILE][12] = 127, + [1][1][0][0][RTW89_QATAR][12] = 127, [1][1][0][0][RTW89_FCC][13] = 127, [1][1][0][0][RTW89_ETSI][13] = 127, [1][1][0][0][RTW89_MKK][13] = 127, @@ -29210,6 +32414,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][0][0][RTW89_ACMA][13] = 127, [1][1][0][0][RTW89_CN][13] = 127, [1][1][0][0][RTW89_UK][13] = 127, + [1][1][0][0][RTW89_MEXICO][13] = 127, + [1][1][0][0][RTW89_UKRAINE][13] = 127, + [1][1][0][0][RTW89_CHILE][13] = 127, + [1][1][0][0][RTW89_QATAR][13] = 127, [0][0][1][0][RTW89_FCC][0] = 66, [0][0][1][0][RTW89_ETSI][0] = 60, [0][0][1][0][RTW89_MKK][0] = 76, @@ -29218,6 +32426,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][0] = 60, [0][0][1][0][RTW89_CN][0] = 58, [0][0][1][0][RTW89_UK][0] = 60, + [0][0][1][0][RTW89_MEXICO][0] = 66, + [0][0][1][0][RTW89_UKRAINE][0] = 60, + [0][0][1][0][RTW89_CHILE][0] = 66, + [0][0][1][0][RTW89_QATAR][0] = 60, [0][0][1][0][RTW89_FCC][1] = 68, [0][0][1][0][RTW89_ETSI][1] = 60, [0][0][1][0][RTW89_MKK][1] = 78, @@ -29226,6 +32438,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][1] = 60, [0][0][1][0][RTW89_CN][1] = 58, [0][0][1][0][RTW89_UK][1] = 60, + [0][0][1][0][RTW89_MEXICO][1] = 68, + [0][0][1][0][RTW89_UKRAINE][1] = 60, + [0][0][1][0][RTW89_CHILE][1] = 68, + [0][0][1][0][RTW89_QATAR][1] = 60, [0][0][1][0][RTW89_FCC][2] = 72, [0][0][1][0][RTW89_ETSI][2] = 60, [0][0][1][0][RTW89_MKK][2] = 78, @@ -29234,6 +32450,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][2] = 60, [0][0][1][0][RTW89_CN][2] = 58, [0][0][1][0][RTW89_UK][2] = 60, + [0][0][1][0][RTW89_MEXICO][2] = 72, + [0][0][1][0][RTW89_UKRAINE][2] = 60, + [0][0][1][0][RTW89_CHILE][2] = 62, + [0][0][1][0][RTW89_QATAR][2] = 60, [0][0][1][0][RTW89_FCC][3] = 76, [0][0][1][0][RTW89_ETSI][3] = 60, [0][0][1][0][RTW89_MKK][3] = 78, @@ -29242,6 +32462,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][3] = 60, [0][0][1][0][RTW89_CN][3] = 58, [0][0][1][0][RTW89_UK][3] = 60, + [0][0][1][0][RTW89_MEXICO][3] = 76, + [0][0][1][0][RTW89_UKRAINE][3] = 60, + [0][0][1][0][RTW89_CHILE][3] = 62, + [0][0][1][0][RTW89_QATAR][3] = 60, [0][0][1][0][RTW89_FCC][4] = 80, [0][0][1][0][RTW89_ETSI][4] = 60, [0][0][1][0][RTW89_MKK][4] = 78, @@ -29250,6 +32474,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][4] = 60, [0][0][1][0][RTW89_CN][4] = 58, [0][0][1][0][RTW89_UK][4] = 60, + [0][0][1][0][RTW89_MEXICO][4] = 80, + [0][0][1][0][RTW89_UKRAINE][4] = 60, + [0][0][1][0][RTW89_CHILE][4] = 62, + [0][0][1][0][RTW89_QATAR][4] = 60, [0][0][1][0][RTW89_FCC][5] = 80, [0][0][1][0][RTW89_ETSI][5] = 60, [0][0][1][0][RTW89_MKK][5] = 78, @@ -29258,6 +32486,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][5] = 60, [0][0][1][0][RTW89_CN][5] = 58, [0][0][1][0][RTW89_UK][5] = 60, + [0][0][1][0][RTW89_MEXICO][5] = 80, + [0][0][1][0][RTW89_UKRAINE][5] = 60, + [0][0][1][0][RTW89_CHILE][5] = 80, + [0][0][1][0][RTW89_QATAR][5] = 60, [0][0][1][0][RTW89_FCC][6] = 80, [0][0][1][0][RTW89_ETSI][6] = 60, [0][0][1][0][RTW89_MKK][6] = 76, @@ -29266,6 +32498,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][6] = 60, [0][0][1][0][RTW89_CN][6] = 58, [0][0][1][0][RTW89_UK][6] = 60, + [0][0][1][0][RTW89_MEXICO][6] = 80, + [0][0][1][0][RTW89_UKRAINE][6] = 60, + [0][0][1][0][RTW89_CHILE][6] = 70, + [0][0][1][0][RTW89_QATAR][6] = 60, [0][0][1][0][RTW89_FCC][7] = 80, [0][0][1][0][RTW89_ETSI][7] = 60, [0][0][1][0][RTW89_MKK][7] = 78, @@ -29274,6 +32510,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][7] = 60, [0][0][1][0][RTW89_CN][7] = 58, [0][0][1][0][RTW89_UK][7] = 60, + [0][0][1][0][RTW89_MEXICO][7] = 80, + [0][0][1][0][RTW89_UKRAINE][7] = 60, + [0][0][1][0][RTW89_CHILE][7] = 70, + [0][0][1][0][RTW89_QATAR][7] = 60, [0][0][1][0][RTW89_FCC][8] = 80, [0][0][1][0][RTW89_ETSI][8] = 60, [0][0][1][0][RTW89_MKK][8] = 78, @@ -29282,6 +32522,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][8] = 60, [0][0][1][0][RTW89_CN][8] = 58, [0][0][1][0][RTW89_UK][8] = 60, + [0][0][1][0][RTW89_MEXICO][8] = 80, + [0][0][1][0][RTW89_UKRAINE][8] = 60, + [0][0][1][0][RTW89_CHILE][8] = 70, + [0][0][1][0][RTW89_QATAR][8] = 60, [0][0][1][0][RTW89_FCC][9] = 76, [0][0][1][0][RTW89_ETSI][9] = 60, [0][0][1][0][RTW89_MKK][9] = 78, @@ -29290,6 +32534,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][9] = 60, [0][0][1][0][RTW89_CN][9] = 58, [0][0][1][0][RTW89_UK][9] = 60, + [0][0][1][0][RTW89_MEXICO][9] = 76, + [0][0][1][0][RTW89_UKRAINE][9] = 60, + [0][0][1][0][RTW89_CHILE][9] = 76, + [0][0][1][0][RTW89_QATAR][9] = 60, [0][0][1][0][RTW89_FCC][10] = 66, [0][0][1][0][RTW89_ETSI][10] = 60, [0][0][1][0][RTW89_MKK][10] = 78, @@ -29298,6 +32546,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][10] = 60, [0][0][1][0][RTW89_CN][10] = 58, [0][0][1][0][RTW89_UK][10] = 60, + [0][0][1][0][RTW89_MEXICO][10] = 66, + [0][0][1][0][RTW89_UKRAINE][10] = 60, + [0][0][1][0][RTW89_CHILE][10] = 66, + [0][0][1][0][RTW89_QATAR][10] = 60, [0][0][1][0][RTW89_FCC][11] = 62, [0][0][1][0][RTW89_ETSI][11] = 60, [0][0][1][0][RTW89_MKK][11] = 78, @@ -29306,6 +32558,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][11] = 60, [0][0][1][0][RTW89_CN][11] = 58, [0][0][1][0][RTW89_UK][11] = 60, + [0][0][1][0][RTW89_MEXICO][11] = 62, + [0][0][1][0][RTW89_UKRAINE][11] = 60, + [0][0][1][0][RTW89_CHILE][11] = 62, + [0][0][1][0][RTW89_QATAR][11] = 60, [0][0][1][0][RTW89_FCC][12] = 60, [0][0][1][0][RTW89_ETSI][12] = 60, [0][0][1][0][RTW89_MKK][12] = 78, @@ -29314,6 +32570,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][12] = 60, [0][0][1][0][RTW89_CN][12] = 58, [0][0][1][0][RTW89_UK][12] = 60, + [0][0][1][0][RTW89_MEXICO][12] = 60, + [0][0][1][0][RTW89_UKRAINE][12] = 60, + [0][0][1][0][RTW89_CHILE][12] = 60, + [0][0][1][0][RTW89_QATAR][12] = 60, [0][0][1][0][RTW89_FCC][13] = 127, [0][0][1][0][RTW89_ETSI][13] = 127, [0][0][1][0][RTW89_MKK][13] = 127, @@ -29322,6 +32582,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][13] = 127, [0][0][1][0][RTW89_CN][13] = 127, [0][0][1][0][RTW89_UK][13] = 127, + [0][0][1][0][RTW89_MEXICO][13] = 127, + [0][0][1][0][RTW89_UKRAINE][13] = 127, + [0][0][1][0][RTW89_CHILE][13] = 127, + [0][0][1][0][RTW89_QATAR][13] = 127, [0][1][1][0][RTW89_FCC][0] = 66, [0][1][1][0][RTW89_ETSI][0] = 48, [0][1][1][0][RTW89_MKK][0] = 66, @@ -29330,6 +32594,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][0] = 48, [0][1][1][0][RTW89_CN][0] = 46, [0][1][1][0][RTW89_UK][0] = 48, + [0][1][1][0][RTW89_MEXICO][0] = 66, + [0][1][1][0][RTW89_UKRAINE][0] = 48, + [0][1][1][0][RTW89_CHILE][0] = 66, + [0][1][1][0][RTW89_QATAR][0] = 48, [0][1][1][0][RTW89_FCC][1] = 68, [0][1][1][0][RTW89_ETSI][1] = 48, [0][1][1][0][RTW89_MKK][1] = 66, @@ -29338,6 +32606,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][1] = 48, [0][1][1][0][RTW89_CN][1] = 46, [0][1][1][0][RTW89_UK][1] = 48, + [0][1][1][0][RTW89_MEXICO][1] = 68, + [0][1][1][0][RTW89_UKRAINE][1] = 48, + [0][1][1][0][RTW89_CHILE][1] = 68, + [0][1][1][0][RTW89_QATAR][1] = 48, [0][1][1][0][RTW89_FCC][2] = 72, [0][1][1][0][RTW89_ETSI][2] = 48, [0][1][1][0][RTW89_MKK][2] = 66, @@ -29346,6 +32618,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][2] = 48, [0][1][1][0][RTW89_CN][2] = 46, [0][1][1][0][RTW89_UK][2] = 48, + [0][1][1][0][RTW89_MEXICO][2] = 72, + [0][1][1][0][RTW89_UKRAINE][2] = 48, + [0][1][1][0][RTW89_CHILE][2] = 54, + [0][1][1][0][RTW89_QATAR][2] = 48, [0][1][1][0][RTW89_FCC][3] = 76, [0][1][1][0][RTW89_ETSI][3] = 48, [0][1][1][0][RTW89_MKK][3] = 66, @@ -29354,6 +32630,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][3] = 48, [0][1][1][0][RTW89_CN][3] = 46, [0][1][1][0][RTW89_UK][3] = 48, + [0][1][1][0][RTW89_MEXICO][3] = 76, + [0][1][1][0][RTW89_UKRAINE][3] = 48, + [0][1][1][0][RTW89_CHILE][3] = 54, + [0][1][1][0][RTW89_QATAR][3] = 48, [0][1][1][0][RTW89_FCC][4] = 80, [0][1][1][0][RTW89_ETSI][4] = 48, [0][1][1][0][RTW89_MKK][4] = 66, @@ -29362,6 +32642,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][4] = 48, [0][1][1][0][RTW89_CN][4] = 46, [0][1][1][0][RTW89_UK][4] = 48, + [0][1][1][0][RTW89_MEXICO][4] = 80, + [0][1][1][0][RTW89_UKRAINE][4] = 48, + [0][1][1][0][RTW89_CHILE][4] = 54, + [0][1][1][0][RTW89_QATAR][4] = 48, [0][1][1][0][RTW89_FCC][5] = 80, [0][1][1][0][RTW89_ETSI][5] = 48, [0][1][1][0][RTW89_MKK][5] = 66, @@ -29370,6 +32654,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][5] = 48, [0][1][1][0][RTW89_CN][5] = 46, [0][1][1][0][RTW89_UK][5] = 48, + [0][1][1][0][RTW89_MEXICO][5] = 80, + [0][1][1][0][RTW89_UKRAINE][5] = 48, + [0][1][1][0][RTW89_CHILE][5] = 80, + [0][1][1][0][RTW89_QATAR][5] = 48, [0][1][1][0][RTW89_FCC][6] = 80, [0][1][1][0][RTW89_ETSI][6] = 48, [0][1][1][0][RTW89_MKK][6] = 66, @@ -29378,6 +32666,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][6] = 48, [0][1][1][0][RTW89_CN][6] = 46, [0][1][1][0][RTW89_UK][6] = 48, + [0][1][1][0][RTW89_MEXICO][6] = 80, + [0][1][1][0][RTW89_UKRAINE][6] = 48, + [0][1][1][0][RTW89_CHILE][6] = 56, + [0][1][1][0][RTW89_QATAR][6] = 48, [0][1][1][0][RTW89_FCC][7] = 78, [0][1][1][0][RTW89_ETSI][7] = 48, [0][1][1][0][RTW89_MKK][7] = 66, @@ -29386,6 +32678,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][7] = 48, [0][1][1][0][RTW89_CN][7] = 46, [0][1][1][0][RTW89_UK][7] = 48, + [0][1][1][0][RTW89_MEXICO][7] = 78, + [0][1][1][0][RTW89_UKRAINE][7] = 48, + [0][1][1][0][RTW89_CHILE][7] = 56, + [0][1][1][0][RTW89_QATAR][7] = 48, [0][1][1][0][RTW89_FCC][8] = 74, [0][1][1][0][RTW89_ETSI][8] = 48, [0][1][1][0][RTW89_MKK][8] = 66, @@ -29394,6 +32690,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][8] = 48, [0][1][1][0][RTW89_CN][8] = 46, [0][1][1][0][RTW89_UK][8] = 48, + [0][1][1][0][RTW89_MEXICO][8] = 74, + [0][1][1][0][RTW89_UKRAINE][8] = 48, + [0][1][1][0][RTW89_CHILE][8] = 56, + [0][1][1][0][RTW89_QATAR][8] = 48, [0][1][1][0][RTW89_FCC][9] = 70, [0][1][1][0][RTW89_ETSI][9] = 48, [0][1][1][0][RTW89_MKK][9] = 66, @@ -29402,6 +32702,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][9] = 48, [0][1][1][0][RTW89_CN][9] = 46, [0][1][1][0][RTW89_UK][9] = 48, + [0][1][1][0][RTW89_MEXICO][9] = 70, + [0][1][1][0][RTW89_UKRAINE][9] = 48, + [0][1][1][0][RTW89_CHILE][9] = 70, + [0][1][1][0][RTW89_QATAR][9] = 48, [0][1][1][0][RTW89_FCC][10] = 62, [0][1][1][0][RTW89_ETSI][10] = 48, [0][1][1][0][RTW89_MKK][10] = 66, @@ -29410,6 +32714,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][10] = 48, [0][1][1][0][RTW89_CN][10] = 46, [0][1][1][0][RTW89_UK][10] = 48, + [0][1][1][0][RTW89_MEXICO][10] = 62, + [0][1][1][0][RTW89_UKRAINE][10] = 48, + [0][1][1][0][RTW89_CHILE][10] = 62, + [0][1][1][0][RTW89_QATAR][10] = 48, [0][1][1][0][RTW89_FCC][11] = 60, [0][1][1][0][RTW89_ETSI][11] = 48, [0][1][1][0][RTW89_MKK][11] = 66, @@ -29418,6 +32726,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][11] = 48, [0][1][1][0][RTW89_CN][11] = 46, [0][1][1][0][RTW89_UK][11] = 48, + [0][1][1][0][RTW89_MEXICO][11] = 60, + [0][1][1][0][RTW89_UKRAINE][11] = 48, + [0][1][1][0][RTW89_CHILE][11] = 60, + [0][1][1][0][RTW89_QATAR][11] = 48, [0][1][1][0][RTW89_FCC][12] = 36, [0][1][1][0][RTW89_ETSI][12] = 48, [0][1][1][0][RTW89_MKK][12] = 66, @@ -29426,6 +32738,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][12] = 48, [0][1][1][0][RTW89_CN][12] = 46, [0][1][1][0][RTW89_UK][12] = 48, + [0][1][1][0][RTW89_MEXICO][12] = 36, + [0][1][1][0][RTW89_UKRAINE][12] = 48, + [0][1][1][0][RTW89_CHILE][12] = 36, + [0][1][1][0][RTW89_QATAR][12] = 48, [0][1][1][0][RTW89_FCC][13] = 127, [0][1][1][0][RTW89_ETSI][13] = 127, [0][1][1][0][RTW89_MKK][13] = 127, @@ -29434,6 +32750,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][13] = 127, [0][1][1][0][RTW89_CN][13] = 127, [0][1][1][0][RTW89_UK][13] = 127, + [0][1][1][0][RTW89_MEXICO][13] = 127, + [0][1][1][0][RTW89_UKRAINE][13] = 127, + [0][1][1][0][RTW89_CHILE][13] = 127, + [0][1][1][0][RTW89_QATAR][13] = 127, [0][0][2][0][RTW89_FCC][0] = 66, [0][0][2][0][RTW89_ETSI][0] = 60, [0][0][2][0][RTW89_MKK][0] = 78, @@ -29442,6 +32762,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][0] = 60, [0][0][2][0][RTW89_CN][0] = 58, [0][0][2][0][RTW89_UK][0] = 60, + [0][0][2][0][RTW89_MEXICO][0] = 66, + [0][0][2][0][RTW89_UKRAINE][0] = 60, + [0][0][2][0][RTW89_CHILE][0] = 66, + [0][0][2][0][RTW89_QATAR][0] = 60, [0][0][2][0][RTW89_FCC][1] = 70, [0][0][2][0][RTW89_ETSI][1] = 60, [0][0][2][0][RTW89_MKK][1] = 78, @@ -29450,6 +32774,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][1] = 60, [0][0][2][0][RTW89_CN][1] = 58, [0][0][2][0][RTW89_UK][1] = 60, + [0][0][2][0][RTW89_MEXICO][1] = 70, + [0][0][2][0][RTW89_UKRAINE][1] = 60, + [0][0][2][0][RTW89_CHILE][1] = 70, + [0][0][2][0][RTW89_QATAR][1] = 60, [0][0][2][0][RTW89_FCC][2] = 74, [0][0][2][0][RTW89_ETSI][2] = 60, [0][0][2][0][RTW89_MKK][2] = 78, @@ -29458,6 +32786,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][2] = 60, [0][0][2][0][RTW89_CN][2] = 58, [0][0][2][0][RTW89_UK][2] = 60, + [0][0][2][0][RTW89_MEXICO][2] = 74, + [0][0][2][0][RTW89_UKRAINE][2] = 60, + [0][0][2][0][RTW89_CHILE][2] = 64, + [0][0][2][0][RTW89_QATAR][2] = 60, [0][0][2][0][RTW89_FCC][3] = 78, [0][0][2][0][RTW89_ETSI][3] = 60, [0][0][2][0][RTW89_MKK][3] = 78, @@ -29466,6 +32798,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][3] = 60, [0][0][2][0][RTW89_CN][3] = 58, [0][0][2][0][RTW89_UK][3] = 60, + [0][0][2][0][RTW89_MEXICO][3] = 78, + [0][0][2][0][RTW89_UKRAINE][3] = 60, + [0][0][2][0][RTW89_CHILE][3] = 64, + [0][0][2][0][RTW89_QATAR][3] = 60, [0][0][2][0][RTW89_FCC][4] = 80, [0][0][2][0][RTW89_ETSI][4] = 60, [0][0][2][0][RTW89_MKK][4] = 78, @@ -29474,6 +32810,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][4] = 60, [0][0][2][0][RTW89_CN][4] = 58, [0][0][2][0][RTW89_UK][4] = 60, + [0][0][2][0][RTW89_MEXICO][4] = 80, + [0][0][2][0][RTW89_UKRAINE][4] = 60, + [0][0][2][0][RTW89_CHILE][4] = 64, + [0][0][2][0][RTW89_QATAR][4] = 60, [0][0][2][0][RTW89_FCC][5] = 80, [0][0][2][0][RTW89_ETSI][5] = 60, [0][0][2][0][RTW89_MKK][5] = 78, @@ -29482,6 +32822,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][5] = 60, [0][0][2][0][RTW89_CN][5] = 58, [0][0][2][0][RTW89_UK][5] = 60, + [0][0][2][0][RTW89_MEXICO][5] = 80, + [0][0][2][0][RTW89_UKRAINE][5] = 60, + [0][0][2][0][RTW89_CHILE][5] = 80, + [0][0][2][0][RTW89_QATAR][5] = 60, [0][0][2][0][RTW89_FCC][6] = 80, [0][0][2][0][RTW89_ETSI][6] = 60, [0][0][2][0][RTW89_MKK][6] = 78, @@ -29490,6 +32834,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][6] = 60, [0][0][2][0][RTW89_CN][6] = 58, [0][0][2][0][RTW89_UK][6] = 60, + [0][0][2][0][RTW89_MEXICO][6] = 80, + [0][0][2][0][RTW89_UKRAINE][6] = 60, + [0][0][2][0][RTW89_CHILE][6] = 68, + [0][0][2][0][RTW89_QATAR][6] = 60, [0][0][2][0][RTW89_FCC][7] = 80, [0][0][2][0][RTW89_ETSI][7] = 60, [0][0][2][0][RTW89_MKK][7] = 78, @@ -29498,6 +32846,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][7] = 60, [0][0][2][0][RTW89_CN][7] = 58, [0][0][2][0][RTW89_UK][7] = 60, + [0][0][2][0][RTW89_MEXICO][7] = 80, + [0][0][2][0][RTW89_UKRAINE][7] = 60, + [0][0][2][0][RTW89_CHILE][7] = 68, + [0][0][2][0][RTW89_QATAR][7] = 60, [0][0][2][0][RTW89_FCC][8] = 78, [0][0][2][0][RTW89_ETSI][8] = 60, [0][0][2][0][RTW89_MKK][8] = 78, @@ -29506,6 +32858,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][8] = 60, [0][0][2][0][RTW89_CN][8] = 58, [0][0][2][0][RTW89_UK][8] = 60, + [0][0][2][0][RTW89_MEXICO][8] = 78, + [0][0][2][0][RTW89_UKRAINE][8] = 60, + [0][0][2][0][RTW89_CHILE][8] = 68, + [0][0][2][0][RTW89_QATAR][8] = 60, [0][0][2][0][RTW89_FCC][9] = 74, [0][0][2][0][RTW89_ETSI][9] = 60, [0][0][2][0][RTW89_MKK][9] = 78, @@ -29514,6 +32870,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][9] = 60, [0][0][2][0][RTW89_CN][9] = 58, [0][0][2][0][RTW89_UK][9] = 60, + [0][0][2][0][RTW89_MEXICO][9] = 74, + [0][0][2][0][RTW89_UKRAINE][9] = 60, + [0][0][2][0][RTW89_CHILE][9] = 74, + [0][0][2][0][RTW89_QATAR][9] = 60, [0][0][2][0][RTW89_FCC][10] = 62, [0][0][2][0][RTW89_ETSI][10] = 60, [0][0][2][0][RTW89_MKK][10] = 78, @@ -29522,6 +32882,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][10] = 60, [0][0][2][0][RTW89_CN][10] = 58, [0][0][2][0][RTW89_UK][10] = 60, + [0][0][2][0][RTW89_MEXICO][10] = 62, + [0][0][2][0][RTW89_UKRAINE][10] = 60, + [0][0][2][0][RTW89_CHILE][10] = 62, + [0][0][2][0][RTW89_QATAR][10] = 60, [0][0][2][0][RTW89_FCC][11] = 60, [0][0][2][0][RTW89_ETSI][11] = 60, [0][0][2][0][RTW89_MKK][11] = 78, @@ -29530,6 +32894,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][11] = 60, [0][0][2][0][RTW89_CN][11] = 58, [0][0][2][0][RTW89_UK][11] = 60, + [0][0][2][0][RTW89_MEXICO][11] = 60, + [0][0][2][0][RTW89_UKRAINE][11] = 60, + [0][0][2][0][RTW89_CHILE][11] = 60, + [0][0][2][0][RTW89_QATAR][11] = 60, [0][0][2][0][RTW89_FCC][12] = 38, [0][0][2][0][RTW89_ETSI][12] = 60, [0][0][2][0][RTW89_MKK][12] = 78, @@ -29538,6 +32906,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][12] = 60, [0][0][2][0][RTW89_CN][12] = 58, [0][0][2][0][RTW89_UK][12] = 60, + [0][0][2][0][RTW89_MEXICO][12] = 38, + [0][0][2][0][RTW89_UKRAINE][12] = 60, + [0][0][2][0][RTW89_CHILE][12] = 38, + [0][0][2][0][RTW89_QATAR][12] = 60, [0][0][2][0][RTW89_FCC][13] = 127, [0][0][2][0][RTW89_ETSI][13] = 127, [0][0][2][0][RTW89_MKK][13] = 127, @@ -29546,6 +32918,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][13] = 127, [0][0][2][0][RTW89_CN][13] = 127, [0][0][2][0][RTW89_UK][13] = 127, + [0][0][2][0][RTW89_MEXICO][13] = 127, + [0][0][2][0][RTW89_UKRAINE][13] = 127, + [0][0][2][0][RTW89_CHILE][13] = 127, + [0][0][2][0][RTW89_QATAR][13] = 127, [0][1][2][0][RTW89_FCC][0] = 64, [0][1][2][0][RTW89_ETSI][0] = 48, [0][1][2][0][RTW89_MKK][0] = 68, @@ -29554,6 +32930,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][0] = 48, [0][1][2][0][RTW89_CN][0] = 46, [0][1][2][0][RTW89_UK][0] = 48, + [0][1][2][0][RTW89_MEXICO][0] = 64, + [0][1][2][0][RTW89_UKRAINE][0] = 48, + [0][1][2][0][RTW89_CHILE][0] = 64, + [0][1][2][0][RTW89_QATAR][0] = 48, [0][1][2][0][RTW89_FCC][1] = 70, [0][1][2][0][RTW89_ETSI][1] = 48, [0][1][2][0][RTW89_MKK][1] = 68, @@ -29562,6 +32942,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][1] = 48, [0][1][2][0][RTW89_CN][1] = 46, [0][1][2][0][RTW89_UK][1] = 48, + [0][1][2][0][RTW89_MEXICO][1] = 70, + [0][1][2][0][RTW89_UKRAINE][1] = 48, + [0][1][2][0][RTW89_CHILE][1] = 70, + [0][1][2][0][RTW89_QATAR][1] = 48, [0][1][2][0][RTW89_FCC][2] = 74, [0][1][2][0][RTW89_ETSI][2] = 48, [0][1][2][0][RTW89_MKK][2] = 68, @@ -29570,6 +32954,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][2] = 48, [0][1][2][0][RTW89_CN][2] = 46, [0][1][2][0][RTW89_UK][2] = 48, + [0][1][2][0][RTW89_MEXICO][2] = 74, + [0][1][2][0][RTW89_UKRAINE][2] = 48, + [0][1][2][0][RTW89_CHILE][2] = 56, + [0][1][2][0][RTW89_QATAR][2] = 48, [0][1][2][0][RTW89_FCC][3] = 78, [0][1][2][0][RTW89_ETSI][3] = 48, [0][1][2][0][RTW89_MKK][3] = 68, @@ -29578,6 +32966,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][3] = 48, [0][1][2][0][RTW89_CN][3] = 46, [0][1][2][0][RTW89_UK][3] = 48, + [0][1][2][0][RTW89_MEXICO][3] = 78, + [0][1][2][0][RTW89_UKRAINE][3] = 48, + [0][1][2][0][RTW89_CHILE][3] = 56, + [0][1][2][0][RTW89_QATAR][3] = 48, [0][1][2][0][RTW89_FCC][4] = 80, [0][1][2][0][RTW89_ETSI][4] = 48, [0][1][2][0][RTW89_MKK][4] = 68, @@ -29586,6 +32978,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][4] = 48, [0][1][2][0][RTW89_CN][4] = 46, [0][1][2][0][RTW89_UK][4] = 48, + [0][1][2][0][RTW89_MEXICO][4] = 80, + [0][1][2][0][RTW89_UKRAINE][4] = 48, + [0][1][2][0][RTW89_CHILE][4] = 56, + [0][1][2][0][RTW89_QATAR][4] = 48, [0][1][2][0][RTW89_FCC][5] = 80, [0][1][2][0][RTW89_ETSI][5] = 48, [0][1][2][0][RTW89_MKK][5] = 68, @@ -29594,6 +32990,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][5] = 48, [0][1][2][0][RTW89_CN][5] = 46, [0][1][2][0][RTW89_UK][5] = 48, + [0][1][2][0][RTW89_MEXICO][5] = 80, + [0][1][2][0][RTW89_UKRAINE][5] = 48, + [0][1][2][0][RTW89_CHILE][5] = 78, + [0][1][2][0][RTW89_QATAR][5] = 48, [0][1][2][0][RTW89_FCC][6] = 80, [0][1][2][0][RTW89_ETSI][6] = 48, [0][1][2][0][RTW89_MKK][6] = 68, @@ -29602,6 +33002,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][6] = 48, [0][1][2][0][RTW89_CN][6] = 46, [0][1][2][0][RTW89_UK][6] = 48, + [0][1][2][0][RTW89_MEXICO][6] = 80, + [0][1][2][0][RTW89_UKRAINE][6] = 48, + [0][1][2][0][RTW89_CHILE][6] = 54, + [0][1][2][0][RTW89_QATAR][6] = 48, [0][1][2][0][RTW89_FCC][7] = 74, [0][1][2][0][RTW89_ETSI][7] = 48, [0][1][2][0][RTW89_MKK][7] = 68, @@ -29610,6 +33014,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][7] = 48, [0][1][2][0][RTW89_CN][7] = 46, [0][1][2][0][RTW89_UK][7] = 48, + [0][1][2][0][RTW89_MEXICO][7] = 74, + [0][1][2][0][RTW89_UKRAINE][7] = 48, + [0][1][2][0][RTW89_CHILE][7] = 54, + [0][1][2][0][RTW89_QATAR][7] = 48, [0][1][2][0][RTW89_FCC][8] = 70, [0][1][2][0][RTW89_ETSI][8] = 48, [0][1][2][0][RTW89_MKK][8] = 68, @@ -29618,6 +33026,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][8] = 48, [0][1][2][0][RTW89_CN][8] = 46, [0][1][2][0][RTW89_UK][8] = 48, + [0][1][2][0][RTW89_MEXICO][8] = 70, + [0][1][2][0][RTW89_UKRAINE][8] = 48, + [0][1][2][0][RTW89_CHILE][8] = 54, + [0][1][2][0][RTW89_QATAR][8] = 48, [0][1][2][0][RTW89_FCC][9] = 66, [0][1][2][0][RTW89_ETSI][9] = 48, [0][1][2][0][RTW89_MKK][9] = 68, @@ -29626,6 +33038,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][9] = 48, [0][1][2][0][RTW89_CN][9] = 46, [0][1][2][0][RTW89_UK][9] = 48, + [0][1][2][0][RTW89_MEXICO][9] = 66, + [0][1][2][0][RTW89_UKRAINE][9] = 48, + [0][1][2][0][RTW89_CHILE][9] = 66, + [0][1][2][0][RTW89_QATAR][9] = 48, [0][1][2][0][RTW89_FCC][10] = 58, [0][1][2][0][RTW89_ETSI][10] = 48, [0][1][2][0][RTW89_MKK][10] = 68, @@ -29634,6 +33050,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][10] = 48, [0][1][2][0][RTW89_CN][10] = 46, [0][1][2][0][RTW89_UK][10] = 48, + [0][1][2][0][RTW89_MEXICO][10] = 58, + [0][1][2][0][RTW89_UKRAINE][10] = 48, + [0][1][2][0][RTW89_CHILE][10] = 58, + [0][1][2][0][RTW89_QATAR][10] = 48, [0][1][2][0][RTW89_FCC][11] = 58, [0][1][2][0][RTW89_ETSI][11] = 48, [0][1][2][0][RTW89_MKK][11] = 68, @@ -29642,6 +33062,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][11] = 48, [0][1][2][0][RTW89_CN][11] = 46, [0][1][2][0][RTW89_UK][11] = 48, + [0][1][2][0][RTW89_MEXICO][11] = 58, + [0][1][2][0][RTW89_UKRAINE][11] = 48, + [0][1][2][0][RTW89_CHILE][11] = 58, + [0][1][2][0][RTW89_QATAR][11] = 48, [0][1][2][0][RTW89_FCC][12] = 16, [0][1][2][0][RTW89_ETSI][12] = 48, [0][1][2][0][RTW89_MKK][12] = 68, @@ -29650,6 +33074,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][12] = 48, [0][1][2][0][RTW89_CN][12] = 46, [0][1][2][0][RTW89_UK][12] = 48, + [0][1][2][0][RTW89_MEXICO][12] = 16, + [0][1][2][0][RTW89_UKRAINE][12] = 48, + [0][1][2][0][RTW89_CHILE][12] = 16, + [0][1][2][0][RTW89_QATAR][12] = 48, [0][1][2][0][RTW89_FCC][13] = 127, [0][1][2][0][RTW89_ETSI][13] = 127, [0][1][2][0][RTW89_MKK][13] = 127, @@ -29658,6 +33086,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][13] = 127, [0][1][2][0][RTW89_CN][13] = 127, [0][1][2][0][RTW89_UK][13] = 127, + [0][1][2][0][RTW89_MEXICO][13] = 127, + [0][1][2][0][RTW89_UKRAINE][13] = 127, + [0][1][2][0][RTW89_CHILE][13] = 127, + [0][1][2][0][RTW89_QATAR][13] = 127, [0][1][2][1][RTW89_FCC][0] = 64, [0][1][2][1][RTW89_ETSI][0] = 36, [0][1][2][1][RTW89_MKK][0] = 68, @@ -29666,6 +33098,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][0] = 36, [0][1][2][1][RTW89_CN][0] = 36, [0][1][2][1][RTW89_UK][0] = 36, + [0][1][2][1][RTW89_MEXICO][0] = 64, + [0][1][2][1][RTW89_UKRAINE][0] = 36, + [0][1][2][1][RTW89_CHILE][0] = 64, + [0][1][2][1][RTW89_QATAR][0] = 36, [0][1][2][1][RTW89_FCC][1] = 70, [0][1][2][1][RTW89_ETSI][1] = 36, [0][1][2][1][RTW89_MKK][1] = 68, @@ -29674,6 +33110,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][1] = 36, [0][1][2][1][RTW89_CN][1] = 34, [0][1][2][1][RTW89_UK][1] = 36, + [0][1][2][1][RTW89_MEXICO][1] = 70, + [0][1][2][1][RTW89_UKRAINE][1] = 36, + [0][1][2][1][RTW89_CHILE][1] = 70, + [0][1][2][1][RTW89_QATAR][1] = 36, [0][1][2][1][RTW89_FCC][2] = 74, [0][1][2][1][RTW89_ETSI][2] = 36, [0][1][2][1][RTW89_MKK][2] = 68, @@ -29682,6 +33122,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][2] = 36, [0][1][2][1][RTW89_CN][2] = 34, [0][1][2][1][RTW89_UK][2] = 36, + [0][1][2][1][RTW89_MEXICO][2] = 74, + [0][1][2][1][RTW89_UKRAINE][2] = 36, + [0][1][2][1][RTW89_CHILE][2] = 44, + [0][1][2][1][RTW89_QATAR][2] = 36, [0][1][2][1][RTW89_FCC][3] = 78, [0][1][2][1][RTW89_ETSI][3] = 36, [0][1][2][1][RTW89_MKK][3] = 68, @@ -29690,6 +33134,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][3] = 36, [0][1][2][1][RTW89_CN][3] = 34, [0][1][2][1][RTW89_UK][3] = 36, + [0][1][2][1][RTW89_MEXICO][3] = 78, + [0][1][2][1][RTW89_UKRAINE][3] = 36, + [0][1][2][1][RTW89_CHILE][3] = 44, + [0][1][2][1][RTW89_QATAR][3] = 36, [0][1][2][1][RTW89_FCC][4] = 80, [0][1][2][1][RTW89_ETSI][4] = 36, [0][1][2][1][RTW89_MKK][4] = 68, @@ -29698,6 +33146,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][4] = 36, [0][1][2][1][RTW89_CN][4] = 34, [0][1][2][1][RTW89_UK][4] = 36, + [0][1][2][1][RTW89_MEXICO][4] = 80, + [0][1][2][1][RTW89_UKRAINE][4] = 36, + [0][1][2][1][RTW89_CHILE][4] = 44, + [0][1][2][1][RTW89_QATAR][4] = 36, [0][1][2][1][RTW89_FCC][5] = 80, [0][1][2][1][RTW89_ETSI][5] = 36, [0][1][2][1][RTW89_MKK][5] = 68, @@ -29706,6 +33158,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][5] = 36, [0][1][2][1][RTW89_CN][5] = 34, [0][1][2][1][RTW89_UK][5] = 36, + [0][1][2][1][RTW89_MEXICO][5] = 80, + [0][1][2][1][RTW89_UKRAINE][5] = 36, + [0][1][2][1][RTW89_CHILE][5] = 74, + [0][1][2][1][RTW89_QATAR][5] = 36, [0][1][2][1][RTW89_FCC][6] = 80, [0][1][2][1][RTW89_ETSI][6] = 36, [0][1][2][1][RTW89_MKK][6] = 68, @@ -29714,6 +33170,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][6] = 36, [0][1][2][1][RTW89_CN][6] = 34, [0][1][2][1][RTW89_UK][6] = 36, + [0][1][2][1][RTW89_MEXICO][6] = 80, + [0][1][2][1][RTW89_UKRAINE][6] = 36, + [0][1][2][1][RTW89_CHILE][6] = 42, + [0][1][2][1][RTW89_QATAR][6] = 36, [0][1][2][1][RTW89_FCC][7] = 74, [0][1][2][1][RTW89_ETSI][7] = 36, [0][1][2][1][RTW89_MKK][7] = 68, @@ -29722,6 +33182,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][7] = 36, [0][1][2][1][RTW89_CN][7] = 34, [0][1][2][1][RTW89_UK][7] = 36, + [0][1][2][1][RTW89_MEXICO][7] = 74, + [0][1][2][1][RTW89_UKRAINE][7] = 36, + [0][1][2][1][RTW89_CHILE][7] = 42, + [0][1][2][1][RTW89_QATAR][7] = 36, [0][1][2][1][RTW89_FCC][8] = 70, [0][1][2][1][RTW89_ETSI][8] = 36, [0][1][2][1][RTW89_MKK][8] = 68, @@ -29730,6 +33194,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][8] = 36, [0][1][2][1][RTW89_CN][8] = 34, [0][1][2][1][RTW89_UK][8] = 36, + [0][1][2][1][RTW89_MEXICO][8] = 70, + [0][1][2][1][RTW89_UKRAINE][8] = 36, + [0][1][2][1][RTW89_CHILE][8] = 42, + [0][1][2][1][RTW89_QATAR][8] = 36, [0][1][2][1][RTW89_FCC][9] = 66, [0][1][2][1][RTW89_ETSI][9] = 36, [0][1][2][1][RTW89_MKK][9] = 68, @@ -29738,6 +33206,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][9] = 36, [0][1][2][1][RTW89_CN][9] = 34, [0][1][2][1][RTW89_UK][9] = 36, + [0][1][2][1][RTW89_MEXICO][9] = 66, + [0][1][2][1][RTW89_UKRAINE][9] = 36, + [0][1][2][1][RTW89_CHILE][9] = 66, + [0][1][2][1][RTW89_QATAR][9] = 36, [0][1][2][1][RTW89_FCC][10] = 58, [0][1][2][1][RTW89_ETSI][10] = 36, [0][1][2][1][RTW89_MKK][10] = 68, @@ -29746,6 +33218,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][10] = 36, [0][1][2][1][RTW89_CN][10] = 34, [0][1][2][1][RTW89_UK][10] = 36, + [0][1][2][1][RTW89_MEXICO][10] = 58, + [0][1][2][1][RTW89_UKRAINE][10] = 36, + [0][1][2][1][RTW89_CHILE][10] = 58, + [0][1][2][1][RTW89_QATAR][10] = 36, [0][1][2][1][RTW89_FCC][11] = 58, [0][1][2][1][RTW89_ETSI][11] = 36, [0][1][2][1][RTW89_MKK][11] = 68, @@ -29754,6 +33230,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][11] = 36, [0][1][2][1][RTW89_CN][11] = 34, [0][1][2][1][RTW89_UK][11] = 36, + [0][1][2][1][RTW89_MEXICO][11] = 58, + [0][1][2][1][RTW89_UKRAINE][11] = 36, + [0][1][2][1][RTW89_CHILE][11] = 58, + [0][1][2][1][RTW89_QATAR][11] = 36, [0][1][2][1][RTW89_FCC][12] = 16, [0][1][2][1][RTW89_ETSI][12] = 36, [0][1][2][1][RTW89_MKK][12] = 68, @@ -29762,6 +33242,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][12] = 36, [0][1][2][1][RTW89_CN][12] = 34, [0][1][2][1][RTW89_UK][12] = 36, + [0][1][2][1][RTW89_MEXICO][12] = 16, + [0][1][2][1][RTW89_UKRAINE][12] = 36, + [0][1][2][1][RTW89_CHILE][12] = 16, + [0][1][2][1][RTW89_QATAR][12] = 36, [0][1][2][1][RTW89_FCC][13] = 127, [0][1][2][1][RTW89_ETSI][13] = 127, [0][1][2][1][RTW89_MKK][13] = 127, @@ -29770,6 +33254,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][13] = 127, [0][1][2][1][RTW89_CN][13] = 127, [0][1][2][1][RTW89_UK][13] = 127, + [0][1][2][1][RTW89_MEXICO][13] = 127, + [0][1][2][1][RTW89_UKRAINE][13] = 127, + [0][1][2][1][RTW89_CHILE][13] = 127, + [0][1][2][1][RTW89_QATAR][13] = 127, [1][0][2][0][RTW89_FCC][0] = 127, [1][0][2][0][RTW89_ETSI][0] = 127, [1][0][2][0][RTW89_MKK][0] = 127, @@ -29778,6 +33266,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][0] = 127, [1][0][2][0][RTW89_CN][0] = 127, [1][0][2][0][RTW89_UK][0] = 127, + [1][0][2][0][RTW89_MEXICO][0] = 127, + [1][0][2][0][RTW89_UKRAINE][0] = 127, + [1][0][2][0][RTW89_CHILE][0] = 127, + [1][0][2][0][RTW89_QATAR][0] = 127, [1][0][2][0][RTW89_FCC][1] = 127, [1][0][2][0][RTW89_ETSI][1] = 127, [1][0][2][0][RTW89_MKK][1] = 127, @@ -29786,6 +33278,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][1] = 127, [1][0][2][0][RTW89_CN][1] = 127, [1][0][2][0][RTW89_UK][1] = 127, + [1][0][2][0][RTW89_MEXICO][1] = 127, + [1][0][2][0][RTW89_UKRAINE][1] = 127, + [1][0][2][0][RTW89_CHILE][1] = 127, + [1][0][2][0][RTW89_QATAR][1] = 127, [1][0][2][0][RTW89_FCC][2] = 64, [1][0][2][0][RTW89_ETSI][2] = 60, [1][0][2][0][RTW89_MKK][2] = 74, @@ -29794,6 +33290,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][2] = 60, [1][0][2][0][RTW89_CN][2] = 58, [1][0][2][0][RTW89_UK][2] = 60, + [1][0][2][0][RTW89_MEXICO][2] = 64, + [1][0][2][0][RTW89_UKRAINE][2] = 60, + [1][0][2][0][RTW89_CHILE][2] = 64, + [1][0][2][0][RTW89_QATAR][2] = 60, [1][0][2][0][RTW89_FCC][3] = 64, [1][0][2][0][RTW89_ETSI][3] = 60, [1][0][2][0][RTW89_MKK][3] = 74, @@ -29802,6 +33302,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][3] = 60, [1][0][2][0][RTW89_CN][3] = 58, [1][0][2][0][RTW89_UK][3] = 60, + [1][0][2][0][RTW89_MEXICO][3] = 64, + [1][0][2][0][RTW89_UKRAINE][3] = 60, + [1][0][2][0][RTW89_CHILE][3] = 64, + [1][0][2][0][RTW89_QATAR][3] = 60, [1][0][2][0][RTW89_FCC][4] = 68, [1][0][2][0][RTW89_ETSI][4] = 60, [1][0][2][0][RTW89_MKK][4] = 74, @@ -29810,6 +33314,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][4] = 60, [1][0][2][0][RTW89_CN][4] = 58, [1][0][2][0][RTW89_UK][4] = 60, + [1][0][2][0][RTW89_MEXICO][4] = 68, + [1][0][2][0][RTW89_UKRAINE][4] = 60, + [1][0][2][0][RTW89_CHILE][4] = 68, + [1][0][2][0][RTW89_QATAR][4] = 60, [1][0][2][0][RTW89_FCC][5] = 68, [1][0][2][0][RTW89_ETSI][5] = 60, [1][0][2][0][RTW89_MKK][5] = 74, @@ -29818,6 +33326,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][5] = 60, [1][0][2][0][RTW89_CN][5] = 58, [1][0][2][0][RTW89_UK][5] = 60, + [1][0][2][0][RTW89_MEXICO][5] = 68, + [1][0][2][0][RTW89_UKRAINE][5] = 60, + [1][0][2][0][RTW89_CHILE][5] = 68, + [1][0][2][0][RTW89_QATAR][5] = 60, [1][0][2][0][RTW89_FCC][6] = 66, [1][0][2][0][RTW89_ETSI][6] = 60, [1][0][2][0][RTW89_MKK][6] = 74, @@ -29826,6 +33338,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][6] = 60, [1][0][2][0][RTW89_CN][6] = 58, [1][0][2][0][RTW89_UK][6] = 60, + [1][0][2][0][RTW89_MEXICO][6] = 66, + [1][0][2][0][RTW89_UKRAINE][6] = 60, + [1][0][2][0][RTW89_CHILE][6] = 66, + [1][0][2][0][RTW89_QATAR][6] = 60, [1][0][2][0][RTW89_FCC][7] = 62, [1][0][2][0][RTW89_ETSI][7] = 60, [1][0][2][0][RTW89_MKK][7] = 74, @@ -29834,6 +33350,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][7] = 60, [1][0][2][0][RTW89_CN][7] = 58, [1][0][2][0][RTW89_UK][7] = 60, + [1][0][2][0][RTW89_MEXICO][7] = 62, + [1][0][2][0][RTW89_UKRAINE][7] = 60, + [1][0][2][0][RTW89_CHILE][7] = 62, + [1][0][2][0][RTW89_QATAR][7] = 60, [1][0][2][0][RTW89_FCC][8] = 62, [1][0][2][0][RTW89_ETSI][8] = 60, [1][0][2][0][RTW89_MKK][8] = 74, @@ -29842,6 +33362,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][8] = 60, [1][0][2][0][RTW89_CN][8] = 58, [1][0][2][0][RTW89_UK][8] = 60, + [1][0][2][0][RTW89_MEXICO][8] = 62, + [1][0][2][0][RTW89_UKRAINE][8] = 60, + [1][0][2][0][RTW89_CHILE][8] = 62, + [1][0][2][0][RTW89_QATAR][8] = 60, [1][0][2][0][RTW89_FCC][9] = 60, [1][0][2][0][RTW89_ETSI][9] = 60, [1][0][2][0][RTW89_MKK][9] = 74, @@ -29850,6 +33374,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][9] = 60, [1][0][2][0][RTW89_CN][9] = 58, [1][0][2][0][RTW89_UK][9] = 60, + [1][0][2][0][RTW89_MEXICO][9] = 60, + [1][0][2][0][RTW89_UKRAINE][9] = 60, + [1][0][2][0][RTW89_CHILE][9] = 60, + [1][0][2][0][RTW89_QATAR][9] = 60, [1][0][2][0][RTW89_FCC][10] = 56, [1][0][2][0][RTW89_ETSI][10] = 60, [1][0][2][0][RTW89_MKK][10] = 74, @@ -29858,6 +33386,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][10] = 60, [1][0][2][0][RTW89_CN][10] = 58, [1][0][2][0][RTW89_UK][10] = 60, + [1][0][2][0][RTW89_MEXICO][10] = 56, + [1][0][2][0][RTW89_UKRAINE][10] = 60, + [1][0][2][0][RTW89_CHILE][10] = 56, + [1][0][2][0][RTW89_QATAR][10] = 60, [1][0][2][0][RTW89_FCC][11] = 127, [1][0][2][0][RTW89_ETSI][11] = 127, [1][0][2][0][RTW89_MKK][11] = 127, @@ -29866,6 +33398,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][11] = 127, [1][0][2][0][RTW89_CN][11] = 127, [1][0][2][0][RTW89_UK][11] = 127, + [1][0][2][0][RTW89_MEXICO][11] = 127, + [1][0][2][0][RTW89_UKRAINE][11] = 127, + [1][0][2][0][RTW89_CHILE][11] = 127, + [1][0][2][0][RTW89_QATAR][11] = 127, [1][0][2][0][RTW89_FCC][12] = 127, [1][0][2][0][RTW89_ETSI][12] = 127, [1][0][2][0][RTW89_MKK][12] = 127, @@ -29874,6 +33410,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][12] = 127, [1][0][2][0][RTW89_CN][12] = 127, [1][0][2][0][RTW89_UK][12] = 127, + [1][0][2][0][RTW89_MEXICO][12] = 127, + [1][0][2][0][RTW89_UKRAINE][12] = 127, + [1][0][2][0][RTW89_CHILE][12] = 127, + [1][0][2][0][RTW89_QATAR][12] = 127, [1][0][2][0][RTW89_FCC][13] = 127, [1][0][2][0][RTW89_ETSI][13] = 127, [1][0][2][0][RTW89_MKK][13] = 127, @@ -29882,6 +33422,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][13] = 127, [1][0][2][0][RTW89_CN][13] = 127, [1][0][2][0][RTW89_UK][13] = 127, + [1][0][2][0][RTW89_MEXICO][13] = 127, + [1][0][2][0][RTW89_UKRAINE][13] = 127, + [1][0][2][0][RTW89_CHILE][13] = 127, + [1][0][2][0][RTW89_QATAR][13] = 127, [1][1][2][0][RTW89_FCC][0] = 127, [1][1][2][0][RTW89_ETSI][0] = 127, [1][1][2][0][RTW89_MKK][0] = 127, @@ -29890,6 +33434,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][0] = 127, [1][1][2][0][RTW89_CN][0] = 127, [1][1][2][0][RTW89_UK][0] = 127, + [1][1][2][0][RTW89_MEXICO][0] = 127, + [1][1][2][0][RTW89_UKRAINE][0] = 127, + [1][1][2][0][RTW89_CHILE][0] = 127, + [1][1][2][0][RTW89_QATAR][0] = 127, [1][1][2][0][RTW89_FCC][1] = 127, [1][1][2][0][RTW89_ETSI][1] = 127, [1][1][2][0][RTW89_MKK][1] = 127, @@ -29898,6 +33446,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][1] = 127, [1][1][2][0][RTW89_CN][1] = 127, [1][1][2][0][RTW89_UK][1] = 127, + [1][1][2][0][RTW89_MEXICO][1] = 127, + [1][1][2][0][RTW89_UKRAINE][1] = 127, + [1][1][2][0][RTW89_CHILE][1] = 127, + [1][1][2][0][RTW89_QATAR][1] = 127, [1][1][2][0][RTW89_FCC][2] = 60, [1][1][2][0][RTW89_ETSI][2] = 48, [1][1][2][0][RTW89_MKK][2] = 68, @@ -29906,6 +33458,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][2] = 48, [1][1][2][0][RTW89_CN][2] = 34, [1][1][2][0][RTW89_UK][2] = 48, + [1][1][2][0][RTW89_MEXICO][2] = 60, + [1][1][2][0][RTW89_UKRAINE][2] = 48, + [1][1][2][0][RTW89_CHILE][2] = 60, + [1][1][2][0][RTW89_QATAR][2] = 48, [1][1][2][0][RTW89_FCC][3] = 60, [1][1][2][0][RTW89_ETSI][3] = 48, [1][1][2][0][RTW89_MKK][3] = 68, @@ -29914,6 +33470,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][3] = 48, [1][1][2][0][RTW89_CN][3] = 34, [1][1][2][0][RTW89_UK][3] = 48, + [1][1][2][0][RTW89_MEXICO][3] = 60, + [1][1][2][0][RTW89_UKRAINE][3] = 48, + [1][1][2][0][RTW89_CHILE][3] = 56, + [1][1][2][0][RTW89_QATAR][3] = 48, [1][1][2][0][RTW89_FCC][4] = 60, [1][1][2][0][RTW89_ETSI][4] = 48, [1][1][2][0][RTW89_MKK][4] = 68, @@ -29922,6 +33482,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][4] = 48, [1][1][2][0][RTW89_CN][4] = 34, [1][1][2][0][RTW89_UK][4] = 48, + [1][1][2][0][RTW89_MEXICO][4] = 60, + [1][1][2][0][RTW89_UKRAINE][4] = 48, + [1][1][2][0][RTW89_CHILE][4] = 56, + [1][1][2][0][RTW89_QATAR][4] = 48, [1][1][2][0][RTW89_FCC][5] = 60, [1][1][2][0][RTW89_ETSI][5] = 48, [1][1][2][0][RTW89_MKK][5] = 68, @@ -29930,6 +33494,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][5] = 48, [1][1][2][0][RTW89_CN][5] = 34, [1][1][2][0][RTW89_UK][5] = 48, + [1][1][2][0][RTW89_MEXICO][5] = 60, + [1][1][2][0][RTW89_UKRAINE][5] = 48, + [1][1][2][0][RTW89_CHILE][5] = 60, + [1][1][2][0][RTW89_QATAR][5] = 48, [1][1][2][0][RTW89_FCC][6] = 58, [1][1][2][0][RTW89_ETSI][6] = 48, [1][1][2][0][RTW89_MKK][6] = 68, @@ -29938,6 +33506,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][6] = 48, [1][1][2][0][RTW89_CN][6] = 34, [1][1][2][0][RTW89_UK][6] = 48, + [1][1][2][0][RTW89_MEXICO][6] = 58, + [1][1][2][0][RTW89_UKRAINE][6] = 48, + [1][1][2][0][RTW89_CHILE][6] = 52, + [1][1][2][0][RTW89_QATAR][6] = 48, [1][1][2][0][RTW89_FCC][7] = 54, [1][1][2][0][RTW89_ETSI][7] = 48, [1][1][2][0][RTW89_MKK][7] = 68, @@ -29946,6 +33518,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][7] = 48, [1][1][2][0][RTW89_CN][7] = 34, [1][1][2][0][RTW89_UK][7] = 48, + [1][1][2][0][RTW89_MEXICO][7] = 54, + [1][1][2][0][RTW89_UKRAINE][7] = 48, + [1][1][2][0][RTW89_CHILE][7] = 52, + [1][1][2][0][RTW89_QATAR][7] = 48, [1][1][2][0][RTW89_FCC][8] = 54, [1][1][2][0][RTW89_ETSI][8] = 48, [1][1][2][0][RTW89_MKK][8] = 68, @@ -29954,6 +33530,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][8] = 48, [1][1][2][0][RTW89_CN][8] = 34, [1][1][2][0][RTW89_UK][8] = 48, + [1][1][2][0][RTW89_MEXICO][8] = 54, + [1][1][2][0][RTW89_UKRAINE][8] = 48, + [1][1][2][0][RTW89_CHILE][8] = 54, + [1][1][2][0][RTW89_QATAR][8] = 48, [1][1][2][0][RTW89_FCC][9] = 54, [1][1][2][0][RTW89_ETSI][9] = 48, [1][1][2][0][RTW89_MKK][9] = 68, @@ -29962,6 +33542,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][9] = 48, [1][1][2][0][RTW89_CN][9] = 34, [1][1][2][0][RTW89_UK][9] = 48, + [1][1][2][0][RTW89_MEXICO][9] = 54, + [1][1][2][0][RTW89_UKRAINE][9] = 48, + [1][1][2][0][RTW89_CHILE][9] = 54, + [1][1][2][0][RTW89_QATAR][9] = 48, [1][1][2][0][RTW89_FCC][10] = 46, [1][1][2][0][RTW89_ETSI][10] = 48, [1][1][2][0][RTW89_MKK][10] = 68, @@ -29970,6 +33554,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][10] = 48, [1][1][2][0][RTW89_CN][10] = 34, [1][1][2][0][RTW89_UK][10] = 48, + [1][1][2][0][RTW89_MEXICO][10] = 46, + [1][1][2][0][RTW89_UKRAINE][10] = 48, + [1][1][2][0][RTW89_CHILE][10] = 46, + [1][1][2][0][RTW89_QATAR][10] = 48, [1][1][2][0][RTW89_FCC][11] = 127, [1][1][2][0][RTW89_ETSI][11] = 127, [1][1][2][0][RTW89_MKK][11] = 127, @@ -29978,6 +33566,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][11] = 127, [1][1][2][0][RTW89_CN][11] = 127, [1][1][2][0][RTW89_UK][11] = 127, + [1][1][2][0][RTW89_MEXICO][11] = 127, + [1][1][2][0][RTW89_UKRAINE][11] = 127, + [1][1][2][0][RTW89_CHILE][11] = 127, + [1][1][2][0][RTW89_QATAR][11] = 127, [1][1][2][0][RTW89_FCC][12] = 127, [1][1][2][0][RTW89_ETSI][12] = 127, [1][1][2][0][RTW89_MKK][12] = 127, @@ -29986,6 +33578,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][12] = 127, [1][1][2][0][RTW89_CN][12] = 127, [1][1][2][0][RTW89_UK][12] = 127, + [1][1][2][0][RTW89_MEXICO][12] = 127, + [1][1][2][0][RTW89_UKRAINE][12] = 127, + [1][1][2][0][RTW89_CHILE][12] = 127, + [1][1][2][0][RTW89_QATAR][12] = 127, [1][1][2][0][RTW89_FCC][13] = 127, [1][1][2][0][RTW89_ETSI][13] = 127, [1][1][2][0][RTW89_MKK][13] = 127, @@ -29994,6 +33590,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][13] = 127, [1][1][2][0][RTW89_CN][13] = 127, [1][1][2][0][RTW89_UK][13] = 127, + [1][1][2][0][RTW89_MEXICO][13] = 127, + [1][1][2][0][RTW89_UKRAINE][13] = 127, + [1][1][2][0][RTW89_CHILE][13] = 127, + [1][1][2][0][RTW89_QATAR][13] = 127, [1][1][2][1][RTW89_FCC][0] = 127, [1][1][2][1][RTW89_ETSI][0] = 127, [1][1][2][1][RTW89_MKK][0] = 127, @@ -30002,6 +33602,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][0] = 127, [1][1][2][1][RTW89_CN][0] = 127, [1][1][2][1][RTW89_UK][0] = 127, + [1][1][2][1][RTW89_MEXICO][0] = 127, + [1][1][2][1][RTW89_UKRAINE][0] = 127, + [1][1][2][1][RTW89_CHILE][0] = 127, + [1][1][2][1][RTW89_QATAR][0] = 127, [1][1][2][1][RTW89_FCC][1] = 127, [1][1][2][1][RTW89_ETSI][1] = 127, [1][1][2][1][RTW89_MKK][1] = 127, @@ -30010,6 +33614,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][1] = 127, [1][1][2][1][RTW89_CN][1] = 127, [1][1][2][1][RTW89_UK][1] = 127, + [1][1][2][1][RTW89_MEXICO][1] = 127, + [1][1][2][1][RTW89_UKRAINE][1] = 127, + [1][1][2][1][RTW89_CHILE][1] = 127, + [1][1][2][1][RTW89_QATAR][1] = 127, [1][1][2][1][RTW89_FCC][2] = 60, [1][1][2][1][RTW89_ETSI][2] = 36, [1][1][2][1][RTW89_MKK][2] = 68, @@ -30018,6 +33626,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][2] = 36, [1][1][2][1][RTW89_CN][2] = 34, [1][1][2][1][RTW89_UK][2] = 36, + [1][1][2][1][RTW89_MEXICO][2] = 60, + [1][1][2][1][RTW89_UKRAINE][2] = 36, + [1][1][2][1][RTW89_CHILE][2] = 60, + [1][1][2][1][RTW89_QATAR][2] = 36, [1][1][2][1][RTW89_FCC][3] = 60, [1][1][2][1][RTW89_ETSI][3] = 36, [1][1][2][1][RTW89_MKK][3] = 68, @@ -30026,6 +33638,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][3] = 36, [1][1][2][1][RTW89_CN][3] = 34, [1][1][2][1][RTW89_UK][3] = 36, + [1][1][2][1][RTW89_MEXICO][3] = 60, + [1][1][2][1][RTW89_UKRAINE][3] = 36, + [1][1][2][1][RTW89_CHILE][3] = 44, + [1][1][2][1][RTW89_QATAR][3] = 36, [1][1][2][1][RTW89_FCC][4] = 60, [1][1][2][1][RTW89_ETSI][4] = 36, [1][1][2][1][RTW89_MKK][4] = 68, @@ -30034,6 +33650,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][4] = 36, [1][1][2][1][RTW89_CN][4] = 34, [1][1][2][1][RTW89_UK][4] = 36, + [1][1][2][1][RTW89_MEXICO][4] = 60, + [1][1][2][1][RTW89_UKRAINE][4] = 36, + [1][1][2][1][RTW89_CHILE][4] = 44, + [1][1][2][1][RTW89_QATAR][4] = 36, [1][1][2][1][RTW89_FCC][5] = 60, [1][1][2][1][RTW89_ETSI][5] = 36, [1][1][2][1][RTW89_MKK][5] = 68, @@ -30042,6 +33662,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][5] = 36, [1][1][2][1][RTW89_CN][5] = 34, [1][1][2][1][RTW89_UK][5] = 36, + [1][1][2][1][RTW89_MEXICO][5] = 60, + [1][1][2][1][RTW89_UKRAINE][5] = 36, + [1][1][2][1][RTW89_CHILE][5] = 60, + [1][1][2][1][RTW89_QATAR][5] = 36, [1][1][2][1][RTW89_FCC][6] = 58, [1][1][2][1][RTW89_ETSI][6] = 36, [1][1][2][1][RTW89_MKK][6] = 68, @@ -30050,6 +33674,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][6] = 36, [1][1][2][1][RTW89_CN][6] = 34, [1][1][2][1][RTW89_UK][6] = 36, + [1][1][2][1][RTW89_MEXICO][6] = 58, + [1][1][2][1][RTW89_UKRAINE][6] = 36, + [1][1][2][1][RTW89_CHILE][6] = 40, + [1][1][2][1][RTW89_QATAR][6] = 36, [1][1][2][1][RTW89_FCC][7] = 54, [1][1][2][1][RTW89_ETSI][7] = 36, [1][1][2][1][RTW89_MKK][7] = 68, @@ -30058,6 +33686,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][7] = 36, [1][1][2][1][RTW89_CN][7] = 34, [1][1][2][1][RTW89_UK][7] = 36, + [1][1][2][1][RTW89_MEXICO][7] = 54, + [1][1][2][1][RTW89_UKRAINE][7] = 36, + [1][1][2][1][RTW89_CHILE][7] = 40, + [1][1][2][1][RTW89_QATAR][7] = 36, [1][1][2][1][RTW89_FCC][8] = 54, [1][1][2][1][RTW89_ETSI][8] = 36, [1][1][2][1][RTW89_MKK][8] = 68, @@ -30066,6 +33698,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][8] = 36, [1][1][2][1][RTW89_CN][8] = 34, [1][1][2][1][RTW89_UK][8] = 36, + [1][1][2][1][RTW89_MEXICO][8] = 54, + [1][1][2][1][RTW89_UKRAINE][8] = 36, + [1][1][2][1][RTW89_CHILE][8] = 54, + [1][1][2][1][RTW89_QATAR][8] = 36, [1][1][2][1][RTW89_FCC][9] = 54, [1][1][2][1][RTW89_ETSI][9] = 36, [1][1][2][1][RTW89_MKK][9] = 68, @@ -30074,6 +33710,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][9] = 36, [1][1][2][1][RTW89_CN][9] = 34, [1][1][2][1][RTW89_UK][9] = 36, + [1][1][2][1][RTW89_MEXICO][9] = 54, + [1][1][2][1][RTW89_UKRAINE][9] = 36, + [1][1][2][1][RTW89_CHILE][9] = 54, + [1][1][2][1][RTW89_QATAR][9] = 36, [1][1][2][1][RTW89_FCC][10] = 46, [1][1][2][1][RTW89_ETSI][10] = 36, [1][1][2][1][RTW89_MKK][10] = 68, @@ -30082,6 +33722,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][10] = 36, [1][1][2][1][RTW89_CN][10] = 36, [1][1][2][1][RTW89_UK][10] = 36, + [1][1][2][1][RTW89_MEXICO][10] = 46, + [1][1][2][1][RTW89_UKRAINE][10] = 36, + [1][1][2][1][RTW89_CHILE][10] = 46, + [1][1][2][1][RTW89_QATAR][10] = 36, [1][1][2][1][RTW89_FCC][11] = 127, [1][1][2][1][RTW89_ETSI][11] = 127, [1][1][2][1][RTW89_MKK][11] = 127, @@ -30090,6 +33734,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][11] = 127, [1][1][2][1][RTW89_CN][11] = 127, [1][1][2][1][RTW89_UK][11] = 127, + [1][1][2][1][RTW89_MEXICO][11] = 127, + [1][1][2][1][RTW89_UKRAINE][11] = 127, + [1][1][2][1][RTW89_CHILE][11] = 127, + [1][1][2][1][RTW89_QATAR][11] = 127, [1][1][2][1][RTW89_FCC][12] = 127, [1][1][2][1][RTW89_ETSI][12] = 127, [1][1][2][1][RTW89_MKK][12] = 127, @@ -30098,6 +33746,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][12] = 127, [1][1][2][1][RTW89_CN][12] = 127, [1][1][2][1][RTW89_UK][12] = 127, + [1][1][2][1][RTW89_MEXICO][12] = 127, + [1][1][2][1][RTW89_UKRAINE][12] = 127, + [1][1][2][1][RTW89_CHILE][12] = 127, + [1][1][2][1][RTW89_QATAR][12] = 127, [1][1][2][1][RTW89_FCC][13] = 127, [1][1][2][1][RTW89_ETSI][13] = 127, [1][1][2][1][RTW89_MKK][13] = 127, @@ -30106,6 +33758,10 @@ const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][13] = 127, [1][1][2][1][RTW89_CN][13] = 127, [1][1][2][1][RTW89_UK][13] = 127, + [1][1][2][1][RTW89_MEXICO][13] = 127, + [1][1][2][1][RTW89_UKRAINE][13] = 127, + [1][1][2][1][RTW89_CHILE][13] = 127, + [1][1][2][1][RTW89_QATAR][13] = 127, }; static @@ -30120,17 +33776,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_WW][10] = 50, [0][0][1][0][RTW89_WW][12] = 50, [0][0][1][0][RTW89_WW][14] = 50, - [0][0][1][0][RTW89_WW][15] = 66, - [0][0][1][0][RTW89_WW][17] = 66, - [0][0][1][0][RTW89_WW][19] = 66, - [0][0][1][0][RTW89_WW][21] = 66, - [0][0][1][0][RTW89_WW][23] = 66, - [0][0][1][0][RTW89_WW][25] = 66, - [0][0][1][0][RTW89_WW][27] = 66, - [0][0][1][0][RTW89_WW][29] = 66, - [0][0][1][0][RTW89_WW][31] = 66, - [0][0][1][0][RTW89_WW][33] = 66, - [0][0][1][0][RTW89_WW][35] = 60, + [0][0][1][0][RTW89_WW][15] = 54, + [0][0][1][0][RTW89_WW][17] = 54, + [0][0][1][0][RTW89_WW][19] = 54, + [0][0][1][0][RTW89_WW][21] = 54, + [0][0][1][0][RTW89_WW][23] = 54, + [0][0][1][0][RTW89_WW][25] = 54, + [0][0][1][0][RTW89_WW][27] = 54, + [0][0][1][0][RTW89_WW][29] = 54, + [0][0][1][0][RTW89_WW][31] = 54, + [0][0][1][0][RTW89_WW][33] = 54, + [0][0][1][0][RTW89_WW][35] = 54, [0][0][1][0][RTW89_WW][37] = 64, [0][0][1][0][RTW89_WW][38] = 30, [0][0][1][0][RTW89_WW][40] = 30, @@ -30144,21 +33800,21 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_WW][2] = 34, [0][1][1][0][RTW89_WW][4] = 34, [0][1][1][0][RTW89_WW][6] = 36, - [0][1][1][0][RTW89_WW][8] = 46, - [0][1][1][0][RTW89_WW][10] = 46, - [0][1][1][0][RTW89_WW][12] = 46, - [0][1][1][0][RTW89_WW][14] = 46, - [0][1][1][0][RTW89_WW][15] = 54, - [0][1][1][0][RTW89_WW][17] = 54, - [0][1][1][0][RTW89_WW][19] = 54, - [0][1][1][0][RTW89_WW][21] = 54, - [0][1][1][0][RTW89_WW][23] = 54, - [0][1][1][0][RTW89_WW][25] = 54, - [0][1][1][0][RTW89_WW][27] = 54, - [0][1][1][0][RTW89_WW][29] = 54, - [0][1][1][0][RTW89_WW][31] = 54, - [0][1][1][0][RTW89_WW][33] = 54, - [0][1][1][0][RTW89_WW][35] = 52, + [0][1][1][0][RTW89_WW][8] = 42, + [0][1][1][0][RTW89_WW][10] = 42, + [0][1][1][0][RTW89_WW][12] = 42, + [0][1][1][0][RTW89_WW][14] = 42, + [0][1][1][0][RTW89_WW][15] = 42, + [0][1][1][0][RTW89_WW][17] = 42, + [0][1][1][0][RTW89_WW][19] = 42, + [0][1][1][0][RTW89_WW][21] = 42, + [0][1][1][0][RTW89_WW][23] = 42, + [0][1][1][0][RTW89_WW][25] = 42, + [0][1][1][0][RTW89_WW][27] = 42, + [0][1][1][0][RTW89_WW][29] = 42, + [0][1][1][0][RTW89_WW][31] = 42, + [0][1][1][0][RTW89_WW][33] = 42, + [0][1][1][0][RTW89_WW][35] = 42, [0][1][1][0][RTW89_WW][37] = 52, [0][1][1][0][RTW89_WW][38] = 18, [0][1][1][0][RTW89_WW][40] = 18, @@ -30176,17 +33832,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_WW][10] = 52, [0][0][2][0][RTW89_WW][12] = 52, [0][0][2][0][RTW89_WW][14] = 52, - [0][0][2][0][RTW89_WW][15] = 66, - [0][0][2][0][RTW89_WW][17] = 66, - [0][0][2][0][RTW89_WW][19] = 66, - [0][0][2][0][RTW89_WW][21] = 66, - [0][0][2][0][RTW89_WW][23] = 66, - [0][0][2][0][RTW89_WW][25] = 66, - [0][0][2][0][RTW89_WW][27] = 66, - [0][0][2][0][RTW89_WW][29] = 66, - [0][0][2][0][RTW89_WW][31] = 66, - [0][0][2][0][RTW89_WW][33] = 66, - [0][0][2][0][RTW89_WW][35] = 56, + [0][0][2][0][RTW89_WW][15] = 54, + [0][0][2][0][RTW89_WW][17] = 54, + [0][0][2][0][RTW89_WW][19] = 54, + [0][0][2][0][RTW89_WW][21] = 54, + [0][0][2][0][RTW89_WW][23] = 54, + [0][0][2][0][RTW89_WW][25] = 54, + [0][0][2][0][RTW89_WW][27] = 54, + [0][0][2][0][RTW89_WW][29] = 54, + [0][0][2][0][RTW89_WW][31] = 54, + [0][0][2][0][RTW89_WW][33] = 54, + [0][0][2][0][RTW89_WW][35] = 54, [0][0][2][0][RTW89_WW][37] = 64, [0][0][2][0][RTW89_WW][38] = 30, [0][0][2][0][RTW89_WW][40] = 30, @@ -30204,17 +33860,17 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_WW][10] = 40, [0][1][2][0][RTW89_WW][12] = 40, [0][1][2][0][RTW89_WW][14] = 40, - [0][1][2][0][RTW89_WW][15] = 54, - [0][1][2][0][RTW89_WW][17] = 54, - [0][1][2][0][RTW89_WW][19] = 54, - [0][1][2][0][RTW89_WW][21] = 54, - [0][1][2][0][RTW89_WW][23] = 54, - [0][1][2][0][RTW89_WW][25] = 54, - [0][1][2][0][RTW89_WW][27] = 54, - [0][1][2][0][RTW89_WW][29] = 54, - [0][1][2][0][RTW89_WW][31] = 54, - [0][1][2][0][RTW89_WW][33] = 54, - [0][1][2][0][RTW89_WW][35] = 46, + [0][1][2][0][RTW89_WW][15] = 42, + [0][1][2][0][RTW89_WW][17] = 42, + [0][1][2][0][RTW89_WW][19] = 42, + [0][1][2][0][RTW89_WW][21] = 42, + [0][1][2][0][RTW89_WW][23] = 42, + [0][1][2][0][RTW89_WW][25] = 42, + [0][1][2][0][RTW89_WW][27] = 42, + [0][1][2][0][RTW89_WW][29] = 42, + [0][1][2][0][RTW89_WW][31] = 42, + [0][1][2][0][RTW89_WW][33] = 42, + [0][1][2][0][RTW89_WW][35] = 42, [0][1][2][0][RTW89_WW][37] = 52, [0][1][2][0][RTW89_WW][38] = 18, [0][1][2][0][RTW89_WW][40] = 18, @@ -30224,25 +33880,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_WW][48] = 48, [0][1][2][0][RTW89_WW][50] = 50, [0][1][2][0][RTW89_WW][52] = 48, - [0][1][2][1][RTW89_WW][0] = 36, - [0][1][2][1][RTW89_WW][2] = 36, - [0][1][2][1][RTW89_WW][4] = 36, - [0][1][2][1][RTW89_WW][6] = 36, - [0][1][2][1][RTW89_WW][8] = 36, - [0][1][2][1][RTW89_WW][10] = 36, - [0][1][2][1][RTW89_WW][12] = 36, - [0][1][2][1][RTW89_WW][14] = 36, - [0][1][2][1][RTW89_WW][15] = 40, - [0][1][2][1][RTW89_WW][17] = 40, - [0][1][2][1][RTW89_WW][19] = 40, - [0][1][2][1][RTW89_WW][21] = 40, - [0][1][2][1][RTW89_WW][23] = 40, - [0][1][2][1][RTW89_WW][25] = 40, - [0][1][2][1][RTW89_WW][27] = 40, - [0][1][2][1][RTW89_WW][29] = 40, - [0][1][2][1][RTW89_WW][31] = 40, - [0][1][2][1][RTW89_WW][33] = 40, - [0][1][2][1][RTW89_WW][35] = 40, + [0][1][2][1][RTW89_WW][0] = 30, + [0][1][2][1][RTW89_WW][2] = 30, + [0][1][2][1][RTW89_WW][4] = 30, + [0][1][2][1][RTW89_WW][6] = 30, + [0][1][2][1][RTW89_WW][8] = 30, + [0][1][2][1][RTW89_WW][10] = 30, + [0][1][2][1][RTW89_WW][12] = 30, + [0][1][2][1][RTW89_WW][14] = 30, + [0][1][2][1][RTW89_WW][15] = 30, + [0][1][2][1][RTW89_WW][17] = 30, + [0][1][2][1][RTW89_WW][19] = 30, + [0][1][2][1][RTW89_WW][21] = 30, + [0][1][2][1][RTW89_WW][23] = 30, + [0][1][2][1][RTW89_WW][25] = 30, + [0][1][2][1][RTW89_WW][27] = 30, + [0][1][2][1][RTW89_WW][29] = 30, + [0][1][2][1][RTW89_WW][31] = 30, + [0][1][2][1][RTW89_WW][33] = 30, + [0][1][2][1][RTW89_WW][35] = 30, [0][1][2][1][RTW89_WW][37] = 40, [0][1][2][1][RTW89_WW][38] = 6, [0][1][2][1][RTW89_WW][40] = 6, @@ -30256,11 +33912,11 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_WW][5] = 54, [1][0][2][0][RTW89_WW][9] = 54, [1][0][2][0][RTW89_WW][13] = 52, - [1][0][2][0][RTW89_WW][16] = 56, - [1][0][2][0][RTW89_WW][20] = 56, - [1][0][2][0][RTW89_WW][24] = 56, - [1][0][2][0][RTW89_WW][28] = 66, - [1][0][2][0][RTW89_WW][32] = 62, + [1][0][2][0][RTW89_WW][16] = 54, + [1][0][2][0][RTW89_WW][20] = 54, + [1][0][2][0][RTW89_WW][24] = 54, + [1][0][2][0][RTW89_WW][28] = 54, + [1][0][2][0][RTW89_WW][32] = 54, [1][0][2][0][RTW89_WW][36] = 64, [1][0][2][0][RTW89_WW][39] = 30, [1][0][2][0][RTW89_WW][43] = 30, @@ -30270,25 +33926,25 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_WW][5] = 42, [1][1][2][0][RTW89_WW][9] = 42, [1][1][2][0][RTW89_WW][13] = 42, - [1][1][2][0][RTW89_WW][16] = 54, - [1][1][2][0][RTW89_WW][20] = 54, - [1][1][2][0][RTW89_WW][24] = 54, - [1][1][2][0][RTW89_WW][28] = 54, - [1][1][2][0][RTW89_WW][32] = 54, + [1][1][2][0][RTW89_WW][16] = 42, + [1][1][2][0][RTW89_WW][20] = 42, + [1][1][2][0][RTW89_WW][24] = 42, + [1][1][2][0][RTW89_WW][28] = 42, + [1][1][2][0][RTW89_WW][32] = 42, [1][1][2][0][RTW89_WW][36] = 52, [1][1][2][0][RTW89_WW][39] = 18, [1][1][2][0][RTW89_WW][43] = 18, [1][1][2][0][RTW89_WW][47] = 62, [1][1][2][0][RTW89_WW][51] = 60, - [1][1][2][1][RTW89_WW][1] = 40, - [1][1][2][1][RTW89_WW][5] = 40, - [1][1][2][1][RTW89_WW][9] = 40, - [1][1][2][1][RTW89_WW][13] = 40, - [1][1][2][1][RTW89_WW][16] = 40, - [1][1][2][1][RTW89_WW][20] = 40, - [1][1][2][1][RTW89_WW][24] = 40, - [1][1][2][1][RTW89_WW][28] = 40, - [1][1][2][1][RTW89_WW][32] = 40, + [1][1][2][1][RTW89_WW][1] = 30, + [1][1][2][1][RTW89_WW][5] = 30, + [1][1][2][1][RTW89_WW][9] = 30, + [1][1][2][1][RTW89_WW][13] = 30, + [1][1][2][1][RTW89_WW][16] = 30, + [1][1][2][1][RTW89_WW][20] = 30, + [1][1][2][1][RTW89_WW][24] = 30, + [1][1][2][1][RTW89_WW][28] = 30, + [1][1][2][1][RTW89_WW][32] = 30, [1][1][2][1][RTW89_WW][36] = 40, [1][1][2][1][RTW89_WW][39] = 6, [1][1][2][1][RTW89_WW][43] = 6, @@ -30296,22 +33952,22 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_WW][51] = 60, [2][0][2][0][RTW89_WW][3] = 54, [2][0][2][0][RTW89_WW][11] = 50, - [2][0][2][0][RTW89_WW][18] = 56, - [2][0][2][0][RTW89_WW][26] = 60, + [2][0][2][0][RTW89_WW][18] = 54, + [2][0][2][0][RTW89_WW][26] = 54, [2][0][2][0][RTW89_WW][34] = 60, [2][0][2][0][RTW89_WW][41] = 30, [2][0][2][0][RTW89_WW][49] = 62, - [2][1][2][0][RTW89_WW][3] = 46, + [2][1][2][0][RTW89_WW][3] = 42, [2][1][2][0][RTW89_WW][11] = 38, - [2][1][2][0][RTW89_WW][18] = 50, - [2][1][2][0][RTW89_WW][26] = 52, + [2][1][2][0][RTW89_WW][18] = 42, + [2][1][2][0][RTW89_WW][26] = 42, [2][1][2][0][RTW89_WW][34] = 52, [2][1][2][0][RTW89_WW][41] = 18, [2][1][2][0][RTW89_WW][49] = 62, - [2][1][2][1][RTW89_WW][3] = 40, - [2][1][2][1][RTW89_WW][11] = 38, - [2][1][2][1][RTW89_WW][18] = 40, - [2][1][2][1][RTW89_WW][26] = 42, + [2][1][2][1][RTW89_WW][3] = 30, + [2][1][2][1][RTW89_WW][11] = 30, + [2][1][2][1][RTW89_WW][18] = 30, + [2][1][2][1][RTW89_WW][26] = 30, [2][1][2][1][RTW89_WW][34] = 40, [2][1][2][1][RTW89_WW][41] = 6, [2][1][2][1][RTW89_WW][49] = 62, @@ -30328,34 +33984,50 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ETSI][0] = 66, [0][0][1][0][RTW89_MKK][0] = 66, [0][0][1][0][RTW89_IC][0] = 60, - [0][0][1][0][RTW89_KCC][0] = 52, + [0][0][1][0][RTW89_KCC][0] = 62, [0][0][1][0][RTW89_ACMA][0] = 66, [0][0][1][0][RTW89_CN][0] = 50, [0][0][1][0][RTW89_UK][0] = 66, + [0][0][1][0][RTW89_MEXICO][0] = 62, + [0][0][1][0][RTW89_UKRAINE][0] = 54, + [0][0][1][0][RTW89_CHILE][0] = 70, + [0][0][1][0][RTW89_QATAR][0] = 66, [0][0][1][0][RTW89_FCC][2] = 72, [0][0][1][0][RTW89_ETSI][2] = 66, [0][0][1][0][RTW89_MKK][2] = 66, [0][0][1][0][RTW89_IC][2] = 60, - [0][0][1][0][RTW89_KCC][2] = 52, + [0][0][1][0][RTW89_KCC][2] = 62, [0][0][1][0][RTW89_ACMA][2] = 66, [0][0][1][0][RTW89_CN][2] = 50, [0][0][1][0][RTW89_UK][2] = 66, + [0][0][1][0][RTW89_MEXICO][2] = 62, + [0][0][1][0][RTW89_UKRAINE][2] = 54, + [0][0][1][0][RTW89_CHILE][2] = 70, + [0][0][1][0][RTW89_QATAR][2] = 66, [0][0][1][0][RTW89_FCC][4] = 72, [0][0][1][0][RTW89_ETSI][4] = 66, [0][0][1][0][RTW89_MKK][4] = 66, [0][0][1][0][RTW89_IC][4] = 60, - [0][0][1][0][RTW89_KCC][4] = 52, + [0][0][1][0][RTW89_KCC][4] = 62, [0][0][1][0][RTW89_ACMA][4] = 66, [0][0][1][0][RTW89_CN][4] = 50, [0][0][1][0][RTW89_UK][4] = 66, + [0][0][1][0][RTW89_MEXICO][4] = 62, + [0][0][1][0][RTW89_UKRAINE][4] = 54, + [0][0][1][0][RTW89_CHILE][4] = 70, + [0][0][1][0][RTW89_QATAR][4] = 66, [0][0][1][0][RTW89_FCC][6] = 72, [0][0][1][0][RTW89_ETSI][6] = 66, [0][0][1][0][RTW89_MKK][6] = 66, [0][0][1][0][RTW89_IC][6] = 58, - [0][0][1][0][RTW89_KCC][6] = 62, + [0][0][1][0][RTW89_KCC][6] = 52, [0][0][1][0][RTW89_ACMA][6] = 66, [0][0][1][0][RTW89_CN][6] = 50, [0][0][1][0][RTW89_UK][6] = 66, + [0][0][1][0][RTW89_MEXICO][6] = 62, + [0][0][1][0][RTW89_UKRAINE][6] = 54, + [0][0][1][0][RTW89_CHILE][6] = 70, + [0][0][1][0][RTW89_QATAR][6] = 66, [0][0][1][0][RTW89_FCC][8] = 72, [0][0][1][0][RTW89_ETSI][8] = 66, [0][0][1][0][RTW89_MKK][8] = 66, @@ -30364,6 +34036,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][8] = 66, [0][0][1][0][RTW89_CN][8] = 50, [0][0][1][0][RTW89_UK][8] = 66, + [0][0][1][0][RTW89_MEXICO][8] = 72, + [0][0][1][0][RTW89_UKRAINE][8] = 54, + [0][0][1][0][RTW89_CHILE][8] = 70, + [0][0][1][0][RTW89_QATAR][8] = 66, [0][0][1][0][RTW89_FCC][10] = 72, [0][0][1][0][RTW89_ETSI][10] = 66, [0][0][1][0][RTW89_MKK][10] = 66, @@ -30372,6 +34048,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][10] = 66, [0][0][1][0][RTW89_CN][10] = 50, [0][0][1][0][RTW89_UK][10] = 66, + [0][0][1][0][RTW89_MEXICO][10] = 72, + [0][0][1][0][RTW89_UKRAINE][10] = 54, + [0][0][1][0][RTW89_CHILE][10] = 70, + [0][0][1][0][RTW89_QATAR][10] = 66, [0][0][1][0][RTW89_FCC][12] = 72, [0][0][1][0][RTW89_ETSI][12] = 66, [0][0][1][0][RTW89_MKK][12] = 66, @@ -30380,6 +34060,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][12] = 66, [0][0][1][0][RTW89_CN][12] = 50, [0][0][1][0][RTW89_UK][12] = 66, + [0][0][1][0][RTW89_MEXICO][12] = 72, + [0][0][1][0][RTW89_UKRAINE][12] = 54, + [0][0][1][0][RTW89_CHILE][12] = 70, + [0][0][1][0][RTW89_QATAR][12] = 66, [0][0][1][0][RTW89_FCC][14] = 70, [0][0][1][0][RTW89_ETSI][14] = 66, [0][0][1][0][RTW89_MKK][14] = 66, @@ -30388,6 +34072,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][14] = 66, [0][0][1][0][RTW89_CN][14] = 50, [0][0][1][0][RTW89_UK][14] = 66, + [0][0][1][0][RTW89_MEXICO][14] = 70, + [0][0][1][0][RTW89_UKRAINE][14] = 54, + [0][0][1][0][RTW89_CHILE][14] = 68, + [0][0][1][0][RTW89_QATAR][14] = 66, [0][0][1][0][RTW89_FCC][15] = 72, [0][0][1][0][RTW89_ETSI][15] = 66, [0][0][1][0][RTW89_MKK][15] = 70, @@ -30396,6 +34084,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][15] = 66, [0][0][1][0][RTW89_CN][15] = 127, [0][0][1][0][RTW89_UK][15] = 66, + [0][0][1][0][RTW89_MEXICO][15] = 72, + [0][0][1][0][RTW89_UKRAINE][15] = 54, + [0][0][1][0][RTW89_CHILE][15] = 70, + [0][0][1][0][RTW89_QATAR][15] = 66, [0][0][1][0][RTW89_FCC][17] = 72, [0][0][1][0][RTW89_ETSI][17] = 66, [0][0][1][0][RTW89_MKK][17] = 70, @@ -30404,6 +34096,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][17] = 66, [0][0][1][0][RTW89_CN][17] = 127, [0][0][1][0][RTW89_UK][17] = 66, + [0][0][1][0][RTW89_MEXICO][17] = 72, + [0][0][1][0][RTW89_UKRAINE][17] = 54, + [0][0][1][0][RTW89_CHILE][17] = 70, + [0][0][1][0][RTW89_QATAR][17] = 66, [0][0][1][0][RTW89_FCC][19] = 72, [0][0][1][0][RTW89_ETSI][19] = 66, [0][0][1][0][RTW89_MKK][19] = 70, @@ -30412,6 +34108,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][19] = 66, [0][0][1][0][RTW89_CN][19] = 127, [0][0][1][0][RTW89_UK][19] = 66, + [0][0][1][0][RTW89_MEXICO][19] = 72, + [0][0][1][0][RTW89_UKRAINE][19] = 54, + [0][0][1][0][RTW89_CHILE][19] = 70, + [0][0][1][0][RTW89_QATAR][19] = 66, [0][0][1][0][RTW89_FCC][21] = 72, [0][0][1][0][RTW89_ETSI][21] = 66, [0][0][1][0][RTW89_MKK][21] = 70, @@ -30420,6 +34120,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][21] = 66, [0][0][1][0][RTW89_CN][21] = 127, [0][0][1][0][RTW89_UK][21] = 66, + [0][0][1][0][RTW89_MEXICO][21] = 72, + [0][0][1][0][RTW89_UKRAINE][21] = 54, + [0][0][1][0][RTW89_CHILE][21] = 70, + [0][0][1][0][RTW89_QATAR][21] = 66, [0][0][1][0][RTW89_FCC][23] = 72, [0][0][1][0][RTW89_ETSI][23] = 66, [0][0][1][0][RTW89_MKK][23] = 70, @@ -30428,6 +34132,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][23] = 66, [0][0][1][0][RTW89_CN][23] = 127, [0][0][1][0][RTW89_UK][23] = 66, + [0][0][1][0][RTW89_MEXICO][23] = 72, + [0][0][1][0][RTW89_UKRAINE][23] = 54, + [0][0][1][0][RTW89_CHILE][23] = 70, + [0][0][1][0][RTW89_QATAR][23] = 66, [0][0][1][0][RTW89_FCC][25] = 72, [0][0][1][0][RTW89_ETSI][25] = 66, [0][0][1][0][RTW89_MKK][25] = 70, @@ -30436,6 +34144,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][25] = 127, [0][0][1][0][RTW89_CN][25] = 127, [0][0][1][0][RTW89_UK][25] = 66, + [0][0][1][0][RTW89_MEXICO][25] = 72, + [0][0][1][0][RTW89_UKRAINE][25] = 54, + [0][0][1][0][RTW89_CHILE][25] = 70, + [0][0][1][0][RTW89_QATAR][25] = 66, [0][0][1][0][RTW89_FCC][27] = 72, [0][0][1][0][RTW89_ETSI][27] = 66, [0][0][1][0][RTW89_MKK][27] = 70, @@ -30444,6 +34156,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][27] = 127, [0][0][1][0][RTW89_CN][27] = 127, [0][0][1][0][RTW89_UK][27] = 66, + [0][0][1][0][RTW89_MEXICO][27] = 72, + [0][0][1][0][RTW89_UKRAINE][27] = 54, + [0][0][1][0][RTW89_CHILE][27] = 58, + [0][0][1][0][RTW89_QATAR][27] = 66, [0][0][1][0][RTW89_FCC][29] = 72, [0][0][1][0][RTW89_ETSI][29] = 66, [0][0][1][0][RTW89_MKK][29] = 70, @@ -30452,6 +34168,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][29] = 127, [0][0][1][0][RTW89_CN][29] = 127, [0][0][1][0][RTW89_UK][29] = 66, + [0][0][1][0][RTW89_MEXICO][29] = 72, + [0][0][1][0][RTW89_UKRAINE][29] = 54, + [0][0][1][0][RTW89_CHILE][29] = 58, + [0][0][1][0][RTW89_QATAR][29] = 66, [0][0][1][0][RTW89_FCC][31] = 72, [0][0][1][0][RTW89_ETSI][31] = 66, [0][0][1][0][RTW89_MKK][31] = 70, @@ -30460,6 +34180,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][31] = 66, [0][0][1][0][RTW89_CN][31] = 127, [0][0][1][0][RTW89_UK][31] = 66, + [0][0][1][0][RTW89_MEXICO][31] = 72, + [0][0][1][0][RTW89_UKRAINE][31] = 54, + [0][0][1][0][RTW89_CHILE][31] = 58, + [0][0][1][0][RTW89_QATAR][31] = 66, [0][0][1][0][RTW89_FCC][33] = 72, [0][0][1][0][RTW89_ETSI][33] = 66, [0][0][1][0][RTW89_MKK][33] = 70, @@ -30468,6 +34192,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][33] = 66, [0][0][1][0][RTW89_CN][33] = 127, [0][0][1][0][RTW89_UK][33] = 66, + [0][0][1][0][RTW89_MEXICO][33] = 72, + [0][0][1][0][RTW89_UKRAINE][33] = 54, + [0][0][1][0][RTW89_CHILE][33] = 58, + [0][0][1][0][RTW89_QATAR][33] = 66, [0][0][1][0][RTW89_FCC][35] = 60, [0][0][1][0][RTW89_ETSI][35] = 66, [0][0][1][0][RTW89_MKK][35] = 70, @@ -30476,6 +34204,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][35] = 66, [0][0][1][0][RTW89_CN][35] = 127, [0][0][1][0][RTW89_UK][35] = 66, + [0][0][1][0][RTW89_MEXICO][35] = 60, + [0][0][1][0][RTW89_UKRAINE][35] = 54, + [0][0][1][0][RTW89_CHILE][35] = 58, + [0][0][1][0][RTW89_QATAR][35] = 66, [0][0][1][0][RTW89_FCC][37] = 72, [0][0][1][0][RTW89_ETSI][37] = 127, [0][0][1][0][RTW89_MKK][37] = 70, @@ -30484,6 +34216,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][37] = 70, [0][0][1][0][RTW89_CN][37] = 127, [0][0][1][0][RTW89_UK][37] = 64, + [0][0][1][0][RTW89_MEXICO][37] = 72, + [0][0][1][0][RTW89_UKRAINE][37] = 127, + [0][0][1][0][RTW89_CHILE][37] = 70, + [0][0][1][0][RTW89_QATAR][37] = 127, [0][0][1][0][RTW89_FCC][38] = 72, [0][0][1][0][RTW89_ETSI][38] = 30, [0][0][1][0][RTW89_MKK][38] = 127, @@ -30492,6 +34228,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][38] = 70, [0][0][1][0][RTW89_CN][38] = 68, [0][0][1][0][RTW89_UK][38] = 64, + [0][0][1][0][RTW89_MEXICO][38] = 72, + [0][0][1][0][RTW89_UKRAINE][38] = 30, + [0][0][1][0][RTW89_CHILE][38] = 70, + [0][0][1][0][RTW89_QATAR][38] = 30, [0][0][1][0][RTW89_FCC][40] = 72, [0][0][1][0][RTW89_ETSI][40] = 30, [0][0][1][0][RTW89_MKK][40] = 127, @@ -30500,6 +34240,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][40] = 70, [0][0][1][0][RTW89_CN][40] = 68, [0][0][1][0][RTW89_UK][40] = 64, + [0][0][1][0][RTW89_MEXICO][40] = 72, + [0][0][1][0][RTW89_UKRAINE][40] = 30, + [0][0][1][0][RTW89_CHILE][40] = 70, + [0][0][1][0][RTW89_QATAR][40] = 30, [0][0][1][0][RTW89_FCC][42] = 72, [0][0][1][0][RTW89_ETSI][42] = 30, [0][0][1][0][RTW89_MKK][42] = 127, @@ -30508,6 +34252,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][42] = 70, [0][0][1][0][RTW89_CN][42] = 68, [0][0][1][0][RTW89_UK][42] = 64, + [0][0][1][0][RTW89_MEXICO][42] = 72, + [0][0][1][0][RTW89_UKRAINE][42] = 30, + [0][0][1][0][RTW89_CHILE][42] = 70, + [0][0][1][0][RTW89_QATAR][42] = 30, [0][0][1][0][RTW89_FCC][44] = 72, [0][0][1][0][RTW89_ETSI][44] = 30, [0][0][1][0][RTW89_MKK][44] = 127, @@ -30516,6 +34264,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][44] = 70, [0][0][1][0][RTW89_CN][44] = 68, [0][0][1][0][RTW89_UK][44] = 64, + [0][0][1][0][RTW89_MEXICO][44] = 72, + [0][0][1][0][RTW89_UKRAINE][44] = 30, + [0][0][1][0][RTW89_CHILE][44] = 70, + [0][0][1][0][RTW89_QATAR][44] = 30, [0][0][1][0][RTW89_FCC][46] = 72, [0][0][1][0][RTW89_ETSI][46] = 30, [0][0][1][0][RTW89_MKK][46] = 127, @@ -30524,6 +34276,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][46] = 70, [0][0][1][0][RTW89_CN][46] = 68, [0][0][1][0][RTW89_UK][46] = 64, + [0][0][1][0][RTW89_MEXICO][46] = 72, + [0][0][1][0][RTW89_UKRAINE][46] = 30, + [0][0][1][0][RTW89_CHILE][46] = 70, + [0][0][1][0][RTW89_QATAR][46] = 30, [0][0][1][0][RTW89_FCC][48] = 72, [0][0][1][0][RTW89_ETSI][48] = 127, [0][0][1][0][RTW89_MKK][48] = 127, @@ -30532,6 +34288,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][48] = 127, [0][0][1][0][RTW89_CN][48] = 127, [0][0][1][0][RTW89_UK][48] = 127, + [0][0][1][0][RTW89_MEXICO][48] = 127, + [0][0][1][0][RTW89_UKRAINE][48] = 127, + [0][0][1][0][RTW89_CHILE][48] = 127, + [0][0][1][0][RTW89_QATAR][48] = 127, [0][0][1][0][RTW89_FCC][50] = 72, [0][0][1][0][RTW89_ETSI][50] = 127, [0][0][1][0][RTW89_MKK][50] = 127, @@ -30540,6 +34300,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][50] = 127, [0][0][1][0][RTW89_CN][50] = 127, [0][0][1][0][RTW89_UK][50] = 127, + [0][0][1][0][RTW89_MEXICO][50] = 127, + [0][0][1][0][RTW89_UKRAINE][50] = 127, + [0][0][1][0][RTW89_CHILE][50] = 127, + [0][0][1][0][RTW89_QATAR][50] = 127, [0][0][1][0][RTW89_FCC][52] = 72, [0][0][1][0][RTW89_ETSI][52] = 127, [0][0][1][0][RTW89_MKK][52] = 127, @@ -30548,38 +34312,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][1][0][RTW89_ACMA][52] = 127, [0][0][1][0][RTW89_CN][52] = 127, [0][0][1][0][RTW89_UK][52] = 127, + [0][0][1][0][RTW89_MEXICO][52] = 127, + [0][0][1][0][RTW89_UKRAINE][52] = 127, + [0][0][1][0][RTW89_CHILE][52] = 127, + [0][0][1][0][RTW89_QATAR][52] = 127, [0][1][1][0][RTW89_FCC][0] = 60, [0][1][1][0][RTW89_ETSI][0] = 54, [0][1][1][0][RTW89_MKK][0] = 54, [0][1][1][0][RTW89_IC][0] = 34, - [0][1][1][0][RTW89_KCC][0] = 40, + [0][1][1][0][RTW89_KCC][0] = 60, [0][1][1][0][RTW89_ACMA][0] = 54, [0][1][1][0][RTW89_CN][0] = 46, [0][1][1][0][RTW89_UK][0] = 54, + [0][1][1][0][RTW89_MEXICO][0] = 50, + [0][1][1][0][RTW89_UKRAINE][0] = 42, + [0][1][1][0][RTW89_CHILE][0] = 60, + [0][1][1][0][RTW89_QATAR][0] = 54, [0][1][1][0][RTW89_FCC][2] = 60, [0][1][1][0][RTW89_ETSI][2] = 54, [0][1][1][0][RTW89_MKK][2] = 54, [0][1][1][0][RTW89_IC][2] = 34, - [0][1][1][0][RTW89_KCC][2] = 40, + [0][1][1][0][RTW89_KCC][2] = 60, [0][1][1][0][RTW89_ACMA][2] = 54, [0][1][1][0][RTW89_CN][2] = 46, [0][1][1][0][RTW89_UK][2] = 54, + [0][1][1][0][RTW89_MEXICO][2] = 50, + [0][1][1][0][RTW89_UKRAINE][2] = 42, + [0][1][1][0][RTW89_CHILE][2] = 60, + [0][1][1][0][RTW89_QATAR][2] = 54, [0][1][1][0][RTW89_FCC][4] = 60, [0][1][1][0][RTW89_ETSI][4] = 54, [0][1][1][0][RTW89_MKK][4] = 54, [0][1][1][0][RTW89_IC][4] = 34, - [0][1][1][0][RTW89_KCC][4] = 40, + [0][1][1][0][RTW89_KCC][4] = 60, [0][1][1][0][RTW89_ACMA][4] = 54, [0][1][1][0][RTW89_CN][4] = 46, [0][1][1][0][RTW89_UK][4] = 54, + [0][1][1][0][RTW89_MEXICO][4] = 50, + [0][1][1][0][RTW89_UKRAINE][4] = 42, + [0][1][1][0][RTW89_CHILE][4] = 60, + [0][1][1][0][RTW89_QATAR][4] = 54, [0][1][1][0][RTW89_FCC][6] = 60, [0][1][1][0][RTW89_ETSI][6] = 54, [0][1][1][0][RTW89_MKK][6] = 54, [0][1][1][0][RTW89_IC][6] = 36, - [0][1][1][0][RTW89_KCC][6] = 60, + [0][1][1][0][RTW89_KCC][6] = 40, [0][1][1][0][RTW89_ACMA][6] = 54, [0][1][1][0][RTW89_CN][6] = 46, [0][1][1][0][RTW89_UK][6] = 54, + [0][1][1][0][RTW89_MEXICO][6] = 50, + [0][1][1][0][RTW89_UKRAINE][6] = 42, + [0][1][1][0][RTW89_CHILE][6] = 60, + [0][1][1][0][RTW89_QATAR][6] = 54, [0][1][1][0][RTW89_FCC][8] = 62, [0][1][1][0][RTW89_ETSI][8] = 54, [0][1][1][0][RTW89_MKK][8] = 52, @@ -30588,6 +34372,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][8] = 54, [0][1][1][0][RTW89_CN][8] = 46, [0][1][1][0][RTW89_UK][8] = 54, + [0][1][1][0][RTW89_MEXICO][8] = 62, + [0][1][1][0][RTW89_UKRAINE][8] = 42, + [0][1][1][0][RTW89_CHILE][8] = 62, + [0][1][1][0][RTW89_QATAR][8] = 54, [0][1][1][0][RTW89_FCC][10] = 62, [0][1][1][0][RTW89_ETSI][10] = 54, [0][1][1][0][RTW89_MKK][10] = 54, @@ -30596,6 +34384,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][10] = 54, [0][1][1][0][RTW89_CN][10] = 46, [0][1][1][0][RTW89_UK][10] = 54, + [0][1][1][0][RTW89_MEXICO][10] = 62, + [0][1][1][0][RTW89_UKRAINE][10] = 42, + [0][1][1][0][RTW89_CHILE][10] = 62, + [0][1][1][0][RTW89_QATAR][10] = 54, [0][1][1][0][RTW89_FCC][12] = 62, [0][1][1][0][RTW89_ETSI][12] = 54, [0][1][1][0][RTW89_MKK][12] = 54, @@ -30604,6 +34396,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][12] = 54, [0][1][1][0][RTW89_CN][12] = 46, [0][1][1][0][RTW89_UK][12] = 54, + [0][1][1][0][RTW89_MEXICO][12] = 62, + [0][1][1][0][RTW89_UKRAINE][12] = 42, + [0][1][1][0][RTW89_CHILE][12] = 62, + [0][1][1][0][RTW89_QATAR][12] = 54, [0][1][1][0][RTW89_FCC][14] = 60, [0][1][1][0][RTW89_ETSI][14] = 54, [0][1][1][0][RTW89_MKK][14] = 54, @@ -30612,6 +34408,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][14] = 54, [0][1][1][0][RTW89_CN][14] = 46, [0][1][1][0][RTW89_UK][14] = 54, + [0][1][1][0][RTW89_MEXICO][14] = 60, + [0][1][1][0][RTW89_UKRAINE][14] = 42, + [0][1][1][0][RTW89_CHILE][14] = 60, + [0][1][1][0][RTW89_QATAR][14] = 54, [0][1][1][0][RTW89_FCC][15] = 60, [0][1][1][0][RTW89_ETSI][15] = 54, [0][1][1][0][RTW89_MKK][15] = 70, @@ -30620,6 +34420,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][15] = 54, [0][1][1][0][RTW89_CN][15] = 127, [0][1][1][0][RTW89_UK][15] = 54, + [0][1][1][0][RTW89_MEXICO][15] = 60, + [0][1][1][0][RTW89_UKRAINE][15] = 42, + [0][1][1][0][RTW89_CHILE][15] = 60, + [0][1][1][0][RTW89_QATAR][15] = 54, [0][1][1][0][RTW89_FCC][17] = 60, [0][1][1][0][RTW89_ETSI][17] = 54, [0][1][1][0][RTW89_MKK][17] = 70, @@ -30628,6 +34432,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][17] = 54, [0][1][1][0][RTW89_CN][17] = 127, [0][1][1][0][RTW89_UK][17] = 54, + [0][1][1][0][RTW89_MEXICO][17] = 60, + [0][1][1][0][RTW89_UKRAINE][17] = 42, + [0][1][1][0][RTW89_CHILE][17] = 60, + [0][1][1][0][RTW89_QATAR][17] = 54, [0][1][1][0][RTW89_FCC][19] = 60, [0][1][1][0][RTW89_ETSI][19] = 54, [0][1][1][0][RTW89_MKK][19] = 70, @@ -30636,6 +34444,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][19] = 54, [0][1][1][0][RTW89_CN][19] = 127, [0][1][1][0][RTW89_UK][19] = 54, + [0][1][1][0][RTW89_MEXICO][19] = 60, + [0][1][1][0][RTW89_UKRAINE][19] = 42, + [0][1][1][0][RTW89_CHILE][19] = 60, + [0][1][1][0][RTW89_QATAR][19] = 54, [0][1][1][0][RTW89_FCC][21] = 60, [0][1][1][0][RTW89_ETSI][21] = 54, [0][1][1][0][RTW89_MKK][21] = 70, @@ -30644,6 +34456,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][21] = 54, [0][1][1][0][RTW89_CN][21] = 127, [0][1][1][0][RTW89_UK][21] = 54, + [0][1][1][0][RTW89_MEXICO][21] = 60, + [0][1][1][0][RTW89_UKRAINE][21] = 42, + [0][1][1][0][RTW89_CHILE][21] = 60, + [0][1][1][0][RTW89_QATAR][21] = 54, [0][1][1][0][RTW89_FCC][23] = 60, [0][1][1][0][RTW89_ETSI][23] = 54, [0][1][1][0][RTW89_MKK][23] = 70, @@ -30652,6 +34468,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][23] = 54, [0][1][1][0][RTW89_CN][23] = 127, [0][1][1][0][RTW89_UK][23] = 54, + [0][1][1][0][RTW89_MEXICO][23] = 60, + [0][1][1][0][RTW89_UKRAINE][23] = 42, + [0][1][1][0][RTW89_CHILE][23] = 60, + [0][1][1][0][RTW89_QATAR][23] = 54, [0][1][1][0][RTW89_FCC][25] = 60, [0][1][1][0][RTW89_ETSI][25] = 54, [0][1][1][0][RTW89_MKK][25] = 70, @@ -30660,6 +34480,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][25] = 127, [0][1][1][0][RTW89_CN][25] = 127, [0][1][1][0][RTW89_UK][25] = 54, + [0][1][1][0][RTW89_MEXICO][25] = 60, + [0][1][1][0][RTW89_UKRAINE][25] = 42, + [0][1][1][0][RTW89_CHILE][25] = 60, + [0][1][1][0][RTW89_QATAR][25] = 54, [0][1][1][0][RTW89_FCC][27] = 60, [0][1][1][0][RTW89_ETSI][27] = 54, [0][1][1][0][RTW89_MKK][27] = 70, @@ -30668,6 +34492,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][27] = 127, [0][1][1][0][RTW89_CN][27] = 127, [0][1][1][0][RTW89_UK][27] = 54, + [0][1][1][0][RTW89_MEXICO][27] = 60, + [0][1][1][0][RTW89_UKRAINE][27] = 42, + [0][1][1][0][RTW89_CHILE][27] = 52, + [0][1][1][0][RTW89_QATAR][27] = 54, [0][1][1][0][RTW89_FCC][29] = 60, [0][1][1][0][RTW89_ETSI][29] = 54, [0][1][1][0][RTW89_MKK][29] = 70, @@ -30676,6 +34504,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][29] = 127, [0][1][1][0][RTW89_CN][29] = 127, [0][1][1][0][RTW89_UK][29] = 54, + [0][1][1][0][RTW89_MEXICO][29] = 60, + [0][1][1][0][RTW89_UKRAINE][29] = 42, + [0][1][1][0][RTW89_CHILE][29] = 52, + [0][1][1][0][RTW89_QATAR][29] = 54, [0][1][1][0][RTW89_FCC][31] = 60, [0][1][1][0][RTW89_ETSI][31] = 54, [0][1][1][0][RTW89_MKK][31] = 70, @@ -30684,6 +34516,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][31] = 54, [0][1][1][0][RTW89_CN][31] = 127, [0][1][1][0][RTW89_UK][31] = 54, + [0][1][1][0][RTW89_MEXICO][31] = 60, + [0][1][1][0][RTW89_UKRAINE][31] = 42, + [0][1][1][0][RTW89_CHILE][31] = 52, + [0][1][1][0][RTW89_QATAR][31] = 54, [0][1][1][0][RTW89_FCC][33] = 60, [0][1][1][0][RTW89_ETSI][33] = 54, [0][1][1][0][RTW89_MKK][33] = 70, @@ -30692,6 +34528,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][33] = 54, [0][1][1][0][RTW89_CN][33] = 127, [0][1][1][0][RTW89_UK][33] = 54, + [0][1][1][0][RTW89_MEXICO][33] = 60, + [0][1][1][0][RTW89_UKRAINE][33] = 42, + [0][1][1][0][RTW89_CHILE][33] = 52, + [0][1][1][0][RTW89_QATAR][33] = 54, [0][1][1][0][RTW89_FCC][35] = 52, [0][1][1][0][RTW89_ETSI][35] = 54, [0][1][1][0][RTW89_MKK][35] = 70, @@ -30700,6 +34540,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][35] = 54, [0][1][1][0][RTW89_CN][35] = 127, [0][1][1][0][RTW89_UK][35] = 54, + [0][1][1][0][RTW89_MEXICO][35] = 52, + [0][1][1][0][RTW89_UKRAINE][35] = 42, + [0][1][1][0][RTW89_CHILE][35] = 52, + [0][1][1][0][RTW89_QATAR][35] = 54, [0][1][1][0][RTW89_FCC][37] = 62, [0][1][1][0][RTW89_ETSI][37] = 127, [0][1][1][0][RTW89_MKK][37] = 70, @@ -30708,6 +34552,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][37] = 64, [0][1][1][0][RTW89_CN][37] = 127, [0][1][1][0][RTW89_UK][37] = 52, + [0][1][1][0][RTW89_MEXICO][37] = 62, + [0][1][1][0][RTW89_UKRAINE][37] = 127, + [0][1][1][0][RTW89_CHILE][37] = 62, + [0][1][1][0][RTW89_QATAR][37] = 127, [0][1][1][0][RTW89_FCC][38] = 72, [0][1][1][0][RTW89_ETSI][38] = 18, [0][1][1][0][RTW89_MKK][38] = 127, @@ -30716,6 +34564,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][38] = 70, [0][1][1][0][RTW89_CN][38] = 64, [0][1][1][0][RTW89_UK][38] = 52, + [0][1][1][0][RTW89_MEXICO][38] = 72, + [0][1][1][0][RTW89_UKRAINE][38] = 18, + [0][1][1][0][RTW89_CHILE][38] = 70, + [0][1][1][0][RTW89_QATAR][38] = 18, [0][1][1][0][RTW89_FCC][40] = 72, [0][1][1][0][RTW89_ETSI][40] = 18, [0][1][1][0][RTW89_MKK][40] = 127, @@ -30724,6 +34576,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][40] = 70, [0][1][1][0][RTW89_CN][40] = 64, [0][1][1][0][RTW89_UK][40] = 52, + [0][1][1][0][RTW89_MEXICO][40] = 72, + [0][1][1][0][RTW89_UKRAINE][40] = 18, + [0][1][1][0][RTW89_CHILE][40] = 70, + [0][1][1][0][RTW89_QATAR][40] = 18, [0][1][1][0][RTW89_FCC][42] = 72, [0][1][1][0][RTW89_ETSI][42] = 18, [0][1][1][0][RTW89_MKK][42] = 127, @@ -30732,6 +34588,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][42] = 70, [0][1][1][0][RTW89_CN][42] = 64, [0][1][1][0][RTW89_UK][42] = 52, + [0][1][1][0][RTW89_MEXICO][42] = 72, + [0][1][1][0][RTW89_UKRAINE][42] = 18, + [0][1][1][0][RTW89_CHILE][42] = 70, + [0][1][1][0][RTW89_QATAR][42] = 18, [0][1][1][0][RTW89_FCC][44] = 72, [0][1][1][0][RTW89_ETSI][44] = 18, [0][1][1][0][RTW89_MKK][44] = 127, @@ -30740,6 +34600,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][44] = 70, [0][1][1][0][RTW89_CN][44] = 60, [0][1][1][0][RTW89_UK][44] = 52, + [0][1][1][0][RTW89_MEXICO][44] = 72, + [0][1][1][0][RTW89_UKRAINE][44] = 18, + [0][1][1][0][RTW89_CHILE][44] = 70, + [0][1][1][0][RTW89_QATAR][44] = 18, [0][1][1][0][RTW89_FCC][46] = 72, [0][1][1][0][RTW89_ETSI][46] = 18, [0][1][1][0][RTW89_MKK][46] = 127, @@ -30748,6 +34612,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][46] = 70, [0][1][1][0][RTW89_CN][46] = 60, [0][1][1][0][RTW89_UK][46] = 52, + [0][1][1][0][RTW89_MEXICO][46] = 72, + [0][1][1][0][RTW89_UKRAINE][46] = 18, + [0][1][1][0][RTW89_CHILE][46] = 70, + [0][1][1][0][RTW89_QATAR][46] = 18, [0][1][1][0][RTW89_FCC][48] = 48, [0][1][1][0][RTW89_ETSI][48] = 127, [0][1][1][0][RTW89_MKK][48] = 127, @@ -30756,6 +34624,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][48] = 127, [0][1][1][0][RTW89_CN][48] = 127, [0][1][1][0][RTW89_UK][48] = 127, + [0][1][1][0][RTW89_MEXICO][48] = 127, + [0][1][1][0][RTW89_UKRAINE][48] = 127, + [0][1][1][0][RTW89_CHILE][48] = 127, + [0][1][1][0][RTW89_QATAR][48] = 127, [0][1][1][0][RTW89_FCC][50] = 48, [0][1][1][0][RTW89_ETSI][50] = 127, [0][1][1][0][RTW89_MKK][50] = 127, @@ -30764,6 +34636,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][50] = 127, [0][1][1][0][RTW89_CN][50] = 127, [0][1][1][0][RTW89_UK][50] = 127, + [0][1][1][0][RTW89_MEXICO][50] = 127, + [0][1][1][0][RTW89_UKRAINE][50] = 127, + [0][1][1][0][RTW89_CHILE][50] = 127, + [0][1][1][0][RTW89_QATAR][50] = 127, [0][1][1][0][RTW89_FCC][52] = 48, [0][1][1][0][RTW89_ETSI][52] = 127, [0][1][1][0][RTW89_MKK][52] = 127, @@ -30772,38 +34648,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][1][0][RTW89_ACMA][52] = 127, [0][1][1][0][RTW89_CN][52] = 127, [0][1][1][0][RTW89_UK][52] = 127, + [0][1][1][0][RTW89_MEXICO][52] = 127, + [0][1][1][0][RTW89_UKRAINE][52] = 127, + [0][1][1][0][RTW89_CHILE][52] = 127, + [0][1][1][0][RTW89_QATAR][52] = 127, [0][0][2][0][RTW89_FCC][0] = 70, [0][0][2][0][RTW89_ETSI][0] = 66, [0][0][2][0][RTW89_MKK][0] = 68, [0][0][2][0][RTW89_IC][0] = 60, - [0][0][2][0][RTW89_KCC][0] = 54, + [0][0][2][0][RTW89_KCC][0] = 68, [0][0][2][0][RTW89_ACMA][0] = 66, [0][0][2][0][RTW89_CN][0] = 52, [0][0][2][0][RTW89_UK][0] = 66, + [0][0][2][0][RTW89_MEXICO][0] = 62, + [0][0][2][0][RTW89_UKRAINE][0] = 54, + [0][0][2][0][RTW89_CHILE][0] = 68, + [0][0][2][0][RTW89_QATAR][0] = 66, [0][0][2][0][RTW89_FCC][2] = 72, [0][0][2][0][RTW89_ETSI][2] = 66, [0][0][2][0][RTW89_MKK][2] = 68, [0][0][2][0][RTW89_IC][2] = 60, - [0][0][2][0][RTW89_KCC][2] = 54, + [0][0][2][0][RTW89_KCC][2] = 68, [0][0][2][0][RTW89_ACMA][2] = 66, [0][0][2][0][RTW89_CN][2] = 52, [0][0][2][0][RTW89_UK][2] = 66, + [0][0][2][0][RTW89_MEXICO][2] = 62, + [0][0][2][0][RTW89_UKRAINE][2] = 54, + [0][0][2][0][RTW89_CHILE][2] = 70, + [0][0][2][0][RTW89_QATAR][2] = 66, [0][0][2][0][RTW89_FCC][4] = 72, [0][0][2][0][RTW89_ETSI][4] = 66, [0][0][2][0][RTW89_MKK][4] = 68, [0][0][2][0][RTW89_IC][4] = 60, - [0][0][2][0][RTW89_KCC][4] = 54, + [0][0][2][0][RTW89_KCC][4] = 68, [0][0][2][0][RTW89_ACMA][4] = 66, [0][0][2][0][RTW89_CN][4] = 52, [0][0][2][0][RTW89_UK][4] = 66, + [0][0][2][0][RTW89_MEXICO][4] = 62, + [0][0][2][0][RTW89_UKRAINE][4] = 54, + [0][0][2][0][RTW89_CHILE][4] = 70, + [0][0][2][0][RTW89_QATAR][4] = 66, [0][0][2][0][RTW89_FCC][6] = 72, [0][0][2][0][RTW89_ETSI][6] = 66, [0][0][2][0][RTW89_MKK][6] = 60, [0][0][2][0][RTW89_IC][6] = 60, - [0][0][2][0][RTW89_KCC][6] = 68, + [0][0][2][0][RTW89_KCC][6] = 54, [0][0][2][0][RTW89_ACMA][6] = 66, [0][0][2][0][RTW89_CN][6] = 52, [0][0][2][0][RTW89_UK][6] = 66, + [0][0][2][0][RTW89_MEXICO][6] = 62, + [0][0][2][0][RTW89_UKRAINE][6] = 54, + [0][0][2][0][RTW89_CHILE][6] = 70, + [0][0][2][0][RTW89_QATAR][6] = 66, [0][0][2][0][RTW89_FCC][8] = 72, [0][0][2][0][RTW89_ETSI][8] = 66, [0][0][2][0][RTW89_MKK][8] = 58, @@ -30812,6 +34708,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][8] = 66, [0][0][2][0][RTW89_CN][8] = 52, [0][0][2][0][RTW89_UK][8] = 66, + [0][0][2][0][RTW89_MEXICO][8] = 72, + [0][0][2][0][RTW89_UKRAINE][8] = 54, + [0][0][2][0][RTW89_CHILE][8] = 70, + [0][0][2][0][RTW89_QATAR][8] = 66, [0][0][2][0][RTW89_FCC][10] = 72, [0][0][2][0][RTW89_ETSI][10] = 66, [0][0][2][0][RTW89_MKK][10] = 70, @@ -30820,6 +34720,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][10] = 66, [0][0][2][0][RTW89_CN][10] = 52, [0][0][2][0][RTW89_UK][10] = 66, + [0][0][2][0][RTW89_MEXICO][10] = 72, + [0][0][2][0][RTW89_UKRAINE][10] = 54, + [0][0][2][0][RTW89_CHILE][10] = 70, + [0][0][2][0][RTW89_QATAR][10] = 66, [0][0][2][0][RTW89_FCC][12] = 72, [0][0][2][0][RTW89_ETSI][12] = 66, [0][0][2][0][RTW89_MKK][12] = 70, @@ -30828,6 +34732,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][12] = 66, [0][0][2][0][RTW89_CN][12] = 52, [0][0][2][0][RTW89_UK][12] = 66, + [0][0][2][0][RTW89_MEXICO][12] = 72, + [0][0][2][0][RTW89_UKRAINE][12] = 54, + [0][0][2][0][RTW89_CHILE][12] = 70, + [0][0][2][0][RTW89_QATAR][12] = 66, [0][0][2][0][RTW89_FCC][14] = 68, [0][0][2][0][RTW89_ETSI][14] = 66, [0][0][2][0][RTW89_MKK][14] = 70, @@ -30836,6 +34744,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][14] = 66, [0][0][2][0][RTW89_CN][14] = 52, [0][0][2][0][RTW89_UK][14] = 66, + [0][0][2][0][RTW89_MEXICO][14] = 68, + [0][0][2][0][RTW89_UKRAINE][14] = 54, + [0][0][2][0][RTW89_CHILE][14] = 66, + [0][0][2][0][RTW89_QATAR][14] = 66, [0][0][2][0][RTW89_FCC][15] = 70, [0][0][2][0][RTW89_ETSI][15] = 66, [0][0][2][0][RTW89_MKK][15] = 70, @@ -30844,6 +34756,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][15] = 66, [0][0][2][0][RTW89_CN][15] = 127, [0][0][2][0][RTW89_UK][15] = 66, + [0][0][2][0][RTW89_MEXICO][15] = 70, + [0][0][2][0][RTW89_UKRAINE][15] = 54, + [0][0][2][0][RTW89_CHILE][15] = 68, + [0][0][2][0][RTW89_QATAR][15] = 66, [0][0][2][0][RTW89_FCC][17] = 72, [0][0][2][0][RTW89_ETSI][17] = 66, [0][0][2][0][RTW89_MKK][17] = 70, @@ -30852,6 +34768,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][17] = 66, [0][0][2][0][RTW89_CN][17] = 127, [0][0][2][0][RTW89_UK][17] = 66, + [0][0][2][0][RTW89_MEXICO][17] = 72, + [0][0][2][0][RTW89_UKRAINE][17] = 54, + [0][0][2][0][RTW89_CHILE][17] = 68, + [0][0][2][0][RTW89_QATAR][17] = 66, [0][0][2][0][RTW89_FCC][19] = 72, [0][0][2][0][RTW89_ETSI][19] = 66, [0][0][2][0][RTW89_MKK][19] = 70, @@ -30860,6 +34780,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][19] = 66, [0][0][2][0][RTW89_CN][19] = 127, [0][0][2][0][RTW89_UK][19] = 66, + [0][0][2][0][RTW89_MEXICO][19] = 72, + [0][0][2][0][RTW89_UKRAINE][19] = 54, + [0][0][2][0][RTW89_CHILE][19] = 68, + [0][0][2][0][RTW89_QATAR][19] = 66, [0][0][2][0][RTW89_FCC][21] = 72, [0][0][2][0][RTW89_ETSI][21] = 66, [0][0][2][0][RTW89_MKK][21] = 70, @@ -30868,6 +34792,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][21] = 66, [0][0][2][0][RTW89_CN][21] = 127, [0][0][2][0][RTW89_UK][21] = 66, + [0][0][2][0][RTW89_MEXICO][21] = 72, + [0][0][2][0][RTW89_UKRAINE][21] = 54, + [0][0][2][0][RTW89_CHILE][21] = 70, + [0][0][2][0][RTW89_QATAR][21] = 66, [0][0][2][0][RTW89_FCC][23] = 72, [0][0][2][0][RTW89_ETSI][23] = 66, [0][0][2][0][RTW89_MKK][23] = 70, @@ -30876,6 +34804,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][23] = 66, [0][0][2][0][RTW89_CN][23] = 127, [0][0][2][0][RTW89_UK][23] = 66, + [0][0][2][0][RTW89_MEXICO][23] = 72, + [0][0][2][0][RTW89_UKRAINE][23] = 54, + [0][0][2][0][RTW89_CHILE][23] = 70, + [0][0][2][0][RTW89_QATAR][23] = 66, [0][0][2][0][RTW89_FCC][25] = 72, [0][0][2][0][RTW89_ETSI][25] = 66, [0][0][2][0][RTW89_MKK][25] = 70, @@ -30884,6 +34816,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][25] = 127, [0][0][2][0][RTW89_CN][25] = 127, [0][0][2][0][RTW89_UK][25] = 66, + [0][0][2][0][RTW89_MEXICO][25] = 72, + [0][0][2][0][RTW89_UKRAINE][25] = 54, + [0][0][2][0][RTW89_CHILE][25] = 70, + [0][0][2][0][RTW89_QATAR][25] = 66, [0][0][2][0][RTW89_FCC][27] = 72, [0][0][2][0][RTW89_ETSI][27] = 66, [0][0][2][0][RTW89_MKK][27] = 70, @@ -30892,6 +34828,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][27] = 127, [0][0][2][0][RTW89_CN][27] = 127, [0][0][2][0][RTW89_UK][27] = 66, + [0][0][2][0][RTW89_MEXICO][27] = 72, + [0][0][2][0][RTW89_UKRAINE][27] = 54, + [0][0][2][0][RTW89_CHILE][27] = 56, + [0][0][2][0][RTW89_QATAR][27] = 66, [0][0][2][0][RTW89_FCC][29] = 72, [0][0][2][0][RTW89_ETSI][29] = 66, [0][0][2][0][RTW89_MKK][29] = 70, @@ -30900,6 +34840,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][29] = 127, [0][0][2][0][RTW89_CN][29] = 127, [0][0][2][0][RTW89_UK][29] = 66, + [0][0][2][0][RTW89_MEXICO][29] = 72, + [0][0][2][0][RTW89_UKRAINE][29] = 54, + [0][0][2][0][RTW89_CHILE][29] = 56, + [0][0][2][0][RTW89_QATAR][29] = 66, [0][0][2][0][RTW89_FCC][31] = 72, [0][0][2][0][RTW89_ETSI][31] = 66, [0][0][2][0][RTW89_MKK][31] = 70, @@ -30908,6 +34852,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][31] = 66, [0][0][2][0][RTW89_CN][31] = 127, [0][0][2][0][RTW89_UK][31] = 66, + [0][0][2][0][RTW89_MEXICO][31] = 72, + [0][0][2][0][RTW89_UKRAINE][31] = 54, + [0][0][2][0][RTW89_CHILE][31] = 56, + [0][0][2][0][RTW89_QATAR][31] = 66, [0][0][2][0][RTW89_FCC][33] = 72, [0][0][2][0][RTW89_ETSI][33] = 66, [0][0][2][0][RTW89_MKK][33] = 70, @@ -30916,6 +34864,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][33] = 66, [0][0][2][0][RTW89_CN][33] = 127, [0][0][2][0][RTW89_UK][33] = 66, + [0][0][2][0][RTW89_MEXICO][33] = 72, + [0][0][2][0][RTW89_UKRAINE][33] = 54, + [0][0][2][0][RTW89_CHILE][33] = 56, + [0][0][2][0][RTW89_QATAR][33] = 66, [0][0][2][0][RTW89_FCC][35] = 56, [0][0][2][0][RTW89_ETSI][35] = 66, [0][0][2][0][RTW89_MKK][35] = 70, @@ -30924,6 +34876,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][35] = 66, [0][0][2][0][RTW89_CN][35] = 127, [0][0][2][0][RTW89_UK][35] = 66, + [0][0][2][0][RTW89_MEXICO][35] = 56, + [0][0][2][0][RTW89_UKRAINE][35] = 54, + [0][0][2][0][RTW89_CHILE][35] = 56, + [0][0][2][0][RTW89_QATAR][35] = 66, [0][0][2][0][RTW89_FCC][37] = 72, [0][0][2][0][RTW89_ETSI][37] = 127, [0][0][2][0][RTW89_MKK][37] = 70, @@ -30932,6 +34888,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][37] = 70, [0][0][2][0][RTW89_CN][37] = 127, [0][0][2][0][RTW89_UK][37] = 64, + [0][0][2][0][RTW89_MEXICO][37] = 72, + [0][0][2][0][RTW89_UKRAINE][37] = 127, + [0][0][2][0][RTW89_CHILE][37] = 70, + [0][0][2][0][RTW89_QATAR][37] = 127, [0][0][2][0][RTW89_FCC][38] = 72, [0][0][2][0][RTW89_ETSI][38] = 30, [0][0][2][0][RTW89_MKK][38] = 127, @@ -30940,6 +34900,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][38] = 70, [0][0][2][0][RTW89_CN][38] = 68, [0][0][2][0][RTW89_UK][38] = 64, + [0][0][2][0][RTW89_MEXICO][38] = 72, + [0][0][2][0][RTW89_UKRAINE][38] = 30, + [0][0][2][0][RTW89_CHILE][38] = 70, + [0][0][2][0][RTW89_QATAR][38] = 30, [0][0][2][0][RTW89_FCC][40] = 72, [0][0][2][0][RTW89_ETSI][40] = 30, [0][0][2][0][RTW89_MKK][40] = 127, @@ -30948,6 +34912,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][40] = 70, [0][0][2][0][RTW89_CN][40] = 68, [0][0][2][0][RTW89_UK][40] = 64, + [0][0][2][0][RTW89_MEXICO][40] = 72, + [0][0][2][0][RTW89_UKRAINE][40] = 30, + [0][0][2][0][RTW89_CHILE][40] = 70, + [0][0][2][0][RTW89_QATAR][40] = 30, [0][0][2][0][RTW89_FCC][42] = 72, [0][0][2][0][RTW89_ETSI][42] = 30, [0][0][2][0][RTW89_MKK][42] = 127, @@ -30956,6 +34924,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][42] = 70, [0][0][2][0][RTW89_CN][42] = 68, [0][0][2][0][RTW89_UK][42] = 64, + [0][0][2][0][RTW89_MEXICO][42] = 72, + [0][0][2][0][RTW89_UKRAINE][42] = 30, + [0][0][2][0][RTW89_CHILE][42] = 70, + [0][0][2][0][RTW89_QATAR][42] = 30, [0][0][2][0][RTW89_FCC][44] = 72, [0][0][2][0][RTW89_ETSI][44] = 30, [0][0][2][0][RTW89_MKK][44] = 127, @@ -30964,6 +34936,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][44] = 70, [0][0][2][0][RTW89_CN][44] = 68, [0][0][2][0][RTW89_UK][44] = 64, + [0][0][2][0][RTW89_MEXICO][44] = 72, + [0][0][2][0][RTW89_UKRAINE][44] = 30, + [0][0][2][0][RTW89_CHILE][44] = 70, + [0][0][2][0][RTW89_QATAR][44] = 30, [0][0][2][0][RTW89_FCC][46] = 72, [0][0][2][0][RTW89_ETSI][46] = 30, [0][0][2][0][RTW89_MKK][46] = 127, @@ -30972,6 +34948,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][46] = 70, [0][0][2][0][RTW89_CN][46] = 68, [0][0][2][0][RTW89_UK][46] = 64, + [0][0][2][0][RTW89_MEXICO][46] = 72, + [0][0][2][0][RTW89_UKRAINE][46] = 30, + [0][0][2][0][RTW89_CHILE][46] = 70, + [0][0][2][0][RTW89_QATAR][46] = 30, [0][0][2][0][RTW89_FCC][48] = 72, [0][0][2][0][RTW89_ETSI][48] = 127, [0][0][2][0][RTW89_MKK][48] = 127, @@ -30980,6 +34960,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][48] = 127, [0][0][2][0][RTW89_CN][48] = 127, [0][0][2][0][RTW89_UK][48] = 127, + [0][0][2][0][RTW89_MEXICO][48] = 127, + [0][0][2][0][RTW89_UKRAINE][48] = 127, + [0][0][2][0][RTW89_CHILE][48] = 127, + [0][0][2][0][RTW89_QATAR][48] = 127, [0][0][2][0][RTW89_FCC][50] = 72, [0][0][2][0][RTW89_ETSI][50] = 127, [0][0][2][0][RTW89_MKK][50] = 127, @@ -30988,6 +34972,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][50] = 127, [0][0][2][0][RTW89_CN][50] = 127, [0][0][2][0][RTW89_UK][50] = 127, + [0][0][2][0][RTW89_MEXICO][50] = 127, + [0][0][2][0][RTW89_UKRAINE][50] = 127, + [0][0][2][0][RTW89_CHILE][50] = 127, + [0][0][2][0][RTW89_QATAR][50] = 127, [0][0][2][0][RTW89_FCC][52] = 72, [0][0][2][0][RTW89_ETSI][52] = 127, [0][0][2][0][RTW89_MKK][52] = 127, @@ -30996,38 +34984,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][0][2][0][RTW89_ACMA][52] = 127, [0][0][2][0][RTW89_CN][52] = 127, [0][0][2][0][RTW89_UK][52] = 127, + [0][0][2][0][RTW89_MEXICO][52] = 127, + [0][0][2][0][RTW89_UKRAINE][52] = 127, + [0][0][2][0][RTW89_CHILE][52] = 127, + [0][0][2][0][RTW89_QATAR][52] = 127, [0][1][2][0][RTW89_FCC][0] = 60, [0][1][2][0][RTW89_ETSI][0] = 54, [0][1][2][0][RTW89_MKK][0] = 54, [0][1][2][0][RTW89_IC][0] = 36, - [0][1][2][0][RTW89_KCC][0] = 40, + [0][1][2][0][RTW89_KCC][0] = 64, [0][1][2][0][RTW89_ACMA][0] = 54, [0][1][2][0][RTW89_CN][0] = 40, [0][1][2][0][RTW89_UK][0] = 54, + [0][1][2][0][RTW89_MEXICO][0] = 50, + [0][1][2][0][RTW89_UKRAINE][0] = 42, + [0][1][2][0][RTW89_CHILE][0] = 60, + [0][1][2][0][RTW89_QATAR][0] = 54, [0][1][2][0][RTW89_FCC][2] = 62, [0][1][2][0][RTW89_ETSI][2] = 54, [0][1][2][0][RTW89_MKK][2] = 54, [0][1][2][0][RTW89_IC][2] = 36, - [0][1][2][0][RTW89_KCC][2] = 40, + [0][1][2][0][RTW89_KCC][2] = 64, [0][1][2][0][RTW89_ACMA][2] = 54, [0][1][2][0][RTW89_CN][2] = 40, [0][1][2][0][RTW89_UK][2] = 54, + [0][1][2][0][RTW89_MEXICO][2] = 50, + [0][1][2][0][RTW89_UKRAINE][2] = 42, + [0][1][2][0][RTW89_CHILE][2] = 62, + [0][1][2][0][RTW89_QATAR][2] = 54, [0][1][2][0][RTW89_FCC][4] = 62, [0][1][2][0][RTW89_ETSI][4] = 54, [0][1][2][0][RTW89_MKK][4] = 54, [0][1][2][0][RTW89_IC][4] = 36, - [0][1][2][0][RTW89_KCC][4] = 40, + [0][1][2][0][RTW89_KCC][4] = 64, [0][1][2][0][RTW89_ACMA][4] = 54, [0][1][2][0][RTW89_CN][4] = 40, [0][1][2][0][RTW89_UK][4] = 54, + [0][1][2][0][RTW89_MEXICO][4] = 50, + [0][1][2][0][RTW89_UKRAINE][4] = 42, + [0][1][2][0][RTW89_CHILE][4] = 62, + [0][1][2][0][RTW89_QATAR][4] = 54, [0][1][2][0][RTW89_FCC][6] = 62, [0][1][2][0][RTW89_ETSI][6] = 54, [0][1][2][0][RTW89_MKK][6] = 50, [0][1][2][0][RTW89_IC][6] = 38, - [0][1][2][0][RTW89_KCC][6] = 64, + [0][1][2][0][RTW89_KCC][6] = 40, [0][1][2][0][RTW89_ACMA][6] = 54, [0][1][2][0][RTW89_CN][6] = 40, [0][1][2][0][RTW89_UK][6] = 54, + [0][1][2][0][RTW89_MEXICO][6] = 50, + [0][1][2][0][RTW89_UKRAINE][6] = 42, + [0][1][2][0][RTW89_CHILE][6] = 62, + [0][1][2][0][RTW89_QATAR][6] = 54, [0][1][2][0][RTW89_FCC][8] = 62, [0][1][2][0][RTW89_ETSI][8] = 54, [0][1][2][0][RTW89_MKK][8] = 42, @@ -31036,6 +35044,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][8] = 54, [0][1][2][0][RTW89_CN][8] = 40, [0][1][2][0][RTW89_UK][8] = 54, + [0][1][2][0][RTW89_MEXICO][8] = 62, + [0][1][2][0][RTW89_UKRAINE][8] = 42, + [0][1][2][0][RTW89_CHILE][8] = 62, + [0][1][2][0][RTW89_QATAR][8] = 54, [0][1][2][0][RTW89_FCC][10] = 62, [0][1][2][0][RTW89_ETSI][10] = 54, [0][1][2][0][RTW89_MKK][10] = 54, @@ -31044,6 +35056,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][10] = 54, [0][1][2][0][RTW89_CN][10] = 40, [0][1][2][0][RTW89_UK][10] = 54, + [0][1][2][0][RTW89_MEXICO][10] = 62, + [0][1][2][0][RTW89_UKRAINE][10] = 42, + [0][1][2][0][RTW89_CHILE][10] = 62, + [0][1][2][0][RTW89_QATAR][10] = 54, [0][1][2][0][RTW89_FCC][12] = 62, [0][1][2][0][RTW89_ETSI][12] = 54, [0][1][2][0][RTW89_MKK][12] = 54, @@ -31052,6 +35068,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][12] = 54, [0][1][2][0][RTW89_CN][12] = 40, [0][1][2][0][RTW89_UK][12] = 54, + [0][1][2][0][RTW89_MEXICO][12] = 62, + [0][1][2][0][RTW89_UKRAINE][12] = 42, + [0][1][2][0][RTW89_CHILE][12] = 62, + [0][1][2][0][RTW89_QATAR][12] = 54, [0][1][2][0][RTW89_FCC][14] = 62, [0][1][2][0][RTW89_ETSI][14] = 54, [0][1][2][0][RTW89_MKK][14] = 54, @@ -31060,6 +35080,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][14] = 54, [0][1][2][0][RTW89_CN][14] = 40, [0][1][2][0][RTW89_UK][14] = 54, + [0][1][2][0][RTW89_MEXICO][14] = 62, + [0][1][2][0][RTW89_UKRAINE][14] = 42, + [0][1][2][0][RTW89_CHILE][14] = 62, + [0][1][2][0][RTW89_QATAR][14] = 54, [0][1][2][0][RTW89_FCC][15] = 60, [0][1][2][0][RTW89_ETSI][15] = 54, [0][1][2][0][RTW89_MKK][15] = 68, @@ -31068,6 +35092,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][15] = 54, [0][1][2][0][RTW89_CN][15] = 127, [0][1][2][0][RTW89_UK][15] = 54, + [0][1][2][0][RTW89_MEXICO][15] = 60, + [0][1][2][0][RTW89_UKRAINE][15] = 42, + [0][1][2][0][RTW89_CHILE][15] = 60, + [0][1][2][0][RTW89_QATAR][15] = 54, [0][1][2][0][RTW89_FCC][17] = 62, [0][1][2][0][RTW89_ETSI][17] = 54, [0][1][2][0][RTW89_MKK][17] = 68, @@ -31076,6 +35104,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][17] = 54, [0][1][2][0][RTW89_CN][17] = 127, [0][1][2][0][RTW89_UK][17] = 54, + [0][1][2][0][RTW89_MEXICO][17] = 62, + [0][1][2][0][RTW89_UKRAINE][17] = 42, + [0][1][2][0][RTW89_CHILE][17] = 60, + [0][1][2][0][RTW89_QATAR][17] = 54, [0][1][2][0][RTW89_FCC][19] = 62, [0][1][2][0][RTW89_ETSI][19] = 54, [0][1][2][0][RTW89_MKK][19] = 68, @@ -31084,6 +35116,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][19] = 54, [0][1][2][0][RTW89_CN][19] = 127, [0][1][2][0][RTW89_UK][19] = 54, + [0][1][2][0][RTW89_MEXICO][19] = 62, + [0][1][2][0][RTW89_UKRAINE][19] = 42, + [0][1][2][0][RTW89_CHILE][19] = 62, + [0][1][2][0][RTW89_QATAR][19] = 54, [0][1][2][0][RTW89_FCC][21] = 62, [0][1][2][0][RTW89_ETSI][21] = 54, [0][1][2][0][RTW89_MKK][21] = 68, @@ -31092,6 +35128,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][21] = 54, [0][1][2][0][RTW89_CN][21] = 127, [0][1][2][0][RTW89_UK][21] = 54, + [0][1][2][0][RTW89_MEXICO][21] = 62, + [0][1][2][0][RTW89_UKRAINE][21] = 42, + [0][1][2][0][RTW89_CHILE][21] = 62, + [0][1][2][0][RTW89_QATAR][21] = 54, [0][1][2][0][RTW89_FCC][23] = 62, [0][1][2][0][RTW89_ETSI][23] = 54, [0][1][2][0][RTW89_MKK][23] = 68, @@ -31100,6 +35140,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][23] = 54, [0][1][2][0][RTW89_CN][23] = 127, [0][1][2][0][RTW89_UK][23] = 54, + [0][1][2][0][RTW89_MEXICO][23] = 62, + [0][1][2][0][RTW89_UKRAINE][23] = 42, + [0][1][2][0][RTW89_CHILE][23] = 62, + [0][1][2][0][RTW89_QATAR][23] = 54, [0][1][2][0][RTW89_FCC][25] = 62, [0][1][2][0][RTW89_ETSI][25] = 54, [0][1][2][0][RTW89_MKK][25] = 68, @@ -31108,6 +35152,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][25] = 127, [0][1][2][0][RTW89_CN][25] = 127, [0][1][2][0][RTW89_UK][25] = 54, + [0][1][2][0][RTW89_MEXICO][25] = 62, + [0][1][2][0][RTW89_UKRAINE][25] = 42, + [0][1][2][0][RTW89_CHILE][25] = 62, + [0][1][2][0][RTW89_QATAR][25] = 54, [0][1][2][0][RTW89_FCC][27] = 62, [0][1][2][0][RTW89_ETSI][27] = 54, [0][1][2][0][RTW89_MKK][27] = 68, @@ -31116,6 +35164,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][27] = 127, [0][1][2][0][RTW89_CN][27] = 127, [0][1][2][0][RTW89_UK][27] = 54, + [0][1][2][0][RTW89_MEXICO][27] = 62, + [0][1][2][0][RTW89_UKRAINE][27] = 42, + [0][1][2][0][RTW89_CHILE][27] = 46, + [0][1][2][0][RTW89_QATAR][27] = 54, [0][1][2][0][RTW89_FCC][29] = 62, [0][1][2][0][RTW89_ETSI][29] = 54, [0][1][2][0][RTW89_MKK][29] = 68, @@ -31124,6 +35176,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][29] = 127, [0][1][2][0][RTW89_CN][29] = 127, [0][1][2][0][RTW89_UK][29] = 54, + [0][1][2][0][RTW89_MEXICO][29] = 62, + [0][1][2][0][RTW89_UKRAINE][29] = 42, + [0][1][2][0][RTW89_CHILE][29] = 46, + [0][1][2][0][RTW89_QATAR][29] = 54, [0][1][2][0][RTW89_FCC][31] = 62, [0][1][2][0][RTW89_ETSI][31] = 54, [0][1][2][0][RTW89_MKK][31] = 68, @@ -31132,6 +35188,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][31] = 54, [0][1][2][0][RTW89_CN][31] = 127, [0][1][2][0][RTW89_UK][31] = 54, + [0][1][2][0][RTW89_MEXICO][31] = 62, + [0][1][2][0][RTW89_UKRAINE][31] = 42, + [0][1][2][0][RTW89_CHILE][31] = 46, + [0][1][2][0][RTW89_QATAR][31] = 54, [0][1][2][0][RTW89_FCC][33] = 62, [0][1][2][0][RTW89_ETSI][33] = 54, [0][1][2][0][RTW89_MKK][33] = 68, @@ -31140,6 +35200,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][33] = 54, [0][1][2][0][RTW89_CN][33] = 127, [0][1][2][0][RTW89_UK][33] = 54, + [0][1][2][0][RTW89_MEXICO][33] = 62, + [0][1][2][0][RTW89_UKRAINE][33] = 42, + [0][1][2][0][RTW89_CHILE][33] = 46, + [0][1][2][0][RTW89_QATAR][33] = 54, [0][1][2][0][RTW89_FCC][35] = 46, [0][1][2][0][RTW89_ETSI][35] = 54, [0][1][2][0][RTW89_MKK][35] = 68, @@ -31148,6 +35212,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][35] = 54, [0][1][2][0][RTW89_CN][35] = 127, [0][1][2][0][RTW89_UK][35] = 54, + [0][1][2][0][RTW89_MEXICO][35] = 46, + [0][1][2][0][RTW89_UKRAINE][35] = 42, + [0][1][2][0][RTW89_CHILE][35] = 46, + [0][1][2][0][RTW89_QATAR][35] = 54, [0][1][2][0][RTW89_FCC][37] = 64, [0][1][2][0][RTW89_ETSI][37] = 127, [0][1][2][0][RTW89_MKK][37] = 68, @@ -31156,6 +35224,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][37] = 64, [0][1][2][0][RTW89_CN][37] = 127, [0][1][2][0][RTW89_UK][37] = 52, + [0][1][2][0][RTW89_MEXICO][37] = 64, + [0][1][2][0][RTW89_UKRAINE][37] = 127, + [0][1][2][0][RTW89_CHILE][37] = 64, + [0][1][2][0][RTW89_QATAR][37] = 127, [0][1][2][0][RTW89_FCC][38] = 72, [0][1][2][0][RTW89_ETSI][38] = 18, [0][1][2][0][RTW89_MKK][38] = 127, @@ -31164,6 +35236,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][38] = 70, [0][1][2][0][RTW89_CN][38] = 68, [0][1][2][0][RTW89_UK][38] = 52, + [0][1][2][0][RTW89_MEXICO][38] = 72, + [0][1][2][0][RTW89_UKRAINE][38] = 18, + [0][1][2][0][RTW89_CHILE][38] = 70, + [0][1][2][0][RTW89_QATAR][38] = 18, [0][1][2][0][RTW89_FCC][40] = 72, [0][1][2][0][RTW89_ETSI][40] = 18, [0][1][2][0][RTW89_MKK][40] = 127, @@ -31172,6 +35248,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][40] = 70, [0][1][2][0][RTW89_CN][40] = 68, [0][1][2][0][RTW89_UK][40] = 52, + [0][1][2][0][RTW89_MEXICO][40] = 72, + [0][1][2][0][RTW89_UKRAINE][40] = 18, + [0][1][2][0][RTW89_CHILE][40] = 70, + [0][1][2][0][RTW89_QATAR][40] = 18, [0][1][2][0][RTW89_FCC][42] = 72, [0][1][2][0][RTW89_ETSI][42] = 18, [0][1][2][0][RTW89_MKK][42] = 127, @@ -31180,6 +35260,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][42] = 70, [0][1][2][0][RTW89_CN][42] = 68, [0][1][2][0][RTW89_UK][42] = 52, + [0][1][2][0][RTW89_MEXICO][42] = 72, + [0][1][2][0][RTW89_UKRAINE][42] = 18, + [0][1][2][0][RTW89_CHILE][42] = 70, + [0][1][2][0][RTW89_QATAR][42] = 18, [0][1][2][0][RTW89_FCC][44] = 72, [0][1][2][0][RTW89_ETSI][44] = 18, [0][1][2][0][RTW89_MKK][44] = 127, @@ -31188,6 +35272,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][44] = 70, [0][1][2][0][RTW89_CN][44] = 68, [0][1][2][0][RTW89_UK][44] = 52, + [0][1][2][0][RTW89_MEXICO][44] = 72, + [0][1][2][0][RTW89_UKRAINE][44] = 18, + [0][1][2][0][RTW89_CHILE][44] = 70, + [0][1][2][0][RTW89_QATAR][44] = 18, [0][1][2][0][RTW89_FCC][46] = 72, [0][1][2][0][RTW89_ETSI][46] = 18, [0][1][2][0][RTW89_MKK][46] = 127, @@ -31196,6 +35284,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][46] = 70, [0][1][2][0][RTW89_CN][46] = 68, [0][1][2][0][RTW89_UK][46] = 52, + [0][1][2][0][RTW89_MEXICO][46] = 72, + [0][1][2][0][RTW89_UKRAINE][46] = 18, + [0][1][2][0][RTW89_CHILE][46] = 70, + [0][1][2][0][RTW89_QATAR][46] = 18, [0][1][2][0][RTW89_FCC][48] = 48, [0][1][2][0][RTW89_ETSI][48] = 127, [0][1][2][0][RTW89_MKK][48] = 127, @@ -31204,6 +35296,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][48] = 127, [0][1][2][0][RTW89_CN][48] = 127, [0][1][2][0][RTW89_UK][48] = 127, + [0][1][2][0][RTW89_MEXICO][48] = 127, + [0][1][2][0][RTW89_UKRAINE][48] = 127, + [0][1][2][0][RTW89_CHILE][48] = 127, + [0][1][2][0][RTW89_QATAR][48] = 127, [0][1][2][0][RTW89_FCC][50] = 50, [0][1][2][0][RTW89_ETSI][50] = 127, [0][1][2][0][RTW89_MKK][50] = 127, @@ -31212,6 +35308,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][50] = 127, [0][1][2][0][RTW89_CN][50] = 127, [0][1][2][0][RTW89_UK][50] = 127, + [0][1][2][0][RTW89_MEXICO][50] = 127, + [0][1][2][0][RTW89_UKRAINE][50] = 127, + [0][1][2][0][RTW89_CHILE][50] = 127, + [0][1][2][0][RTW89_QATAR][50] = 127, [0][1][2][0][RTW89_FCC][52] = 48, [0][1][2][0][RTW89_ETSI][52] = 127, [0][1][2][0][RTW89_MKK][52] = 127, @@ -31220,38 +35320,58 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][0][RTW89_ACMA][52] = 127, [0][1][2][0][RTW89_CN][52] = 127, [0][1][2][0][RTW89_UK][52] = 127, + [0][1][2][0][RTW89_MEXICO][52] = 127, + [0][1][2][0][RTW89_UKRAINE][52] = 127, + [0][1][2][0][RTW89_CHILE][52] = 127, + [0][1][2][0][RTW89_QATAR][52] = 127, [0][1][2][1][RTW89_FCC][0] = 60, [0][1][2][1][RTW89_ETSI][0] = 40, [0][1][2][1][RTW89_MKK][0] = 54, [0][1][2][1][RTW89_IC][0] = 40, - [0][1][2][1][RTW89_KCC][0] = 40, + [0][1][2][1][RTW89_KCC][0] = 64, [0][1][2][1][RTW89_ACMA][0] = 40, [0][1][2][1][RTW89_CN][0] = 36, [0][1][2][1][RTW89_UK][0] = 40, + [0][1][2][1][RTW89_MEXICO][0] = 50, + [0][1][2][1][RTW89_UKRAINE][0] = 30, + [0][1][2][1][RTW89_CHILE][0] = 60, + [0][1][2][1][RTW89_QATAR][0] = 40, [0][1][2][1][RTW89_FCC][2] = 62, [0][1][2][1][RTW89_ETSI][2] = 40, [0][1][2][1][RTW89_MKK][2] = 54, [0][1][2][1][RTW89_IC][2] = 40, - [0][1][2][1][RTW89_KCC][2] = 40, + [0][1][2][1][RTW89_KCC][2] = 64, [0][1][2][1][RTW89_ACMA][2] = 40, [0][1][2][1][RTW89_CN][2] = 36, [0][1][2][1][RTW89_UK][2] = 40, + [0][1][2][1][RTW89_MEXICO][2] = 50, + [0][1][2][1][RTW89_UKRAINE][2] = 30, + [0][1][2][1][RTW89_CHILE][2] = 60, + [0][1][2][1][RTW89_QATAR][2] = 40, [0][1][2][1][RTW89_FCC][4] = 62, [0][1][2][1][RTW89_ETSI][4] = 40, [0][1][2][1][RTW89_MKK][4] = 54, [0][1][2][1][RTW89_IC][4] = 40, - [0][1][2][1][RTW89_KCC][4] = 40, + [0][1][2][1][RTW89_KCC][4] = 64, [0][1][2][1][RTW89_ACMA][4] = 40, [0][1][2][1][RTW89_CN][4] = 36, [0][1][2][1][RTW89_UK][4] = 40, + [0][1][2][1][RTW89_MEXICO][4] = 50, + [0][1][2][1][RTW89_UKRAINE][4] = 30, + [0][1][2][1][RTW89_CHILE][4] = 60, + [0][1][2][1][RTW89_QATAR][4] = 40, [0][1][2][1][RTW89_FCC][6] = 62, [0][1][2][1][RTW89_ETSI][6] = 40, [0][1][2][1][RTW89_MKK][6] = 50, [0][1][2][1][RTW89_IC][6] = 40, - [0][1][2][1][RTW89_KCC][6] = 64, + [0][1][2][1][RTW89_KCC][6] = 40, [0][1][2][1][RTW89_ACMA][6] = 40, [0][1][2][1][RTW89_CN][6] = 36, [0][1][2][1][RTW89_UK][6] = 40, + [0][1][2][1][RTW89_MEXICO][6] = 50, + [0][1][2][1][RTW89_UKRAINE][6] = 30, + [0][1][2][1][RTW89_CHILE][6] = 60, + [0][1][2][1][RTW89_QATAR][6] = 40, [0][1][2][1][RTW89_FCC][8] = 62, [0][1][2][1][RTW89_ETSI][8] = 40, [0][1][2][1][RTW89_MKK][8] = 42, @@ -31260,6 +35380,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][8] = 40, [0][1][2][1][RTW89_CN][8] = 36, [0][1][2][1][RTW89_UK][8] = 40, + [0][1][2][1][RTW89_MEXICO][8] = 62, + [0][1][2][1][RTW89_UKRAINE][8] = 30, + [0][1][2][1][RTW89_CHILE][8] = 60, + [0][1][2][1][RTW89_QATAR][8] = 40, [0][1][2][1][RTW89_FCC][10] = 62, [0][1][2][1][RTW89_ETSI][10] = 40, [0][1][2][1][RTW89_MKK][10] = 54, @@ -31268,6 +35392,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][10] = 40, [0][1][2][1][RTW89_CN][10] = 36, [0][1][2][1][RTW89_UK][10] = 40, + [0][1][2][1][RTW89_MEXICO][10] = 62, + [0][1][2][1][RTW89_UKRAINE][10] = 30, + [0][1][2][1][RTW89_CHILE][10] = 60, + [0][1][2][1][RTW89_QATAR][10] = 40, [0][1][2][1][RTW89_FCC][12] = 62, [0][1][2][1][RTW89_ETSI][12] = 40, [0][1][2][1][RTW89_MKK][12] = 54, @@ -31276,6 +35404,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][12] = 40, [0][1][2][1][RTW89_CN][12] = 36, [0][1][2][1][RTW89_UK][12] = 40, + [0][1][2][1][RTW89_MEXICO][12] = 62, + [0][1][2][1][RTW89_UKRAINE][12] = 30, + [0][1][2][1][RTW89_CHILE][12] = 60, + [0][1][2][1][RTW89_QATAR][12] = 40, [0][1][2][1][RTW89_FCC][14] = 62, [0][1][2][1][RTW89_ETSI][14] = 40, [0][1][2][1][RTW89_MKK][14] = 54, @@ -31284,6 +35416,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][14] = 40, [0][1][2][1][RTW89_CN][14] = 36, [0][1][2][1][RTW89_UK][14] = 40, + [0][1][2][1][RTW89_MEXICO][14] = 62, + [0][1][2][1][RTW89_UKRAINE][14] = 30, + [0][1][2][1][RTW89_CHILE][14] = 60, + [0][1][2][1][RTW89_QATAR][14] = 40, [0][1][2][1][RTW89_FCC][15] = 60, [0][1][2][1][RTW89_ETSI][15] = 40, [0][1][2][1][RTW89_MKK][15] = 68, @@ -31292,6 +35428,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][15] = 40, [0][1][2][1][RTW89_CN][15] = 127, [0][1][2][1][RTW89_UK][15] = 40, + [0][1][2][1][RTW89_MEXICO][15] = 60, + [0][1][2][1][RTW89_UKRAINE][15] = 30, + [0][1][2][1][RTW89_CHILE][15] = 60, + [0][1][2][1][RTW89_QATAR][15] = 40, [0][1][2][1][RTW89_FCC][17] = 62, [0][1][2][1][RTW89_ETSI][17] = 40, [0][1][2][1][RTW89_MKK][17] = 68, @@ -31300,6 +35440,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][17] = 40, [0][1][2][1][RTW89_CN][17] = 127, [0][1][2][1][RTW89_UK][17] = 40, + [0][1][2][1][RTW89_MEXICO][17] = 62, + [0][1][2][1][RTW89_UKRAINE][17] = 30, + [0][1][2][1][RTW89_CHILE][17] = 60, + [0][1][2][1][RTW89_QATAR][17] = 40, [0][1][2][1][RTW89_FCC][19] = 62, [0][1][2][1][RTW89_ETSI][19] = 40, [0][1][2][1][RTW89_MKK][19] = 68, @@ -31308,6 +35452,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][19] = 40, [0][1][2][1][RTW89_CN][19] = 127, [0][1][2][1][RTW89_UK][19] = 40, + [0][1][2][1][RTW89_MEXICO][19] = 62, + [0][1][2][1][RTW89_UKRAINE][19] = 30, + [0][1][2][1][RTW89_CHILE][19] = 60, + [0][1][2][1][RTW89_QATAR][19] = 40, [0][1][2][1][RTW89_FCC][21] = 62, [0][1][2][1][RTW89_ETSI][21] = 40, [0][1][2][1][RTW89_MKK][21] = 68, @@ -31316,6 +35464,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][21] = 40, [0][1][2][1][RTW89_CN][21] = 127, [0][1][2][1][RTW89_UK][21] = 40, + [0][1][2][1][RTW89_MEXICO][21] = 62, + [0][1][2][1][RTW89_UKRAINE][21] = 30, + [0][1][2][1][RTW89_CHILE][21] = 60, + [0][1][2][1][RTW89_QATAR][21] = 40, [0][1][2][1][RTW89_FCC][23] = 62, [0][1][2][1][RTW89_ETSI][23] = 40, [0][1][2][1][RTW89_MKK][23] = 68, @@ -31324,6 +35476,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][23] = 40, [0][1][2][1][RTW89_CN][23] = 127, [0][1][2][1][RTW89_UK][23] = 40, + [0][1][2][1][RTW89_MEXICO][23] = 62, + [0][1][2][1][RTW89_UKRAINE][23] = 30, + [0][1][2][1][RTW89_CHILE][23] = 60, + [0][1][2][1][RTW89_QATAR][23] = 40, [0][1][2][1][RTW89_FCC][25] = 46, [0][1][2][1][RTW89_ETSI][25] = 40, [0][1][2][1][RTW89_MKK][25] = 68, @@ -31332,6 +35488,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][25] = 127, [0][1][2][1][RTW89_CN][25] = 127, [0][1][2][1][RTW89_UK][25] = 40, + [0][1][2][1][RTW89_MEXICO][25] = 46, + [0][1][2][1][RTW89_UKRAINE][25] = 30, + [0][1][2][1][RTW89_CHILE][25] = 60, + [0][1][2][1][RTW89_QATAR][25] = 40, [0][1][2][1][RTW89_FCC][27] = 46, [0][1][2][1][RTW89_ETSI][27] = 40, [0][1][2][1][RTW89_MKK][27] = 68, @@ -31340,6 +35500,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][27] = 127, [0][1][2][1][RTW89_CN][27] = 127, [0][1][2][1][RTW89_UK][27] = 40, + [0][1][2][1][RTW89_MEXICO][27] = 46, + [0][1][2][1][RTW89_UKRAINE][27] = 30, + [0][1][2][1][RTW89_CHILE][27] = 46, + [0][1][2][1][RTW89_QATAR][27] = 40, [0][1][2][1][RTW89_FCC][29] = 46, [0][1][2][1][RTW89_ETSI][29] = 40, [0][1][2][1][RTW89_MKK][29] = 68, @@ -31348,6 +35512,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][29] = 127, [0][1][2][1][RTW89_CN][29] = 127, [0][1][2][1][RTW89_UK][29] = 40, + [0][1][2][1][RTW89_MEXICO][29] = 46, + [0][1][2][1][RTW89_UKRAINE][29] = 30, + [0][1][2][1][RTW89_CHILE][29] = 46, + [0][1][2][1][RTW89_QATAR][29] = 40, [0][1][2][1][RTW89_FCC][31] = 46, [0][1][2][1][RTW89_ETSI][31] = 40, [0][1][2][1][RTW89_MKK][31] = 68, @@ -31356,6 +35524,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][31] = 40, [0][1][2][1][RTW89_CN][31] = 127, [0][1][2][1][RTW89_UK][31] = 40, + [0][1][2][1][RTW89_MEXICO][31] = 46, + [0][1][2][1][RTW89_UKRAINE][31] = 30, + [0][1][2][1][RTW89_CHILE][31] = 46, + [0][1][2][1][RTW89_QATAR][31] = 40, [0][1][2][1][RTW89_FCC][33] = 46, [0][1][2][1][RTW89_ETSI][33] = 40, [0][1][2][1][RTW89_MKK][33] = 68, @@ -31364,6 +35536,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][33] = 40, [0][1][2][1][RTW89_CN][33] = 127, [0][1][2][1][RTW89_UK][33] = 40, + [0][1][2][1][RTW89_MEXICO][33] = 46, + [0][1][2][1][RTW89_UKRAINE][33] = 30, + [0][1][2][1][RTW89_CHILE][33] = 46, + [0][1][2][1][RTW89_QATAR][33] = 40, [0][1][2][1][RTW89_FCC][35] = 46, [0][1][2][1][RTW89_ETSI][35] = 40, [0][1][2][1][RTW89_MKK][35] = 68, @@ -31372,6 +35548,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][35] = 40, [0][1][2][1][RTW89_CN][35] = 127, [0][1][2][1][RTW89_UK][35] = 40, + [0][1][2][1][RTW89_MEXICO][35] = 46, + [0][1][2][1][RTW89_UKRAINE][35] = 30, + [0][1][2][1][RTW89_CHILE][35] = 46, + [0][1][2][1][RTW89_QATAR][35] = 40, [0][1][2][1][RTW89_FCC][37] = 64, [0][1][2][1][RTW89_ETSI][37] = 127, [0][1][2][1][RTW89_MKK][37] = 68, @@ -31380,6 +35560,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][37] = 64, [0][1][2][1][RTW89_CN][37] = 127, [0][1][2][1][RTW89_UK][37] = 40, + [0][1][2][1][RTW89_MEXICO][37] = 64, + [0][1][2][1][RTW89_UKRAINE][37] = 127, + [0][1][2][1][RTW89_CHILE][37] = 64, + [0][1][2][1][RTW89_QATAR][37] = 127, [0][1][2][1][RTW89_FCC][38] = 72, [0][1][2][1][RTW89_ETSI][38] = 6, [0][1][2][1][RTW89_MKK][38] = 127, @@ -31388,6 +35572,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][38] = 70, [0][1][2][1][RTW89_CN][38] = 60, [0][1][2][1][RTW89_UK][38] = 40, + [0][1][2][1][RTW89_MEXICO][38] = 72, + [0][1][2][1][RTW89_UKRAINE][38] = 6, + [0][1][2][1][RTW89_CHILE][38] = 60, + [0][1][2][1][RTW89_QATAR][38] = 6, [0][1][2][1][RTW89_FCC][40] = 72, [0][1][2][1][RTW89_ETSI][40] = 6, [0][1][2][1][RTW89_MKK][40] = 127, @@ -31396,6 +35584,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][40] = 70, [0][1][2][1][RTW89_CN][40] = 60, [0][1][2][1][RTW89_UK][40] = 40, + [0][1][2][1][RTW89_MEXICO][40] = 72, + [0][1][2][1][RTW89_UKRAINE][40] = 6, + [0][1][2][1][RTW89_CHILE][40] = 60, + [0][1][2][1][RTW89_QATAR][40] = 6, [0][1][2][1][RTW89_FCC][42] = 72, [0][1][2][1][RTW89_ETSI][42] = 6, [0][1][2][1][RTW89_MKK][42] = 127, @@ -31404,6 +35596,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][42] = 70, [0][1][2][1][RTW89_CN][42] = 60, [0][1][2][1][RTW89_UK][42] = 40, + [0][1][2][1][RTW89_MEXICO][42] = 72, + [0][1][2][1][RTW89_UKRAINE][42] = 6, + [0][1][2][1][RTW89_CHILE][42] = 60, + [0][1][2][1][RTW89_QATAR][42] = 6, [0][1][2][1][RTW89_FCC][44] = 72, [0][1][2][1][RTW89_ETSI][44] = 6, [0][1][2][1][RTW89_MKK][44] = 127, @@ -31412,6 +35608,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][44] = 70, [0][1][2][1][RTW89_CN][44] = 54, [0][1][2][1][RTW89_UK][44] = 40, + [0][1][2][1][RTW89_MEXICO][44] = 72, + [0][1][2][1][RTW89_UKRAINE][44] = 6, + [0][1][2][1][RTW89_CHILE][44] = 60, + [0][1][2][1][RTW89_QATAR][44] = 6, [0][1][2][1][RTW89_FCC][46] = 72, [0][1][2][1][RTW89_ETSI][46] = 6, [0][1][2][1][RTW89_MKK][46] = 127, @@ -31420,6 +35620,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][46] = 70, [0][1][2][1][RTW89_CN][46] = 54, [0][1][2][1][RTW89_UK][46] = 40, + [0][1][2][1][RTW89_MEXICO][46] = 72, + [0][1][2][1][RTW89_UKRAINE][46] = 6, + [0][1][2][1][RTW89_CHILE][46] = 60, + [0][1][2][1][RTW89_QATAR][46] = 6, [0][1][2][1][RTW89_FCC][48] = 48, [0][1][2][1][RTW89_ETSI][48] = 127, [0][1][2][1][RTW89_MKK][48] = 127, @@ -31428,6 +35632,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][48] = 127, [0][1][2][1][RTW89_CN][48] = 127, [0][1][2][1][RTW89_UK][48] = 127, + [0][1][2][1][RTW89_MEXICO][48] = 127, + [0][1][2][1][RTW89_UKRAINE][48] = 127, + [0][1][2][1][RTW89_CHILE][48] = 127, + [0][1][2][1][RTW89_QATAR][48] = 127, [0][1][2][1][RTW89_FCC][50] = 50, [0][1][2][1][RTW89_ETSI][50] = 127, [0][1][2][1][RTW89_MKK][50] = 127, @@ -31436,6 +35644,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][50] = 127, [0][1][2][1][RTW89_CN][50] = 127, [0][1][2][1][RTW89_UK][50] = 127, + [0][1][2][1][RTW89_MEXICO][50] = 127, + [0][1][2][1][RTW89_UKRAINE][50] = 127, + [0][1][2][1][RTW89_CHILE][50] = 127, + [0][1][2][1][RTW89_QATAR][50] = 127, [0][1][2][1][RTW89_FCC][52] = 48, [0][1][2][1][RTW89_ETSI][52] = 127, [0][1][2][1][RTW89_MKK][52] = 127, @@ -31444,22 +35656,34 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [0][1][2][1][RTW89_ACMA][52] = 127, [0][1][2][1][RTW89_CN][52] = 127, [0][1][2][1][RTW89_UK][52] = 127, + [0][1][2][1][RTW89_MEXICO][52] = 127, + [0][1][2][1][RTW89_UKRAINE][52] = 127, + [0][1][2][1][RTW89_CHILE][52] = 127, + [0][1][2][1][RTW89_QATAR][52] = 127, [1][0][2][0][RTW89_FCC][1] = 64, [1][0][2][0][RTW89_ETSI][1] = 66, [1][0][2][0][RTW89_MKK][1] = 66, [1][0][2][0][RTW89_IC][1] = 62, - [1][0][2][0][RTW89_KCC][1] = 66, + [1][0][2][0][RTW89_KCC][1] = 54, [1][0][2][0][RTW89_ACMA][1] = 66, [1][0][2][0][RTW89_CN][1] = 54, [1][0][2][0][RTW89_UK][1] = 66, + [1][0][2][0][RTW89_MEXICO][1] = 62, + [1][0][2][0][RTW89_UKRAINE][1] = 54, + [1][0][2][0][RTW89_CHILE][1] = 62, + [1][0][2][0][RTW89_QATAR][1] = 66, [1][0][2][0][RTW89_FCC][5] = 68, [1][0][2][0][RTW89_ETSI][5] = 66, [1][0][2][0][RTW89_MKK][5] = 66, [1][0][2][0][RTW89_IC][5] = 64, - [1][0][2][0][RTW89_KCC][5] = 54, + [1][0][2][0][RTW89_KCC][5] = 66, [1][0][2][0][RTW89_ACMA][5] = 66, [1][0][2][0][RTW89_CN][5] = 54, [1][0][2][0][RTW89_UK][5] = 66, + [1][0][2][0][RTW89_MEXICO][5] = 62, + [1][0][2][0][RTW89_UKRAINE][5] = 54, + [1][0][2][0][RTW89_CHILE][5] = 66, + [1][0][2][0][RTW89_QATAR][5] = 66, [1][0][2][0][RTW89_FCC][9] = 68, [1][0][2][0][RTW89_ETSI][9] = 66, [1][0][2][0][RTW89_MKK][9] = 66, @@ -31468,6 +35692,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][9] = 66, [1][0][2][0][RTW89_CN][9] = 54, [1][0][2][0][RTW89_UK][9] = 66, + [1][0][2][0][RTW89_MEXICO][9] = 68, + [1][0][2][0][RTW89_UKRAINE][9] = 54, + [1][0][2][0][RTW89_CHILE][9] = 66, + [1][0][2][0][RTW89_QATAR][9] = 66, [1][0][2][0][RTW89_FCC][13] = 60, [1][0][2][0][RTW89_ETSI][13] = 66, [1][0][2][0][RTW89_MKK][13] = 66, @@ -31476,6 +35704,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][13] = 66, [1][0][2][0][RTW89_CN][13] = 54, [1][0][2][0][RTW89_UK][13] = 66, + [1][0][2][0][RTW89_MEXICO][13] = 60, + [1][0][2][0][RTW89_UKRAINE][13] = 54, + [1][0][2][0][RTW89_CHILE][13] = 60, + [1][0][2][0][RTW89_QATAR][13] = 66, [1][0][2][0][RTW89_FCC][16] = 64, [1][0][2][0][RTW89_ETSI][16] = 66, [1][0][2][0][RTW89_MKK][16] = 66, @@ -31484,6 +35716,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][16] = 66, [1][0][2][0][RTW89_CN][16] = 127, [1][0][2][0][RTW89_UK][16] = 66, + [1][0][2][0][RTW89_MEXICO][16] = 64, + [1][0][2][0][RTW89_UKRAINE][16] = 54, + [1][0][2][0][RTW89_CHILE][16] = 64, + [1][0][2][0][RTW89_QATAR][16] = 66, [1][0][2][0][RTW89_FCC][20] = 68, [1][0][2][0][RTW89_ETSI][20] = 66, [1][0][2][0][RTW89_MKK][20] = 66, @@ -31492,6 +35728,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][20] = 66, [1][0][2][0][RTW89_CN][20] = 127, [1][0][2][0][RTW89_UK][20] = 66, + [1][0][2][0][RTW89_MEXICO][20] = 68, + [1][0][2][0][RTW89_UKRAINE][20] = 54, + [1][0][2][0][RTW89_CHILE][20] = 66, + [1][0][2][0][RTW89_QATAR][20] = 66, [1][0][2][0][RTW89_FCC][24] = 68, [1][0][2][0][RTW89_ETSI][24] = 66, [1][0][2][0][RTW89_MKK][24] = 66, @@ -31500,6 +35740,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][24] = 127, [1][0][2][0][RTW89_CN][24] = 127, [1][0][2][0][RTW89_UK][24] = 66, + [1][0][2][0][RTW89_MEXICO][24] = 68, + [1][0][2][0][RTW89_UKRAINE][24] = 54, + [1][0][2][0][RTW89_CHILE][24] = 66, + [1][0][2][0][RTW89_QATAR][24] = 66, [1][0][2][0][RTW89_FCC][28] = 68, [1][0][2][0][RTW89_ETSI][28] = 66, [1][0][2][0][RTW89_MKK][28] = 66, @@ -31508,6 +35752,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][28] = 127, [1][0][2][0][RTW89_CN][28] = 127, [1][0][2][0][RTW89_UK][28] = 66, + [1][0][2][0][RTW89_MEXICO][28] = 68, + [1][0][2][0][RTW89_UKRAINE][28] = 54, + [1][0][2][0][RTW89_CHILE][28] = 62, + [1][0][2][0][RTW89_QATAR][28] = 66, [1][0][2][0][RTW89_FCC][32] = 62, [1][0][2][0][RTW89_ETSI][32] = 66, [1][0][2][0][RTW89_MKK][32] = 66, @@ -31516,6 +35764,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][32] = 66, [1][0][2][0][RTW89_CN][32] = 127, [1][0][2][0][RTW89_UK][32] = 66, + [1][0][2][0][RTW89_MEXICO][32] = 62, + [1][0][2][0][RTW89_UKRAINE][32] = 54, + [1][0][2][0][RTW89_CHILE][32] = 62, + [1][0][2][0][RTW89_QATAR][32] = 66, [1][0][2][0][RTW89_FCC][36] = 68, [1][0][2][0][RTW89_ETSI][36] = 127, [1][0][2][0][RTW89_MKK][36] = 66, @@ -31524,6 +35776,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][36] = 66, [1][0][2][0][RTW89_CN][36] = 127, [1][0][2][0][RTW89_UK][36] = 64, + [1][0][2][0][RTW89_MEXICO][36] = 68, + [1][0][2][0][RTW89_UKRAINE][36] = 127, + [1][0][2][0][RTW89_CHILE][36] = 66, + [1][0][2][0][RTW89_QATAR][36] = 127, [1][0][2][0][RTW89_FCC][39] = 68, [1][0][2][0][RTW89_ETSI][39] = 30, [1][0][2][0][RTW89_MKK][39] = 127, @@ -31532,6 +35788,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][39] = 66, [1][0][2][0][RTW89_CN][39] = 62, [1][0][2][0][RTW89_UK][39] = 64, + [1][0][2][0][RTW89_MEXICO][39] = 68, + [1][0][2][0][RTW89_UKRAINE][39] = 30, + [1][0][2][0][RTW89_CHILE][39] = 66, + [1][0][2][0][RTW89_QATAR][39] = 30, [1][0][2][0][RTW89_FCC][43] = 68, [1][0][2][0][RTW89_ETSI][43] = 30, [1][0][2][0][RTW89_MKK][43] = 127, @@ -31540,6 +35800,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][43] = 66, [1][0][2][0][RTW89_CN][43] = 66, [1][0][2][0][RTW89_UK][43] = 64, + [1][0][2][0][RTW89_MEXICO][43] = 68, + [1][0][2][0][RTW89_UKRAINE][43] = 30, + [1][0][2][0][RTW89_CHILE][43] = 66, + [1][0][2][0][RTW89_QATAR][43] = 30, [1][0][2][0][RTW89_FCC][47] = 68, [1][0][2][0][RTW89_ETSI][47] = 127, [1][0][2][0][RTW89_MKK][47] = 127, @@ -31548,6 +35812,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][47] = 127, [1][0][2][0][RTW89_CN][47] = 127, [1][0][2][0][RTW89_UK][47] = 127, + [1][0][2][0][RTW89_MEXICO][47] = 127, + [1][0][2][0][RTW89_UKRAINE][47] = 127, + [1][0][2][0][RTW89_CHILE][47] = 127, + [1][0][2][0][RTW89_QATAR][47] = 127, [1][0][2][0][RTW89_FCC][51] = 68, [1][0][2][0][RTW89_ETSI][51] = 127, [1][0][2][0][RTW89_MKK][51] = 127, @@ -31556,6 +35824,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][0][2][0][RTW89_ACMA][51] = 127, [1][0][2][0][RTW89_CN][51] = 127, [1][0][2][0][RTW89_UK][51] = 127, + [1][0][2][0][RTW89_MEXICO][51] = 127, + [1][0][2][0][RTW89_UKRAINE][51] = 127, + [1][0][2][0][RTW89_CHILE][51] = 127, + [1][0][2][0][RTW89_QATAR][51] = 127, [1][1][2][0][RTW89_FCC][1] = 54, [1][1][2][0][RTW89_ETSI][1] = 54, [1][1][2][0][RTW89_MKK][1] = 48, @@ -31564,6 +35836,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][1] = 54, [1][1][2][0][RTW89_CN][1] = 42, [1][1][2][0][RTW89_UK][1] = 54, + [1][1][2][0][RTW89_MEXICO][1] = 50, + [1][1][2][0][RTW89_UKRAINE][1] = 42, + [1][1][2][0][RTW89_CHILE][1] = 54, + [1][1][2][0][RTW89_QATAR][1] = 54, [1][1][2][0][RTW89_FCC][5] = 68, [1][1][2][0][RTW89_ETSI][5] = 54, [1][1][2][0][RTW89_MKK][5] = 52, @@ -31572,6 +35848,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][5] = 54, [1][1][2][0][RTW89_CN][5] = 42, [1][1][2][0][RTW89_UK][5] = 54, + [1][1][2][0][RTW89_MEXICO][5] = 50, + [1][1][2][0][RTW89_UKRAINE][5] = 42, + [1][1][2][0][RTW89_CHILE][5] = 66, + [1][1][2][0][RTW89_QATAR][5] = 54, [1][1][2][0][RTW89_FCC][9] = 68, [1][1][2][0][RTW89_ETSI][9] = 54, [1][1][2][0][RTW89_MKK][9] = 52, @@ -31580,6 +35860,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][9] = 54, [1][1][2][0][RTW89_CN][9] = 42, [1][1][2][0][RTW89_UK][9] = 54, + [1][1][2][0][RTW89_MEXICO][9] = 68, + [1][1][2][0][RTW89_UKRAINE][9] = 42, + [1][1][2][0][RTW89_CHILE][9] = 66, + [1][1][2][0][RTW89_QATAR][9] = 54, [1][1][2][0][RTW89_FCC][13] = 54, [1][1][2][0][RTW89_ETSI][13] = 54, [1][1][2][0][RTW89_MKK][13] = 52, @@ -31588,6 +35872,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][13] = 54, [1][1][2][0][RTW89_CN][13] = 42, [1][1][2][0][RTW89_UK][13] = 54, + [1][1][2][0][RTW89_MEXICO][13] = 54, + [1][1][2][0][RTW89_UKRAINE][13] = 42, + [1][1][2][0][RTW89_CHILE][13] = 54, + [1][1][2][0][RTW89_QATAR][13] = 54, [1][1][2][0][RTW89_FCC][16] = 56, [1][1][2][0][RTW89_ETSI][16] = 54, [1][1][2][0][RTW89_MKK][16] = 66, @@ -31596,6 +35884,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][16] = 54, [1][1][2][0][RTW89_CN][16] = 127, [1][1][2][0][RTW89_UK][16] = 54, + [1][1][2][0][RTW89_MEXICO][16] = 56, + [1][1][2][0][RTW89_UKRAINE][16] = 42, + [1][1][2][0][RTW89_CHILE][16] = 54, + [1][1][2][0][RTW89_QATAR][16] = 54, [1][1][2][0][RTW89_FCC][20] = 68, [1][1][2][0][RTW89_ETSI][20] = 54, [1][1][2][0][RTW89_MKK][20] = 66, @@ -31604,6 +35896,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][20] = 54, [1][1][2][0][RTW89_CN][20] = 127, [1][1][2][0][RTW89_UK][20] = 54, + [1][1][2][0][RTW89_MEXICO][20] = 68, + [1][1][2][0][RTW89_UKRAINE][20] = 42, + [1][1][2][0][RTW89_CHILE][20] = 66, + [1][1][2][0][RTW89_QATAR][20] = 54, [1][1][2][0][RTW89_FCC][24] = 68, [1][1][2][0][RTW89_ETSI][24] = 54, [1][1][2][0][RTW89_MKK][24] = 66, @@ -31612,6 +35908,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][24] = 127, [1][1][2][0][RTW89_CN][24] = 127, [1][1][2][0][RTW89_UK][24] = 54, + [1][1][2][0][RTW89_MEXICO][24] = 68, + [1][1][2][0][RTW89_UKRAINE][24] = 42, + [1][1][2][0][RTW89_CHILE][24] = 66, + [1][1][2][0][RTW89_QATAR][24] = 54, [1][1][2][0][RTW89_FCC][28] = 68, [1][1][2][0][RTW89_ETSI][28] = 54, [1][1][2][0][RTW89_MKK][28] = 66, @@ -31620,6 +35920,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][28] = 127, [1][1][2][0][RTW89_CN][28] = 127, [1][1][2][0][RTW89_UK][28] = 54, + [1][1][2][0][RTW89_MEXICO][28] = 68, + [1][1][2][0][RTW89_UKRAINE][28] = 42, + [1][1][2][0][RTW89_CHILE][28] = 54, + [1][1][2][0][RTW89_QATAR][28] = 54, [1][1][2][0][RTW89_FCC][32] = 56, [1][1][2][0][RTW89_ETSI][32] = 54, [1][1][2][0][RTW89_MKK][32] = 66, @@ -31628,6 +35932,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][32] = 54, [1][1][2][0][RTW89_CN][32] = 127, [1][1][2][0][RTW89_UK][32] = 54, + [1][1][2][0][RTW89_MEXICO][32] = 56, + [1][1][2][0][RTW89_UKRAINE][32] = 42, + [1][1][2][0][RTW89_CHILE][32] = 54, + [1][1][2][0][RTW89_QATAR][32] = 54, [1][1][2][0][RTW89_FCC][36] = 68, [1][1][2][0][RTW89_ETSI][36] = 127, [1][1][2][0][RTW89_MKK][36] = 66, @@ -31636,6 +35944,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][36] = 66, [1][1][2][0][RTW89_CN][36] = 127, [1][1][2][0][RTW89_UK][36] = 52, + [1][1][2][0][RTW89_MEXICO][36] = 68, + [1][1][2][0][RTW89_UKRAINE][36] = 127, + [1][1][2][0][RTW89_CHILE][36] = 66, + [1][1][2][0][RTW89_QATAR][36] = 127, [1][1][2][0][RTW89_FCC][39] = 68, [1][1][2][0][RTW89_ETSI][39] = 18, [1][1][2][0][RTW89_MKK][39] = 127, @@ -31644,6 +35956,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][39] = 66, [1][1][2][0][RTW89_CN][39] = 62, [1][1][2][0][RTW89_UK][39] = 52, + [1][1][2][0][RTW89_MEXICO][39] = 68, + [1][1][2][0][RTW89_UKRAINE][39] = 18, + [1][1][2][0][RTW89_CHILE][39] = 66, + [1][1][2][0][RTW89_QATAR][39] = 18, [1][1][2][0][RTW89_FCC][43] = 68, [1][1][2][0][RTW89_ETSI][43] = 18, [1][1][2][0][RTW89_MKK][43] = 127, @@ -31652,6 +35968,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][43] = 66, [1][1][2][0][RTW89_CN][43] = 66, [1][1][2][0][RTW89_UK][43] = 52, + [1][1][2][0][RTW89_MEXICO][43] = 68, + [1][1][2][0][RTW89_UKRAINE][43] = 18, + [1][1][2][0][RTW89_CHILE][43] = 66, + [1][1][2][0][RTW89_QATAR][43] = 18, [1][1][2][0][RTW89_FCC][47] = 62, [1][1][2][0][RTW89_ETSI][47] = 127, [1][1][2][0][RTW89_MKK][47] = 127, @@ -31660,6 +35980,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][47] = 127, [1][1][2][0][RTW89_CN][47] = 127, [1][1][2][0][RTW89_UK][47] = 127, + [1][1][2][0][RTW89_MEXICO][47] = 127, + [1][1][2][0][RTW89_UKRAINE][47] = 127, + [1][1][2][0][RTW89_CHILE][47] = 127, + [1][1][2][0][RTW89_QATAR][47] = 127, [1][1][2][0][RTW89_FCC][51] = 60, [1][1][2][0][RTW89_ETSI][51] = 127, [1][1][2][0][RTW89_MKK][51] = 127, @@ -31668,6 +35992,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][0][RTW89_ACMA][51] = 127, [1][1][2][0][RTW89_CN][51] = 127, [1][1][2][0][RTW89_UK][51] = 127, + [1][1][2][0][RTW89_MEXICO][51] = 127, + [1][1][2][0][RTW89_UKRAINE][51] = 127, + [1][1][2][0][RTW89_CHILE][51] = 127, + [1][1][2][0][RTW89_QATAR][51] = 127, [1][1][2][1][RTW89_FCC][1] = 54, [1][1][2][1][RTW89_ETSI][1] = 40, [1][1][2][1][RTW89_MKK][1] = 48, @@ -31676,6 +36004,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][1] = 40, [1][1][2][1][RTW89_CN][1] = 42, [1][1][2][1][RTW89_UK][1] = 40, + [1][1][2][1][RTW89_MEXICO][1] = 50, + [1][1][2][1][RTW89_UKRAINE][1] = 30, + [1][1][2][1][RTW89_CHILE][1] = 54, + [1][1][2][1][RTW89_QATAR][1] = 40, [1][1][2][1][RTW89_FCC][5] = 68, [1][1][2][1][RTW89_ETSI][5] = 40, [1][1][2][1][RTW89_MKK][5] = 52, @@ -31684,6 +36016,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][5] = 40, [1][1][2][1][RTW89_CN][5] = 42, [1][1][2][1][RTW89_UK][5] = 40, + [1][1][2][1][RTW89_MEXICO][5] = 50, + [1][1][2][1][RTW89_UKRAINE][5] = 30, + [1][1][2][1][RTW89_CHILE][5] = 60, + [1][1][2][1][RTW89_QATAR][5] = 40, [1][1][2][1][RTW89_FCC][9] = 68, [1][1][2][1][RTW89_ETSI][9] = 40, [1][1][2][1][RTW89_MKK][9] = 52, @@ -31692,6 +36028,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][9] = 40, [1][1][2][1][RTW89_CN][9] = 42, [1][1][2][1][RTW89_UK][9] = 40, + [1][1][2][1][RTW89_MEXICO][9] = 68, + [1][1][2][1][RTW89_UKRAINE][9] = 30, + [1][1][2][1][RTW89_CHILE][9] = 60, + [1][1][2][1][RTW89_QATAR][9] = 40, [1][1][2][1][RTW89_FCC][13] = 54, [1][1][2][1][RTW89_ETSI][13] = 40, [1][1][2][1][RTW89_MKK][13] = 52, @@ -31700,6 +36040,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][13] = 40, [1][1][2][1][RTW89_CN][13] = 42, [1][1][2][1][RTW89_UK][13] = 40, + [1][1][2][1][RTW89_MEXICO][13] = 54, + [1][1][2][1][RTW89_UKRAINE][13] = 30, + [1][1][2][1][RTW89_CHILE][13] = 54, + [1][1][2][1][RTW89_QATAR][13] = 40, [1][1][2][1][RTW89_FCC][16] = 56, [1][1][2][1][RTW89_ETSI][16] = 40, [1][1][2][1][RTW89_MKK][16] = 66, @@ -31708,6 +36052,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][16] = 40, [1][1][2][1][RTW89_CN][16] = 127, [1][1][2][1][RTW89_UK][16] = 40, + [1][1][2][1][RTW89_MEXICO][16] = 56, + [1][1][2][1][RTW89_UKRAINE][16] = 30, + [1][1][2][1][RTW89_CHILE][16] = 54, + [1][1][2][1][RTW89_QATAR][16] = 40, [1][1][2][1][RTW89_FCC][20] = 68, [1][1][2][1][RTW89_ETSI][20] = 40, [1][1][2][1][RTW89_MKK][20] = 66, @@ -31716,6 +36064,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][20] = 40, [1][1][2][1][RTW89_CN][20] = 127, [1][1][2][1][RTW89_UK][20] = 40, + [1][1][2][1][RTW89_MEXICO][20] = 68, + [1][1][2][1][RTW89_UKRAINE][20] = 30, + [1][1][2][1][RTW89_CHILE][20] = 60, + [1][1][2][1][RTW89_QATAR][20] = 40, [1][1][2][1][RTW89_FCC][24] = 68, [1][1][2][1][RTW89_ETSI][24] = 40, [1][1][2][1][RTW89_MKK][24] = 66, @@ -31724,6 +36076,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][24] = 127, [1][1][2][1][RTW89_CN][24] = 127, [1][1][2][1][RTW89_UK][24] = 40, + [1][1][2][1][RTW89_MEXICO][24] = 68, + [1][1][2][1][RTW89_UKRAINE][24] = 30, + [1][1][2][1][RTW89_CHILE][24] = 60, + [1][1][2][1][RTW89_QATAR][24] = 40, [1][1][2][1][RTW89_FCC][28] = 68, [1][1][2][1][RTW89_ETSI][28] = 40, [1][1][2][1][RTW89_MKK][28] = 66, @@ -31732,6 +36088,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][28] = 127, [1][1][2][1][RTW89_CN][28] = 127, [1][1][2][1][RTW89_UK][28] = 40, + [1][1][2][1][RTW89_MEXICO][28] = 68, + [1][1][2][1][RTW89_UKRAINE][28] = 30, + [1][1][2][1][RTW89_CHILE][28] = 54, + [1][1][2][1][RTW89_QATAR][28] = 40, [1][1][2][1][RTW89_FCC][32] = 56, [1][1][2][1][RTW89_ETSI][32] = 40, [1][1][2][1][RTW89_MKK][32] = 66, @@ -31740,6 +36100,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][32] = 40, [1][1][2][1][RTW89_CN][32] = 127, [1][1][2][1][RTW89_UK][32] = 40, + [1][1][2][1][RTW89_MEXICO][32] = 56, + [1][1][2][1][RTW89_UKRAINE][32] = 30, + [1][1][2][1][RTW89_CHILE][32] = 54, + [1][1][2][1][RTW89_QATAR][32] = 40, [1][1][2][1][RTW89_FCC][36] = 68, [1][1][2][1][RTW89_ETSI][36] = 127, [1][1][2][1][RTW89_MKK][36] = 66, @@ -31748,6 +36112,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][36] = 66, [1][1][2][1][RTW89_CN][36] = 127, [1][1][2][1][RTW89_UK][36] = 40, + [1][1][2][1][RTW89_MEXICO][36] = 68, + [1][1][2][1][RTW89_UKRAINE][36] = 127, + [1][1][2][1][RTW89_CHILE][36] = 66, + [1][1][2][1][RTW89_QATAR][36] = 127, [1][1][2][1][RTW89_FCC][39] = 68, [1][1][2][1][RTW89_ETSI][39] = 6, [1][1][2][1][RTW89_MKK][39] = 127, @@ -31756,6 +36124,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][39] = 66, [1][1][2][1][RTW89_CN][39] = 60, [1][1][2][1][RTW89_UK][39] = 40, + [1][1][2][1][RTW89_MEXICO][39] = 68, + [1][1][2][1][RTW89_UKRAINE][39] = 6, + [1][1][2][1][RTW89_CHILE][39] = 60, + [1][1][2][1][RTW89_QATAR][39] = 6, [1][1][2][1][RTW89_FCC][43] = 68, [1][1][2][1][RTW89_ETSI][43] = 6, [1][1][2][1][RTW89_MKK][43] = 127, @@ -31764,6 +36136,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][43] = 66, [1][1][2][1][RTW89_CN][43] = 52, [1][1][2][1][RTW89_UK][43] = 40, + [1][1][2][1][RTW89_MEXICO][43] = 68, + [1][1][2][1][RTW89_UKRAINE][43] = 6, + [1][1][2][1][RTW89_CHILE][43] = 60, + [1][1][2][1][RTW89_QATAR][43] = 6, [1][1][2][1][RTW89_FCC][47] = 62, [1][1][2][1][RTW89_ETSI][47] = 127, [1][1][2][1][RTW89_MKK][47] = 127, @@ -31772,6 +36148,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][47] = 127, [1][1][2][1][RTW89_CN][47] = 127, [1][1][2][1][RTW89_UK][47] = 127, + [1][1][2][1][RTW89_MEXICO][47] = 127, + [1][1][2][1][RTW89_UKRAINE][47] = 127, + [1][1][2][1][RTW89_CHILE][47] = 127, + [1][1][2][1][RTW89_QATAR][47] = 127, [1][1][2][1][RTW89_FCC][51] = 60, [1][1][2][1][RTW89_ETSI][51] = 127, [1][1][2][1][RTW89_MKK][51] = 127, @@ -31780,6 +36160,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [1][1][2][1][RTW89_ACMA][51] = 127, [1][1][2][1][RTW89_CN][51] = 127, [1][1][2][1][RTW89_UK][51] = 127, + [1][1][2][1][RTW89_MEXICO][51] = 127, + [1][1][2][1][RTW89_UKRAINE][51] = 127, + [1][1][2][1][RTW89_CHILE][51] = 127, + [1][1][2][1][RTW89_QATAR][51] = 127, [2][0][2][0][RTW89_FCC][3] = 58, [2][0][2][0][RTW89_ETSI][3] = 60, [2][0][2][0][RTW89_MKK][3] = 60, @@ -31788,6 +36172,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][3] = 60, [2][0][2][0][RTW89_CN][3] = 54, [2][0][2][0][RTW89_UK][3] = 60, + [2][0][2][0][RTW89_MEXICO][3] = 58, + [2][0][2][0][RTW89_UKRAINE][3] = 54, + [2][0][2][0][RTW89_CHILE][3] = 58, + [2][0][2][0][RTW89_QATAR][3] = 60, [2][0][2][0][RTW89_FCC][11] = 50, [2][0][2][0][RTW89_ETSI][11] = 60, [2][0][2][0][RTW89_MKK][11] = 60, @@ -31796,6 +36184,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][11] = 60, [2][0][2][0][RTW89_CN][11] = 54, [2][0][2][0][RTW89_UK][11] = 60, + [2][0][2][0][RTW89_MEXICO][11] = 50, + [2][0][2][0][RTW89_UKRAINE][11] = 54, + [2][0][2][0][RTW89_CHILE][11] = 50, + [2][0][2][0][RTW89_QATAR][11] = 60, [2][0][2][0][RTW89_FCC][18] = 60, [2][0][2][0][RTW89_ETSI][18] = 60, [2][0][2][0][RTW89_MKK][18] = 60, @@ -31804,6 +36196,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][18] = 60, [2][0][2][0][RTW89_CN][18] = 127, [2][0][2][0][RTW89_UK][18] = 60, + [2][0][2][0][RTW89_MEXICO][18] = 60, + [2][0][2][0][RTW89_UKRAINE][18] = 54, + [2][0][2][0][RTW89_CHILE][18] = 60, + [2][0][2][0][RTW89_QATAR][18] = 60, [2][0][2][0][RTW89_FCC][26] = 62, [2][0][2][0][RTW89_ETSI][26] = 60, [2][0][2][0][RTW89_MKK][26] = 60, @@ -31812,6 +36208,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][26] = 127, [2][0][2][0][RTW89_CN][26] = 127, [2][0][2][0][RTW89_UK][26] = 60, + [2][0][2][0][RTW89_MEXICO][26] = 62, + [2][0][2][0][RTW89_UKRAINE][26] = 54, + [2][0][2][0][RTW89_CHILE][26] = 60, + [2][0][2][0][RTW89_QATAR][26] = 60, [2][0][2][0][RTW89_FCC][34] = 62, [2][0][2][0][RTW89_ETSI][34] = 127, [2][0][2][0][RTW89_MKK][34] = 60, @@ -31820,6 +36220,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][34] = 60, [2][0][2][0][RTW89_CN][34] = 127, [2][0][2][0][RTW89_UK][34] = 60, + [2][0][2][0][RTW89_MEXICO][34] = 62, + [2][0][2][0][RTW89_UKRAINE][34] = 127, + [2][0][2][0][RTW89_CHILE][34] = 60, + [2][0][2][0][RTW89_QATAR][34] = 127, [2][0][2][0][RTW89_FCC][41] = 62, [2][0][2][0][RTW89_ETSI][41] = 30, [2][0][2][0][RTW89_MKK][41] = 127, @@ -31828,6 +36232,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][41] = 60, [2][0][2][0][RTW89_CN][41] = 62, [2][0][2][0][RTW89_UK][41] = 60, + [2][0][2][0][RTW89_MEXICO][41] = 62, + [2][0][2][0][RTW89_UKRAINE][41] = 30, + [2][0][2][0][RTW89_CHILE][41] = 60, + [2][0][2][0][RTW89_QATAR][41] = 30, [2][0][2][0][RTW89_FCC][49] = 62, [2][0][2][0][RTW89_ETSI][49] = 127, [2][0][2][0][RTW89_MKK][49] = 127, @@ -31836,6 +36244,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][0][2][0][RTW89_ACMA][49] = 127, [2][0][2][0][RTW89_CN][49] = 127, [2][0][2][0][RTW89_UK][49] = 127, + [2][0][2][0][RTW89_MEXICO][49] = 127, + [2][0][2][0][RTW89_UKRAINE][49] = 127, + [2][0][2][0][RTW89_CHILE][49] = 127, + [2][0][2][0][RTW89_QATAR][49] = 127, [2][1][2][0][RTW89_FCC][3] = 48, [2][1][2][0][RTW89_ETSI][3] = 54, [2][1][2][0][RTW89_MKK][3] = 56, @@ -31844,6 +36256,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][3] = 54, [2][1][2][0][RTW89_CN][3] = 52, [2][1][2][0][RTW89_UK][3] = 54, + [2][1][2][0][RTW89_MEXICO][3] = 48, + [2][1][2][0][RTW89_UKRAINE][3] = 42, + [2][1][2][0][RTW89_CHILE][3] = 46, + [2][1][2][0][RTW89_QATAR][3] = 54, [2][1][2][0][RTW89_FCC][11] = 38, [2][1][2][0][RTW89_ETSI][11] = 54, [2][1][2][0][RTW89_MKK][11] = 54, @@ -31852,6 +36268,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][11] = 54, [2][1][2][0][RTW89_CN][11] = 52, [2][1][2][0][RTW89_UK][11] = 54, + [2][1][2][0][RTW89_MEXICO][11] = 38, + [2][1][2][0][RTW89_UKRAINE][11] = 42, + [2][1][2][0][RTW89_CHILE][11] = 38, + [2][1][2][0][RTW89_QATAR][11] = 54, [2][1][2][0][RTW89_FCC][18] = 50, [2][1][2][0][RTW89_ETSI][18] = 54, [2][1][2][0][RTW89_MKK][18] = 60, @@ -31860,6 +36280,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][18] = 54, [2][1][2][0][RTW89_CN][18] = 127, [2][1][2][0][RTW89_UK][18] = 54, + [2][1][2][0][RTW89_MEXICO][18] = 50, + [2][1][2][0][RTW89_UKRAINE][18] = 42, + [2][1][2][0][RTW89_CHILE][18] = 50, + [2][1][2][0][RTW89_QATAR][18] = 54, [2][1][2][0][RTW89_FCC][26] = 52, [2][1][2][0][RTW89_ETSI][26] = 54, [2][1][2][0][RTW89_MKK][26] = 56, @@ -31868,6 +36292,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][26] = 127, [2][1][2][0][RTW89_CN][26] = 127, [2][1][2][0][RTW89_UK][26] = 54, + [2][1][2][0][RTW89_MEXICO][26] = 52, + [2][1][2][0][RTW89_UKRAINE][26] = 42, + [2][1][2][0][RTW89_CHILE][26] = 52, + [2][1][2][0][RTW89_QATAR][26] = 54, [2][1][2][0][RTW89_FCC][34] = 62, [2][1][2][0][RTW89_ETSI][34] = 127, [2][1][2][0][RTW89_MKK][34] = 60, @@ -31876,6 +36304,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][34] = 60, [2][1][2][0][RTW89_CN][34] = 127, [2][1][2][0][RTW89_UK][34] = 52, + [2][1][2][0][RTW89_MEXICO][34] = 62, + [2][1][2][0][RTW89_UKRAINE][34] = 127, + [2][1][2][0][RTW89_CHILE][34] = 60, + [2][1][2][0][RTW89_QATAR][34] = 127, [2][1][2][0][RTW89_FCC][41] = 60, [2][1][2][0][RTW89_ETSI][41] = 18, [2][1][2][0][RTW89_MKK][41] = 127, @@ -31884,6 +36316,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][41] = 58, [2][1][2][0][RTW89_CN][41] = 62, [2][1][2][0][RTW89_UK][41] = 52, + [2][1][2][0][RTW89_MEXICO][41] = 60, + [2][1][2][0][RTW89_UKRAINE][41] = 18, + [2][1][2][0][RTW89_CHILE][41] = 58, + [2][1][2][0][RTW89_QATAR][41] = 18, [2][1][2][0][RTW89_FCC][49] = 62, [2][1][2][0][RTW89_ETSI][49] = 127, [2][1][2][0][RTW89_MKK][49] = 127, @@ -31892,6 +36328,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][0][RTW89_ACMA][49] = 127, [2][1][2][0][RTW89_CN][49] = 127, [2][1][2][0][RTW89_UK][49] = 127, + [2][1][2][0][RTW89_MEXICO][49] = 127, + [2][1][2][0][RTW89_UKRAINE][49] = 127, + [2][1][2][0][RTW89_CHILE][49] = 127, + [2][1][2][0][RTW89_QATAR][49] = 127, [2][1][2][1][RTW89_FCC][3] = 48, [2][1][2][1][RTW89_ETSI][3] = 40, [2][1][2][1][RTW89_MKK][3] = 56, @@ -31900,6 +36340,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][3] = 40, [2][1][2][1][RTW89_CN][3] = 42, [2][1][2][1][RTW89_UK][3] = 40, + [2][1][2][1][RTW89_MEXICO][3] = 48, + [2][1][2][1][RTW89_UKRAINE][3] = 30, + [2][1][2][1][RTW89_CHILE][3] = 46, + [2][1][2][1][RTW89_QATAR][3] = 40, [2][1][2][1][RTW89_FCC][11] = 38, [2][1][2][1][RTW89_ETSI][11] = 40, [2][1][2][1][RTW89_MKK][11] = 54, @@ -31908,6 +36352,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][11] = 40, [2][1][2][1][RTW89_CN][11] = 42, [2][1][2][1][RTW89_UK][11] = 40, + [2][1][2][1][RTW89_MEXICO][11] = 38, + [2][1][2][1][RTW89_UKRAINE][11] = 30, + [2][1][2][1][RTW89_CHILE][11] = 38, + [2][1][2][1][RTW89_QATAR][11] = 40, [2][1][2][1][RTW89_FCC][18] = 50, [2][1][2][1][RTW89_ETSI][18] = 40, [2][1][2][1][RTW89_MKK][18] = 60, @@ -31916,6 +36364,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][18] = 40, [2][1][2][1][RTW89_CN][18] = 127, [2][1][2][1][RTW89_UK][18] = 40, + [2][1][2][1][RTW89_MEXICO][18] = 50, + [2][1][2][1][RTW89_UKRAINE][18] = 30, + [2][1][2][1][RTW89_CHILE][18] = 50, + [2][1][2][1][RTW89_QATAR][18] = 40, [2][1][2][1][RTW89_FCC][26] = 52, [2][1][2][1][RTW89_ETSI][26] = 42, [2][1][2][1][RTW89_MKK][26] = 56, @@ -31924,6 +36376,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][26] = 127, [2][1][2][1][RTW89_CN][26] = 127, [2][1][2][1][RTW89_UK][26] = 42, + [2][1][2][1][RTW89_MEXICO][26] = 52, + [2][1][2][1][RTW89_UKRAINE][26] = 30, + [2][1][2][1][RTW89_CHILE][26] = 52, + [2][1][2][1][RTW89_QATAR][26] = 42, [2][1][2][1][RTW89_FCC][34] = 62, [2][1][2][1][RTW89_ETSI][34] = 127, [2][1][2][1][RTW89_MKK][34] = 60, @@ -31932,6 +36388,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][34] = 60, [2][1][2][1][RTW89_CN][34] = 127, [2][1][2][1][RTW89_UK][34] = 40, + [2][1][2][1][RTW89_MEXICO][34] = 62, + [2][1][2][1][RTW89_UKRAINE][34] = 127, + [2][1][2][1][RTW89_CHILE][34] = 60, + [2][1][2][1][RTW89_QATAR][34] = 127, [2][1][2][1][RTW89_FCC][41] = 60, [2][1][2][1][RTW89_ETSI][41] = 6, [2][1][2][1][RTW89_MKK][41] = 127, @@ -31940,6 +36400,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][41] = 58, [2][1][2][1][RTW89_CN][41] = 40, [2][1][2][1][RTW89_UK][41] = 40, + [2][1][2][1][RTW89_MEXICO][41] = 60, + [2][1][2][1][RTW89_UKRAINE][41] = 6, + [2][1][2][1][RTW89_CHILE][41] = 58, + [2][1][2][1][RTW89_QATAR][41] = 6, [2][1][2][1][RTW89_FCC][49] = 62, [2][1][2][1][RTW89_ETSI][49] = 127, [2][1][2][1][RTW89_MKK][49] = 127, @@ -31948,6 +36412,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [2][1][2][1][RTW89_ACMA][49] = 127, [2][1][2][1][RTW89_CN][49] = 127, [2][1][2][1][RTW89_UK][49] = 127, + [2][1][2][1][RTW89_MEXICO][49] = 127, + [2][1][2][1][RTW89_UKRAINE][49] = 127, + [2][1][2][1][RTW89_CHILE][49] = 127, + [2][1][2][1][RTW89_QATAR][49] = 127, [3][0][2][0][RTW89_FCC][7] = 40, [3][0][2][0][RTW89_ETSI][7] = 50, [3][0][2][0][RTW89_MKK][7] = 50, @@ -31956,6 +36424,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][0][2][0][RTW89_ACMA][7] = 127, [3][0][2][0][RTW89_CN][7] = 66, [3][0][2][0][RTW89_UK][7] = 127, + [3][0][2][0][RTW89_MEXICO][7] = 127, + [3][0][2][0][RTW89_UKRAINE][7] = 50, + [3][0][2][0][RTW89_CHILE][7] = 40, + [3][0][2][0][RTW89_QATAR][7] = 50, [3][0][2][0][RTW89_FCC][22] = 42, [3][0][2][0][RTW89_ETSI][22] = 50, [3][0][2][0][RTW89_MKK][22] = 50, @@ -31964,6 +36436,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][0][2][0][RTW89_ACMA][22] = 127, [3][0][2][0][RTW89_CN][22] = 66, [3][0][2][0][RTW89_UK][22] = 127, + [3][0][2][0][RTW89_MEXICO][22] = 127, + [3][0][2][0][RTW89_UKRAINE][22] = 50, + [3][0][2][0][RTW89_CHILE][22] = 42, + [3][0][2][0][RTW89_QATAR][22] = 50, [3][0][2][0][RTW89_FCC][45] = 52, [3][0][2][0][RTW89_ETSI][45] = 127, [3][0][2][0][RTW89_MKK][45] = 127, @@ -31972,6 +36448,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][0][2][0][RTW89_ACMA][45] = 127, [3][0][2][0][RTW89_CN][45] = 127, [3][0][2][0][RTW89_UK][45] = 127, + [3][0][2][0][RTW89_MEXICO][45] = 127, + [3][0][2][0][RTW89_UKRAINE][45] = 127, + [3][0][2][0][RTW89_CHILE][45] = 127, + [3][0][2][0][RTW89_QATAR][45] = 127, [3][1][2][0][RTW89_FCC][7] = 32, [3][1][2][0][RTW89_ETSI][7] = 50, [3][1][2][0][RTW89_MKK][7] = 36, @@ -31980,6 +36460,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][0][RTW89_ACMA][7] = 127, [3][1][2][0][RTW89_CN][7] = 54, [3][1][2][0][RTW89_UK][7] = 127, + [3][1][2][0][RTW89_MEXICO][7] = 127, + [3][1][2][0][RTW89_UKRAINE][7] = 50, + [3][1][2][0][RTW89_CHILE][7] = 32, + [3][1][2][0][RTW89_QATAR][7] = 50, [3][1][2][0][RTW89_FCC][22] = 36, [3][1][2][0][RTW89_ETSI][22] = 50, [3][1][2][0][RTW89_MKK][22] = 48, @@ -31988,6 +36472,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][0][RTW89_ACMA][22] = 127, [3][1][2][0][RTW89_CN][22] = 54, [3][1][2][0][RTW89_UK][22] = 127, + [3][1][2][0][RTW89_MEXICO][22] = 127, + [3][1][2][0][RTW89_UKRAINE][22] = 50, + [3][1][2][0][RTW89_CHILE][22] = 36, + [3][1][2][0][RTW89_QATAR][22] = 50, [3][1][2][0][RTW89_FCC][45] = 46, [3][1][2][0][RTW89_ETSI][45] = 127, [3][1][2][0][RTW89_MKK][45] = 127, @@ -31996,6 +36484,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][0][RTW89_ACMA][45] = 127, [3][1][2][0][RTW89_CN][45] = 127, [3][1][2][0][RTW89_UK][45] = 127, + [3][1][2][0][RTW89_MEXICO][45] = 127, + [3][1][2][0][RTW89_UKRAINE][45] = 127, + [3][1][2][0][RTW89_CHILE][45] = 127, + [3][1][2][0][RTW89_QATAR][45] = 127, [3][1][2][1][RTW89_FCC][7] = 32, [3][1][2][1][RTW89_ETSI][7] = 42, [3][1][2][1][RTW89_MKK][7] = 36, @@ -32004,6 +36496,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_ACMA][7] = 127, [3][1][2][1][RTW89_CN][7] = 42, [3][1][2][1][RTW89_UK][7] = 127, + [3][1][2][1][RTW89_MEXICO][7] = 127, + [3][1][2][1][RTW89_UKRAINE][7] = 42, + [3][1][2][1][RTW89_CHILE][7] = 32, + [3][1][2][1][RTW89_QATAR][7] = 42, [3][1][2][1][RTW89_FCC][22] = 36, [3][1][2][1][RTW89_ETSI][22] = 42, [3][1][2][1][RTW89_MKK][22] = 48, @@ -32012,6 +36508,10 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_ACMA][22] = 127, [3][1][2][1][RTW89_CN][22] = 42, [3][1][2][1][RTW89_UK][22] = 127, + [3][1][2][1][RTW89_MEXICO][22] = 127, + [3][1][2][1][RTW89_UKRAINE][22] = 42, + [3][1][2][1][RTW89_CHILE][22] = 36, + [3][1][2][1][RTW89_QATAR][22] = 42, [3][1][2][1][RTW89_FCC][45] = 46, [3][1][2][1][RTW89_ETSI][45] = 127, [3][1][2][1][RTW89_MKK][45] = 127, @@ -32020,1964 +36520,9289 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM] [3][1][2][1][RTW89_ACMA][45] = 127, [3][1][2][1][RTW89_CN][45] = 127, [3][1][2][1][RTW89_UK][45] = 127, + [3][1][2][1][RTW89_MEXICO][45] = 127, + [3][1][2][1][RTW89_UKRAINE][45] = 127, + [3][1][2][1][RTW89_CHILE][45] = 127, + [3][1][2][1][RTW89_QATAR][45] = 127, }; static const s8 rtw89_8852c_txpwr_lmt_6g[RTW89_6G_BW_NUM][RTW89_NTX_NUM] [RTW89_RS_LMT_NUM][RTW89_BF_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = { - [0][0][1][0][RTW89_WW][0] = 24, - [0][0][1][0][RTW89_WW][2] = 22, - [0][0][1][0][RTW89_WW][4] = 22, - [0][0][1][0][RTW89_WW][6] = 22, - [0][0][1][0][RTW89_WW][8] = 22, - [0][0][1][0][RTW89_WW][10] = 22, - [0][0][1][0][RTW89_WW][12] = 22, - [0][0][1][0][RTW89_WW][14] = 22, - [0][0][1][0][RTW89_WW][15] = 22, - [0][0][1][0][RTW89_WW][17] = 22, - [0][0][1][0][RTW89_WW][19] = 22, - [0][0][1][0][RTW89_WW][21] = 22, - [0][0][1][0][RTW89_WW][23] = 22, - [0][0][1][0][RTW89_WW][25] = 22, - [0][0][1][0][RTW89_WW][27] = 22, - [0][0][1][0][RTW89_WW][29] = 22, - [0][0][1][0][RTW89_WW][30] = 22, - [0][0][1][0][RTW89_WW][32] = 22, - [0][0][1][0][RTW89_WW][34] = 22, - [0][0][1][0][RTW89_WW][36] = 22, - [0][0][1][0][RTW89_WW][38] = 22, - [0][0][1][0][RTW89_WW][40] = 22, - [0][0][1][0][RTW89_WW][42] = 22, - [0][0][1][0][RTW89_WW][44] = 22, - [0][0][1][0][RTW89_WW][45] = 22, - [0][0][1][0][RTW89_WW][47] = 22, - [0][0][1][0][RTW89_WW][49] = 24, - [0][0][1][0][RTW89_WW][51] = 22, - [0][0][1][0][RTW89_WW][53] = 22, - [0][0][1][0][RTW89_WW][55] = 22, - [0][0][1][0][RTW89_WW][57] = 22, - [0][0][1][0][RTW89_WW][59] = 22, - [0][0][1][0][RTW89_WW][60] = 22, - [0][0][1][0][RTW89_WW][62] = 22, - [0][0][1][0][RTW89_WW][64] = 22, - [0][0][1][0][RTW89_WW][66] = 22, - [0][0][1][0][RTW89_WW][68] = 22, - [0][0][1][0][RTW89_WW][70] = 24, - [0][0][1][0][RTW89_WW][72] = 22, - [0][0][1][0][RTW89_WW][74] = 22, - [0][0][1][0][RTW89_WW][75] = 22, - [0][0][1][0][RTW89_WW][77] = 22, - [0][0][1][0][RTW89_WW][79] = 22, - [0][0][1][0][RTW89_WW][81] = 22, - [0][0][1][0][RTW89_WW][83] = 22, - [0][0][1][0][RTW89_WW][85] = 22, - [0][0][1][0][RTW89_WW][87] = 22, - [0][0][1][0][RTW89_WW][89] = 22, - [0][0][1][0][RTW89_WW][90] = 22, - [0][0][1][0][RTW89_WW][92] = 22, - [0][0][1][0][RTW89_WW][94] = 22, - [0][0][1][0][RTW89_WW][96] = 22, - [0][0][1][0][RTW89_WW][98] = 22, - [0][0][1][0][RTW89_WW][100] = 22, - [0][0][1][0][RTW89_WW][102] = 22, - [0][0][1][0][RTW89_WW][104] = 22, - [0][0][1][0][RTW89_WW][105] = 22, - [0][0][1][0][RTW89_WW][107] = 24, - [0][0][1][0][RTW89_WW][109] = 24, - [0][0][1][0][RTW89_WW][111] = 0, - [0][0][1][0][RTW89_WW][113] = 0, - [0][0][1][0][RTW89_WW][115] = 0, - [0][0][1][0][RTW89_WW][117] = 0, - [0][0][1][0][RTW89_WW][119] = 0, - [0][1][1][0][RTW89_WW][0] = -2, - [0][1][1][0][RTW89_WW][2] = -4, - [0][1][1][0][RTW89_WW][4] = -4, - [0][1][1][0][RTW89_WW][6] = -4, - [0][1][1][0][RTW89_WW][8] = -4, - [0][1][1][0][RTW89_WW][10] = -4, - [0][1][1][0][RTW89_WW][12] = -4, - [0][1][1][0][RTW89_WW][14] = -4, - [0][1][1][0][RTW89_WW][15] = -4, - [0][1][1][0][RTW89_WW][17] = -4, - [0][1][1][0][RTW89_WW][19] = -4, - [0][1][1][0][RTW89_WW][21] = -4, - [0][1][1][0][RTW89_WW][23] = -4, - [0][1][1][0][RTW89_WW][25] = -4, - [0][1][1][0][RTW89_WW][27] = -4, - [0][1][1][0][RTW89_WW][29] = -4, - [0][1][1][0][RTW89_WW][30] = -4, - [0][1][1][0][RTW89_WW][32] = -4, - [0][1][1][0][RTW89_WW][34] = -4, - [0][1][1][0][RTW89_WW][36] = -4, - [0][1][1][0][RTW89_WW][38] = -4, - [0][1][1][0][RTW89_WW][40] = -4, - [0][1][1][0][RTW89_WW][42] = -4, - [0][1][1][0][RTW89_WW][44] = -2, - [0][1][1][0][RTW89_WW][45] = -2, - [0][1][1][0][RTW89_WW][47] = -2, - [0][1][1][0][RTW89_WW][49] = -2, - [0][1][1][0][RTW89_WW][51] = -2, - [0][1][1][0][RTW89_WW][53] = -2, - [0][1][1][0][RTW89_WW][55] = -2, - [0][1][1][0][RTW89_WW][57] = -2, - [0][1][1][0][RTW89_WW][59] = -2, - [0][1][1][0][RTW89_WW][60] = -2, - [0][1][1][0][RTW89_WW][62] = -2, - [0][1][1][0][RTW89_WW][64] = -2, - [0][1][1][0][RTW89_WW][66] = -2, - [0][1][1][0][RTW89_WW][68] = -2, - [0][1][1][0][RTW89_WW][70] = -2, - [0][1][1][0][RTW89_WW][72] = -2, - [0][1][1][0][RTW89_WW][74] = -2, - [0][1][1][0][RTW89_WW][75] = -2, - [0][1][1][0][RTW89_WW][77] = -2, - [0][1][1][0][RTW89_WW][79] = -2, - [0][1][1][0][RTW89_WW][81] = -2, - [0][1][1][0][RTW89_WW][83] = -2, - [0][1][1][0][RTW89_WW][85] = -2, - [0][1][1][0][RTW89_WW][87] = -2, - [0][1][1][0][RTW89_WW][89] = -2, - [0][1][1][0][RTW89_WW][90] = -2, - [0][1][1][0][RTW89_WW][92] = -2, - [0][1][1][0][RTW89_WW][94] = -2, - [0][1][1][0][RTW89_WW][96] = -2, - [0][1][1][0][RTW89_WW][98] = -2, - [0][1][1][0][RTW89_WW][100] = -2, - [0][1][1][0][RTW89_WW][102] = -2, - [0][1][1][0][RTW89_WW][104] = -2, - [0][1][1][0][RTW89_WW][105] = -2, - [0][1][1][0][RTW89_WW][107] = 1, - [0][1][1][0][RTW89_WW][109] = 1, - [0][1][1][0][RTW89_WW][111] = 0, - [0][1][1][0][RTW89_WW][113] = 0, - [0][1][1][0][RTW89_WW][115] = 0, - [0][1][1][0][RTW89_WW][117] = 0, - [0][1][1][0][RTW89_WW][119] = 0, - [0][0][2][0][RTW89_WW][0] = 24, - [0][0][2][0][RTW89_WW][2] = 22, - [0][0][2][0][RTW89_WW][4] = 22, - [0][0][2][0][RTW89_WW][6] = 22, - [0][0][2][0][RTW89_WW][8] = 22, - [0][0][2][0][RTW89_WW][10] = 22, - [0][0][2][0][RTW89_WW][12] = 22, - [0][0][2][0][RTW89_WW][14] = 22, - [0][0][2][0][RTW89_WW][15] = 22, - [0][0][2][0][RTW89_WW][17] = 22, - [0][0][2][0][RTW89_WW][19] = 22, - [0][0][2][0][RTW89_WW][21] = 22, - [0][0][2][0][RTW89_WW][23] = 22, - [0][0][2][0][RTW89_WW][25] = 22, - [0][0][2][0][RTW89_WW][27] = 22, - [0][0][2][0][RTW89_WW][29] = 22, - [0][0][2][0][RTW89_WW][30] = 22, - [0][0][2][0][RTW89_WW][32] = 22, - [0][0][2][0][RTW89_WW][34] = 22, - [0][0][2][0][RTW89_WW][36] = 22, - [0][0][2][0][RTW89_WW][38] = 22, - [0][0][2][0][RTW89_WW][40] = 22, - [0][0][2][0][RTW89_WW][42] = 22, - [0][0][2][0][RTW89_WW][44] = 22, - [0][0][2][0][RTW89_WW][45] = 22, - [0][0][2][0][RTW89_WW][47] = 22, - [0][0][2][0][RTW89_WW][49] = 24, - [0][0][2][0][RTW89_WW][51] = 22, - [0][0][2][0][RTW89_WW][53] = 22, - [0][0][2][0][RTW89_WW][55] = 22, - [0][0][2][0][RTW89_WW][57] = 22, - [0][0][2][0][RTW89_WW][59] = 22, - [0][0][2][0][RTW89_WW][60] = 22, - [0][0][2][0][RTW89_WW][62] = 22, - [0][0][2][0][RTW89_WW][64] = 22, - [0][0][2][0][RTW89_WW][66] = 22, - [0][0][2][0][RTW89_WW][68] = 22, - [0][0][2][0][RTW89_WW][70] = 24, - [0][0][2][0][RTW89_WW][72] = 22, - [0][0][2][0][RTW89_WW][74] = 22, - [0][0][2][0][RTW89_WW][75] = 22, - [0][0][2][0][RTW89_WW][77] = 22, - [0][0][2][0][RTW89_WW][79] = 22, - [0][0][2][0][RTW89_WW][81] = 22, - [0][0][2][0][RTW89_WW][83] = 22, - [0][0][2][0][RTW89_WW][85] = 22, - [0][0][2][0][RTW89_WW][87] = 22, - [0][0][2][0][RTW89_WW][89] = 22, - [0][0][2][0][RTW89_WW][90] = 22, - [0][0][2][0][RTW89_WW][92] = 22, - [0][0][2][0][RTW89_WW][94] = 22, - [0][0][2][0][RTW89_WW][96] = 22, - [0][0][2][0][RTW89_WW][98] = 22, - [0][0][2][0][RTW89_WW][100] = 22, - [0][0][2][0][RTW89_WW][102] = 22, - [0][0][2][0][RTW89_WW][104] = 22, - [0][0][2][0][RTW89_WW][105] = 22, - [0][0][2][0][RTW89_WW][107] = 24, - [0][0][2][0][RTW89_WW][109] = 24, - [0][0][2][0][RTW89_WW][111] = 0, - [0][0][2][0][RTW89_WW][113] = 0, - [0][0][2][0][RTW89_WW][115] = 0, - [0][0][2][0][RTW89_WW][117] = 0, - [0][0][2][0][RTW89_WW][119] = 0, - [0][1][2][0][RTW89_WW][0] = -2, - [0][1][2][0][RTW89_WW][2] = -4, - [0][1][2][0][RTW89_WW][4] = -4, - [0][1][2][0][RTW89_WW][6] = -4, - [0][1][2][0][RTW89_WW][8] = -4, - [0][1][2][0][RTW89_WW][10] = -4, - [0][1][2][0][RTW89_WW][12] = -4, - [0][1][2][0][RTW89_WW][14] = -4, - [0][1][2][0][RTW89_WW][15] = -4, - [0][1][2][0][RTW89_WW][17] = -4, - [0][1][2][0][RTW89_WW][19] = -4, - [0][1][2][0][RTW89_WW][21] = -4, - [0][1][2][0][RTW89_WW][23] = -4, - [0][1][2][0][RTW89_WW][25] = -4, - [0][1][2][0][RTW89_WW][27] = -4, - [0][1][2][0][RTW89_WW][29] = -4, - [0][1][2][0][RTW89_WW][30] = -4, - [0][1][2][0][RTW89_WW][32] = -4, - [0][1][2][0][RTW89_WW][34] = -4, - [0][1][2][0][RTW89_WW][36] = -4, - [0][1][2][0][RTW89_WW][38] = -4, - [0][1][2][0][RTW89_WW][40] = -4, - [0][1][2][0][RTW89_WW][42] = -4, - [0][1][2][0][RTW89_WW][44] = -2, - [0][1][2][0][RTW89_WW][45] = -2, - [0][1][2][0][RTW89_WW][47] = -2, - [0][1][2][0][RTW89_WW][49] = -2, - [0][1][2][0][RTW89_WW][51] = -2, - [0][1][2][0][RTW89_WW][53] = -2, - [0][1][2][0][RTW89_WW][55] = -2, - [0][1][2][0][RTW89_WW][57] = -2, - [0][1][2][0][RTW89_WW][59] = -2, - [0][1][2][0][RTW89_WW][60] = -2, - [0][1][2][0][RTW89_WW][62] = -2, - [0][1][2][0][RTW89_WW][64] = -2, - [0][1][2][0][RTW89_WW][66] = -2, - [0][1][2][0][RTW89_WW][68] = -2, - [0][1][2][0][RTW89_WW][70] = -2, - [0][1][2][0][RTW89_WW][72] = -2, - [0][1][2][0][RTW89_WW][74] = -2, - [0][1][2][0][RTW89_WW][75] = -2, - [0][1][2][0][RTW89_WW][77] = -2, - [0][1][2][0][RTW89_WW][79] = -2, - [0][1][2][0][RTW89_WW][81] = -2, - [0][1][2][0][RTW89_WW][83] = -2, - [0][1][2][0][RTW89_WW][85] = -2, - [0][1][2][0][RTW89_WW][87] = -2, - [0][1][2][0][RTW89_WW][89] = -2, - [0][1][2][0][RTW89_WW][90] = -2, - [0][1][2][0][RTW89_WW][92] = -2, - [0][1][2][0][RTW89_WW][94] = -2, - [0][1][2][0][RTW89_WW][96] = -2, - [0][1][2][0][RTW89_WW][98] = -2, - [0][1][2][0][RTW89_WW][100] = -2, - [0][1][2][0][RTW89_WW][102] = -2, - [0][1][2][0][RTW89_WW][104] = -2, - [0][1][2][0][RTW89_WW][105] = -2, - [0][1][2][0][RTW89_WW][107] = 1, - [0][1][2][0][RTW89_WW][109] = 1, - [0][1][2][0][RTW89_WW][111] = 0, - [0][1][2][0][RTW89_WW][113] = 0, - [0][1][2][0][RTW89_WW][115] = 0, - [0][1][2][0][RTW89_WW][117] = 0, - [0][1][2][0][RTW89_WW][119] = 0, - [0][1][2][1][RTW89_WW][0] = -2, - [0][1][2][1][RTW89_WW][2] = -4, - [0][1][2][1][RTW89_WW][4] = -4, - [0][1][2][1][RTW89_WW][6] = -4, - [0][1][2][1][RTW89_WW][8] = -4, - [0][1][2][1][RTW89_WW][10] = -4, - [0][1][2][1][RTW89_WW][12] = -4, - [0][1][2][1][RTW89_WW][14] = -4, - [0][1][2][1][RTW89_WW][15] = -4, - [0][1][2][1][RTW89_WW][17] = -4, - [0][1][2][1][RTW89_WW][19] = -4, - [0][1][2][1][RTW89_WW][21] = -4, - [0][1][2][1][RTW89_WW][23] = -4, - [0][1][2][1][RTW89_WW][25] = -4, - [0][1][2][1][RTW89_WW][27] = -4, - [0][1][2][1][RTW89_WW][29] = -4, - [0][1][2][1][RTW89_WW][30] = -4, - [0][1][2][1][RTW89_WW][32] = -4, - [0][1][2][1][RTW89_WW][34] = -4, - [0][1][2][1][RTW89_WW][36] = -4, - [0][1][2][1][RTW89_WW][38] = -4, - [0][1][2][1][RTW89_WW][40] = -4, - [0][1][2][1][RTW89_WW][42] = -4, - [0][1][2][1][RTW89_WW][44] = -2, - [0][1][2][1][RTW89_WW][45] = -2, - [0][1][2][1][RTW89_WW][47] = -2, - [0][1][2][1][RTW89_WW][49] = -2, - [0][1][2][1][RTW89_WW][51] = -2, - [0][1][2][1][RTW89_WW][53] = -2, - [0][1][2][1][RTW89_WW][55] = -2, - [0][1][2][1][RTW89_WW][57] = -2, - [0][1][2][1][RTW89_WW][59] = -2, - [0][1][2][1][RTW89_WW][60] = -2, - [0][1][2][1][RTW89_WW][62] = -2, - [0][1][2][1][RTW89_WW][64] = -2, - [0][1][2][1][RTW89_WW][66] = -2, - [0][1][2][1][RTW89_WW][68] = -2, - [0][1][2][1][RTW89_WW][70] = -2, - [0][1][2][1][RTW89_WW][72] = -2, - [0][1][2][1][RTW89_WW][74] = -2, - [0][1][2][1][RTW89_WW][75] = -2, - [0][1][2][1][RTW89_WW][77] = -2, - [0][1][2][1][RTW89_WW][79] = -2, - [0][1][2][1][RTW89_WW][81] = -2, - [0][1][2][1][RTW89_WW][83] = -2, - [0][1][2][1][RTW89_WW][85] = -2, - [0][1][2][1][RTW89_WW][87] = -2, - [0][1][2][1][RTW89_WW][89] = -2, - [0][1][2][1][RTW89_WW][90] = -2, - [0][1][2][1][RTW89_WW][92] = -2, - [0][1][2][1][RTW89_WW][94] = -2, - [0][1][2][1][RTW89_WW][96] = -2, - [0][1][2][1][RTW89_WW][98] = -2, - [0][1][2][1][RTW89_WW][100] = -2, - [0][1][2][1][RTW89_WW][102] = -2, - [0][1][2][1][RTW89_WW][104] = -2, - [0][1][2][1][RTW89_WW][105] = -2, - [0][1][2][1][RTW89_WW][107] = 1, - [0][1][2][1][RTW89_WW][109] = 1, - [0][1][2][1][RTW89_WW][111] = 0, - [0][1][2][1][RTW89_WW][113] = 0, - [0][1][2][1][RTW89_WW][115] = 0, - [0][1][2][1][RTW89_WW][117] = 0, - [0][1][2][1][RTW89_WW][119] = 0, - [1][0][2][0][RTW89_WW][1] = 34, - [1][0][2][0][RTW89_WW][5] = 34, - [1][0][2][0][RTW89_WW][9] = 34, - [1][0][2][0][RTW89_WW][13] = 34, - [1][0][2][0][RTW89_WW][16] = 34, - [1][0][2][0][RTW89_WW][20] = 34, - [1][0][2][0][RTW89_WW][24] = 36, - [1][0][2][0][RTW89_WW][28] = 34, - [1][0][2][0][RTW89_WW][31] = 34, - [1][0][2][0][RTW89_WW][35] = 34, - [1][0][2][0][RTW89_WW][39] = 34, - [1][0][2][0][RTW89_WW][43] = 34, - [1][0][2][0][RTW89_WW][46] = 34, - [1][0][2][0][RTW89_WW][50] = 34, - [1][0][2][0][RTW89_WW][54] = 36, - [1][0][2][0][RTW89_WW][58] = 36, - [1][0][2][0][RTW89_WW][61] = 34, - [1][0][2][0][RTW89_WW][65] = 34, - [1][0][2][0][RTW89_WW][69] = 34, - [1][0][2][0][RTW89_WW][73] = 34, - [1][0][2][0][RTW89_WW][76] = 34, - [1][0][2][0][RTW89_WW][80] = 34, - [1][0][2][0][RTW89_WW][84] = 34, - [1][0][2][0][RTW89_WW][88] = 34, - [1][0][2][0][RTW89_WW][91] = 36, - [1][0][2][0][RTW89_WW][95] = 34, - [1][0][2][0][RTW89_WW][99] = 34, - [1][0][2][0][RTW89_WW][103] = 34, - [1][0][2][0][RTW89_WW][106] = 36, - [1][0][2][0][RTW89_WW][110] = 0, - [1][0][2][0][RTW89_WW][114] = 0, - [1][0][2][0][RTW89_WW][118] = 0, - [1][1][2][0][RTW89_WW][1] = 10, - [1][1][2][0][RTW89_WW][5] = 10, - [1][1][2][0][RTW89_WW][9] = 10, - [1][1][2][0][RTW89_WW][13] = 10, - [1][1][2][0][RTW89_WW][16] = 10, - [1][1][2][0][RTW89_WW][20] = 10, - [1][1][2][0][RTW89_WW][24] = 10, - [1][1][2][0][RTW89_WW][28] = 10, - [1][1][2][0][RTW89_WW][31] = 10, - [1][1][2][0][RTW89_WW][35] = 10, - [1][1][2][0][RTW89_WW][39] = 10, - [1][1][2][0][RTW89_WW][43] = 10, - [1][1][2][0][RTW89_WW][46] = 12, - [1][1][2][0][RTW89_WW][50] = 12, - [1][1][2][0][RTW89_WW][54] = 10, - [1][1][2][0][RTW89_WW][58] = 10, - [1][1][2][0][RTW89_WW][61] = 10, - [1][1][2][0][RTW89_WW][65] = 10, - [1][1][2][0][RTW89_WW][69] = 10, - [1][1][2][0][RTW89_WW][73] = 10, - [1][1][2][0][RTW89_WW][76] = 10, - [1][1][2][0][RTW89_WW][80] = 10, - [1][1][2][0][RTW89_WW][84] = 10, - [1][1][2][0][RTW89_WW][88] = 10, - [1][1][2][0][RTW89_WW][91] = 12, - [1][1][2][0][RTW89_WW][95] = 10, - [1][1][2][0][RTW89_WW][99] = 10, - [1][1][2][0][RTW89_WW][103] = 10, - [1][1][2][0][RTW89_WW][106] = 12, - [1][1][2][0][RTW89_WW][110] = 0, - [1][1][2][0][RTW89_WW][114] = 0, - [1][1][2][0][RTW89_WW][118] = 0, - [1][1][2][1][RTW89_WW][1] = 10, - [1][1][2][1][RTW89_WW][5] = 10, - [1][1][2][1][RTW89_WW][9] = 10, - [1][1][2][1][RTW89_WW][13] = 10, - [1][1][2][1][RTW89_WW][16] = 10, - [1][1][2][1][RTW89_WW][20] = 10, - [1][1][2][1][RTW89_WW][24] = 10, - [1][1][2][1][RTW89_WW][28] = 10, - [1][1][2][1][RTW89_WW][31] = 10, - [1][1][2][1][RTW89_WW][35] = 10, - [1][1][2][1][RTW89_WW][39] = 10, - [1][1][2][1][RTW89_WW][43] = 10, - [1][1][2][1][RTW89_WW][46] = 12, - [1][1][2][1][RTW89_WW][50] = 12, - [1][1][2][1][RTW89_WW][54] = 10, - [1][1][2][1][RTW89_WW][58] = 10, - [1][1][2][1][RTW89_WW][61] = 10, - [1][1][2][1][RTW89_WW][65] = 10, - [1][1][2][1][RTW89_WW][69] = 10, - [1][1][2][1][RTW89_WW][73] = 10, - [1][1][2][1][RTW89_WW][76] = 10, - [1][1][2][1][RTW89_WW][80] = 10, - [1][1][2][1][RTW89_WW][84] = 10, - [1][1][2][1][RTW89_WW][88] = 10, - [1][1][2][1][RTW89_WW][91] = 12, - [1][1][2][1][RTW89_WW][95] = 10, - [1][1][2][1][RTW89_WW][99] = 10, - [1][1][2][1][RTW89_WW][103] = 10, - [1][1][2][1][RTW89_WW][106] = 12, - [1][1][2][1][RTW89_WW][110] = 0, - [1][1][2][1][RTW89_WW][114] = 0, - [1][1][2][1][RTW89_WW][118] = 0, - [2][0][2][0][RTW89_WW][3] = 46, - [2][0][2][0][RTW89_WW][11] = 46, - [2][0][2][0][RTW89_WW][18] = 46, - [2][0][2][0][RTW89_WW][26] = 46, - [2][0][2][0][RTW89_WW][33] = 46, - [2][0][2][0][RTW89_WW][41] = 46, - [2][0][2][0][RTW89_WW][48] = 46, - [2][0][2][0][RTW89_WW][56] = 46, - [2][0][2][0][RTW89_WW][63] = 46, - [2][0][2][0][RTW89_WW][71] = 46, - [2][0][2][0][RTW89_WW][78] = 46, - [2][0][2][0][RTW89_WW][86] = 46, - [2][0][2][0][RTW89_WW][93] = 46, - [2][0][2][0][RTW89_WW][101] = 44, - [2][0][2][0][RTW89_WW][108] = 0, - [2][0][2][0][RTW89_WW][116] = 0, - [2][1][2][0][RTW89_WW][3] = 22, - [2][1][2][0][RTW89_WW][11] = 20, - [2][1][2][0][RTW89_WW][18] = 20, - [2][1][2][0][RTW89_WW][26] = 20, - [2][1][2][0][RTW89_WW][33] = 20, - [2][1][2][0][RTW89_WW][41] = 22, - [2][1][2][0][RTW89_WW][48] = 22, - [2][1][2][0][RTW89_WW][56] = 20, - [2][1][2][0][RTW89_WW][63] = 22, - [2][1][2][0][RTW89_WW][71] = 20, - [2][1][2][0][RTW89_WW][78] = 20, - [2][1][2][0][RTW89_WW][86] = 20, - [2][1][2][0][RTW89_WW][93] = 22, - [2][1][2][0][RTW89_WW][101] = 22, - [2][1][2][0][RTW89_WW][108] = 0, - [2][1][2][0][RTW89_WW][116] = 0, - [2][1][2][1][RTW89_WW][3] = 22, - [2][1][2][1][RTW89_WW][11] = 20, - [2][1][2][1][RTW89_WW][18] = 20, - [2][1][2][1][RTW89_WW][26] = 20, - [2][1][2][1][RTW89_WW][33] = 20, - [2][1][2][1][RTW89_WW][41] = 22, - [2][1][2][1][RTW89_WW][48] = 22, - [2][1][2][1][RTW89_WW][56] = 20, - [2][1][2][1][RTW89_WW][63] = 22, - [2][1][2][1][RTW89_WW][71] = 20, - [2][1][2][1][RTW89_WW][78] = 20, - [2][1][2][1][RTW89_WW][86] = 20, - [2][1][2][1][RTW89_WW][93] = 22, - [2][1][2][1][RTW89_WW][101] = 22, - [2][1][2][1][RTW89_WW][108] = 0, - [2][1][2][1][RTW89_WW][116] = 0, - [3][0][2][0][RTW89_WW][7] = 38, - [3][0][2][0][RTW89_WW][22] = 38, - [3][0][2][0][RTW89_WW][37] = 38, - [3][0][2][0][RTW89_WW][52] = 54, - [3][0][2][0][RTW89_WW][67] = 54, - [3][0][2][0][RTW89_WW][82] = 26, - [3][0][2][0][RTW89_WW][97] = 26, - [3][0][2][0][RTW89_WW][112] = 0, - [3][1][2][0][RTW89_WW][7] = 32, - [3][1][2][0][RTW89_WW][22] = 30, - [3][1][2][0][RTW89_WW][37] = 30, - [3][1][2][0][RTW89_WW][52] = 30, - [3][1][2][0][RTW89_WW][67] = 32, - [3][1][2][0][RTW89_WW][82] = 24, - [3][1][2][0][RTW89_WW][97] = 14, - [3][1][2][0][RTW89_WW][112] = 0, - [3][1][2][1][RTW89_WW][7] = 32, - [3][1][2][1][RTW89_WW][22] = 30, - [3][1][2][1][RTW89_WW][37] = 30, - [3][1][2][1][RTW89_WW][52] = 30, - [3][1][2][1][RTW89_WW][67] = 32, - [3][1][2][1][RTW89_WW][82] = 24, - [3][1][2][1][RTW89_WW][97] = 14, - [3][1][2][1][RTW89_WW][112] = 0, - [0][0][1][0][RTW89_FCC][0] = 24, - [0][0][1][0][RTW89_ETSI][0] = 66, - [0][0][1][0][RTW89_KCC][0] = 24, - [0][0][1][0][RTW89_FCC][2] = 22, - [0][0][1][0][RTW89_ETSI][2] = 66, - [0][0][1][0][RTW89_KCC][2] = 24, - [0][0][1][0][RTW89_FCC][4] = 22, - [0][0][1][0][RTW89_ETSI][4] = 66, - [0][0][1][0][RTW89_KCC][4] = 24, - [0][0][1][0][RTW89_FCC][6] = 22, - [0][0][1][0][RTW89_ETSI][6] = 66, - [0][0][1][0][RTW89_KCC][6] = 24, - [0][0][1][0][RTW89_FCC][8] = 22, - [0][0][1][0][RTW89_ETSI][8] = 66, - [0][0][1][0][RTW89_KCC][8] = 24, - [0][0][1][0][RTW89_FCC][10] = 22, - [0][0][1][0][RTW89_ETSI][10] = 66, - [0][0][1][0][RTW89_KCC][10] = 24, - [0][0][1][0][RTW89_FCC][12] = 22, - [0][0][1][0][RTW89_ETSI][12] = 66, - [0][0][1][0][RTW89_KCC][12] = 24, - [0][0][1][0][RTW89_FCC][14] = 22, - [0][0][1][0][RTW89_ETSI][14] = 66, - [0][0][1][0][RTW89_KCC][14] = 24, - [0][0][1][0][RTW89_FCC][15] = 22, - [0][0][1][0][RTW89_ETSI][15] = 66, - [0][0][1][0][RTW89_KCC][15] = 24, - [0][0][1][0][RTW89_FCC][17] = 22, - [0][0][1][0][RTW89_ETSI][17] = 66, - [0][0][1][0][RTW89_KCC][17] = 24, - [0][0][1][0][RTW89_FCC][19] = 22, - [0][0][1][0][RTW89_ETSI][19] = 66, - [0][0][1][0][RTW89_KCC][19] = 24, - [0][0][1][0][RTW89_FCC][21] = 22, - [0][0][1][0][RTW89_ETSI][21] = 66, - [0][0][1][0][RTW89_KCC][21] = 24, - [0][0][1][0][RTW89_FCC][23] = 22, - [0][0][1][0][RTW89_ETSI][23] = 66, - [0][0][1][0][RTW89_KCC][23] = 24, - [0][0][1][0][RTW89_FCC][25] = 22, - [0][0][1][0][RTW89_ETSI][25] = 66, - [0][0][1][0][RTW89_KCC][25] = 24, - [0][0][1][0][RTW89_FCC][27] = 22, - [0][0][1][0][RTW89_ETSI][27] = 66, - [0][0][1][0][RTW89_KCC][27] = 24, - [0][0][1][0][RTW89_FCC][29] = 22, - [0][0][1][0][RTW89_ETSI][29] = 66, - [0][0][1][0][RTW89_KCC][29] = 24, - [0][0][1][0][RTW89_FCC][30] = 22, - [0][0][1][0][RTW89_ETSI][30] = 66, - [0][0][1][0][RTW89_KCC][30] = 24, - [0][0][1][0][RTW89_FCC][32] = 22, - [0][0][1][0][RTW89_ETSI][32] = 66, - [0][0][1][0][RTW89_KCC][32] = 24, - [0][0][1][0][RTW89_FCC][34] = 22, - [0][0][1][0][RTW89_ETSI][34] = 66, - [0][0][1][0][RTW89_KCC][34] = 24, - [0][0][1][0][RTW89_FCC][36] = 22, - [0][0][1][0][RTW89_ETSI][36] = 66, - [0][0][1][0][RTW89_KCC][36] = 24, - [0][0][1][0][RTW89_FCC][38] = 22, - [0][0][1][0][RTW89_ETSI][38] = 66, - [0][0][1][0][RTW89_KCC][38] = 24, - [0][0][1][0][RTW89_FCC][40] = 22, - [0][0][1][0][RTW89_ETSI][40] = 66, - [0][0][1][0][RTW89_KCC][40] = 24, - [0][0][1][0][RTW89_FCC][42] = 22, - [0][0][1][0][RTW89_ETSI][42] = 66, - [0][0][1][0][RTW89_KCC][42] = 24, - [0][0][1][0][RTW89_FCC][44] = 22, - [0][0][1][0][RTW89_ETSI][44] = 66, - [0][0][1][0][RTW89_KCC][44] = 24, - [0][0][1][0][RTW89_FCC][45] = 22, - [0][0][1][0][RTW89_ETSI][45] = 127, - [0][0][1][0][RTW89_KCC][45] = 24, - [0][0][1][0][RTW89_FCC][47] = 22, - [0][0][1][0][RTW89_ETSI][47] = 127, - [0][0][1][0][RTW89_KCC][47] = 24, - [0][0][1][0][RTW89_FCC][49] = 24, - [0][0][1][0][RTW89_ETSI][49] = 127, - [0][0][1][0][RTW89_KCC][49] = 24, - [0][0][1][0][RTW89_FCC][51] = 22, - [0][0][1][0][RTW89_ETSI][51] = 127, - [0][0][1][0][RTW89_KCC][51] = 24, - [0][0][1][0][RTW89_FCC][53] = 22, - [0][0][1][0][RTW89_ETSI][53] = 127, - [0][0][1][0][RTW89_KCC][53] = 24, - [0][0][1][0][RTW89_FCC][55] = 22, - [0][0][1][0][RTW89_ETSI][55] = 127, - [0][0][1][0][RTW89_KCC][55] = 26, - [0][0][1][0][RTW89_FCC][57] = 22, - [0][0][1][0][RTW89_ETSI][57] = 127, - [0][0][1][0][RTW89_KCC][57] = 26, - [0][0][1][0][RTW89_FCC][59] = 22, - [0][0][1][0][RTW89_ETSI][59] = 127, - [0][0][1][0][RTW89_KCC][59] = 26, - [0][0][1][0][RTW89_FCC][60] = 22, - [0][0][1][0][RTW89_ETSI][60] = 127, - [0][0][1][0][RTW89_KCC][60] = 26, - [0][0][1][0][RTW89_FCC][62] = 22, - [0][0][1][0][RTW89_ETSI][62] = 127, - [0][0][1][0][RTW89_KCC][62] = 26, - [0][0][1][0][RTW89_FCC][64] = 22, - [0][0][1][0][RTW89_ETSI][64] = 127, - [0][0][1][0][RTW89_KCC][64] = 26, - [0][0][1][0][RTW89_FCC][66] = 22, - [0][0][1][0][RTW89_ETSI][66] = 127, - [0][0][1][0][RTW89_KCC][66] = 26, - [0][0][1][0][RTW89_FCC][68] = 22, - [0][0][1][0][RTW89_ETSI][68] = 127, - [0][0][1][0][RTW89_KCC][68] = 26, - [0][0][1][0][RTW89_FCC][70] = 24, - [0][0][1][0][RTW89_ETSI][70] = 127, - [0][0][1][0][RTW89_KCC][70] = 26, - [0][0][1][0][RTW89_FCC][72] = 22, - [0][0][1][0][RTW89_ETSI][72] = 127, - [0][0][1][0][RTW89_KCC][72] = 26, - [0][0][1][0][RTW89_FCC][74] = 22, - [0][0][1][0][RTW89_ETSI][74] = 127, - [0][0][1][0][RTW89_KCC][74] = 26, - [0][0][1][0][RTW89_FCC][75] = 22, - [0][0][1][0][RTW89_ETSI][75] = 127, - [0][0][1][0][RTW89_KCC][75] = 26, - [0][0][1][0][RTW89_FCC][77] = 22, - [0][0][1][0][RTW89_ETSI][77] = 127, - [0][0][1][0][RTW89_KCC][77] = 26, - [0][0][1][0][RTW89_FCC][79] = 22, - [0][0][1][0][RTW89_ETSI][79] = 127, - [0][0][1][0][RTW89_KCC][79] = 26, - [0][0][1][0][RTW89_FCC][81] = 22, - [0][0][1][0][RTW89_ETSI][81] = 127, - [0][0][1][0][RTW89_KCC][81] = 26, - [0][0][1][0][RTW89_FCC][83] = 22, - [0][0][1][0][RTW89_ETSI][83] = 127, - [0][0][1][0][RTW89_KCC][83] = 32, - [0][0][1][0][RTW89_FCC][85] = 22, - [0][0][1][0][RTW89_ETSI][85] = 127, - [0][0][1][0][RTW89_KCC][85] = 32, - [0][0][1][0][RTW89_FCC][87] = 22, - [0][0][1][0][RTW89_ETSI][87] = 127, - [0][0][1][0][RTW89_KCC][87] = 32, - [0][0][1][0][RTW89_FCC][89] = 22, - [0][0][1][0][RTW89_ETSI][89] = 127, - [0][0][1][0][RTW89_KCC][89] = 32, - [0][0][1][0][RTW89_FCC][90] = 22, - [0][0][1][0][RTW89_ETSI][90] = 127, - [0][0][1][0][RTW89_KCC][90] = 32, - [0][0][1][0][RTW89_FCC][92] = 22, - [0][0][1][0][RTW89_ETSI][92] = 127, - [0][0][1][0][RTW89_KCC][92] = 32, - [0][0][1][0][RTW89_FCC][94] = 22, - [0][0][1][0][RTW89_ETSI][94] = 127, - [0][0][1][0][RTW89_KCC][94] = 32, - [0][0][1][0][RTW89_FCC][96] = 22, - [0][0][1][0][RTW89_ETSI][96] = 127, - [0][0][1][0][RTW89_KCC][96] = 32, - [0][0][1][0][RTW89_FCC][98] = 22, - [0][0][1][0][RTW89_ETSI][98] = 127, - [0][0][1][0][RTW89_KCC][98] = 32, - [0][0][1][0][RTW89_FCC][100] = 22, - [0][0][1][0][RTW89_ETSI][100] = 127, - [0][0][1][0][RTW89_KCC][100] = 32, - [0][0][1][0][RTW89_FCC][102] = 22, - [0][0][1][0][RTW89_ETSI][102] = 127, - [0][0][1][0][RTW89_KCC][102] = 32, - [0][0][1][0][RTW89_FCC][104] = 22, - [0][0][1][0][RTW89_ETSI][104] = 127, - [0][0][1][0][RTW89_KCC][104] = 32, - [0][0][1][0][RTW89_FCC][105] = 22, - [0][0][1][0][RTW89_ETSI][105] = 127, - [0][0][1][0][RTW89_KCC][105] = 32, - [0][0][1][0][RTW89_FCC][107] = 24, - [0][0][1][0][RTW89_ETSI][107] = 127, - [0][0][1][0][RTW89_KCC][107] = 32, - [0][0][1][0][RTW89_FCC][109] = 24, - [0][0][1][0][RTW89_ETSI][109] = 127, - [0][0][1][0][RTW89_KCC][109] = 32, - [0][0][1][0][RTW89_FCC][111] = 127, - [0][0][1][0][RTW89_ETSI][111] = 127, - [0][0][1][0][RTW89_KCC][111] = 127, - [0][0][1][0][RTW89_FCC][113] = 127, - [0][0][1][0][RTW89_ETSI][113] = 127, - [0][0][1][0][RTW89_KCC][113] = 127, - [0][0][1][0][RTW89_FCC][115] = 127, - [0][0][1][0][RTW89_ETSI][115] = 127, - [0][0][1][0][RTW89_KCC][115] = 127, - [0][0][1][0][RTW89_FCC][117] = 127, - [0][0][1][0][RTW89_ETSI][117] = 127, - [0][0][1][0][RTW89_KCC][117] = 127, - [0][0][1][0][RTW89_FCC][119] = 127, - [0][0][1][0][RTW89_ETSI][119] = 127, - [0][0][1][0][RTW89_KCC][119] = 127, - [0][1][1][0][RTW89_FCC][0] = -2, - [0][1][1][0][RTW89_ETSI][0] = 54, - [0][1][1][0][RTW89_KCC][0] = 12, - [0][1][1][0][RTW89_FCC][2] = -4, - [0][1][1][0][RTW89_ETSI][2] = 54, - [0][1][1][0][RTW89_KCC][2] = 12, - [0][1][1][0][RTW89_FCC][4] = -4, - [0][1][1][0][RTW89_ETSI][4] = 54, - [0][1][1][0][RTW89_KCC][4] = 12, - [0][1][1][0][RTW89_FCC][6] = -4, - [0][1][1][0][RTW89_ETSI][6] = 54, - [0][1][1][0][RTW89_KCC][6] = 12, - [0][1][1][0][RTW89_FCC][8] = -4, - [0][1][1][0][RTW89_ETSI][8] = 54, - [0][1][1][0][RTW89_KCC][8] = 12, - [0][1][1][0][RTW89_FCC][10] = -4, - [0][1][1][0][RTW89_ETSI][10] = 54, - [0][1][1][0][RTW89_KCC][10] = 12, - [0][1][1][0][RTW89_FCC][12] = -4, - [0][1][1][0][RTW89_ETSI][12] = 54, - [0][1][1][0][RTW89_KCC][12] = 12, - [0][1][1][0][RTW89_FCC][14] = -4, - [0][1][1][0][RTW89_ETSI][14] = 54, - [0][1][1][0][RTW89_KCC][14] = 12, - [0][1][1][0][RTW89_FCC][15] = -4, - [0][1][1][0][RTW89_ETSI][15] = 54, - [0][1][1][0][RTW89_KCC][15] = 12, - [0][1][1][0][RTW89_FCC][17] = -4, - [0][1][1][0][RTW89_ETSI][17] = 54, - [0][1][1][0][RTW89_KCC][17] = 12, - [0][1][1][0][RTW89_FCC][19] = -4, - [0][1][1][0][RTW89_ETSI][19] = 54, - [0][1][1][0][RTW89_KCC][19] = 12, - [0][1][1][0][RTW89_FCC][21] = -4, - [0][1][1][0][RTW89_ETSI][21] = 54, - [0][1][1][0][RTW89_KCC][21] = 12, - [0][1][1][0][RTW89_FCC][23] = -4, - [0][1][1][0][RTW89_ETSI][23] = 54, - [0][1][1][0][RTW89_KCC][23] = 12, - [0][1][1][0][RTW89_FCC][25] = -4, - [0][1][1][0][RTW89_ETSI][25] = 54, - [0][1][1][0][RTW89_KCC][25] = 12, - [0][1][1][0][RTW89_FCC][27] = -4, - [0][1][1][0][RTW89_ETSI][27] = 54, - [0][1][1][0][RTW89_KCC][27] = 12, - [0][1][1][0][RTW89_FCC][29] = -4, - [0][1][1][0][RTW89_ETSI][29] = 54, - [0][1][1][0][RTW89_KCC][29] = 12, - [0][1][1][0][RTW89_FCC][30] = -4, - [0][1][1][0][RTW89_ETSI][30] = 54, - [0][1][1][0][RTW89_KCC][30] = 12, - [0][1][1][0][RTW89_FCC][32] = -4, - [0][1][1][0][RTW89_ETSI][32] = 54, - [0][1][1][0][RTW89_KCC][32] = 12, - [0][1][1][0][RTW89_FCC][34] = -4, - [0][1][1][0][RTW89_ETSI][34] = 54, - [0][1][1][0][RTW89_KCC][34] = 12, - [0][1][1][0][RTW89_FCC][36] = -4, - [0][1][1][0][RTW89_ETSI][36] = 54, - [0][1][1][0][RTW89_KCC][36] = 12, - [0][1][1][0][RTW89_FCC][38] = -4, - [0][1][1][0][RTW89_ETSI][38] = 54, - [0][1][1][0][RTW89_KCC][38] = 12, - [0][1][1][0][RTW89_FCC][40] = -4, - [0][1][1][0][RTW89_ETSI][40] = 54, - [0][1][1][0][RTW89_KCC][40] = 12, - [0][1][1][0][RTW89_FCC][42] = -4, - [0][1][1][0][RTW89_ETSI][42] = 54, - [0][1][1][0][RTW89_KCC][42] = 12, - [0][1][1][0][RTW89_FCC][44] = -2, - [0][1][1][0][RTW89_ETSI][44] = 54, - [0][1][1][0][RTW89_KCC][44] = 12, - [0][1][1][0][RTW89_FCC][45] = -2, - [0][1][1][0][RTW89_ETSI][45] = 127, - [0][1][1][0][RTW89_KCC][45] = 12, - [0][1][1][0][RTW89_FCC][47] = -2, - [0][1][1][0][RTW89_ETSI][47] = 127, - [0][1][1][0][RTW89_KCC][47] = 12, - [0][1][1][0][RTW89_FCC][49] = -2, - [0][1][1][0][RTW89_ETSI][49] = 127, - [0][1][1][0][RTW89_KCC][49] = 12, - [0][1][1][0][RTW89_FCC][51] = -2, - [0][1][1][0][RTW89_ETSI][51] = 127, - [0][1][1][0][RTW89_KCC][51] = 12, - [0][1][1][0][RTW89_FCC][53] = -2, - [0][1][1][0][RTW89_ETSI][53] = 127, - [0][1][1][0][RTW89_KCC][53] = 12, - [0][1][1][0][RTW89_FCC][55] = -2, - [0][1][1][0][RTW89_ETSI][55] = 127, - [0][1][1][0][RTW89_KCC][55] = 12, - [0][1][1][0][RTW89_FCC][57] = -2, - [0][1][1][0][RTW89_ETSI][57] = 127, - [0][1][1][0][RTW89_KCC][57] = 12, - [0][1][1][0][RTW89_FCC][59] = -2, - [0][1][1][0][RTW89_ETSI][59] = 127, - [0][1][1][0][RTW89_KCC][59] = 12, - [0][1][1][0][RTW89_FCC][60] = -2, - [0][1][1][0][RTW89_ETSI][60] = 127, - [0][1][1][0][RTW89_KCC][60] = 12, - [0][1][1][0][RTW89_FCC][62] = -2, - [0][1][1][0][RTW89_ETSI][62] = 127, - [0][1][1][0][RTW89_KCC][62] = 12, - [0][1][1][0][RTW89_FCC][64] = -2, - [0][1][1][0][RTW89_ETSI][64] = 127, - [0][1][1][0][RTW89_KCC][64] = 12, - [0][1][1][0][RTW89_FCC][66] = -2, - [0][1][1][0][RTW89_ETSI][66] = 127, - [0][1][1][0][RTW89_KCC][66] = 12, - [0][1][1][0][RTW89_FCC][68] = -2, - [0][1][1][0][RTW89_ETSI][68] = 127, - [0][1][1][0][RTW89_KCC][68] = 12, - [0][1][1][0][RTW89_FCC][70] = -2, - [0][1][1][0][RTW89_ETSI][70] = 127, - [0][1][1][0][RTW89_KCC][70] = 12, - [0][1][1][0][RTW89_FCC][72] = -2, - [0][1][1][0][RTW89_ETSI][72] = 127, - [0][1][1][0][RTW89_KCC][72] = 12, - [0][1][1][0][RTW89_FCC][74] = -2, - [0][1][1][0][RTW89_ETSI][74] = 127, - [0][1][1][0][RTW89_KCC][74] = 12, - [0][1][1][0][RTW89_FCC][75] = -2, - [0][1][1][0][RTW89_ETSI][75] = 127, - [0][1][1][0][RTW89_KCC][75] = 12, - [0][1][1][0][RTW89_FCC][77] = -2, - [0][1][1][0][RTW89_ETSI][77] = 127, - [0][1][1][0][RTW89_KCC][77] = 12, - [0][1][1][0][RTW89_FCC][79] = -2, - [0][1][1][0][RTW89_ETSI][79] = 127, - [0][1][1][0][RTW89_KCC][79] = 12, - [0][1][1][0][RTW89_FCC][81] = -2, - [0][1][1][0][RTW89_ETSI][81] = 127, - [0][1][1][0][RTW89_KCC][81] = 12, - [0][1][1][0][RTW89_FCC][83] = -2, - [0][1][1][0][RTW89_ETSI][83] = 127, - [0][1][1][0][RTW89_KCC][83] = 20, - [0][1][1][0][RTW89_FCC][85] = -2, - [0][1][1][0][RTW89_ETSI][85] = 127, - [0][1][1][0][RTW89_KCC][85] = 20, - [0][1][1][0][RTW89_FCC][87] = -2, - [0][1][1][0][RTW89_ETSI][87] = 127, - [0][1][1][0][RTW89_KCC][87] = 20, - [0][1][1][0][RTW89_FCC][89] = -2, - [0][1][1][0][RTW89_ETSI][89] = 127, - [0][1][1][0][RTW89_KCC][89] = 20, - [0][1][1][0][RTW89_FCC][90] = -2, - [0][1][1][0][RTW89_ETSI][90] = 127, - [0][1][1][0][RTW89_KCC][90] = 20, - [0][1][1][0][RTW89_FCC][92] = -2, - [0][1][1][0][RTW89_ETSI][92] = 127, - [0][1][1][0][RTW89_KCC][92] = 20, - [0][1][1][0][RTW89_FCC][94] = -2, - [0][1][1][0][RTW89_ETSI][94] = 127, - [0][1][1][0][RTW89_KCC][94] = 20, - [0][1][1][0][RTW89_FCC][96] = -2, - [0][1][1][0][RTW89_ETSI][96] = 127, - [0][1][1][0][RTW89_KCC][96] = 20, - [0][1][1][0][RTW89_FCC][98] = -2, - [0][1][1][0][RTW89_ETSI][98] = 127, - [0][1][1][0][RTW89_KCC][98] = 20, - [0][1][1][0][RTW89_FCC][100] = -2, - [0][1][1][0][RTW89_ETSI][100] = 127, - [0][1][1][0][RTW89_KCC][100] = 20, - [0][1][1][0][RTW89_FCC][102] = -2, - [0][1][1][0][RTW89_ETSI][102] = 127, - [0][1][1][0][RTW89_KCC][102] = 20, - [0][1][1][0][RTW89_FCC][104] = -2, - [0][1][1][0][RTW89_ETSI][104] = 127, - [0][1][1][0][RTW89_KCC][104] = 20, - [0][1][1][0][RTW89_FCC][105] = -2, - [0][1][1][0][RTW89_ETSI][105] = 127, - [0][1][1][0][RTW89_KCC][105] = 20, - [0][1][1][0][RTW89_FCC][107] = 0, - [0][1][1][0][RTW89_ETSI][107] = 127, - [0][1][1][0][RTW89_KCC][107] = 20, - [0][1][1][0][RTW89_FCC][109] = 0, - [0][1][1][0][RTW89_ETSI][109] = 127, - [0][1][1][0][RTW89_KCC][109] = 20, - [0][1][1][0][RTW89_FCC][111] = 127, - [0][1][1][0][RTW89_ETSI][111] = 127, - [0][1][1][0][RTW89_KCC][111] = 127, - [0][1][1][0][RTW89_FCC][113] = 127, - [0][1][1][0][RTW89_ETSI][113] = 127, - [0][1][1][0][RTW89_KCC][113] = 127, - [0][1][1][0][RTW89_FCC][115] = 127, - [0][1][1][0][RTW89_ETSI][115] = 127, - [0][1][1][0][RTW89_KCC][115] = 127, - [0][1][1][0][RTW89_FCC][117] = 127, - [0][1][1][0][RTW89_ETSI][117] = 127, - [0][1][1][0][RTW89_KCC][117] = 127, - [0][1][1][0][RTW89_FCC][119] = 127, - [0][1][1][0][RTW89_ETSI][119] = 127, - [0][1][1][0][RTW89_KCC][119] = 127, - [0][0][2][0][RTW89_FCC][0] = 24, - [0][0][2][0][RTW89_ETSI][0] = 66, - [0][0][2][0][RTW89_KCC][0] = 24, - [0][0][2][0][RTW89_FCC][2] = 22, - [0][0][2][0][RTW89_ETSI][2] = 66, - [0][0][2][0][RTW89_KCC][2] = 24, - [0][0][2][0][RTW89_FCC][4] = 22, - [0][0][2][0][RTW89_ETSI][4] = 66, - [0][0][2][0][RTW89_KCC][4] = 24, - [0][0][2][0][RTW89_FCC][6] = 22, - [0][0][2][0][RTW89_ETSI][6] = 66, - [0][0][2][0][RTW89_KCC][6] = 24, - [0][0][2][0][RTW89_FCC][8] = 22, - [0][0][2][0][RTW89_ETSI][8] = 66, - [0][0][2][0][RTW89_KCC][8] = 24, - [0][0][2][0][RTW89_FCC][10] = 22, - [0][0][2][0][RTW89_ETSI][10] = 66, - [0][0][2][0][RTW89_KCC][10] = 24, - [0][0][2][0][RTW89_FCC][12] = 22, - [0][0][2][0][RTW89_ETSI][12] = 66, - [0][0][2][0][RTW89_KCC][12] = 24, - [0][0][2][0][RTW89_FCC][14] = 22, - [0][0][2][0][RTW89_ETSI][14] = 66, - [0][0][2][0][RTW89_KCC][14] = 24, - [0][0][2][0][RTW89_FCC][15] = 22, - [0][0][2][0][RTW89_ETSI][15] = 66, - [0][0][2][0][RTW89_KCC][15] = 24, - [0][0][2][0][RTW89_FCC][17] = 22, - [0][0][2][0][RTW89_ETSI][17] = 66, - [0][0][2][0][RTW89_KCC][17] = 24, - [0][0][2][0][RTW89_FCC][19] = 22, - [0][0][2][0][RTW89_ETSI][19] = 66, - [0][0][2][0][RTW89_KCC][19] = 24, - [0][0][2][0][RTW89_FCC][21] = 22, - [0][0][2][0][RTW89_ETSI][21] = 66, - [0][0][2][0][RTW89_KCC][21] = 24, - [0][0][2][0][RTW89_FCC][23] = 22, - [0][0][2][0][RTW89_ETSI][23] = 66, - [0][0][2][0][RTW89_KCC][23] = 24, - [0][0][2][0][RTW89_FCC][25] = 22, - [0][0][2][0][RTW89_ETSI][25] = 66, - [0][0][2][0][RTW89_KCC][25] = 24, - [0][0][2][0][RTW89_FCC][27] = 22, - [0][0][2][0][RTW89_ETSI][27] = 66, - [0][0][2][0][RTW89_KCC][27] = 24, - [0][0][2][0][RTW89_FCC][29] = 22, - [0][0][2][0][RTW89_ETSI][29] = 66, - [0][0][2][0][RTW89_KCC][29] = 24, - [0][0][2][0][RTW89_FCC][30] = 22, - [0][0][2][0][RTW89_ETSI][30] = 66, - [0][0][2][0][RTW89_KCC][30] = 24, - [0][0][2][0][RTW89_FCC][32] = 22, - [0][0][2][0][RTW89_ETSI][32] = 66, - [0][0][2][0][RTW89_KCC][32] = 24, - [0][0][2][0][RTW89_FCC][34] = 22, - [0][0][2][0][RTW89_ETSI][34] = 66, - [0][0][2][0][RTW89_KCC][34] = 24, - [0][0][2][0][RTW89_FCC][36] = 22, - [0][0][2][0][RTW89_ETSI][36] = 66, - [0][0][2][0][RTW89_KCC][36] = 24, - [0][0][2][0][RTW89_FCC][38] = 22, - [0][0][2][0][RTW89_ETSI][38] = 66, - [0][0][2][0][RTW89_KCC][38] = 24, - [0][0][2][0][RTW89_FCC][40] = 22, - [0][0][2][0][RTW89_ETSI][40] = 66, - [0][0][2][0][RTW89_KCC][40] = 24, - [0][0][2][0][RTW89_FCC][42] = 22, - [0][0][2][0][RTW89_ETSI][42] = 66, - [0][0][2][0][RTW89_KCC][42] = 24, - [0][0][2][0][RTW89_FCC][44] = 22, - [0][0][2][0][RTW89_ETSI][44] = 66, - [0][0][2][0][RTW89_KCC][44] = 24, - [0][0][2][0][RTW89_FCC][45] = 22, - [0][0][2][0][RTW89_ETSI][45] = 127, - [0][0][2][0][RTW89_KCC][45] = 24, - [0][0][2][0][RTW89_FCC][47] = 22, - [0][0][2][0][RTW89_ETSI][47] = 127, - [0][0][2][0][RTW89_KCC][47] = 24, - [0][0][2][0][RTW89_FCC][49] = 24, - [0][0][2][0][RTW89_ETSI][49] = 127, - [0][0][2][0][RTW89_KCC][49] = 24, - [0][0][2][0][RTW89_FCC][51] = 22, - [0][0][2][0][RTW89_ETSI][51] = 127, - [0][0][2][0][RTW89_KCC][51] = 24, - [0][0][2][0][RTW89_FCC][53] = 22, - [0][0][2][0][RTW89_ETSI][53] = 127, - [0][0][2][0][RTW89_KCC][53] = 24, - [0][0][2][0][RTW89_FCC][55] = 22, - [0][0][2][0][RTW89_ETSI][55] = 127, - [0][0][2][0][RTW89_KCC][55] = 26, - [0][0][2][0][RTW89_FCC][57] = 22, - [0][0][2][0][RTW89_ETSI][57] = 127, - [0][0][2][0][RTW89_KCC][57] = 26, - [0][0][2][0][RTW89_FCC][59] = 22, - [0][0][2][0][RTW89_ETSI][59] = 127, - [0][0][2][0][RTW89_KCC][59] = 26, - [0][0][2][0][RTW89_FCC][60] = 22, - [0][0][2][0][RTW89_ETSI][60] = 127, - [0][0][2][0][RTW89_KCC][60] = 26, - [0][0][2][0][RTW89_FCC][62] = 22, - [0][0][2][0][RTW89_ETSI][62] = 127, - [0][0][2][0][RTW89_KCC][62] = 26, - [0][0][2][0][RTW89_FCC][64] = 22, - [0][0][2][0][RTW89_ETSI][64] = 127, - [0][0][2][0][RTW89_KCC][64] = 26, - [0][0][2][0][RTW89_FCC][66] = 22, - [0][0][2][0][RTW89_ETSI][66] = 127, - [0][0][2][0][RTW89_KCC][66] = 26, - [0][0][2][0][RTW89_FCC][68] = 22, - [0][0][2][0][RTW89_ETSI][68] = 127, - [0][0][2][0][RTW89_KCC][68] = 26, - [0][0][2][0][RTW89_FCC][70] = 24, - [0][0][2][0][RTW89_ETSI][70] = 127, - [0][0][2][0][RTW89_KCC][70] = 26, - [0][0][2][0][RTW89_FCC][72] = 22, - [0][0][2][0][RTW89_ETSI][72] = 127, - [0][0][2][0][RTW89_KCC][72] = 26, - [0][0][2][0][RTW89_FCC][74] = 22, - [0][0][2][0][RTW89_ETSI][74] = 127, - [0][0][2][0][RTW89_KCC][74] = 26, - [0][0][2][0][RTW89_FCC][75] = 22, - [0][0][2][0][RTW89_ETSI][75] = 127, - [0][0][2][0][RTW89_KCC][75] = 26, - [0][0][2][0][RTW89_FCC][77] = 22, - [0][0][2][0][RTW89_ETSI][77] = 127, - [0][0][2][0][RTW89_KCC][77] = 26, - [0][0][2][0][RTW89_FCC][79] = 22, - [0][0][2][0][RTW89_ETSI][79] = 127, - [0][0][2][0][RTW89_KCC][79] = 26, - [0][0][2][0][RTW89_FCC][81] = 22, - [0][0][2][0][RTW89_ETSI][81] = 127, - [0][0][2][0][RTW89_KCC][81] = 26, - [0][0][2][0][RTW89_FCC][83] = 22, - [0][0][2][0][RTW89_ETSI][83] = 127, - [0][0][2][0][RTW89_KCC][83] = 32, - [0][0][2][0][RTW89_FCC][85] = 22, - [0][0][2][0][RTW89_ETSI][85] = 127, - [0][0][2][0][RTW89_KCC][85] = 32, - [0][0][2][0][RTW89_FCC][87] = 22, - [0][0][2][0][RTW89_ETSI][87] = 127, - [0][0][2][0][RTW89_KCC][87] = 32, - [0][0][2][0][RTW89_FCC][89] = 22, - [0][0][2][0][RTW89_ETSI][89] = 127, - [0][0][2][0][RTW89_KCC][89] = 32, - [0][0][2][0][RTW89_FCC][90] = 22, - [0][0][2][0][RTW89_ETSI][90] = 127, - [0][0][2][0][RTW89_KCC][90] = 32, - [0][0][2][0][RTW89_FCC][92] = 22, - [0][0][2][0][RTW89_ETSI][92] = 127, - [0][0][2][0][RTW89_KCC][92] = 32, - [0][0][2][0][RTW89_FCC][94] = 22, - [0][0][2][0][RTW89_ETSI][94] = 127, - [0][0][2][0][RTW89_KCC][94] = 32, - [0][0][2][0][RTW89_FCC][96] = 22, - [0][0][2][0][RTW89_ETSI][96] = 127, - [0][0][2][0][RTW89_KCC][96] = 32, - [0][0][2][0][RTW89_FCC][98] = 22, - [0][0][2][0][RTW89_ETSI][98] = 127, - [0][0][2][0][RTW89_KCC][98] = 32, - [0][0][2][0][RTW89_FCC][100] = 22, - [0][0][2][0][RTW89_ETSI][100] = 127, - [0][0][2][0][RTW89_KCC][100] = 32, - [0][0][2][0][RTW89_FCC][102] = 22, - [0][0][2][0][RTW89_ETSI][102] = 127, - [0][0][2][0][RTW89_KCC][102] = 32, - [0][0][2][0][RTW89_FCC][104] = 22, - [0][0][2][0][RTW89_ETSI][104] = 127, - [0][0][2][0][RTW89_KCC][104] = 32, - [0][0][2][0][RTW89_FCC][105] = 22, - [0][0][2][0][RTW89_ETSI][105] = 127, - [0][0][2][0][RTW89_KCC][105] = 32, - [0][0][2][0][RTW89_FCC][107] = 24, - [0][0][2][0][RTW89_ETSI][107] = 127, - [0][0][2][0][RTW89_KCC][107] = 32, - [0][0][2][0][RTW89_FCC][109] = 24, - [0][0][2][0][RTW89_ETSI][109] = 127, - [0][0][2][0][RTW89_KCC][109] = 32, - [0][0][2][0][RTW89_FCC][111] = 127, - [0][0][2][0][RTW89_ETSI][111] = 127, - [0][0][2][0][RTW89_KCC][111] = 127, - [0][0][2][0][RTW89_FCC][113] = 127, - [0][0][2][0][RTW89_ETSI][113] = 127, - [0][0][2][0][RTW89_KCC][113] = 127, - [0][0][2][0][RTW89_FCC][115] = 127, - [0][0][2][0][RTW89_ETSI][115] = 127, - [0][0][2][0][RTW89_KCC][115] = 127, - [0][0][2][0][RTW89_FCC][117] = 127, - [0][0][2][0][RTW89_ETSI][117] = 127, - [0][0][2][0][RTW89_KCC][117] = 127, - [0][0][2][0][RTW89_FCC][119] = 127, - [0][0][2][0][RTW89_ETSI][119] = 127, - [0][0][2][0][RTW89_KCC][119] = 127, - [0][1][2][0][RTW89_FCC][0] = -2, - [0][1][2][0][RTW89_ETSI][0] = 54, - [0][1][2][0][RTW89_KCC][0] = 12, - [0][1][2][0][RTW89_FCC][2] = -4, - [0][1][2][0][RTW89_ETSI][2] = 54, - [0][1][2][0][RTW89_KCC][2] = 12, - [0][1][2][0][RTW89_FCC][4] = -4, - [0][1][2][0][RTW89_ETSI][4] = 54, - [0][1][2][0][RTW89_KCC][4] = 12, - [0][1][2][0][RTW89_FCC][6] = -4, - [0][1][2][0][RTW89_ETSI][6] = 54, - [0][1][2][0][RTW89_KCC][6] = 12, - [0][1][2][0][RTW89_FCC][8] = -4, - [0][1][2][0][RTW89_ETSI][8] = 54, - [0][1][2][0][RTW89_KCC][8] = 12, - [0][1][2][0][RTW89_FCC][10] = -4, - [0][1][2][0][RTW89_ETSI][10] = 54, - [0][1][2][0][RTW89_KCC][10] = 12, - [0][1][2][0][RTW89_FCC][12] = -4, - [0][1][2][0][RTW89_ETSI][12] = 54, - [0][1][2][0][RTW89_KCC][12] = 12, - [0][1][2][0][RTW89_FCC][14] = -4, - [0][1][2][0][RTW89_ETSI][14] = 54, - [0][1][2][0][RTW89_KCC][14] = 12, - [0][1][2][0][RTW89_FCC][15] = -4, - [0][1][2][0][RTW89_ETSI][15] = 54, - [0][1][2][0][RTW89_KCC][15] = 12, - [0][1][2][0][RTW89_FCC][17] = -4, - [0][1][2][0][RTW89_ETSI][17] = 54, - [0][1][2][0][RTW89_KCC][17] = 12, - [0][1][2][0][RTW89_FCC][19] = -4, - [0][1][2][0][RTW89_ETSI][19] = 54, - [0][1][2][0][RTW89_KCC][19] = 12, - [0][1][2][0][RTW89_FCC][21] = -4, - [0][1][2][0][RTW89_ETSI][21] = 54, - [0][1][2][0][RTW89_KCC][21] = 12, - [0][1][2][0][RTW89_FCC][23] = -4, - [0][1][2][0][RTW89_ETSI][23] = 54, - [0][1][2][0][RTW89_KCC][23] = 12, - [0][1][2][0][RTW89_FCC][25] = -4, - [0][1][2][0][RTW89_ETSI][25] = 54, - [0][1][2][0][RTW89_KCC][25] = 12, - [0][1][2][0][RTW89_FCC][27] = -4, - [0][1][2][0][RTW89_ETSI][27] = 54, - [0][1][2][0][RTW89_KCC][27] = 12, - [0][1][2][0][RTW89_FCC][29] = -4, - [0][1][2][0][RTW89_ETSI][29] = 54, - [0][1][2][0][RTW89_KCC][29] = 12, - [0][1][2][0][RTW89_FCC][30] = -4, - [0][1][2][0][RTW89_ETSI][30] = 54, - [0][1][2][0][RTW89_KCC][30] = 12, - [0][1][2][0][RTW89_FCC][32] = -4, - [0][1][2][0][RTW89_ETSI][32] = 54, - [0][1][2][0][RTW89_KCC][32] = 12, - [0][1][2][0][RTW89_FCC][34] = -4, - [0][1][2][0][RTW89_ETSI][34] = 54, - [0][1][2][0][RTW89_KCC][34] = 12, - [0][1][2][0][RTW89_FCC][36] = -4, - [0][1][2][0][RTW89_ETSI][36] = 54, - [0][1][2][0][RTW89_KCC][36] = 12, - [0][1][2][0][RTW89_FCC][38] = -4, - [0][1][2][0][RTW89_ETSI][38] = 54, - [0][1][2][0][RTW89_KCC][38] = 12, - [0][1][2][0][RTW89_FCC][40] = -4, - [0][1][2][0][RTW89_ETSI][40] = 54, - [0][1][2][0][RTW89_KCC][40] = 12, - [0][1][2][0][RTW89_FCC][42] = -4, - [0][1][2][0][RTW89_ETSI][42] = 54, - [0][1][2][0][RTW89_KCC][42] = 12, - [0][1][2][0][RTW89_FCC][44] = -2, - [0][1][2][0][RTW89_ETSI][44] = 54, - [0][1][2][0][RTW89_KCC][44] = 12, - [0][1][2][0][RTW89_FCC][45] = -2, - [0][1][2][0][RTW89_ETSI][45] = 127, - [0][1][2][0][RTW89_KCC][45] = 12, - [0][1][2][0][RTW89_FCC][47] = -2, - [0][1][2][0][RTW89_ETSI][47] = 127, - [0][1][2][0][RTW89_KCC][47] = 12, - [0][1][2][0][RTW89_FCC][49] = -2, - [0][1][2][0][RTW89_ETSI][49] = 127, - [0][1][2][0][RTW89_KCC][49] = 12, - [0][1][2][0][RTW89_FCC][51] = -2, - [0][1][2][0][RTW89_ETSI][51] = 127, - [0][1][2][0][RTW89_KCC][51] = 12, - [0][1][2][0][RTW89_FCC][53] = -2, - [0][1][2][0][RTW89_ETSI][53] = 127, - [0][1][2][0][RTW89_KCC][53] = 12, - [0][1][2][0][RTW89_FCC][55] = -2, - [0][1][2][0][RTW89_ETSI][55] = 127, - [0][1][2][0][RTW89_KCC][55] = 12, - [0][1][2][0][RTW89_FCC][57] = -2, - [0][1][2][0][RTW89_ETSI][57] = 127, - [0][1][2][0][RTW89_KCC][57] = 12, - [0][1][2][0][RTW89_FCC][59] = -2, - [0][1][2][0][RTW89_ETSI][59] = 127, - [0][1][2][0][RTW89_KCC][59] = 12, - [0][1][2][0][RTW89_FCC][60] = -2, - [0][1][2][0][RTW89_ETSI][60] = 127, - [0][1][2][0][RTW89_KCC][60] = 12, - [0][1][2][0][RTW89_FCC][62] = -2, - [0][1][2][0][RTW89_ETSI][62] = 127, - [0][1][2][0][RTW89_KCC][62] = 12, - [0][1][2][0][RTW89_FCC][64] = -2, - [0][1][2][0][RTW89_ETSI][64] = 127, - [0][1][2][0][RTW89_KCC][64] = 12, - [0][1][2][0][RTW89_FCC][66] = -2, - [0][1][2][0][RTW89_ETSI][66] = 127, - [0][1][2][0][RTW89_KCC][66] = 12, - [0][1][2][0][RTW89_FCC][68] = -2, - [0][1][2][0][RTW89_ETSI][68] = 127, - [0][1][2][0][RTW89_KCC][68] = 12, - [0][1][2][0][RTW89_FCC][70] = -2, - [0][1][2][0][RTW89_ETSI][70] = 127, - [0][1][2][0][RTW89_KCC][70] = 12, - [0][1][2][0][RTW89_FCC][72] = -2, - [0][1][2][0][RTW89_ETSI][72] = 127, - [0][1][2][0][RTW89_KCC][72] = 12, - [0][1][2][0][RTW89_FCC][74] = -2, - [0][1][2][0][RTW89_ETSI][74] = 127, - [0][1][2][0][RTW89_KCC][74] = 12, - [0][1][2][0][RTW89_FCC][75] = -2, - [0][1][2][0][RTW89_ETSI][75] = 127, - [0][1][2][0][RTW89_KCC][75] = 12, - [0][1][2][0][RTW89_FCC][77] = -2, - [0][1][2][0][RTW89_ETSI][77] = 127, - [0][1][2][0][RTW89_KCC][77] = 12, - [0][1][2][0][RTW89_FCC][79] = -2, - [0][1][2][0][RTW89_ETSI][79] = 127, - [0][1][2][0][RTW89_KCC][79] = 12, - [0][1][2][0][RTW89_FCC][81] = -2, - [0][1][2][0][RTW89_ETSI][81] = 127, - [0][1][2][0][RTW89_KCC][81] = 12, - [0][1][2][0][RTW89_FCC][83] = -2, - [0][1][2][0][RTW89_ETSI][83] = 127, - [0][1][2][0][RTW89_KCC][83] = 20, - [0][1][2][0][RTW89_FCC][85] = -2, - [0][1][2][0][RTW89_ETSI][85] = 127, - [0][1][2][0][RTW89_KCC][85] = 20, - [0][1][2][0][RTW89_FCC][87] = -2, - [0][1][2][0][RTW89_ETSI][87] = 127, - [0][1][2][0][RTW89_KCC][87] = 20, - [0][1][2][0][RTW89_FCC][89] = -2, - [0][1][2][0][RTW89_ETSI][89] = 127, - [0][1][2][0][RTW89_KCC][89] = 20, - [0][1][2][0][RTW89_FCC][90] = -2, - [0][1][2][0][RTW89_ETSI][90] = 127, - [0][1][2][0][RTW89_KCC][90] = 20, - [0][1][2][0][RTW89_FCC][92] = -2, - [0][1][2][0][RTW89_ETSI][92] = 127, - [0][1][2][0][RTW89_KCC][92] = 20, - [0][1][2][0][RTW89_FCC][94] = -2, - [0][1][2][0][RTW89_ETSI][94] = 127, - [0][1][2][0][RTW89_KCC][94] = 20, - [0][1][2][0][RTW89_FCC][96] = -2, - [0][1][2][0][RTW89_ETSI][96] = 127, - [0][1][2][0][RTW89_KCC][96] = 20, - [0][1][2][0][RTW89_FCC][98] = -2, - [0][1][2][0][RTW89_ETSI][98] = 127, - [0][1][2][0][RTW89_KCC][98] = 20, - [0][1][2][0][RTW89_FCC][100] = -2, - [0][1][2][0][RTW89_ETSI][100] = 127, - [0][1][2][0][RTW89_KCC][100] = 20, - [0][1][2][0][RTW89_FCC][102] = -2, - [0][1][2][0][RTW89_ETSI][102] = 127, - [0][1][2][0][RTW89_KCC][102] = 20, - [0][1][2][0][RTW89_FCC][104] = -2, - [0][1][2][0][RTW89_ETSI][104] = 127, - [0][1][2][0][RTW89_KCC][104] = 20, - [0][1][2][0][RTW89_FCC][105] = -2, - [0][1][2][0][RTW89_ETSI][105] = 127, - [0][1][2][0][RTW89_KCC][105] = 20, - [0][1][2][0][RTW89_FCC][107] = 0, - [0][1][2][0][RTW89_ETSI][107] = 127, - [0][1][2][0][RTW89_KCC][107] = 20, - [0][1][2][0][RTW89_FCC][109] = 0, - [0][1][2][0][RTW89_ETSI][109] = 127, - [0][1][2][0][RTW89_KCC][109] = 20, - [0][1][2][0][RTW89_FCC][111] = 127, - [0][1][2][0][RTW89_ETSI][111] = 127, - [0][1][2][0][RTW89_KCC][111] = 127, - [0][1][2][0][RTW89_FCC][113] = 127, - [0][1][2][0][RTW89_ETSI][113] = 127, - [0][1][2][0][RTW89_KCC][113] = 127, - [0][1][2][0][RTW89_FCC][115] = 127, - [0][1][2][0][RTW89_ETSI][115] = 127, - [0][1][2][0][RTW89_KCC][115] = 127, - [0][1][2][0][RTW89_FCC][117] = 127, - [0][1][2][0][RTW89_ETSI][117] = 127, - [0][1][2][0][RTW89_KCC][117] = 127, - [0][1][2][0][RTW89_FCC][119] = 127, - [0][1][2][0][RTW89_ETSI][119] = 127, - [0][1][2][0][RTW89_KCC][119] = 127, - [0][1][2][1][RTW89_FCC][0] = -2, - [0][1][2][1][RTW89_ETSI][0] = 42, - [0][1][2][1][RTW89_KCC][0] = 12, - [0][1][2][1][RTW89_FCC][2] = -4, - [0][1][2][1][RTW89_ETSI][2] = 42, - [0][1][2][1][RTW89_KCC][2] = 12, - [0][1][2][1][RTW89_FCC][4] = -4, - [0][1][2][1][RTW89_ETSI][4] = 42, - [0][1][2][1][RTW89_KCC][4] = 12, - [0][1][2][1][RTW89_FCC][6] = -4, - [0][1][2][1][RTW89_ETSI][6] = 42, - [0][1][2][1][RTW89_KCC][6] = 12, - [0][1][2][1][RTW89_FCC][8] = -4, - [0][1][2][1][RTW89_ETSI][8] = 42, - [0][1][2][1][RTW89_KCC][8] = 12, - [0][1][2][1][RTW89_FCC][10] = -4, - [0][1][2][1][RTW89_ETSI][10] = 42, - [0][1][2][1][RTW89_KCC][10] = 12, - [0][1][2][1][RTW89_FCC][12] = -4, - [0][1][2][1][RTW89_ETSI][12] = 42, - [0][1][2][1][RTW89_KCC][12] = 12, - [0][1][2][1][RTW89_FCC][14] = -4, - [0][1][2][1][RTW89_ETSI][14] = 42, - [0][1][2][1][RTW89_KCC][14] = 12, - [0][1][2][1][RTW89_FCC][15] = -4, - [0][1][2][1][RTW89_ETSI][15] = 42, - [0][1][2][1][RTW89_KCC][15] = 12, - [0][1][2][1][RTW89_FCC][17] = -4, - [0][1][2][1][RTW89_ETSI][17] = 42, - [0][1][2][1][RTW89_KCC][17] = 12, - [0][1][2][1][RTW89_FCC][19] = -4, - [0][1][2][1][RTW89_ETSI][19] = 42, - [0][1][2][1][RTW89_KCC][19] = 12, - [0][1][2][1][RTW89_FCC][21] = -4, - [0][1][2][1][RTW89_ETSI][21] = 42, - [0][1][2][1][RTW89_KCC][21] = 12, - [0][1][2][1][RTW89_FCC][23] = -4, - [0][1][2][1][RTW89_ETSI][23] = 42, - [0][1][2][1][RTW89_KCC][23] = 12, - [0][1][2][1][RTW89_FCC][25] = -4, - [0][1][2][1][RTW89_ETSI][25] = 42, - [0][1][2][1][RTW89_KCC][25] = 12, - [0][1][2][1][RTW89_FCC][27] = -4, - [0][1][2][1][RTW89_ETSI][27] = 42, - [0][1][2][1][RTW89_KCC][27] = 12, - [0][1][2][1][RTW89_FCC][29] = -4, - [0][1][2][1][RTW89_ETSI][29] = 42, - [0][1][2][1][RTW89_KCC][29] = 12, - [0][1][2][1][RTW89_FCC][30] = -4, - [0][1][2][1][RTW89_ETSI][30] = 42, - [0][1][2][1][RTW89_KCC][30] = 12, - [0][1][2][1][RTW89_FCC][32] = -4, - [0][1][2][1][RTW89_ETSI][32] = 42, - [0][1][2][1][RTW89_KCC][32] = 12, - [0][1][2][1][RTW89_FCC][34] = -4, - [0][1][2][1][RTW89_ETSI][34] = 42, - [0][1][2][1][RTW89_KCC][34] = 12, - [0][1][2][1][RTW89_FCC][36] = -4, - [0][1][2][1][RTW89_ETSI][36] = 42, - [0][1][2][1][RTW89_KCC][36] = 12, - [0][1][2][1][RTW89_FCC][38] = -4, - [0][1][2][1][RTW89_ETSI][38] = 42, - [0][1][2][1][RTW89_KCC][38] = 12, - [0][1][2][1][RTW89_FCC][40] = -4, - [0][1][2][1][RTW89_ETSI][40] = 42, - [0][1][2][1][RTW89_KCC][40] = 12, - [0][1][2][1][RTW89_FCC][42] = -4, - [0][1][2][1][RTW89_ETSI][42] = 42, - [0][1][2][1][RTW89_KCC][42] = 12, - [0][1][2][1][RTW89_FCC][44] = -2, - [0][1][2][1][RTW89_ETSI][44] = 42, - [0][1][2][1][RTW89_KCC][44] = 12, - [0][1][2][1][RTW89_FCC][45] = -2, - [0][1][2][1][RTW89_ETSI][45] = 127, - [0][1][2][1][RTW89_KCC][45] = 12, - [0][1][2][1][RTW89_FCC][47] = -2, - [0][1][2][1][RTW89_ETSI][47] = 127, - [0][1][2][1][RTW89_KCC][47] = 12, - [0][1][2][1][RTW89_FCC][49] = -2, - [0][1][2][1][RTW89_ETSI][49] = 127, - [0][1][2][1][RTW89_KCC][49] = 12, - [0][1][2][1][RTW89_FCC][51] = -2, - [0][1][2][1][RTW89_ETSI][51] = 127, - [0][1][2][1][RTW89_KCC][51] = 12, - [0][1][2][1][RTW89_FCC][53] = -2, - [0][1][2][1][RTW89_ETSI][53] = 127, - [0][1][2][1][RTW89_KCC][53] = 12, - [0][1][2][1][RTW89_FCC][55] = -2, - [0][1][2][1][RTW89_ETSI][55] = 127, - [0][1][2][1][RTW89_KCC][55] = 12, - [0][1][2][1][RTW89_FCC][57] = -2, - [0][1][2][1][RTW89_ETSI][57] = 127, - [0][1][2][1][RTW89_KCC][57] = 12, - [0][1][2][1][RTW89_FCC][59] = -2, - [0][1][2][1][RTW89_ETSI][59] = 127, - [0][1][2][1][RTW89_KCC][59] = 12, - [0][1][2][1][RTW89_FCC][60] = -2, - [0][1][2][1][RTW89_ETSI][60] = 127, - [0][1][2][1][RTW89_KCC][60] = 12, - [0][1][2][1][RTW89_FCC][62] = -2, - [0][1][2][1][RTW89_ETSI][62] = 127, - [0][1][2][1][RTW89_KCC][62] = 12, - [0][1][2][1][RTW89_FCC][64] = -2, - [0][1][2][1][RTW89_ETSI][64] = 127, - [0][1][2][1][RTW89_KCC][64] = 12, - [0][1][2][1][RTW89_FCC][66] = -2, - [0][1][2][1][RTW89_ETSI][66] = 127, - [0][1][2][1][RTW89_KCC][66] = 12, - [0][1][2][1][RTW89_FCC][68] = -2, - [0][1][2][1][RTW89_ETSI][68] = 127, - [0][1][2][1][RTW89_KCC][68] = 12, - [0][1][2][1][RTW89_FCC][70] = -2, - [0][1][2][1][RTW89_ETSI][70] = 127, - [0][1][2][1][RTW89_KCC][70] = 12, - [0][1][2][1][RTW89_FCC][72] = -2, - [0][1][2][1][RTW89_ETSI][72] = 127, - [0][1][2][1][RTW89_KCC][72] = 12, - [0][1][2][1][RTW89_FCC][74] = -2, - [0][1][2][1][RTW89_ETSI][74] = 127, - [0][1][2][1][RTW89_KCC][74] = 12, - [0][1][2][1][RTW89_FCC][75] = -2, - [0][1][2][1][RTW89_ETSI][75] = 127, - [0][1][2][1][RTW89_KCC][75] = 12, - [0][1][2][1][RTW89_FCC][77] = -2, - [0][1][2][1][RTW89_ETSI][77] = 127, - [0][1][2][1][RTW89_KCC][77] = 12, - [0][1][2][1][RTW89_FCC][79] = -2, - [0][1][2][1][RTW89_ETSI][79] = 127, - [0][1][2][1][RTW89_KCC][79] = 12, - [0][1][2][1][RTW89_FCC][81] = -2, - [0][1][2][1][RTW89_ETSI][81] = 127, - [0][1][2][1][RTW89_KCC][81] = 12, - [0][1][2][1][RTW89_FCC][83] = -2, - [0][1][2][1][RTW89_ETSI][83] = 127, - [0][1][2][1][RTW89_KCC][83] = 20, - [0][1][2][1][RTW89_FCC][85] = -2, - [0][1][2][1][RTW89_ETSI][85] = 127, - [0][1][2][1][RTW89_KCC][85] = 20, - [0][1][2][1][RTW89_FCC][87] = -2, - [0][1][2][1][RTW89_ETSI][87] = 127, - [0][1][2][1][RTW89_KCC][87] = 20, - [0][1][2][1][RTW89_FCC][89] = -2, - [0][1][2][1][RTW89_ETSI][89] = 127, - [0][1][2][1][RTW89_KCC][89] = 20, - [0][1][2][1][RTW89_FCC][90] = -2, - [0][1][2][1][RTW89_ETSI][90] = 127, - [0][1][2][1][RTW89_KCC][90] = 20, - [0][1][2][1][RTW89_FCC][92] = -2, - [0][1][2][1][RTW89_ETSI][92] = 127, - [0][1][2][1][RTW89_KCC][92] = 20, - [0][1][2][1][RTW89_FCC][94] = -2, - [0][1][2][1][RTW89_ETSI][94] = 127, - [0][1][2][1][RTW89_KCC][94] = 20, - [0][1][2][1][RTW89_FCC][96] = -2, - [0][1][2][1][RTW89_ETSI][96] = 127, - [0][1][2][1][RTW89_KCC][96] = 20, - [0][1][2][1][RTW89_FCC][98] = -2, - [0][1][2][1][RTW89_ETSI][98] = 127, - [0][1][2][1][RTW89_KCC][98] = 20, - [0][1][2][1][RTW89_FCC][100] = -2, - [0][1][2][1][RTW89_ETSI][100] = 127, - [0][1][2][1][RTW89_KCC][100] = 20, - [0][1][2][1][RTW89_FCC][102] = -2, - [0][1][2][1][RTW89_ETSI][102] = 127, - [0][1][2][1][RTW89_KCC][102] = 20, - [0][1][2][1][RTW89_FCC][104] = -2, - [0][1][2][1][RTW89_ETSI][104] = 127, - [0][1][2][1][RTW89_KCC][104] = 20, - [0][1][2][1][RTW89_FCC][105] = -2, - [0][1][2][1][RTW89_ETSI][105] = 127, - [0][1][2][1][RTW89_KCC][105] = 20, - [0][1][2][1][RTW89_FCC][107] = 0, - [0][1][2][1][RTW89_ETSI][107] = 127, - [0][1][2][1][RTW89_KCC][107] = 20, - [0][1][2][1][RTW89_FCC][109] = 0, - [0][1][2][1][RTW89_ETSI][109] = 127, - [0][1][2][1][RTW89_KCC][109] = 20, - [0][1][2][1][RTW89_FCC][111] = 127, - [0][1][2][1][RTW89_ETSI][111] = 127, - [0][1][2][1][RTW89_KCC][111] = 127, - [0][1][2][1][RTW89_FCC][113] = 127, - [0][1][2][1][RTW89_ETSI][113] = 127, - [0][1][2][1][RTW89_KCC][113] = 127, - [0][1][2][1][RTW89_FCC][115] = 127, - [0][1][2][1][RTW89_ETSI][115] = 127, - [0][1][2][1][RTW89_KCC][115] = 127, - [0][1][2][1][RTW89_FCC][117] = 127, - [0][1][2][1][RTW89_ETSI][117] = 127, - [0][1][2][1][RTW89_KCC][117] = 127, - [0][1][2][1][RTW89_FCC][119] = 127, - [0][1][2][1][RTW89_ETSI][119] = 127, - [0][1][2][1][RTW89_KCC][119] = 127, - [1][0][2][0][RTW89_FCC][1] = 34, - [1][0][2][0][RTW89_ETSI][1] = 66, - [1][0][2][0][RTW89_KCC][1] = 40, - [1][0][2][0][RTW89_FCC][5] = 34, - [1][0][2][0][RTW89_ETSI][5] = 66, - [1][0][2][0][RTW89_KCC][5] = 40, - [1][0][2][0][RTW89_FCC][9] = 34, - [1][0][2][0][RTW89_ETSI][9] = 66, - [1][0][2][0][RTW89_KCC][9] = 40, - [1][0][2][0][RTW89_FCC][13] = 34, - [1][0][2][0][RTW89_ETSI][13] = 66, - [1][0][2][0][RTW89_KCC][13] = 40, - [1][0][2][0][RTW89_FCC][16] = 34, - [1][0][2][0][RTW89_ETSI][16] = 66, - [1][0][2][0][RTW89_KCC][16] = 40, - [1][0][2][0][RTW89_FCC][20] = 34, - [1][0][2][0][RTW89_ETSI][20] = 66, - [1][0][2][0][RTW89_KCC][20] = 40, - [1][0][2][0][RTW89_FCC][24] = 36, - [1][0][2][0][RTW89_ETSI][24] = 66, - [1][0][2][0][RTW89_KCC][24] = 40, - [1][0][2][0][RTW89_FCC][28] = 34, - [1][0][2][0][RTW89_ETSI][28] = 66, - [1][0][2][0][RTW89_KCC][28] = 40, - [1][0][2][0][RTW89_FCC][31] = 34, - [1][0][2][0][RTW89_ETSI][31] = 66, - [1][0][2][0][RTW89_KCC][31] = 40, - [1][0][2][0][RTW89_FCC][35] = 34, - [1][0][2][0][RTW89_ETSI][35] = 66, - [1][0][2][0][RTW89_KCC][35] = 40, - [1][0][2][0][RTW89_FCC][39] = 34, - [1][0][2][0][RTW89_ETSI][39] = 66, - [1][0][2][0][RTW89_KCC][39] = 40, - [1][0][2][0][RTW89_FCC][43] = 34, - [1][0][2][0][RTW89_ETSI][43] = 66, - [1][0][2][0][RTW89_KCC][43] = 40, - [1][0][2][0][RTW89_FCC][46] = 34, - [1][0][2][0][RTW89_ETSI][46] = 127, - [1][0][2][0][RTW89_KCC][46] = 40, - [1][0][2][0][RTW89_FCC][50] = 34, - [1][0][2][0][RTW89_ETSI][50] = 127, - [1][0][2][0][RTW89_KCC][50] = 40, - [1][0][2][0][RTW89_FCC][54] = 36, - [1][0][2][0][RTW89_ETSI][54] = 127, - [1][0][2][0][RTW89_KCC][54] = 40, - [1][0][2][0][RTW89_FCC][58] = 36, - [1][0][2][0][RTW89_ETSI][58] = 127, - [1][0][2][0][RTW89_KCC][58] = 40, - [1][0][2][0][RTW89_FCC][61] = 34, - [1][0][2][0][RTW89_ETSI][61] = 127, - [1][0][2][0][RTW89_KCC][61] = 40, - [1][0][2][0][RTW89_FCC][65] = 34, - [1][0][2][0][RTW89_ETSI][65] = 127, - [1][0][2][0][RTW89_KCC][65] = 40, - [1][0][2][0][RTW89_FCC][69] = 34, - [1][0][2][0][RTW89_ETSI][69] = 127, - [1][0][2][0][RTW89_KCC][69] = 40, - [1][0][2][0][RTW89_FCC][73] = 34, - [1][0][2][0][RTW89_ETSI][73] = 127, - [1][0][2][0][RTW89_KCC][73] = 40, - [1][0][2][0][RTW89_FCC][76] = 34, - [1][0][2][0][RTW89_ETSI][76] = 127, - [1][0][2][0][RTW89_KCC][76] = 40, - [1][0][2][0][RTW89_FCC][80] = 34, - [1][0][2][0][RTW89_ETSI][80] = 127, - [1][0][2][0][RTW89_KCC][80] = 42, - [1][0][2][0][RTW89_FCC][84] = 34, - [1][0][2][0][RTW89_ETSI][84] = 127, - [1][0][2][0][RTW89_KCC][84] = 42, - [1][0][2][0][RTW89_FCC][88] = 34, - [1][0][2][0][RTW89_ETSI][88] = 127, - [1][0][2][0][RTW89_KCC][88] = 42, - [1][0][2][0][RTW89_FCC][91] = 36, - [1][0][2][0][RTW89_ETSI][91] = 127, - [1][0][2][0][RTW89_KCC][91] = 42, - [1][0][2][0][RTW89_FCC][95] = 34, - [1][0][2][0][RTW89_ETSI][95] = 127, - [1][0][2][0][RTW89_KCC][95] = 42, - [1][0][2][0][RTW89_FCC][99] = 34, - [1][0][2][0][RTW89_ETSI][99] = 127, - [1][0][2][0][RTW89_KCC][99] = 42, - [1][0][2][0][RTW89_FCC][103] = 34, - [1][0][2][0][RTW89_ETSI][103] = 127, - [1][0][2][0][RTW89_KCC][103] = 42, - [1][0][2][0][RTW89_FCC][106] = 36, - [1][0][2][0][RTW89_ETSI][106] = 127, - [1][0][2][0][RTW89_KCC][106] = 42, - [1][0][2][0][RTW89_FCC][110] = 127, - [1][0][2][0][RTW89_ETSI][110] = 127, - [1][0][2][0][RTW89_KCC][110] = 127, - [1][0][2][0][RTW89_FCC][114] = 127, - [1][0][2][0][RTW89_ETSI][114] = 127, - [1][0][2][0][RTW89_KCC][114] = 127, - [1][0][2][0][RTW89_FCC][118] = 127, - [1][0][2][0][RTW89_ETSI][118] = 127, - [1][0][2][0][RTW89_KCC][118] = 127, - [1][1][2][0][RTW89_FCC][1] = 10, - [1][1][2][0][RTW89_ETSI][1] = 54, - [1][1][2][0][RTW89_KCC][1] = 28, - [1][1][2][0][RTW89_FCC][5] = 10, - [1][1][2][0][RTW89_ETSI][5] = 54, - [1][1][2][0][RTW89_KCC][5] = 28, - [1][1][2][0][RTW89_FCC][9] = 10, - [1][1][2][0][RTW89_ETSI][9] = 54, - [1][1][2][0][RTW89_KCC][9] = 28, - [1][1][2][0][RTW89_FCC][13] = 10, - [1][1][2][0][RTW89_ETSI][13] = 54, - [1][1][2][0][RTW89_KCC][13] = 28, - [1][1][2][0][RTW89_FCC][16] = 10, - [1][1][2][0][RTW89_ETSI][16] = 54, - [1][1][2][0][RTW89_KCC][16] = 28, - [1][1][2][0][RTW89_FCC][20] = 10, - [1][1][2][0][RTW89_ETSI][20] = 54, - [1][1][2][0][RTW89_KCC][20] = 28, - [1][1][2][0][RTW89_FCC][24] = 10, - [1][1][2][0][RTW89_ETSI][24] = 54, - [1][1][2][0][RTW89_KCC][24] = 28, - [1][1][2][0][RTW89_FCC][28] = 10, - [1][1][2][0][RTW89_ETSI][28] = 54, - [1][1][2][0][RTW89_KCC][28] = 28, - [1][1][2][0][RTW89_FCC][31] = 10, - [1][1][2][0][RTW89_ETSI][31] = 54, - [1][1][2][0][RTW89_KCC][31] = 28, - [1][1][2][0][RTW89_FCC][35] = 10, - [1][1][2][0][RTW89_ETSI][35] = 54, - [1][1][2][0][RTW89_KCC][35] = 28, - [1][1][2][0][RTW89_FCC][39] = 10, - [1][1][2][0][RTW89_ETSI][39] = 54, - [1][1][2][0][RTW89_KCC][39] = 28, - [1][1][2][0][RTW89_FCC][43] = 10, - [1][1][2][0][RTW89_ETSI][43] = 54, - [1][1][2][0][RTW89_KCC][43] = 28, - [1][1][2][0][RTW89_FCC][46] = 12, - [1][1][2][0][RTW89_ETSI][46] = 127, - [1][1][2][0][RTW89_KCC][46] = 28, - [1][1][2][0][RTW89_FCC][50] = 12, - [1][1][2][0][RTW89_ETSI][50] = 127, - [1][1][2][0][RTW89_KCC][50] = 28, - [1][1][2][0][RTW89_FCC][54] = 10, - [1][1][2][0][RTW89_ETSI][54] = 127, - [1][1][2][0][RTW89_KCC][54] = 28, - [1][1][2][0][RTW89_FCC][58] = 10, - [1][1][2][0][RTW89_ETSI][58] = 127, - [1][1][2][0][RTW89_KCC][58] = 28, - [1][1][2][0][RTW89_FCC][61] = 10, - [1][1][2][0][RTW89_ETSI][61] = 127, - [1][1][2][0][RTW89_KCC][61] = 28, - [1][1][2][0][RTW89_FCC][65] = 10, - [1][1][2][0][RTW89_ETSI][65] = 127, - [1][1][2][0][RTW89_KCC][65] = 28, - [1][1][2][0][RTW89_FCC][69] = 10, - [1][1][2][0][RTW89_ETSI][69] = 127, - [1][1][2][0][RTW89_KCC][69] = 28, - [1][1][2][0][RTW89_FCC][73] = 10, - [1][1][2][0][RTW89_ETSI][73] = 127, - [1][1][2][0][RTW89_KCC][73] = 28, - [1][1][2][0][RTW89_FCC][76] = 10, - [1][1][2][0][RTW89_ETSI][76] = 127, - [1][1][2][0][RTW89_KCC][76] = 28, - [1][1][2][0][RTW89_FCC][80] = 10, - [1][1][2][0][RTW89_ETSI][80] = 127, - [1][1][2][0][RTW89_KCC][80] = 32, - [1][1][2][0][RTW89_FCC][84] = 10, - [1][1][2][0][RTW89_ETSI][84] = 127, - [1][1][2][0][RTW89_KCC][84] = 32, - [1][1][2][0][RTW89_FCC][88] = 10, - [1][1][2][0][RTW89_ETSI][88] = 127, - [1][1][2][0][RTW89_KCC][88] = 32, - [1][1][2][0][RTW89_FCC][91] = 12, - [1][1][2][0][RTW89_ETSI][91] = 127, - [1][1][2][0][RTW89_KCC][91] = 32, - [1][1][2][0][RTW89_FCC][95] = 10, - [1][1][2][0][RTW89_ETSI][95] = 127, - [1][1][2][0][RTW89_KCC][95] = 32, - [1][1][2][0][RTW89_FCC][99] = 10, - [1][1][2][0][RTW89_ETSI][99] = 127, - [1][1][2][0][RTW89_KCC][99] = 32, - [1][1][2][0][RTW89_FCC][103] = 10, - [1][1][2][0][RTW89_ETSI][103] = 127, - [1][1][2][0][RTW89_KCC][103] = 32, - [1][1][2][0][RTW89_FCC][106] = 12, - [1][1][2][0][RTW89_ETSI][106] = 127, - [1][1][2][0][RTW89_KCC][106] = 32, - [1][1][2][0][RTW89_FCC][110] = 127, - [1][1][2][0][RTW89_ETSI][110] = 127, - [1][1][2][0][RTW89_KCC][110] = 127, - [1][1][2][0][RTW89_FCC][114] = 127, - [1][1][2][0][RTW89_ETSI][114] = 127, - [1][1][2][0][RTW89_KCC][114] = 127, - [1][1][2][0][RTW89_FCC][118] = 127, - [1][1][2][0][RTW89_ETSI][118] = 127, - [1][1][2][0][RTW89_KCC][118] = 127, - [1][1][2][1][RTW89_FCC][1] = 10, - [1][1][2][1][RTW89_ETSI][1] = 42, - [1][1][2][1][RTW89_KCC][1] = 28, - [1][1][2][1][RTW89_FCC][5] = 10, - [1][1][2][1][RTW89_ETSI][5] = 42, - [1][1][2][1][RTW89_KCC][5] = 28, - [1][1][2][1][RTW89_FCC][9] = 10, - [1][1][2][1][RTW89_ETSI][9] = 42, - [1][1][2][1][RTW89_KCC][9] = 28, - [1][1][2][1][RTW89_FCC][13] = 10, - [1][1][2][1][RTW89_ETSI][13] = 42, - [1][1][2][1][RTW89_KCC][13] = 28, - [1][1][2][1][RTW89_FCC][16] = 10, - [1][1][2][1][RTW89_ETSI][16] = 42, - [1][1][2][1][RTW89_KCC][16] = 28, - [1][1][2][1][RTW89_FCC][20] = 10, - [1][1][2][1][RTW89_ETSI][20] = 42, - [1][1][2][1][RTW89_KCC][20] = 28, - [1][1][2][1][RTW89_FCC][24] = 10, - [1][1][2][1][RTW89_ETSI][24] = 42, - [1][1][2][1][RTW89_KCC][24] = 28, - [1][1][2][1][RTW89_FCC][28] = 10, - [1][1][2][1][RTW89_ETSI][28] = 42, - [1][1][2][1][RTW89_KCC][28] = 28, - [1][1][2][1][RTW89_FCC][31] = 10, - [1][1][2][1][RTW89_ETSI][31] = 42, - [1][1][2][1][RTW89_KCC][31] = 28, - [1][1][2][1][RTW89_FCC][35] = 10, - [1][1][2][1][RTW89_ETSI][35] = 42, - [1][1][2][1][RTW89_KCC][35] = 28, - [1][1][2][1][RTW89_FCC][39] = 10, - [1][1][2][1][RTW89_ETSI][39] = 42, - [1][1][2][1][RTW89_KCC][39] = 28, - [1][1][2][1][RTW89_FCC][43] = 10, - [1][1][2][1][RTW89_ETSI][43] = 42, - [1][1][2][1][RTW89_KCC][43] = 28, - [1][1][2][1][RTW89_FCC][46] = 12, - [1][1][2][1][RTW89_ETSI][46] = 127, - [1][1][2][1][RTW89_KCC][46] = 28, - [1][1][2][1][RTW89_FCC][50] = 12, - [1][1][2][1][RTW89_ETSI][50] = 127, - [1][1][2][1][RTW89_KCC][50] = 28, - [1][1][2][1][RTW89_FCC][54] = 10, - [1][1][2][1][RTW89_ETSI][54] = 127, - [1][1][2][1][RTW89_KCC][54] = 28, - [1][1][2][1][RTW89_FCC][58] = 10, - [1][1][2][1][RTW89_ETSI][58] = 127, - [1][1][2][1][RTW89_KCC][58] = 28, - [1][1][2][1][RTW89_FCC][61] = 10, - [1][1][2][1][RTW89_ETSI][61] = 127, - [1][1][2][1][RTW89_KCC][61] = 28, - [1][1][2][1][RTW89_FCC][65] = 10, - [1][1][2][1][RTW89_ETSI][65] = 127, - [1][1][2][1][RTW89_KCC][65] = 28, - [1][1][2][1][RTW89_FCC][69] = 10, - [1][1][2][1][RTW89_ETSI][69] = 127, - [1][1][2][1][RTW89_KCC][69] = 28, - [1][1][2][1][RTW89_FCC][73] = 10, - [1][1][2][1][RTW89_ETSI][73] = 127, - [1][1][2][1][RTW89_KCC][73] = 28, - [1][1][2][1][RTW89_FCC][76] = 10, - [1][1][2][1][RTW89_ETSI][76] = 127, - [1][1][2][1][RTW89_KCC][76] = 28, - [1][1][2][1][RTW89_FCC][80] = 10, - [1][1][2][1][RTW89_ETSI][80] = 127, - [1][1][2][1][RTW89_KCC][80] = 32, - [1][1][2][1][RTW89_FCC][84] = 10, - [1][1][2][1][RTW89_ETSI][84] = 127, - [1][1][2][1][RTW89_KCC][84] = 32, - [1][1][2][1][RTW89_FCC][88] = 10, - [1][1][2][1][RTW89_ETSI][88] = 127, - [1][1][2][1][RTW89_KCC][88] = 32, - [1][1][2][1][RTW89_FCC][91] = 12, - [1][1][2][1][RTW89_ETSI][91] = 127, - [1][1][2][1][RTW89_KCC][91] = 32, - [1][1][2][1][RTW89_FCC][95] = 10, - [1][1][2][1][RTW89_ETSI][95] = 127, - [1][1][2][1][RTW89_KCC][95] = 32, - [1][1][2][1][RTW89_FCC][99] = 10, - [1][1][2][1][RTW89_ETSI][99] = 127, - [1][1][2][1][RTW89_KCC][99] = 32, - [1][1][2][1][RTW89_FCC][103] = 10, - [1][1][2][1][RTW89_ETSI][103] = 127, - [1][1][2][1][RTW89_KCC][103] = 32, - [1][1][2][1][RTW89_FCC][106] = 12, - [1][1][2][1][RTW89_ETSI][106] = 127, - [1][1][2][1][RTW89_KCC][106] = 32, - [1][1][2][1][RTW89_FCC][110] = 127, - [1][1][2][1][RTW89_ETSI][110] = 127, - [1][1][2][1][RTW89_KCC][110] = 127, - [1][1][2][1][RTW89_FCC][114] = 127, - [1][1][2][1][RTW89_ETSI][114] = 127, - [1][1][2][1][RTW89_KCC][114] = 127, - [1][1][2][1][RTW89_FCC][118] = 127, - [1][1][2][1][RTW89_ETSI][118] = 127, - [1][1][2][1][RTW89_KCC][118] = 127, - [2][0][2][0][RTW89_FCC][3] = 46, - [2][0][2][0][RTW89_ETSI][3] = 48, - [2][0][2][0][RTW89_KCC][3] = 50, - [2][0][2][0][RTW89_FCC][11] = 46, - [2][0][2][0][RTW89_ETSI][11] = 48, - [2][0][2][0][RTW89_KCC][11] = 50, - [2][0][2][0][RTW89_FCC][18] = 46, - [2][0][2][0][RTW89_ETSI][18] = 48, - [2][0][2][0][RTW89_KCC][18] = 50, - [2][0][2][0][RTW89_FCC][26] = 46, - [2][0][2][0][RTW89_ETSI][26] = 48, - [2][0][2][0][RTW89_KCC][26] = 50, - [2][0][2][0][RTW89_FCC][33] = 46, - [2][0][2][0][RTW89_ETSI][33] = 48, - [2][0][2][0][RTW89_KCC][33] = 50, - [2][0][2][0][RTW89_FCC][41] = 46, - [2][0][2][0][RTW89_ETSI][41] = 48, - [2][0][2][0][RTW89_KCC][41] = 50, - [2][0][2][0][RTW89_FCC][48] = 46, - [2][0][2][0][RTW89_ETSI][48] = 127, - [2][0][2][0][RTW89_KCC][48] = 48, - [2][0][2][0][RTW89_FCC][56] = 46, - [2][0][2][0][RTW89_ETSI][56] = 127, - [2][0][2][0][RTW89_KCC][56] = 48, - [2][0][2][0][RTW89_FCC][63] = 46, - [2][0][2][0][RTW89_ETSI][63] = 127, - [2][0][2][0][RTW89_KCC][63] = 48, - [2][0][2][0][RTW89_FCC][71] = 46, - [2][0][2][0][RTW89_ETSI][71] = 127, - [2][0][2][0][RTW89_KCC][71] = 48, - [2][0][2][0][RTW89_FCC][78] = 46, - [2][0][2][0][RTW89_ETSI][78] = 127, - [2][0][2][0][RTW89_KCC][78] = 52, - [2][0][2][0][RTW89_FCC][86] = 46, - [2][0][2][0][RTW89_ETSI][86] = 127, - [2][0][2][0][RTW89_KCC][86] = 52, - [2][0][2][0][RTW89_FCC][93] = 46, - [2][0][2][0][RTW89_ETSI][93] = 127, - [2][0][2][0][RTW89_KCC][93] = 50, - [2][0][2][0][RTW89_FCC][101] = 44, - [2][0][2][0][RTW89_ETSI][101] = 127, - [2][0][2][0][RTW89_KCC][101] = 50, - [2][0][2][0][RTW89_FCC][108] = 127, - [2][0][2][0][RTW89_ETSI][108] = 127, - [2][0][2][0][RTW89_KCC][108] = 127, - [2][0][2][0][RTW89_FCC][116] = 127, - [2][0][2][0][RTW89_ETSI][116] = 127, - [2][0][2][0][RTW89_KCC][116] = 127, - [2][1][2][0][RTW89_FCC][3] = 22, - [2][1][2][0][RTW89_ETSI][3] = 48, - [2][1][2][0][RTW89_KCC][3] = 38, - [2][1][2][0][RTW89_FCC][11] = 20, - [2][1][2][0][RTW89_ETSI][11] = 48, - [2][1][2][0][RTW89_KCC][11] = 38, - [2][1][2][0][RTW89_FCC][18] = 20, - [2][1][2][0][RTW89_ETSI][18] = 48, - [2][1][2][0][RTW89_KCC][18] = 38, - [2][1][2][0][RTW89_FCC][26] = 20, - [2][1][2][0][RTW89_ETSI][26] = 48, - [2][1][2][0][RTW89_KCC][26] = 38, - [2][1][2][0][RTW89_FCC][33] = 20, - [2][1][2][0][RTW89_ETSI][33] = 48, - [2][1][2][0][RTW89_KCC][33] = 38, - [2][1][2][0][RTW89_FCC][41] = 22, - [2][1][2][0][RTW89_ETSI][41] = 48, - [2][1][2][0][RTW89_KCC][41] = 38, - [2][1][2][0][RTW89_FCC][48] = 22, - [2][1][2][0][RTW89_ETSI][48] = 127, - [2][1][2][0][RTW89_KCC][48] = 38, - [2][1][2][0][RTW89_FCC][56] = 20, - [2][1][2][0][RTW89_ETSI][56] = 127, - [2][1][2][0][RTW89_KCC][56] = 38, - [2][1][2][0][RTW89_FCC][63] = 22, - [2][1][2][0][RTW89_ETSI][63] = 127, - [2][1][2][0][RTW89_KCC][63] = 38, - [2][1][2][0][RTW89_FCC][71] = 20, - [2][1][2][0][RTW89_ETSI][71] = 127, - [2][1][2][0][RTW89_KCC][71] = 38, - [2][1][2][0][RTW89_FCC][78] = 20, - [2][1][2][0][RTW89_ETSI][78] = 127, - [2][1][2][0][RTW89_KCC][78] = 38, - [2][1][2][0][RTW89_FCC][86] = 20, - [2][1][2][0][RTW89_ETSI][86] = 127, - [2][1][2][0][RTW89_KCC][86] = 38, - [2][1][2][0][RTW89_FCC][93] = 22, - [2][1][2][0][RTW89_ETSI][93] = 127, - [2][1][2][0][RTW89_KCC][93] = 38, - [2][1][2][0][RTW89_FCC][101] = 22, - [2][1][2][0][RTW89_ETSI][101] = 127, - [2][1][2][0][RTW89_KCC][101] = 38, - [2][1][2][0][RTW89_FCC][108] = 127, - [2][1][2][0][RTW89_ETSI][108] = 127, - [2][1][2][0][RTW89_KCC][108] = 127, - [2][1][2][0][RTW89_FCC][116] = 127, - [2][1][2][0][RTW89_ETSI][116] = 127, - [2][1][2][0][RTW89_KCC][116] = 127, - [2][1][2][1][RTW89_FCC][3] = 22, - [2][1][2][1][RTW89_ETSI][3] = 42, - [2][1][2][1][RTW89_KCC][3] = 38, - [2][1][2][1][RTW89_FCC][11] = 20, - [2][1][2][1][RTW89_ETSI][11] = 42, - [2][1][2][1][RTW89_KCC][11] = 38, - [2][1][2][1][RTW89_FCC][18] = 20, - [2][1][2][1][RTW89_ETSI][18] = 42, - [2][1][2][1][RTW89_KCC][18] = 38, - [2][1][2][1][RTW89_FCC][26] = 20, - [2][1][2][1][RTW89_ETSI][26] = 42, - [2][1][2][1][RTW89_KCC][26] = 38, - [2][1][2][1][RTW89_FCC][33] = 20, - [2][1][2][1][RTW89_ETSI][33] = 42, - [2][1][2][1][RTW89_KCC][33] = 38, - [2][1][2][1][RTW89_FCC][41] = 22, - [2][1][2][1][RTW89_ETSI][41] = 42, - [2][1][2][1][RTW89_KCC][41] = 38, - [2][1][2][1][RTW89_FCC][48] = 22, - [2][1][2][1][RTW89_ETSI][48] = 127, - [2][1][2][1][RTW89_KCC][48] = 38, - [2][1][2][1][RTW89_FCC][56] = 20, - [2][1][2][1][RTW89_ETSI][56] = 127, - [2][1][2][1][RTW89_KCC][56] = 38, - [2][1][2][1][RTW89_FCC][63] = 22, - [2][1][2][1][RTW89_ETSI][63] = 127, - [2][1][2][1][RTW89_KCC][63] = 38, - [2][1][2][1][RTW89_FCC][71] = 20, - [2][1][2][1][RTW89_ETSI][71] = 127, - [2][1][2][1][RTW89_KCC][71] = 38, - [2][1][2][1][RTW89_FCC][78] = 20, - [2][1][2][1][RTW89_ETSI][78] = 127, - [2][1][2][1][RTW89_KCC][78] = 38, - [2][1][2][1][RTW89_FCC][86] = 20, - [2][1][2][1][RTW89_ETSI][86] = 127, - [2][1][2][1][RTW89_KCC][86] = 38, - [2][1][2][1][RTW89_FCC][93] = 22, - [2][1][2][1][RTW89_ETSI][93] = 127, - [2][1][2][1][RTW89_KCC][93] = 38, - [2][1][2][1][RTW89_FCC][101] = 22, - [2][1][2][1][RTW89_ETSI][101] = 127, - [2][1][2][1][RTW89_KCC][101] = 38, - [2][1][2][1][RTW89_FCC][108] = 127, - [2][1][2][1][RTW89_ETSI][108] = 127, - [2][1][2][1][RTW89_KCC][108] = 127, - [2][1][2][1][RTW89_FCC][116] = 127, - [2][1][2][1][RTW89_ETSI][116] = 127, - [2][1][2][1][RTW89_KCC][116] = 127, - [3][0][2][0][RTW89_FCC][7] = 52, - [3][0][2][0][RTW89_ETSI][7] = 38, - [3][0][2][0][RTW89_KCC][7] = 42, - [3][0][2][0][RTW89_FCC][22] = 52, - [3][0][2][0][RTW89_ETSI][22] = 38, - [3][0][2][0][RTW89_KCC][22] = 42, - [3][0][2][0][RTW89_FCC][37] = 52, - [3][0][2][0][RTW89_ETSI][37] = 38, - [3][0][2][0][RTW89_KCC][37] = 42, - [3][0][2][0][RTW89_FCC][52] = 54, - [3][0][2][0][RTW89_ETSI][52] = 127, - [3][0][2][0][RTW89_KCC][52] = 56, - [3][0][2][0][RTW89_FCC][67] = 54, - [3][0][2][0][RTW89_ETSI][67] = 127, - [3][0][2][0][RTW89_KCC][67] = 54, - [3][0][2][0][RTW89_FCC][82] = 54, - [3][0][2][0][RTW89_ETSI][82] = 127, - [3][0][2][0][RTW89_KCC][82] = 26, - [3][0][2][0][RTW89_FCC][97] = 40, - [3][0][2][0][RTW89_ETSI][97] = 127, - [3][0][2][0][RTW89_KCC][97] = 26, - [3][0][2][0][RTW89_FCC][112] = 127, - [3][0][2][0][RTW89_ETSI][112] = 127, - [3][0][2][0][RTW89_KCC][112] = 127, - [3][1][2][0][RTW89_FCC][7] = 32, - [3][1][2][0][RTW89_ETSI][7] = 38, - [3][1][2][0][RTW89_KCC][7] = 40, - [3][1][2][0][RTW89_FCC][22] = 30, - [3][1][2][0][RTW89_ETSI][22] = 38, - [3][1][2][0][RTW89_KCC][22] = 40, - [3][1][2][0][RTW89_FCC][37] = 30, - [3][1][2][0][RTW89_ETSI][37] = 38, - [3][1][2][0][RTW89_KCC][37] = 40, - [3][1][2][0][RTW89_FCC][52] = 30, - [3][1][2][0][RTW89_ETSI][52] = 127, - [3][1][2][0][RTW89_KCC][52] = 48, - [3][1][2][0][RTW89_FCC][67] = 32, - [3][1][2][0][RTW89_ETSI][67] = 127, - [3][1][2][0][RTW89_KCC][67] = 48, - [3][1][2][0][RTW89_FCC][82] = 32, - [3][1][2][0][RTW89_ETSI][82] = 127, - [3][1][2][0][RTW89_KCC][82] = 24, - [3][1][2][0][RTW89_FCC][97] = 14, - [3][1][2][0][RTW89_ETSI][97] = 127, - [3][1][2][0][RTW89_KCC][97] = 24, - [3][1][2][0][RTW89_FCC][112] = 127, - [3][1][2][0][RTW89_ETSI][112] = 127, - [3][1][2][0][RTW89_KCC][112] = 127, - [3][1][2][1][RTW89_FCC][7] = 32, - [3][1][2][1][RTW89_ETSI][7] = 38, - [3][1][2][1][RTW89_KCC][7] = 40, - [3][1][2][1][RTW89_FCC][22] = 30, - [3][1][2][1][RTW89_ETSI][22] = 38, - [3][1][2][1][RTW89_KCC][22] = 40, - [3][1][2][1][RTW89_FCC][37] = 30, - [3][1][2][1][RTW89_ETSI][37] = 38, - [3][1][2][1][RTW89_KCC][37] = 40, - [3][1][2][1][RTW89_FCC][52] = 30, - [3][1][2][1][RTW89_ETSI][52] = 127, - [3][1][2][1][RTW89_KCC][52] = 48, - [3][1][2][1][RTW89_FCC][67] = 32, - [3][1][2][1][RTW89_ETSI][67] = 127, - [3][1][2][1][RTW89_KCC][67] = 48, - [3][1][2][1][RTW89_FCC][82] = 32, - [3][1][2][1][RTW89_ETSI][82] = 127, - [3][1][2][1][RTW89_KCC][82] = 24, - [3][1][2][1][RTW89_FCC][97] = 14, - [3][1][2][1][RTW89_ETSI][97] = 127, - [3][1][2][1][RTW89_KCC][97] = 24, - [3][1][2][1][RTW89_FCC][112] = 127, - [3][1][2][1][RTW89_ETSI][112] = 127, - [3][1][2][1][RTW89_KCC][112] = 127, + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM] = { + [0][0][1][0][RTW89_WW][0][0] = 24, + [0][0][1][0][RTW89_WW][1][0] = 24, + [0][0][1][0][RTW89_WW][2][0] = 56, + [0][0][1][0][RTW89_WW][0][2] = 22, + [0][0][1][0][RTW89_WW][1][2] = 22, + [0][0][1][0][RTW89_WW][2][2] = 56, + [0][0][1][0][RTW89_WW][0][4] = 22, + [0][0][1][0][RTW89_WW][1][4] = 22, + [0][0][1][0][RTW89_WW][2][4] = 56, + [0][0][1][0][RTW89_WW][0][6] = 22, + [0][0][1][0][RTW89_WW][1][6] = 22, + [0][0][1][0][RTW89_WW][2][6] = 56, + [0][0][1][0][RTW89_WW][0][8] = 22, + [0][0][1][0][RTW89_WW][1][8] = 22, + [0][0][1][0][RTW89_WW][2][8] = 56, + [0][0][1][0][RTW89_WW][0][10] = 22, + [0][0][1][0][RTW89_WW][1][10] = 22, + [0][0][1][0][RTW89_WW][2][10] = 56, + [0][0][1][0][RTW89_WW][0][12] = 22, + [0][0][1][0][RTW89_WW][1][12] = 22, + [0][0][1][0][RTW89_WW][2][12] = 56, + [0][0][1][0][RTW89_WW][0][14] = 22, + [0][0][1][0][RTW89_WW][1][14] = 22, + [0][0][1][0][RTW89_WW][2][14] = 56, + [0][0][1][0][RTW89_WW][0][15] = 22, + [0][0][1][0][RTW89_WW][1][15] = 22, + [0][0][1][0][RTW89_WW][2][15] = 56, + [0][0][1][0][RTW89_WW][0][17] = 22, + [0][0][1][0][RTW89_WW][1][17] = 22, + [0][0][1][0][RTW89_WW][2][17] = 56, + [0][0][1][0][RTW89_WW][0][19] = 22, + [0][0][1][0][RTW89_WW][1][19] = 22, + [0][0][1][0][RTW89_WW][2][19] = 56, + [0][0][1][0][RTW89_WW][0][21] = 22, + [0][0][1][0][RTW89_WW][1][21] = 22, + [0][0][1][0][RTW89_WW][2][21] = 56, + [0][0][1][0][RTW89_WW][0][23] = 22, + [0][0][1][0][RTW89_WW][1][23] = 22, + [0][0][1][0][RTW89_WW][2][23] = 70, + [0][0][1][0][RTW89_WW][0][25] = 22, + [0][0][1][0][RTW89_WW][1][25] = 22, + [0][0][1][0][RTW89_WW][2][25] = 70, + [0][0][1][0][RTW89_WW][0][27] = 22, + [0][0][1][0][RTW89_WW][1][27] = 22, + [0][0][1][0][RTW89_WW][2][27] = 70, + [0][0][1][0][RTW89_WW][0][29] = 22, + [0][0][1][0][RTW89_WW][1][29] = 22, + [0][0][1][0][RTW89_WW][2][29] = 70, + [0][0][1][0][RTW89_WW][0][30] = 22, + [0][0][1][0][RTW89_WW][1][30] = 22, + [0][0][1][0][RTW89_WW][2][30] = 70, + [0][0][1][0][RTW89_WW][0][32] = 22, + [0][0][1][0][RTW89_WW][1][32] = 22, + [0][0][1][0][RTW89_WW][2][32] = 70, + [0][0][1][0][RTW89_WW][0][34] = 22, + [0][0][1][0][RTW89_WW][1][34] = 22, + [0][0][1][0][RTW89_WW][2][34] = 70, + [0][0][1][0][RTW89_WW][0][36] = 22, + [0][0][1][0][RTW89_WW][1][36] = 22, + [0][0][1][0][RTW89_WW][2][36] = 70, + [0][0][1][0][RTW89_WW][0][38] = 22, + [0][0][1][0][RTW89_WW][1][38] = 22, + [0][0][1][0][RTW89_WW][2][38] = 70, + [0][0][1][0][RTW89_WW][0][40] = 22, + [0][0][1][0][RTW89_WW][1][40] = 22, + [0][0][1][0][RTW89_WW][2][40] = 70, + [0][0][1][0][RTW89_WW][0][42] = 22, + [0][0][1][0][RTW89_WW][1][42] = 22, + [0][0][1][0][RTW89_WW][2][42] = 70, + [0][0][1][0][RTW89_WW][0][44] = 22, + [0][0][1][0][RTW89_WW][1][44] = 22, + [0][0][1][0][RTW89_WW][2][44] = 70, + [0][0][1][0][RTW89_WW][0][45] = 22, + [0][0][1][0][RTW89_WW][1][45] = 22, + [0][0][1][0][RTW89_WW][2][45] = 0, + [0][0][1][0][RTW89_WW][0][47] = 22, + [0][0][1][0][RTW89_WW][1][47] = 22, + [0][0][1][0][RTW89_WW][2][47] = 0, + [0][0][1][0][RTW89_WW][0][49] = 24, + [0][0][1][0][RTW89_WW][1][49] = 24, + [0][0][1][0][RTW89_WW][2][49] = 0, + [0][0][1][0][RTW89_WW][0][51] = 22, + [0][0][1][0][RTW89_WW][1][51] = 22, + [0][0][1][0][RTW89_WW][2][51] = 0, + [0][0][1][0][RTW89_WW][0][53] = 22, + [0][0][1][0][RTW89_WW][1][53] = 22, + [0][0][1][0][RTW89_WW][2][53] = 0, + [0][0][1][0][RTW89_WW][0][55] = 22, + [0][0][1][0][RTW89_WW][1][55] = 22, + [0][0][1][0][RTW89_WW][2][55] = 68, + [0][0][1][0][RTW89_WW][0][57] = 22, + [0][0][1][0][RTW89_WW][1][57] = 22, + [0][0][1][0][RTW89_WW][2][57] = 68, + [0][0][1][0][RTW89_WW][0][59] = 22, + [0][0][1][0][RTW89_WW][1][59] = 22, + [0][0][1][0][RTW89_WW][2][59] = 68, + [0][0][1][0][RTW89_WW][0][60] = 22, + [0][0][1][0][RTW89_WW][1][60] = 22, + [0][0][1][0][RTW89_WW][2][60] = 68, + [0][0][1][0][RTW89_WW][0][62] = 22, + [0][0][1][0][RTW89_WW][1][62] = 22, + [0][0][1][0][RTW89_WW][2][62] = 68, + [0][0][1][0][RTW89_WW][0][64] = 22, + [0][0][1][0][RTW89_WW][1][64] = 22, + [0][0][1][0][RTW89_WW][2][64] = 68, + [0][0][1][0][RTW89_WW][0][66] = 22, + [0][0][1][0][RTW89_WW][1][66] = 22, + [0][0][1][0][RTW89_WW][2][66] = 68, + [0][0][1][0][RTW89_WW][0][68] = 22, + [0][0][1][0][RTW89_WW][1][68] = 22, + [0][0][1][0][RTW89_WW][2][68] = 68, + [0][0][1][0][RTW89_WW][0][70] = 24, + [0][0][1][0][RTW89_WW][1][70] = 24, + [0][0][1][0][RTW89_WW][2][70] = 68, + [0][0][1][0][RTW89_WW][0][72] = 22, + [0][0][1][0][RTW89_WW][1][72] = 22, + [0][0][1][0][RTW89_WW][2][72] = 68, + [0][0][1][0][RTW89_WW][0][74] = 22, + [0][0][1][0][RTW89_WW][1][74] = 22, + [0][0][1][0][RTW89_WW][2][74] = 68, + [0][0][1][0][RTW89_WW][0][75] = 22, + [0][0][1][0][RTW89_WW][1][75] = 22, + [0][0][1][0][RTW89_WW][2][75] = 68, + [0][0][1][0][RTW89_WW][0][77] = 22, + [0][0][1][0][RTW89_WW][1][77] = 22, + [0][0][1][0][RTW89_WW][2][77] = 68, + [0][0][1][0][RTW89_WW][0][79] = 22, + [0][0][1][0][RTW89_WW][1][79] = 22, + [0][0][1][0][RTW89_WW][2][79] = 68, + [0][0][1][0][RTW89_WW][0][81] = 22, + [0][0][1][0][RTW89_WW][1][81] = 22, + [0][0][1][0][RTW89_WW][2][81] = 68, + [0][0][1][0][RTW89_WW][0][83] = 22, + [0][0][1][0][RTW89_WW][1][83] = 22, + [0][0][1][0][RTW89_WW][2][83] = 68, + [0][0][1][0][RTW89_WW][0][85] = 22, + [0][0][1][0][RTW89_WW][1][85] = 22, + [0][0][1][0][RTW89_WW][2][85] = 68, + [0][0][1][0][RTW89_WW][0][87] = 22, + [0][0][1][0][RTW89_WW][1][87] = 22, + [0][0][1][0][RTW89_WW][2][87] = 0, + [0][0][1][0][RTW89_WW][0][89] = 22, + [0][0][1][0][RTW89_WW][1][89] = 22, + [0][0][1][0][RTW89_WW][2][89] = 0, + [0][0][1][0][RTW89_WW][0][90] = 22, + [0][0][1][0][RTW89_WW][1][90] = 22, + [0][0][1][0][RTW89_WW][2][90] = 0, + [0][0][1][0][RTW89_WW][0][92] = 22, + [0][0][1][0][RTW89_WW][1][92] = 22, + [0][0][1][0][RTW89_WW][2][92] = 0, + [0][0][1][0][RTW89_WW][0][94] = 22, + [0][0][1][0][RTW89_WW][1][94] = 22, + [0][0][1][0][RTW89_WW][2][94] = 0, + [0][0][1][0][RTW89_WW][0][96] = 22, + [0][0][1][0][RTW89_WW][1][96] = 22, + [0][0][1][0][RTW89_WW][2][96] = 0, + [0][0][1][0][RTW89_WW][0][98] = 22, + [0][0][1][0][RTW89_WW][1][98] = 22, + [0][0][1][0][RTW89_WW][2][98] = 0, + [0][0][1][0][RTW89_WW][0][100] = 22, + [0][0][1][0][RTW89_WW][1][100] = 22, + [0][0][1][0][RTW89_WW][2][100] = 0, + [0][0][1][0][RTW89_WW][0][102] = 22, + [0][0][1][0][RTW89_WW][1][102] = 22, + [0][0][1][0][RTW89_WW][2][102] = 0, + [0][0][1][0][RTW89_WW][0][104] = 22, + [0][0][1][0][RTW89_WW][1][104] = 22, + [0][0][1][0][RTW89_WW][2][104] = 0, + [0][0][1][0][RTW89_WW][0][105] = 22, + [0][0][1][0][RTW89_WW][1][105] = 22, + [0][0][1][0][RTW89_WW][2][105] = 0, + [0][0][1][0][RTW89_WW][0][107] = 24, + [0][0][1][0][RTW89_WW][1][107] = 24, + [0][0][1][0][RTW89_WW][2][107] = 0, + [0][0][1][0][RTW89_WW][0][109] = 24, + [0][0][1][0][RTW89_WW][1][109] = 24, + [0][0][1][0][RTW89_WW][2][109] = 0, + [0][0][1][0][RTW89_WW][0][111] = 0, + [0][0][1][0][RTW89_WW][1][111] = 0, + [0][0][1][0][RTW89_WW][2][111] = 0, + [0][0][1][0][RTW89_WW][0][113] = 0, + [0][0][1][0][RTW89_WW][1][113] = 0, + [0][0][1][0][RTW89_WW][2][113] = 0, + [0][0][1][0][RTW89_WW][0][115] = 0, + [0][0][1][0][RTW89_WW][1][115] = 0, + [0][0][1][0][RTW89_WW][2][115] = 0, + [0][0][1][0][RTW89_WW][0][117] = 0, + [0][0][1][0][RTW89_WW][1][117] = 0, + [0][0][1][0][RTW89_WW][2][117] = 0, + [0][0][1][0][RTW89_WW][0][119] = 0, + [0][0][1][0][RTW89_WW][1][119] = 0, + [0][0][1][0][RTW89_WW][2][119] = 0, + [0][1][1][0][RTW89_WW][0][0] = -2, + [0][1][1][0][RTW89_WW][1][0] = -2, + [0][1][1][0][RTW89_WW][2][0] = 54, + [0][1][1][0][RTW89_WW][0][2] = -4, + [0][1][1][0][RTW89_WW][1][2] = -4, + [0][1][1][0][RTW89_WW][2][2] = 54, + [0][1][1][0][RTW89_WW][0][4] = -4, + [0][1][1][0][RTW89_WW][1][4] = -4, + [0][1][1][0][RTW89_WW][2][4] = 54, + [0][1][1][0][RTW89_WW][0][6] = -4, + [0][1][1][0][RTW89_WW][1][6] = -4, + [0][1][1][0][RTW89_WW][2][6] = 54, + [0][1][1][0][RTW89_WW][0][8] = -4, + [0][1][1][0][RTW89_WW][1][8] = -4, + [0][1][1][0][RTW89_WW][2][8] = 54, + [0][1][1][0][RTW89_WW][0][10] = -4, + [0][1][1][0][RTW89_WW][1][10] = -4, + [0][1][1][0][RTW89_WW][2][10] = 54, + [0][1][1][0][RTW89_WW][0][12] = -4, + [0][1][1][0][RTW89_WW][1][12] = -4, + [0][1][1][0][RTW89_WW][2][12] = 54, + [0][1][1][0][RTW89_WW][0][14] = -4, + [0][1][1][0][RTW89_WW][1][14] = -4, + [0][1][1][0][RTW89_WW][2][14] = 54, + [0][1][1][0][RTW89_WW][0][15] = -4, + [0][1][1][0][RTW89_WW][1][15] = -4, + [0][1][1][0][RTW89_WW][2][15] = 54, + [0][1][1][0][RTW89_WW][0][17] = -4, + [0][1][1][0][RTW89_WW][1][17] = -4, + [0][1][1][0][RTW89_WW][2][17] = 54, + [0][1][1][0][RTW89_WW][0][19] = -4, + [0][1][1][0][RTW89_WW][1][19] = -4, + [0][1][1][0][RTW89_WW][2][19] = 54, + [0][1][1][0][RTW89_WW][0][21] = -4, + [0][1][1][0][RTW89_WW][1][21] = -4, + [0][1][1][0][RTW89_WW][2][21] = 54, + [0][1][1][0][RTW89_WW][0][23] = -4, + [0][1][1][0][RTW89_WW][1][23] = -4, + [0][1][1][0][RTW89_WW][2][23] = 68, + [0][1][1][0][RTW89_WW][0][25] = -4, + [0][1][1][0][RTW89_WW][1][25] = -4, + [0][1][1][0][RTW89_WW][2][25] = 68, + [0][1][1][0][RTW89_WW][0][27] = -4, + [0][1][1][0][RTW89_WW][1][27] = -4, + [0][1][1][0][RTW89_WW][2][27] = 68, + [0][1][1][0][RTW89_WW][0][29] = -4, + [0][1][1][0][RTW89_WW][1][29] = -4, + [0][1][1][0][RTW89_WW][2][29] = 68, + [0][1][1][0][RTW89_WW][0][30] = -4, + [0][1][1][0][RTW89_WW][1][30] = -4, + [0][1][1][0][RTW89_WW][2][30] = 68, + [0][1][1][0][RTW89_WW][0][32] = -4, + [0][1][1][0][RTW89_WW][1][32] = -4, + [0][1][1][0][RTW89_WW][2][32] = 68, + [0][1][1][0][RTW89_WW][0][34] = -4, + [0][1][1][0][RTW89_WW][1][34] = -4, + [0][1][1][0][RTW89_WW][2][34] = 68, + [0][1][1][0][RTW89_WW][0][36] = -4, + [0][1][1][0][RTW89_WW][1][36] = -4, + [0][1][1][0][RTW89_WW][2][36] = 68, + [0][1][1][0][RTW89_WW][0][38] = -4, + [0][1][1][0][RTW89_WW][1][38] = -4, + [0][1][1][0][RTW89_WW][2][38] = 68, + [0][1][1][0][RTW89_WW][0][40] = -4, + [0][1][1][0][RTW89_WW][1][40] = -4, + [0][1][1][0][RTW89_WW][2][40] = 68, + [0][1][1][0][RTW89_WW][0][42] = -4, + [0][1][1][0][RTW89_WW][1][42] = -4, + [0][1][1][0][RTW89_WW][2][42] = 68, + [0][1][1][0][RTW89_WW][0][44] = -2, + [0][1][1][0][RTW89_WW][1][44] = -2, + [0][1][1][0][RTW89_WW][2][44] = 68, + [0][1][1][0][RTW89_WW][0][45] = -2, + [0][1][1][0][RTW89_WW][1][45] = -2, + [0][1][1][0][RTW89_WW][2][45] = 0, + [0][1][1][0][RTW89_WW][0][47] = -2, + [0][1][1][0][RTW89_WW][1][47] = -2, + [0][1][1][0][RTW89_WW][2][47] = 0, + [0][1][1][0][RTW89_WW][0][49] = -2, + [0][1][1][0][RTW89_WW][1][49] = -2, + [0][1][1][0][RTW89_WW][2][49] = 0, + [0][1][1][0][RTW89_WW][0][51] = -2, + [0][1][1][0][RTW89_WW][1][51] = -2, + [0][1][1][0][RTW89_WW][2][51] = 0, + [0][1][1][0][RTW89_WW][0][53] = -2, + [0][1][1][0][RTW89_WW][1][53] = -2, + [0][1][1][0][RTW89_WW][2][53] = 0, + [0][1][1][0][RTW89_WW][0][55] = -2, + [0][1][1][0][RTW89_WW][1][55] = -2, + [0][1][1][0][RTW89_WW][2][55] = 68, + [0][1][1][0][RTW89_WW][0][57] = -2, + [0][1][1][0][RTW89_WW][1][57] = -2, + [0][1][1][0][RTW89_WW][2][57] = 68, + [0][1][1][0][RTW89_WW][0][59] = -2, + [0][1][1][0][RTW89_WW][1][59] = -2, + [0][1][1][0][RTW89_WW][2][59] = 68, + [0][1][1][0][RTW89_WW][0][60] = -2, + [0][1][1][0][RTW89_WW][1][60] = -2, + [0][1][1][0][RTW89_WW][2][60] = 68, + [0][1][1][0][RTW89_WW][0][62] = -2, + [0][1][1][0][RTW89_WW][1][62] = -2, + [0][1][1][0][RTW89_WW][2][62] = 68, + [0][1][1][0][RTW89_WW][0][64] = -2, + [0][1][1][0][RTW89_WW][1][64] = -2, + [0][1][1][0][RTW89_WW][2][64] = 68, + [0][1][1][0][RTW89_WW][0][66] = -2, + [0][1][1][0][RTW89_WW][1][66] = -2, + [0][1][1][0][RTW89_WW][2][66] = 68, + [0][1][1][0][RTW89_WW][0][68] = -2, + [0][1][1][0][RTW89_WW][1][68] = -2, + [0][1][1][0][RTW89_WW][2][68] = 68, + [0][1][1][0][RTW89_WW][0][70] = -2, + [0][1][1][0][RTW89_WW][1][70] = -2, + [0][1][1][0][RTW89_WW][2][70] = 68, + [0][1][1][0][RTW89_WW][0][72] = -2, + [0][1][1][0][RTW89_WW][1][72] = -2, + [0][1][1][0][RTW89_WW][2][72] = 68, + [0][1][1][0][RTW89_WW][0][74] = -2, + [0][1][1][0][RTW89_WW][1][74] = -2, + [0][1][1][0][RTW89_WW][2][74] = 68, + [0][1][1][0][RTW89_WW][0][75] = -2, + [0][1][1][0][RTW89_WW][1][75] = -2, + [0][1][1][0][RTW89_WW][2][75] = 68, + [0][1][1][0][RTW89_WW][0][77] = -2, + [0][1][1][0][RTW89_WW][1][77] = -2, + [0][1][1][0][RTW89_WW][2][77] = 68, + [0][1][1][0][RTW89_WW][0][79] = -2, + [0][1][1][0][RTW89_WW][1][79] = -2, + [0][1][1][0][RTW89_WW][2][79] = 68, + [0][1][1][0][RTW89_WW][0][81] = -2, + [0][1][1][0][RTW89_WW][1][81] = -2, + [0][1][1][0][RTW89_WW][2][81] = 68, + [0][1][1][0][RTW89_WW][0][83] = -2, + [0][1][1][0][RTW89_WW][1][83] = -2, + [0][1][1][0][RTW89_WW][2][83] = 68, + [0][1][1][0][RTW89_WW][0][85] = -2, + [0][1][1][0][RTW89_WW][1][85] = -2, + [0][1][1][0][RTW89_WW][2][85] = 68, + [0][1][1][0][RTW89_WW][0][87] = -2, + [0][1][1][0][RTW89_WW][1][87] = -2, + [0][1][1][0][RTW89_WW][2][87] = 0, + [0][1][1][0][RTW89_WW][0][89] = -2, + [0][1][1][0][RTW89_WW][1][89] = -2, + [0][1][1][0][RTW89_WW][2][89] = 0, + [0][1][1][0][RTW89_WW][0][90] = -2, + [0][1][1][0][RTW89_WW][1][90] = -2, + [0][1][1][0][RTW89_WW][2][90] = 0, + [0][1][1][0][RTW89_WW][0][92] = -2, + [0][1][1][0][RTW89_WW][1][92] = -2, + [0][1][1][0][RTW89_WW][2][92] = 0, + [0][1][1][0][RTW89_WW][0][94] = -2, + [0][1][1][0][RTW89_WW][1][94] = -2, + [0][1][1][0][RTW89_WW][2][94] = 0, + [0][1][1][0][RTW89_WW][0][96] = -2, + [0][1][1][0][RTW89_WW][1][96] = -2, + [0][1][1][0][RTW89_WW][2][96] = 0, + [0][1][1][0][RTW89_WW][0][98] = -2, + [0][1][1][0][RTW89_WW][1][98] = -2, + [0][1][1][0][RTW89_WW][2][98] = 0, + [0][1][1][0][RTW89_WW][0][100] = -2, + [0][1][1][0][RTW89_WW][1][100] = -2, + [0][1][1][0][RTW89_WW][2][100] = 0, + [0][1][1][0][RTW89_WW][0][102] = -2, + [0][1][1][0][RTW89_WW][1][102] = -2, + [0][1][1][0][RTW89_WW][2][102] = 0, + [0][1][1][0][RTW89_WW][0][104] = -2, + [0][1][1][0][RTW89_WW][1][104] = -2, + [0][1][1][0][RTW89_WW][2][104] = 0, + [0][1][1][0][RTW89_WW][0][105] = -2, + [0][1][1][0][RTW89_WW][1][105] = -2, + [0][1][1][0][RTW89_WW][2][105] = 0, + [0][1][1][0][RTW89_WW][0][107] = 1, + [0][1][1][0][RTW89_WW][1][107] = 1, + [0][1][1][0][RTW89_WW][2][107] = 0, + [0][1][1][0][RTW89_WW][0][109] = 1, + [0][1][1][0][RTW89_WW][1][109] = 1, + [0][1][1][0][RTW89_WW][2][109] = 0, + [0][1][1][0][RTW89_WW][0][111] = 0, + [0][1][1][0][RTW89_WW][1][111] = 0, + [0][1][1][0][RTW89_WW][2][111] = 0, + [0][1][1][0][RTW89_WW][0][113] = 0, + [0][1][1][0][RTW89_WW][1][113] = 0, + [0][1][1][0][RTW89_WW][2][113] = 0, + [0][1][1][0][RTW89_WW][0][115] = 0, + [0][1][1][0][RTW89_WW][1][115] = 0, + [0][1][1][0][RTW89_WW][2][115] = 0, + [0][1][1][0][RTW89_WW][0][117] = 0, + [0][1][1][0][RTW89_WW][1][117] = 0, + [0][1][1][0][RTW89_WW][2][117] = 0, + [0][1][1][0][RTW89_WW][0][119] = 0, + [0][1][1][0][RTW89_WW][1][119] = 0, + [0][1][1][0][RTW89_WW][2][119] = 0, + [0][0][2][0][RTW89_WW][0][0] = 24, + [0][0][2][0][RTW89_WW][1][0] = 24, + [0][0][2][0][RTW89_WW][2][0] = 56, + [0][0][2][0][RTW89_WW][0][2] = 22, + [0][0][2][0][RTW89_WW][1][2] = 22, + [0][0][2][0][RTW89_WW][2][2] = 56, + [0][0][2][0][RTW89_WW][0][4] = 22, + [0][0][2][0][RTW89_WW][1][4] = 22, + [0][0][2][0][RTW89_WW][2][4] = 56, + [0][0][2][0][RTW89_WW][0][6] = 22, + [0][0][2][0][RTW89_WW][1][6] = 22, + [0][0][2][0][RTW89_WW][2][6] = 56, + [0][0][2][0][RTW89_WW][0][8] = 22, + [0][0][2][0][RTW89_WW][1][8] = 22, + [0][0][2][0][RTW89_WW][2][8] = 56, + [0][0][2][0][RTW89_WW][0][10] = 22, + [0][0][2][0][RTW89_WW][1][10] = 22, + [0][0][2][0][RTW89_WW][2][10] = 56, + [0][0][2][0][RTW89_WW][0][12] = 22, + [0][0][2][0][RTW89_WW][1][12] = 22, + [0][0][2][0][RTW89_WW][2][12] = 56, + [0][0][2][0][RTW89_WW][0][14] = 22, + [0][0][2][0][RTW89_WW][1][14] = 22, + [0][0][2][0][RTW89_WW][2][14] = 56, + [0][0][2][0][RTW89_WW][0][15] = 22, + [0][0][2][0][RTW89_WW][1][15] = 22, + [0][0][2][0][RTW89_WW][2][15] = 56, + [0][0][2][0][RTW89_WW][0][17] = 22, + [0][0][2][0][RTW89_WW][1][17] = 22, + [0][0][2][0][RTW89_WW][2][17] = 56, + [0][0][2][0][RTW89_WW][0][19] = 22, + [0][0][2][0][RTW89_WW][1][19] = 22, + [0][0][2][0][RTW89_WW][2][19] = 56, + [0][0][2][0][RTW89_WW][0][21] = 22, + [0][0][2][0][RTW89_WW][1][21] = 22, + [0][0][2][0][RTW89_WW][2][21] = 56, + [0][0][2][0][RTW89_WW][0][23] = 22, + [0][0][2][0][RTW89_WW][1][23] = 22, + [0][0][2][0][RTW89_WW][2][23] = 70, + [0][0][2][0][RTW89_WW][0][25] = 22, + [0][0][2][0][RTW89_WW][1][25] = 22, + [0][0][2][0][RTW89_WW][2][25] = 70, + [0][0][2][0][RTW89_WW][0][27] = 22, + [0][0][2][0][RTW89_WW][1][27] = 22, + [0][0][2][0][RTW89_WW][2][27] = 70, + [0][0][2][0][RTW89_WW][0][29] = 22, + [0][0][2][0][RTW89_WW][1][29] = 22, + [0][0][2][0][RTW89_WW][2][29] = 70, + [0][0][2][0][RTW89_WW][0][30] = 22, + [0][0][2][0][RTW89_WW][1][30] = 22, + [0][0][2][0][RTW89_WW][2][30] = 70, + [0][0][2][0][RTW89_WW][0][32] = 22, + [0][0][2][0][RTW89_WW][1][32] = 22, + [0][0][2][0][RTW89_WW][2][32] = 70, + [0][0][2][0][RTW89_WW][0][34] = 22, + [0][0][2][0][RTW89_WW][1][34] = 22, + [0][0][2][0][RTW89_WW][2][34] = 70, + [0][0][2][0][RTW89_WW][0][36] = 22, + [0][0][2][0][RTW89_WW][1][36] = 22, + [0][0][2][0][RTW89_WW][2][36] = 70, + [0][0][2][0][RTW89_WW][0][38] = 22, + [0][0][2][0][RTW89_WW][1][38] = 22, + [0][0][2][0][RTW89_WW][2][38] = 70, + [0][0][2][0][RTW89_WW][0][40] = 22, + [0][0][2][0][RTW89_WW][1][40] = 22, + [0][0][2][0][RTW89_WW][2][40] = 70, + [0][0][2][0][RTW89_WW][0][42] = 22, + [0][0][2][0][RTW89_WW][1][42] = 22, + [0][0][2][0][RTW89_WW][2][42] = 70, + [0][0][2][0][RTW89_WW][0][44] = 22, + [0][0][2][0][RTW89_WW][1][44] = 22, + [0][0][2][0][RTW89_WW][2][44] = 70, + [0][0][2][0][RTW89_WW][0][45] = 22, + [0][0][2][0][RTW89_WW][1][45] = 22, + [0][0][2][0][RTW89_WW][2][45] = 0, + [0][0][2][0][RTW89_WW][0][47] = 22, + [0][0][2][0][RTW89_WW][1][47] = 22, + [0][0][2][0][RTW89_WW][2][47] = 0, + [0][0][2][0][RTW89_WW][0][49] = 24, + [0][0][2][0][RTW89_WW][1][49] = 24, + [0][0][2][0][RTW89_WW][2][49] = 0, + [0][0][2][0][RTW89_WW][0][51] = 22, + [0][0][2][0][RTW89_WW][1][51] = 22, + [0][0][2][0][RTW89_WW][2][51] = 0, + [0][0][2][0][RTW89_WW][0][53] = 22, + [0][0][2][0][RTW89_WW][1][53] = 22, + [0][0][2][0][RTW89_WW][2][53] = 0, + [0][0][2][0][RTW89_WW][0][55] = 22, + [0][0][2][0][RTW89_WW][1][55] = 22, + [0][0][2][0][RTW89_WW][2][55] = 68, + [0][0][2][0][RTW89_WW][0][57] = 22, + [0][0][2][0][RTW89_WW][1][57] = 22, + [0][0][2][0][RTW89_WW][2][57] = 68, + [0][0][2][0][RTW89_WW][0][59] = 22, + [0][0][2][0][RTW89_WW][1][59] = 22, + [0][0][2][0][RTW89_WW][2][59] = 68, + [0][0][2][0][RTW89_WW][0][60] = 22, + [0][0][2][0][RTW89_WW][1][60] = 22, + [0][0][2][0][RTW89_WW][2][60] = 68, + [0][0][2][0][RTW89_WW][0][62] = 22, + [0][0][2][0][RTW89_WW][1][62] = 22, + [0][0][2][0][RTW89_WW][2][62] = 68, + [0][0][2][0][RTW89_WW][0][64] = 22, + [0][0][2][0][RTW89_WW][1][64] = 22, + [0][0][2][0][RTW89_WW][2][64] = 68, + [0][0][2][0][RTW89_WW][0][66] = 22, + [0][0][2][0][RTW89_WW][1][66] = 22, + [0][0][2][0][RTW89_WW][2][66] = 68, + [0][0][2][0][RTW89_WW][0][68] = 22, + [0][0][2][0][RTW89_WW][1][68] = 22, + [0][0][2][0][RTW89_WW][2][68] = 68, + [0][0][2][0][RTW89_WW][0][70] = 24, + [0][0][2][0][RTW89_WW][1][70] = 24, + [0][0][2][0][RTW89_WW][2][70] = 68, + [0][0][2][0][RTW89_WW][0][72] = 22, + [0][0][2][0][RTW89_WW][1][72] = 22, + [0][0][2][0][RTW89_WW][2][72] = 68, + [0][0][2][0][RTW89_WW][0][74] = 22, + [0][0][2][0][RTW89_WW][1][74] = 22, + [0][0][2][0][RTW89_WW][2][74] = 68, + [0][0][2][0][RTW89_WW][0][75] = 22, + [0][0][2][0][RTW89_WW][1][75] = 22, + [0][0][2][0][RTW89_WW][2][75] = 68, + [0][0][2][0][RTW89_WW][0][77] = 22, + [0][0][2][0][RTW89_WW][1][77] = 22, + [0][0][2][0][RTW89_WW][2][77] = 68, + [0][0][2][0][RTW89_WW][0][79] = 22, + [0][0][2][0][RTW89_WW][1][79] = 22, + [0][0][2][0][RTW89_WW][2][79] = 68, + [0][0][2][0][RTW89_WW][0][81] = 22, + [0][0][2][0][RTW89_WW][1][81] = 22, + [0][0][2][0][RTW89_WW][2][81] = 68, + [0][0][2][0][RTW89_WW][0][83] = 22, + [0][0][2][0][RTW89_WW][1][83] = 22, + [0][0][2][0][RTW89_WW][2][83] = 68, + [0][0][2][0][RTW89_WW][0][85] = 22, + [0][0][2][0][RTW89_WW][1][85] = 22, + [0][0][2][0][RTW89_WW][2][85] = 68, + [0][0][2][0][RTW89_WW][0][87] = 22, + [0][0][2][0][RTW89_WW][1][87] = 22, + [0][0][2][0][RTW89_WW][2][87] = 0, + [0][0][2][0][RTW89_WW][0][89] = 22, + [0][0][2][0][RTW89_WW][1][89] = 22, + [0][0][2][0][RTW89_WW][2][89] = 0, + [0][0][2][0][RTW89_WW][0][90] = 22, + [0][0][2][0][RTW89_WW][1][90] = 22, + [0][0][2][0][RTW89_WW][2][90] = 0, + [0][0][2][0][RTW89_WW][0][92] = 22, + [0][0][2][0][RTW89_WW][1][92] = 22, + [0][0][2][0][RTW89_WW][2][92] = 0, + [0][0][2][0][RTW89_WW][0][94] = 22, + [0][0][2][0][RTW89_WW][1][94] = 22, + [0][0][2][0][RTW89_WW][2][94] = 0, + [0][0][2][0][RTW89_WW][0][96] = 22, + [0][0][2][0][RTW89_WW][1][96] = 22, + [0][0][2][0][RTW89_WW][2][96] = 0, + [0][0][2][0][RTW89_WW][0][98] = 22, + [0][0][2][0][RTW89_WW][1][98] = 22, + [0][0][2][0][RTW89_WW][2][98] = 0, + [0][0][2][0][RTW89_WW][0][100] = 22, + [0][0][2][0][RTW89_WW][1][100] = 22, + [0][0][2][0][RTW89_WW][2][100] = 0, + [0][0][2][0][RTW89_WW][0][102] = 22, + [0][0][2][0][RTW89_WW][1][102] = 22, + [0][0][2][0][RTW89_WW][2][102] = 0, + [0][0][2][0][RTW89_WW][0][104] = 22, + [0][0][2][0][RTW89_WW][1][104] = 22, + [0][0][2][0][RTW89_WW][2][104] = 0, + [0][0][2][0][RTW89_WW][0][105] = 22, + [0][0][2][0][RTW89_WW][1][105] = 22, + [0][0][2][0][RTW89_WW][2][105] = 0, + [0][0][2][0][RTW89_WW][0][107] = 24, + [0][0][2][0][RTW89_WW][1][107] = 24, + [0][0][2][0][RTW89_WW][2][107] = 0, + [0][0][2][0][RTW89_WW][0][109] = 24, + [0][0][2][0][RTW89_WW][1][109] = 24, + [0][0][2][0][RTW89_WW][2][109] = 0, + [0][0][2][0][RTW89_WW][0][111] = 0, + [0][0][2][0][RTW89_WW][1][111] = 0, + [0][0][2][0][RTW89_WW][2][111] = 0, + [0][0][2][0][RTW89_WW][0][113] = 0, + [0][0][2][0][RTW89_WW][1][113] = 0, + [0][0][2][0][RTW89_WW][2][113] = 0, + [0][0][2][0][RTW89_WW][0][115] = 0, + [0][0][2][0][RTW89_WW][1][115] = 0, + [0][0][2][0][RTW89_WW][2][115] = 0, + [0][0][2][0][RTW89_WW][0][117] = 0, + [0][0][2][0][RTW89_WW][1][117] = 0, + [0][0][2][0][RTW89_WW][2][117] = 0, + [0][0][2][0][RTW89_WW][0][119] = 0, + [0][0][2][0][RTW89_WW][1][119] = 0, + [0][0][2][0][RTW89_WW][2][119] = 0, + [0][1][2][0][RTW89_WW][0][0] = -2, + [0][1][2][0][RTW89_WW][1][0] = -2, + [0][1][2][0][RTW89_WW][2][0] = 54, + [0][1][2][0][RTW89_WW][0][2] = -4, + [0][1][2][0][RTW89_WW][1][2] = -4, + [0][1][2][0][RTW89_WW][2][2] = 54, + [0][1][2][0][RTW89_WW][0][4] = -4, + [0][1][2][0][RTW89_WW][1][4] = -4, + [0][1][2][0][RTW89_WW][2][4] = 54, + [0][1][2][0][RTW89_WW][0][6] = -4, + [0][1][2][0][RTW89_WW][1][6] = -4, + [0][1][2][0][RTW89_WW][2][6] = 54, + [0][1][2][0][RTW89_WW][0][8] = -4, + [0][1][2][0][RTW89_WW][1][8] = -4, + [0][1][2][0][RTW89_WW][2][8] = 54, + [0][1][2][0][RTW89_WW][0][10] = -4, + [0][1][2][0][RTW89_WW][1][10] = -4, + [0][1][2][0][RTW89_WW][2][10] = 54, + [0][1][2][0][RTW89_WW][0][12] = -4, + [0][1][2][0][RTW89_WW][1][12] = -4, + [0][1][2][0][RTW89_WW][2][12] = 54, + [0][1][2][0][RTW89_WW][0][14] = -4, + [0][1][2][0][RTW89_WW][1][14] = -4, + [0][1][2][0][RTW89_WW][2][14] = 54, + [0][1][2][0][RTW89_WW][0][15] = -4, + [0][1][2][0][RTW89_WW][1][15] = -4, + [0][1][2][0][RTW89_WW][2][15] = 54, + [0][1][2][0][RTW89_WW][0][17] = -4, + [0][1][2][0][RTW89_WW][1][17] = -4, + [0][1][2][0][RTW89_WW][2][17] = 54, + [0][1][2][0][RTW89_WW][0][19] = -4, + [0][1][2][0][RTW89_WW][1][19] = -4, + [0][1][2][0][RTW89_WW][2][19] = 54, + [0][1][2][0][RTW89_WW][0][21] = -4, + [0][1][2][0][RTW89_WW][1][21] = -4, + [0][1][2][0][RTW89_WW][2][21] = 54, + [0][1][2][0][RTW89_WW][0][23] = -4, + [0][1][2][0][RTW89_WW][1][23] = -4, + [0][1][2][0][RTW89_WW][2][23] = 68, + [0][1][2][0][RTW89_WW][0][25] = -4, + [0][1][2][0][RTW89_WW][1][25] = -4, + [0][1][2][0][RTW89_WW][2][25] = 68, + [0][1][2][0][RTW89_WW][0][27] = -4, + [0][1][2][0][RTW89_WW][1][27] = -4, + [0][1][2][0][RTW89_WW][2][27] = 68, + [0][1][2][0][RTW89_WW][0][29] = -4, + [0][1][2][0][RTW89_WW][1][29] = -4, + [0][1][2][0][RTW89_WW][2][29] = 68, + [0][1][2][0][RTW89_WW][0][30] = -4, + [0][1][2][0][RTW89_WW][1][30] = -4, + [0][1][2][0][RTW89_WW][2][30] = 68, + [0][1][2][0][RTW89_WW][0][32] = -4, + [0][1][2][0][RTW89_WW][1][32] = -4, + [0][1][2][0][RTW89_WW][2][32] = 68, + [0][1][2][0][RTW89_WW][0][34] = -4, + [0][1][2][0][RTW89_WW][1][34] = -4, + [0][1][2][0][RTW89_WW][2][34] = 68, + [0][1][2][0][RTW89_WW][0][36] = -4, + [0][1][2][0][RTW89_WW][1][36] = -4, + [0][1][2][0][RTW89_WW][2][36] = 68, + [0][1][2][0][RTW89_WW][0][38] = -4, + [0][1][2][0][RTW89_WW][1][38] = -4, + [0][1][2][0][RTW89_WW][2][38] = 68, + [0][1][2][0][RTW89_WW][0][40] = -4, + [0][1][2][0][RTW89_WW][1][40] = -4, + [0][1][2][0][RTW89_WW][2][40] = 68, + [0][1][2][0][RTW89_WW][0][42] = -4, + [0][1][2][0][RTW89_WW][1][42] = -4, + [0][1][2][0][RTW89_WW][2][42] = 68, + [0][1][2][0][RTW89_WW][0][44] = -2, + [0][1][2][0][RTW89_WW][1][44] = -2, + [0][1][2][0][RTW89_WW][2][44] = 68, + [0][1][2][0][RTW89_WW][0][45] = -2, + [0][1][2][0][RTW89_WW][1][45] = -2, + [0][1][2][0][RTW89_WW][2][45] = 0, + [0][1][2][0][RTW89_WW][0][47] = -2, + [0][1][2][0][RTW89_WW][1][47] = -2, + [0][1][2][0][RTW89_WW][2][47] = 0, + [0][1][2][0][RTW89_WW][0][49] = -2, + [0][1][2][0][RTW89_WW][1][49] = -2, + [0][1][2][0][RTW89_WW][2][49] = 0, + [0][1][2][0][RTW89_WW][0][51] = -2, + [0][1][2][0][RTW89_WW][1][51] = -2, + [0][1][2][0][RTW89_WW][2][51] = 0, + [0][1][2][0][RTW89_WW][0][53] = -2, + [0][1][2][0][RTW89_WW][1][53] = -2, + [0][1][2][0][RTW89_WW][2][53] = 0, + [0][1][2][0][RTW89_WW][0][55] = -2, + [0][1][2][0][RTW89_WW][1][55] = -2, + [0][1][2][0][RTW89_WW][2][55] = 68, + [0][1][2][0][RTW89_WW][0][57] = -2, + [0][1][2][0][RTW89_WW][1][57] = -2, + [0][1][2][0][RTW89_WW][2][57] = 68, + [0][1][2][0][RTW89_WW][0][59] = -2, + [0][1][2][0][RTW89_WW][1][59] = -2, + [0][1][2][0][RTW89_WW][2][59] = 68, + [0][1][2][0][RTW89_WW][0][60] = -2, + [0][1][2][0][RTW89_WW][1][60] = -2, + [0][1][2][0][RTW89_WW][2][60] = 68, + [0][1][2][0][RTW89_WW][0][62] = -2, + [0][1][2][0][RTW89_WW][1][62] = -2, + [0][1][2][0][RTW89_WW][2][62] = 68, + [0][1][2][0][RTW89_WW][0][64] = -2, + [0][1][2][0][RTW89_WW][1][64] = -2, + [0][1][2][0][RTW89_WW][2][64] = 68, + [0][1][2][0][RTW89_WW][0][66] = -2, + [0][1][2][0][RTW89_WW][1][66] = -2, + [0][1][2][0][RTW89_WW][2][66] = 68, + [0][1][2][0][RTW89_WW][0][68] = -2, + [0][1][2][0][RTW89_WW][1][68] = -2, + [0][1][2][0][RTW89_WW][2][68] = 68, + [0][1][2][0][RTW89_WW][0][70] = -2, + [0][1][2][0][RTW89_WW][1][70] = -2, + [0][1][2][0][RTW89_WW][2][70] = 68, + [0][1][2][0][RTW89_WW][0][72] = -2, + [0][1][2][0][RTW89_WW][1][72] = -2, + [0][1][2][0][RTW89_WW][2][72] = 68, + [0][1][2][0][RTW89_WW][0][74] = -2, + [0][1][2][0][RTW89_WW][1][74] = -2, + [0][1][2][0][RTW89_WW][2][74] = 68, + [0][1][2][0][RTW89_WW][0][75] = -2, + [0][1][2][0][RTW89_WW][1][75] = -2, + [0][1][2][0][RTW89_WW][2][75] = 68, + [0][1][2][0][RTW89_WW][0][77] = -2, + [0][1][2][0][RTW89_WW][1][77] = -2, + [0][1][2][0][RTW89_WW][2][77] = 68, + [0][1][2][0][RTW89_WW][0][79] = -2, + [0][1][2][0][RTW89_WW][1][79] = -2, + [0][1][2][0][RTW89_WW][2][79] = 68, + [0][1][2][0][RTW89_WW][0][81] = -2, + [0][1][2][0][RTW89_WW][1][81] = -2, + [0][1][2][0][RTW89_WW][2][81] = 68, + [0][1][2][0][RTW89_WW][0][83] = -2, + [0][1][2][0][RTW89_WW][1][83] = -2, + [0][1][2][0][RTW89_WW][2][83] = 68, + [0][1][2][0][RTW89_WW][0][85] = -2, + [0][1][2][0][RTW89_WW][1][85] = -2, + [0][1][2][0][RTW89_WW][2][85] = 68, + [0][1][2][0][RTW89_WW][0][87] = -2, + [0][1][2][0][RTW89_WW][1][87] = -2, + [0][1][2][0][RTW89_WW][2][87] = 0, + [0][1][2][0][RTW89_WW][0][89] = -2, + [0][1][2][0][RTW89_WW][1][89] = -2, + [0][1][2][0][RTW89_WW][2][89] = 0, + [0][1][2][0][RTW89_WW][0][90] = -2, + [0][1][2][0][RTW89_WW][1][90] = -2, + [0][1][2][0][RTW89_WW][2][90] = 0, + [0][1][2][0][RTW89_WW][0][92] = -2, + [0][1][2][0][RTW89_WW][1][92] = -2, + [0][1][2][0][RTW89_WW][2][92] = 0, + [0][1][2][0][RTW89_WW][0][94] = -2, + [0][1][2][0][RTW89_WW][1][94] = -2, + [0][1][2][0][RTW89_WW][2][94] = 0, + [0][1][2][0][RTW89_WW][0][96] = -2, + [0][1][2][0][RTW89_WW][1][96] = -2, + [0][1][2][0][RTW89_WW][2][96] = 0, + [0][1][2][0][RTW89_WW][0][98] = -2, + [0][1][2][0][RTW89_WW][1][98] = -2, + [0][1][2][0][RTW89_WW][2][98] = 0, + [0][1][2][0][RTW89_WW][0][100] = -2, + [0][1][2][0][RTW89_WW][1][100] = -2, + [0][1][2][0][RTW89_WW][2][100] = 0, + [0][1][2][0][RTW89_WW][0][102] = -2, + [0][1][2][0][RTW89_WW][1][102] = -2, + [0][1][2][0][RTW89_WW][2][102] = 0, + [0][1][2][0][RTW89_WW][0][104] = -2, + [0][1][2][0][RTW89_WW][1][104] = -2, + [0][1][2][0][RTW89_WW][2][104] = 0, + [0][1][2][0][RTW89_WW][0][105] = -2, + [0][1][2][0][RTW89_WW][1][105] = -2, + [0][1][2][0][RTW89_WW][2][105] = 0, + [0][1][2][0][RTW89_WW][0][107] = 1, + [0][1][2][0][RTW89_WW][1][107] = 1, + [0][1][2][0][RTW89_WW][2][107] = 0, + [0][1][2][0][RTW89_WW][0][109] = 1, + [0][1][2][0][RTW89_WW][1][109] = 1, + [0][1][2][0][RTW89_WW][2][109] = 0, + [0][1][2][0][RTW89_WW][0][111] = 0, + [0][1][2][0][RTW89_WW][1][111] = 0, + [0][1][2][0][RTW89_WW][2][111] = 0, + [0][1][2][0][RTW89_WW][0][113] = 0, + [0][1][2][0][RTW89_WW][1][113] = 0, + [0][1][2][0][RTW89_WW][2][113] = 0, + [0][1][2][0][RTW89_WW][0][115] = 0, + [0][1][2][0][RTW89_WW][1][115] = 0, + [0][1][2][0][RTW89_WW][2][115] = 0, + [0][1][2][0][RTW89_WW][0][117] = 0, + [0][1][2][0][RTW89_WW][1][117] = 0, + [0][1][2][0][RTW89_WW][2][117] = 0, + [0][1][2][0][RTW89_WW][0][119] = 0, + [0][1][2][0][RTW89_WW][1][119] = 0, + [0][1][2][0][RTW89_WW][2][119] = 0, + [0][1][2][1][RTW89_WW][0][0] = -2, + [0][1][2][1][RTW89_WW][1][0] = -2, + [0][1][2][1][RTW89_WW][2][0] = 54, + [0][1][2][1][RTW89_WW][0][2] = -4, + [0][1][2][1][RTW89_WW][1][2] = -4, + [0][1][2][1][RTW89_WW][2][2] = 54, + [0][1][2][1][RTW89_WW][0][4] = -4, + [0][1][2][1][RTW89_WW][1][4] = -4, + [0][1][2][1][RTW89_WW][2][4] = 54, + [0][1][2][1][RTW89_WW][0][6] = -4, + [0][1][2][1][RTW89_WW][1][6] = -4, + [0][1][2][1][RTW89_WW][2][6] = 54, + [0][1][2][1][RTW89_WW][0][8] = -4, + [0][1][2][1][RTW89_WW][1][8] = -4, + [0][1][2][1][RTW89_WW][2][8] = 54, + [0][1][2][1][RTW89_WW][0][10] = -4, + [0][1][2][1][RTW89_WW][1][10] = -4, + [0][1][2][1][RTW89_WW][2][10] = 54, + [0][1][2][1][RTW89_WW][0][12] = -4, + [0][1][2][1][RTW89_WW][1][12] = -4, + [0][1][2][1][RTW89_WW][2][12] = 54, + [0][1][2][1][RTW89_WW][0][14] = -4, + [0][1][2][1][RTW89_WW][1][14] = -4, + [0][1][2][1][RTW89_WW][2][14] = 54, + [0][1][2][1][RTW89_WW][0][15] = -4, + [0][1][2][1][RTW89_WW][1][15] = -4, + [0][1][2][1][RTW89_WW][2][15] = 54, + [0][1][2][1][RTW89_WW][0][17] = -4, + [0][1][2][1][RTW89_WW][1][17] = -4, + [0][1][2][1][RTW89_WW][2][17] = 54, + [0][1][2][1][RTW89_WW][0][19] = -4, + [0][1][2][1][RTW89_WW][1][19] = -4, + [0][1][2][1][RTW89_WW][2][19] = 54, + [0][1][2][1][RTW89_WW][0][21] = -4, + [0][1][2][1][RTW89_WW][1][21] = -4, + [0][1][2][1][RTW89_WW][2][21] = 54, + [0][1][2][1][RTW89_WW][0][23] = -4, + [0][1][2][1][RTW89_WW][1][23] = -4, + [0][1][2][1][RTW89_WW][2][23] = 68, + [0][1][2][1][RTW89_WW][0][25] = -4, + [0][1][2][1][RTW89_WW][1][25] = -4, + [0][1][2][1][RTW89_WW][2][25] = 68, + [0][1][2][1][RTW89_WW][0][27] = -4, + [0][1][2][1][RTW89_WW][1][27] = -4, + [0][1][2][1][RTW89_WW][2][27] = 68, + [0][1][2][1][RTW89_WW][0][29] = -4, + [0][1][2][1][RTW89_WW][1][29] = -4, + [0][1][2][1][RTW89_WW][2][29] = 68, + [0][1][2][1][RTW89_WW][0][30] = -4, + [0][1][2][1][RTW89_WW][1][30] = -4, + [0][1][2][1][RTW89_WW][2][30] = 68, + [0][1][2][1][RTW89_WW][0][32] = -4, + [0][1][2][1][RTW89_WW][1][32] = -4, + [0][1][2][1][RTW89_WW][2][32] = 68, + [0][1][2][1][RTW89_WW][0][34] = -4, + [0][1][2][1][RTW89_WW][1][34] = -4, + [0][1][2][1][RTW89_WW][2][34] = 68, + [0][1][2][1][RTW89_WW][0][36] = -4, + [0][1][2][1][RTW89_WW][1][36] = -4, + [0][1][2][1][RTW89_WW][2][36] = 68, + [0][1][2][1][RTW89_WW][0][38] = -4, + [0][1][2][1][RTW89_WW][1][38] = -4, + [0][1][2][1][RTW89_WW][2][38] = 68, + [0][1][2][1][RTW89_WW][0][40] = -4, + [0][1][2][1][RTW89_WW][1][40] = -4, + [0][1][2][1][RTW89_WW][2][40] = 68, + [0][1][2][1][RTW89_WW][0][42] = -4, + [0][1][2][1][RTW89_WW][1][42] = -4, + [0][1][2][1][RTW89_WW][2][42] = 68, + [0][1][2][1][RTW89_WW][0][44] = -2, + [0][1][2][1][RTW89_WW][1][44] = -2, + [0][1][2][1][RTW89_WW][2][44] = 68, + [0][1][2][1][RTW89_WW][0][45] = -2, + [0][1][2][1][RTW89_WW][1][45] = -2, + [0][1][2][1][RTW89_WW][2][45] = 0, + [0][1][2][1][RTW89_WW][0][47] = -2, + [0][1][2][1][RTW89_WW][1][47] = -2, + [0][1][2][1][RTW89_WW][2][47] = 0, + [0][1][2][1][RTW89_WW][0][49] = -2, + [0][1][2][1][RTW89_WW][1][49] = -2, + [0][1][2][1][RTW89_WW][2][49] = 0, + [0][1][2][1][RTW89_WW][0][51] = -2, + [0][1][2][1][RTW89_WW][1][51] = -2, + [0][1][2][1][RTW89_WW][2][51] = 0, + [0][1][2][1][RTW89_WW][0][53] = -2, + [0][1][2][1][RTW89_WW][1][53] = -2, + [0][1][2][1][RTW89_WW][2][53] = 0, + [0][1][2][1][RTW89_WW][0][55] = -2, + [0][1][2][1][RTW89_WW][1][55] = -2, + [0][1][2][1][RTW89_WW][2][55] = 68, + [0][1][2][1][RTW89_WW][0][57] = -2, + [0][1][2][1][RTW89_WW][1][57] = -2, + [0][1][2][1][RTW89_WW][2][57] = 68, + [0][1][2][1][RTW89_WW][0][59] = -2, + [0][1][2][1][RTW89_WW][1][59] = -2, + [0][1][2][1][RTW89_WW][2][59] = 68, + [0][1][2][1][RTW89_WW][0][60] = -2, + [0][1][2][1][RTW89_WW][1][60] = -2, + [0][1][2][1][RTW89_WW][2][60] = 68, + [0][1][2][1][RTW89_WW][0][62] = -2, + [0][1][2][1][RTW89_WW][1][62] = -2, + [0][1][2][1][RTW89_WW][2][62] = 68, + [0][1][2][1][RTW89_WW][0][64] = -2, + [0][1][2][1][RTW89_WW][1][64] = -2, + [0][1][2][1][RTW89_WW][2][64] = 68, + [0][1][2][1][RTW89_WW][0][66] = -2, + [0][1][2][1][RTW89_WW][1][66] = -2, + [0][1][2][1][RTW89_WW][2][66] = 68, + [0][1][2][1][RTW89_WW][0][68] = -2, + [0][1][2][1][RTW89_WW][1][68] = -2, + [0][1][2][1][RTW89_WW][2][68] = 68, + [0][1][2][1][RTW89_WW][0][70] = -2, + [0][1][2][1][RTW89_WW][1][70] = -2, + [0][1][2][1][RTW89_WW][2][70] = 68, + [0][1][2][1][RTW89_WW][0][72] = -2, + [0][1][2][1][RTW89_WW][1][72] = -2, + [0][1][2][1][RTW89_WW][2][72] = 68, + [0][1][2][1][RTW89_WW][0][74] = -2, + [0][1][2][1][RTW89_WW][1][74] = -2, + [0][1][2][1][RTW89_WW][2][74] = 68, + [0][1][2][1][RTW89_WW][0][75] = -2, + [0][1][2][1][RTW89_WW][1][75] = -2, + [0][1][2][1][RTW89_WW][2][75] = 68, + [0][1][2][1][RTW89_WW][0][77] = -2, + [0][1][2][1][RTW89_WW][1][77] = -2, + [0][1][2][1][RTW89_WW][2][77] = 68, + [0][1][2][1][RTW89_WW][0][79] = -2, + [0][1][2][1][RTW89_WW][1][79] = -2, + [0][1][2][1][RTW89_WW][2][79] = 68, + [0][1][2][1][RTW89_WW][0][81] = -2, + [0][1][2][1][RTW89_WW][1][81] = -2, + [0][1][2][1][RTW89_WW][2][81] = 68, + [0][1][2][1][RTW89_WW][0][83] = -2, + [0][1][2][1][RTW89_WW][1][83] = -2, + [0][1][2][1][RTW89_WW][2][83] = 68, + [0][1][2][1][RTW89_WW][0][85] = -2, + [0][1][2][1][RTW89_WW][1][85] = -2, + [0][1][2][1][RTW89_WW][2][85] = 68, + [0][1][2][1][RTW89_WW][0][87] = -2, + [0][1][2][1][RTW89_WW][1][87] = -2, + [0][1][2][1][RTW89_WW][2][87] = 0, + [0][1][2][1][RTW89_WW][0][89] = -2, + [0][1][2][1][RTW89_WW][1][89] = -2, + [0][1][2][1][RTW89_WW][2][89] = 0, + [0][1][2][1][RTW89_WW][0][90] = -2, + [0][1][2][1][RTW89_WW][1][90] = -2, + [0][1][2][1][RTW89_WW][2][90] = 0, + [0][1][2][1][RTW89_WW][0][92] = -2, + [0][1][2][1][RTW89_WW][1][92] = -2, + [0][1][2][1][RTW89_WW][2][92] = 0, + [0][1][2][1][RTW89_WW][0][94] = -2, + [0][1][2][1][RTW89_WW][1][94] = -2, + [0][1][2][1][RTW89_WW][2][94] = 0, + [0][1][2][1][RTW89_WW][0][96] = -2, + [0][1][2][1][RTW89_WW][1][96] = -2, + [0][1][2][1][RTW89_WW][2][96] = 0, + [0][1][2][1][RTW89_WW][0][98] = -2, + [0][1][2][1][RTW89_WW][1][98] = -2, + [0][1][2][1][RTW89_WW][2][98] = 0, + [0][1][2][1][RTW89_WW][0][100] = -2, + [0][1][2][1][RTW89_WW][1][100] = -2, + [0][1][2][1][RTW89_WW][2][100] = 0, + [0][1][2][1][RTW89_WW][0][102] = -2, + [0][1][2][1][RTW89_WW][1][102] = -2, + [0][1][2][1][RTW89_WW][2][102] = 0, + [0][1][2][1][RTW89_WW][0][104] = -2, + [0][1][2][1][RTW89_WW][1][104] = -2, + [0][1][2][1][RTW89_WW][2][104] = 0, + [0][1][2][1][RTW89_WW][0][105] = -2, + [0][1][2][1][RTW89_WW][1][105] = -2, + [0][1][2][1][RTW89_WW][2][105] = 0, + [0][1][2][1][RTW89_WW][0][107] = 1, + [0][1][2][1][RTW89_WW][1][107] = 1, + [0][1][2][1][RTW89_WW][2][107] = 0, + [0][1][2][1][RTW89_WW][0][109] = 1, + [0][1][2][1][RTW89_WW][1][109] = 1, + [0][1][2][1][RTW89_WW][2][109] = 0, + [0][1][2][1][RTW89_WW][0][111] = 0, + [0][1][2][1][RTW89_WW][1][111] = 0, + [0][1][2][1][RTW89_WW][2][111] = 0, + [0][1][2][1][RTW89_WW][0][113] = 0, + [0][1][2][1][RTW89_WW][1][113] = 0, + [0][1][2][1][RTW89_WW][2][113] = 0, + [0][1][2][1][RTW89_WW][0][115] = 0, + [0][1][2][1][RTW89_WW][1][115] = 0, + [0][1][2][1][RTW89_WW][2][115] = 0, + [0][1][2][1][RTW89_WW][0][117] = 0, + [0][1][2][1][RTW89_WW][1][117] = 0, + [0][1][2][1][RTW89_WW][2][117] = 0, + [0][1][2][1][RTW89_WW][0][119] = 0, + [0][1][2][1][RTW89_WW][1][119] = 0, + [0][1][2][1][RTW89_WW][2][119] = 0, + [1][0][2][0][RTW89_WW][0][1] = 24, + [1][0][2][0][RTW89_WW][1][1] = 34, + [1][0][2][0][RTW89_WW][2][1] = 70, + [1][0][2][0][RTW89_WW][0][5] = 24, + [1][0][2][0][RTW89_WW][1][5] = 34, + [1][0][2][0][RTW89_WW][2][5] = 70, + [1][0][2][0][RTW89_WW][0][9] = 24, + [1][0][2][0][RTW89_WW][1][9] = 34, + [1][0][2][0][RTW89_WW][2][9] = 70, + [1][0][2][0][RTW89_WW][0][13] = 24, + [1][0][2][0][RTW89_WW][1][13] = 34, + [1][0][2][0][RTW89_WW][2][13] = 70, + [1][0][2][0][RTW89_WW][0][16] = 24, + [1][0][2][0][RTW89_WW][1][16] = 34, + [1][0][2][0][RTW89_WW][2][16] = 70, + [1][0][2][0][RTW89_WW][0][20] = 24, + [1][0][2][0][RTW89_WW][1][20] = 34, + [1][0][2][0][RTW89_WW][2][20] = 70, + [1][0][2][0][RTW89_WW][0][24] = 26, + [1][0][2][0][RTW89_WW][1][24] = 36, + [1][0][2][0][RTW89_WW][2][24] = 70, + [1][0][2][0][RTW89_WW][0][28] = 26, + [1][0][2][0][RTW89_WW][1][28] = 34, + [1][0][2][0][RTW89_WW][2][28] = 70, + [1][0][2][0][RTW89_WW][0][31] = 26, + [1][0][2][0][RTW89_WW][1][31] = 34, + [1][0][2][0][RTW89_WW][2][31] = 70, + [1][0][2][0][RTW89_WW][0][35] = 26, + [1][0][2][0][RTW89_WW][1][35] = 34, + [1][0][2][0][RTW89_WW][2][35] = 70, + [1][0][2][0][RTW89_WW][0][39] = 26, + [1][0][2][0][RTW89_WW][1][39] = 34, + [1][0][2][0][RTW89_WW][2][39] = 70, + [1][0][2][0][RTW89_WW][0][43] = 26, + [1][0][2][0][RTW89_WW][1][43] = 34, + [1][0][2][0][RTW89_WW][2][43] = 70, + [1][0][2][0][RTW89_WW][0][46] = 34, + [1][0][2][0][RTW89_WW][1][46] = 34, + [1][0][2][0][RTW89_WW][2][46] = 0, + [1][0][2][0][RTW89_WW][0][50] = 34, + [1][0][2][0][RTW89_WW][1][50] = 34, + [1][0][2][0][RTW89_WW][2][50] = 0, + [1][0][2][0][RTW89_WW][0][54] = 36, + [1][0][2][0][RTW89_WW][1][54] = 36, + [1][0][2][0][RTW89_WW][2][54] = 0, + [1][0][2][0][RTW89_WW][0][58] = 36, + [1][0][2][0][RTW89_WW][1][58] = 36, + [1][0][2][0][RTW89_WW][2][58] = 66, + [1][0][2][0][RTW89_WW][0][61] = 34, + [1][0][2][0][RTW89_WW][1][61] = 34, + [1][0][2][0][RTW89_WW][2][61] = 66, + [1][0][2][0][RTW89_WW][0][65] = 34, + [1][0][2][0][RTW89_WW][1][65] = 34, + [1][0][2][0][RTW89_WW][2][65] = 66, + [1][0][2][0][RTW89_WW][0][69] = 34, + [1][0][2][0][RTW89_WW][1][69] = 34, + [1][0][2][0][RTW89_WW][2][69] = 66, + [1][0][2][0][RTW89_WW][0][73] = 34, + [1][0][2][0][RTW89_WW][1][73] = 34, + [1][0][2][0][RTW89_WW][2][73] = 66, + [1][0][2][0][RTW89_WW][0][76] = 34, + [1][0][2][0][RTW89_WW][1][76] = 34, + [1][0][2][0][RTW89_WW][2][76] = 66, + [1][0][2][0][RTW89_WW][0][80] = 34, + [1][0][2][0][RTW89_WW][1][80] = 34, + [1][0][2][0][RTW89_WW][2][80] = 66, + [1][0][2][0][RTW89_WW][0][84] = 34, + [1][0][2][0][RTW89_WW][1][84] = 34, + [1][0][2][0][RTW89_WW][2][84] = 66, + [1][0][2][0][RTW89_WW][0][88] = 34, + [1][0][2][0][RTW89_WW][1][88] = 34, + [1][0][2][0][RTW89_WW][2][88] = 0, + [1][0][2][0][RTW89_WW][0][91] = 36, + [1][0][2][0][RTW89_WW][1][91] = 36, + [1][0][2][0][RTW89_WW][2][91] = 0, + [1][0][2][0][RTW89_WW][0][95] = 34, + [1][0][2][0][RTW89_WW][1][95] = 34, + [1][0][2][0][RTW89_WW][2][95] = 0, + [1][0][2][0][RTW89_WW][0][99] = 34, + [1][0][2][0][RTW89_WW][1][99] = 34, + [1][0][2][0][RTW89_WW][2][99] = 0, + [1][0][2][0][RTW89_WW][0][103] = 34, + [1][0][2][0][RTW89_WW][1][103] = 34, + [1][0][2][0][RTW89_WW][2][103] = 0, + [1][0][2][0][RTW89_WW][0][106] = 36, + [1][0][2][0][RTW89_WW][1][106] = 36, + [1][0][2][0][RTW89_WW][2][106] = 0, + [1][0][2][0][RTW89_WW][0][110] = 0, + [1][0][2][0][RTW89_WW][1][110] = 0, + [1][0][2][0][RTW89_WW][2][110] = 0, + [1][0][2][0][RTW89_WW][0][114] = 0, + [1][0][2][0][RTW89_WW][1][114] = 0, + [1][0][2][0][RTW89_WW][2][114] = 0, + [1][0][2][0][RTW89_WW][0][118] = 0, + [1][0][2][0][RTW89_WW][1][118] = 0, + [1][0][2][0][RTW89_WW][2][118] = 0, + [1][1][2][0][RTW89_WW][0][1] = 10, + [1][1][2][0][RTW89_WW][1][1] = 10, + [1][1][2][0][RTW89_WW][2][1] = 58, + [1][1][2][0][RTW89_WW][0][5] = 10, + [1][1][2][0][RTW89_WW][1][5] = 10, + [1][1][2][0][RTW89_WW][2][5] = 58, + [1][1][2][0][RTW89_WW][0][9] = 10, + [1][1][2][0][RTW89_WW][1][9] = 10, + [1][1][2][0][RTW89_WW][2][9] = 58, + [1][1][2][0][RTW89_WW][0][13] = 10, + [1][1][2][0][RTW89_WW][1][13] = 10, + [1][1][2][0][RTW89_WW][2][13] = 58, + [1][1][2][0][RTW89_WW][0][16] = 10, + [1][1][2][0][RTW89_WW][1][16] = 10, + [1][1][2][0][RTW89_WW][2][16] = 58, + [1][1][2][0][RTW89_WW][0][20] = 10, + [1][1][2][0][RTW89_WW][1][20] = 10, + [1][1][2][0][RTW89_WW][2][20] = 58, + [1][1][2][0][RTW89_WW][0][24] = 10, + [1][1][2][0][RTW89_WW][1][24] = 10, + [1][1][2][0][RTW89_WW][2][24] = 70, + [1][1][2][0][RTW89_WW][0][28] = 10, + [1][1][2][0][RTW89_WW][1][28] = 10, + [1][1][2][0][RTW89_WW][2][28] = 70, + [1][1][2][0][RTW89_WW][0][31] = 10, + [1][1][2][0][RTW89_WW][1][31] = 10, + [1][1][2][0][RTW89_WW][2][31] = 70, + [1][1][2][0][RTW89_WW][0][35] = 10, + [1][1][2][0][RTW89_WW][1][35] = 10, + [1][1][2][0][RTW89_WW][2][35] = 70, + [1][1][2][0][RTW89_WW][0][39] = 10, + [1][1][2][0][RTW89_WW][1][39] = 10, + [1][1][2][0][RTW89_WW][2][39] = 70, + [1][1][2][0][RTW89_WW][0][43] = 10, + [1][1][2][0][RTW89_WW][1][43] = 10, + [1][1][2][0][RTW89_WW][2][43] = 70, + [1][1][2][0][RTW89_WW][0][46] = 12, + [1][1][2][0][RTW89_WW][1][46] = 12, + [1][1][2][0][RTW89_WW][2][46] = 0, + [1][1][2][0][RTW89_WW][0][50] = 12, + [1][1][2][0][RTW89_WW][1][50] = 12, + [1][1][2][0][RTW89_WW][2][50] = 0, + [1][1][2][0][RTW89_WW][0][54] = 10, + [1][1][2][0][RTW89_WW][1][54] = 10, + [1][1][2][0][RTW89_WW][2][54] = 0, + [1][1][2][0][RTW89_WW][0][58] = 10, + [1][1][2][0][RTW89_WW][1][58] = 10, + [1][1][2][0][RTW89_WW][2][58] = 66, + [1][1][2][0][RTW89_WW][0][61] = 10, + [1][1][2][0][RTW89_WW][1][61] = 10, + [1][1][2][0][RTW89_WW][2][61] = 66, + [1][1][2][0][RTW89_WW][0][65] = 10, + [1][1][2][0][RTW89_WW][1][65] = 10, + [1][1][2][0][RTW89_WW][2][65] = 66, + [1][1][2][0][RTW89_WW][0][69] = 10, + [1][1][2][0][RTW89_WW][1][69] = 10, + [1][1][2][0][RTW89_WW][2][69] = 66, + [1][1][2][0][RTW89_WW][0][73] = 10, + [1][1][2][0][RTW89_WW][1][73] = 10, + [1][1][2][0][RTW89_WW][2][73] = 66, + [1][1][2][0][RTW89_WW][0][76] = 10, + [1][1][2][0][RTW89_WW][1][76] = 10, + [1][1][2][0][RTW89_WW][2][76] = 66, + [1][1][2][0][RTW89_WW][0][80] = 10, + [1][1][2][0][RTW89_WW][1][80] = 10, + [1][1][2][0][RTW89_WW][2][80] = 66, + [1][1][2][0][RTW89_WW][0][84] = 10, + [1][1][2][0][RTW89_WW][1][84] = 10, + [1][1][2][0][RTW89_WW][2][84] = 66, + [1][1][2][0][RTW89_WW][0][88] = 10, + [1][1][2][0][RTW89_WW][1][88] = 10, + [1][1][2][0][RTW89_WW][2][88] = 0, + [1][1][2][0][RTW89_WW][0][91] = 12, + [1][1][2][0][RTW89_WW][1][91] = 12, + [1][1][2][0][RTW89_WW][2][91] = 0, + [1][1][2][0][RTW89_WW][0][95] = 10, + [1][1][2][0][RTW89_WW][1][95] = 10, + [1][1][2][0][RTW89_WW][2][95] = 0, + [1][1][2][0][RTW89_WW][0][99] = 10, + [1][1][2][0][RTW89_WW][1][99] = 10, + [1][1][2][0][RTW89_WW][2][99] = 0, + [1][1][2][0][RTW89_WW][0][103] = 10, + [1][1][2][0][RTW89_WW][1][103] = 10, + [1][1][2][0][RTW89_WW][2][103] = 0, + [1][1][2][0][RTW89_WW][0][106] = 12, + [1][1][2][0][RTW89_WW][1][106] = 12, + [1][1][2][0][RTW89_WW][2][106] = 0, + [1][1][2][0][RTW89_WW][0][110] = 0, + [1][1][2][0][RTW89_WW][1][110] = 0, + [1][1][2][0][RTW89_WW][2][110] = 0, + [1][1][2][0][RTW89_WW][0][114] = 0, + [1][1][2][0][RTW89_WW][1][114] = 0, + [1][1][2][0][RTW89_WW][2][114] = 0, + [1][1][2][0][RTW89_WW][0][118] = 0, + [1][1][2][0][RTW89_WW][1][118] = 0, + [1][1][2][0][RTW89_WW][2][118] = 0, + [1][1][2][1][RTW89_WW][0][1] = 6, + [1][1][2][1][RTW89_WW][1][1] = 10, + [1][1][2][1][RTW89_WW][2][1] = 58, + [1][1][2][1][RTW89_WW][0][5] = 6, + [1][1][2][1][RTW89_WW][1][5] = 10, + [1][1][2][1][RTW89_WW][2][5] = 58, + [1][1][2][1][RTW89_WW][0][9] = 6, + [1][1][2][1][RTW89_WW][1][9] = 10, + [1][1][2][1][RTW89_WW][2][9] = 58, + [1][1][2][1][RTW89_WW][0][13] = 6, + [1][1][2][1][RTW89_WW][1][13] = 10, + [1][1][2][1][RTW89_WW][2][13] = 58, + [1][1][2][1][RTW89_WW][0][16] = 6, + [1][1][2][1][RTW89_WW][1][16] = 10, + [1][1][2][1][RTW89_WW][2][16] = 58, + [1][1][2][1][RTW89_WW][0][20] = 6, + [1][1][2][1][RTW89_WW][1][20] = 10, + [1][1][2][1][RTW89_WW][2][20] = 58, + [1][1][2][1][RTW89_WW][0][24] = 6, + [1][1][2][1][RTW89_WW][1][24] = 10, + [1][1][2][1][RTW89_WW][2][24] = 70, + [1][1][2][1][RTW89_WW][0][28] = 6, + [1][1][2][1][RTW89_WW][1][28] = 10, + [1][1][2][1][RTW89_WW][2][28] = 70, + [1][1][2][1][RTW89_WW][0][31] = 6, + [1][1][2][1][RTW89_WW][1][31] = 10, + [1][1][2][1][RTW89_WW][2][31] = 70, + [1][1][2][1][RTW89_WW][0][35] = 6, + [1][1][2][1][RTW89_WW][1][35] = 10, + [1][1][2][1][RTW89_WW][2][35] = 70, + [1][1][2][1][RTW89_WW][0][39] = 6, + [1][1][2][1][RTW89_WW][1][39] = 10, + [1][1][2][1][RTW89_WW][2][39] = 70, + [1][1][2][1][RTW89_WW][0][43] = 6, + [1][1][2][1][RTW89_WW][1][43] = 10, + [1][1][2][1][RTW89_WW][2][43] = 70, + [1][1][2][1][RTW89_WW][0][46] = 12, + [1][1][2][1][RTW89_WW][1][46] = 12, + [1][1][2][1][RTW89_WW][2][46] = 0, + [1][1][2][1][RTW89_WW][0][50] = 12, + [1][1][2][1][RTW89_WW][1][50] = 12, + [1][1][2][1][RTW89_WW][2][50] = 0, + [1][1][2][1][RTW89_WW][0][54] = 10, + [1][1][2][1][RTW89_WW][1][54] = 10, + [1][1][2][1][RTW89_WW][2][54] = 0, + [1][1][2][1][RTW89_WW][0][58] = 10, + [1][1][2][1][RTW89_WW][1][58] = 10, + [1][1][2][1][RTW89_WW][2][58] = 66, + [1][1][2][1][RTW89_WW][0][61] = 10, + [1][1][2][1][RTW89_WW][1][61] = 10, + [1][1][2][1][RTW89_WW][2][61] = 66, + [1][1][2][1][RTW89_WW][0][65] = 10, + [1][1][2][1][RTW89_WW][1][65] = 10, + [1][1][2][1][RTW89_WW][2][65] = 66, + [1][1][2][1][RTW89_WW][0][69] = 10, + [1][1][2][1][RTW89_WW][1][69] = 10, + [1][1][2][1][RTW89_WW][2][69] = 66, + [1][1][2][1][RTW89_WW][0][73] = 10, + [1][1][2][1][RTW89_WW][1][73] = 10, + [1][1][2][1][RTW89_WW][2][73] = 66, + [1][1][2][1][RTW89_WW][0][76] = 10, + [1][1][2][1][RTW89_WW][1][76] = 10, + [1][1][2][1][RTW89_WW][2][76] = 66, + [1][1][2][1][RTW89_WW][0][80] = 10, + [1][1][2][1][RTW89_WW][1][80] = 10, + [1][1][2][1][RTW89_WW][2][80] = 66, + [1][1][2][1][RTW89_WW][0][84] = 10, + [1][1][2][1][RTW89_WW][1][84] = 10, + [1][1][2][1][RTW89_WW][2][84] = 66, + [1][1][2][1][RTW89_WW][0][88] = 10, + [1][1][2][1][RTW89_WW][1][88] = 10, + [1][1][2][1][RTW89_WW][2][88] = 0, + [1][1][2][1][RTW89_WW][0][91] = 12, + [1][1][2][1][RTW89_WW][1][91] = 12, + [1][1][2][1][RTW89_WW][2][91] = 0, + [1][1][2][1][RTW89_WW][0][95] = 10, + [1][1][2][1][RTW89_WW][1][95] = 10, + [1][1][2][1][RTW89_WW][2][95] = 0, + [1][1][2][1][RTW89_WW][0][99] = 10, + [1][1][2][1][RTW89_WW][1][99] = 10, + [1][1][2][1][RTW89_WW][2][99] = 0, + [1][1][2][1][RTW89_WW][0][103] = 10, + [1][1][2][1][RTW89_WW][1][103] = 10, + [1][1][2][1][RTW89_WW][2][103] = 0, + [1][1][2][1][RTW89_WW][0][106] = 12, + [1][1][2][1][RTW89_WW][1][106] = 12, + [1][1][2][1][RTW89_WW][2][106] = 0, + [1][1][2][1][RTW89_WW][0][110] = 0, + [1][1][2][1][RTW89_WW][1][110] = 0, + [1][1][2][1][RTW89_WW][2][110] = 0, + [1][1][2][1][RTW89_WW][0][114] = 0, + [1][1][2][1][RTW89_WW][1][114] = 0, + [1][1][2][1][RTW89_WW][2][114] = 0, + [1][1][2][1][RTW89_WW][0][118] = 0, + [1][1][2][1][RTW89_WW][1][118] = 0, + [1][1][2][1][RTW89_WW][2][118] = 0, + [2][0][2][0][RTW89_WW][0][3] = 24, + [2][0][2][0][RTW89_WW][1][3] = 46, + [2][0][2][0][RTW89_WW][2][3] = 60, + [2][0][2][0][RTW89_WW][0][11] = 24, + [2][0][2][0][RTW89_WW][1][11] = 46, + [2][0][2][0][RTW89_WW][2][11] = 60, + [2][0][2][0][RTW89_WW][0][18] = 24, + [2][0][2][0][RTW89_WW][1][18] = 46, + [2][0][2][0][RTW89_WW][2][18] = 60, + [2][0][2][0][RTW89_WW][0][26] = 24, + [2][0][2][0][RTW89_WW][1][26] = 46, + [2][0][2][0][RTW89_WW][2][26] = 60, + [2][0][2][0][RTW89_WW][0][33] = 24, + [2][0][2][0][RTW89_WW][1][33] = 46, + [2][0][2][0][RTW89_WW][2][33] = 60, + [2][0][2][0][RTW89_WW][0][41] = 24, + [2][0][2][0][RTW89_WW][1][41] = 46, + [2][0][2][0][RTW89_WW][2][41] = 60, + [2][0][2][0][RTW89_WW][0][48] = 46, + [2][0][2][0][RTW89_WW][1][48] = 46, + [2][0][2][0][RTW89_WW][2][48] = 0, + [2][0][2][0][RTW89_WW][0][56] = 46, + [2][0][2][0][RTW89_WW][1][56] = 46, + [2][0][2][0][RTW89_WW][2][56] = 0, + [2][0][2][0][RTW89_WW][0][63] = 46, + [2][0][2][0][RTW89_WW][1][63] = 46, + [2][0][2][0][RTW89_WW][2][63] = 58, + [2][0][2][0][RTW89_WW][0][71] = 46, + [2][0][2][0][RTW89_WW][1][71] = 46, + [2][0][2][0][RTW89_WW][2][71] = 58, + [2][0][2][0][RTW89_WW][0][78] = 46, + [2][0][2][0][RTW89_WW][1][78] = 46, + [2][0][2][0][RTW89_WW][2][78] = 58, + [2][0][2][0][RTW89_WW][0][86] = 46, + [2][0][2][0][RTW89_WW][1][86] = 46, + [2][0][2][0][RTW89_WW][2][86] = 0, + [2][0][2][0][RTW89_WW][0][93] = 46, + [2][0][2][0][RTW89_WW][1][93] = 46, + [2][0][2][0][RTW89_WW][2][93] = 0, + [2][0][2][0][RTW89_WW][0][101] = 44, + [2][0][2][0][RTW89_WW][1][101] = 44, + [2][0][2][0][RTW89_WW][2][101] = 0, + [2][0][2][0][RTW89_WW][0][108] = 0, + [2][0][2][0][RTW89_WW][1][108] = 0, + [2][0][2][0][RTW89_WW][2][108] = 0, + [2][0][2][0][RTW89_WW][0][116] = 0, + [2][0][2][0][RTW89_WW][1][116] = 0, + [2][0][2][0][RTW89_WW][2][116] = 0, + [2][1][2][0][RTW89_WW][0][3] = 12, + [2][1][2][0][RTW89_WW][1][3] = 22, + [2][1][2][0][RTW89_WW][2][3] = 50, + [2][1][2][0][RTW89_WW][0][11] = 12, + [2][1][2][0][RTW89_WW][1][11] = 20, + [2][1][2][0][RTW89_WW][2][11] = 50, + [2][1][2][0][RTW89_WW][0][18] = 12, + [2][1][2][0][RTW89_WW][1][18] = 20, + [2][1][2][0][RTW89_WW][2][18] = 50, + [2][1][2][0][RTW89_WW][0][26] = 12, + [2][1][2][0][RTW89_WW][1][26] = 20, + [2][1][2][0][RTW89_WW][2][26] = 60, + [2][1][2][0][RTW89_WW][0][33] = 12, + [2][1][2][0][RTW89_WW][1][33] = 20, + [2][1][2][0][RTW89_WW][2][33] = 60, + [2][1][2][0][RTW89_WW][0][41] = 12, + [2][1][2][0][RTW89_WW][1][41] = 22, + [2][1][2][0][RTW89_WW][2][41] = 60, + [2][1][2][0][RTW89_WW][0][48] = 22, + [2][1][2][0][RTW89_WW][1][48] = 22, + [2][1][2][0][RTW89_WW][2][48] = 0, + [2][1][2][0][RTW89_WW][0][56] = 20, + [2][1][2][0][RTW89_WW][1][56] = 20, + [2][1][2][0][RTW89_WW][2][56] = 0, + [2][1][2][0][RTW89_WW][0][63] = 22, + [2][1][2][0][RTW89_WW][1][63] = 22, + [2][1][2][0][RTW89_WW][2][63] = 58, + [2][1][2][0][RTW89_WW][0][71] = 20, + [2][1][2][0][RTW89_WW][1][71] = 20, + [2][1][2][0][RTW89_WW][2][71] = 58, + [2][1][2][0][RTW89_WW][0][78] = 20, + [2][1][2][0][RTW89_WW][1][78] = 20, + [2][1][2][0][RTW89_WW][2][78] = 58, + [2][1][2][0][RTW89_WW][0][86] = 20, + [2][1][2][0][RTW89_WW][1][86] = 20, + [2][1][2][0][RTW89_WW][2][86] = 0, + [2][1][2][0][RTW89_WW][0][93] = 22, + [2][1][2][0][RTW89_WW][1][93] = 22, + [2][1][2][0][RTW89_WW][2][93] = 0, + [2][1][2][0][RTW89_WW][0][101] = 22, + [2][1][2][0][RTW89_WW][1][101] = 22, + [2][1][2][0][RTW89_WW][2][101] = 0, + [2][1][2][0][RTW89_WW][0][108] = 0, + [2][1][2][0][RTW89_WW][1][108] = 0, + [2][1][2][0][RTW89_WW][2][108] = 0, + [2][1][2][0][RTW89_WW][0][116] = 0, + [2][1][2][0][RTW89_WW][1][116] = 0, + [2][1][2][0][RTW89_WW][2][116] = 0, + [2][1][2][1][RTW89_WW][0][3] = 6, + [2][1][2][1][RTW89_WW][1][3] = 22, + [2][1][2][1][RTW89_WW][2][3] = 50, + [2][1][2][1][RTW89_WW][0][11] = 6, + [2][1][2][1][RTW89_WW][1][11] = 20, + [2][1][2][1][RTW89_WW][2][11] = 50, + [2][1][2][1][RTW89_WW][0][18] = 6, + [2][1][2][1][RTW89_WW][1][18] = 20, + [2][1][2][1][RTW89_WW][2][18] = 50, + [2][1][2][1][RTW89_WW][0][26] = 6, + [2][1][2][1][RTW89_WW][1][26] = 20, + [2][1][2][1][RTW89_WW][2][26] = 60, + [2][1][2][1][RTW89_WW][0][33] = 6, + [2][1][2][1][RTW89_WW][1][33] = 20, + [2][1][2][1][RTW89_WW][2][33] = 60, + [2][1][2][1][RTW89_WW][0][41] = 6, + [2][1][2][1][RTW89_WW][1][41] = 22, + [2][1][2][1][RTW89_WW][2][41] = 60, + [2][1][2][1][RTW89_WW][0][48] = 22, + [2][1][2][1][RTW89_WW][1][48] = 22, + [2][1][2][1][RTW89_WW][2][48] = 0, + [2][1][2][1][RTW89_WW][0][56] = 20, + [2][1][2][1][RTW89_WW][1][56] = 20, + [2][1][2][1][RTW89_WW][2][56] = 0, + [2][1][2][1][RTW89_WW][0][63] = 22, + [2][1][2][1][RTW89_WW][1][63] = 22, + [2][1][2][1][RTW89_WW][2][63] = 58, + [2][1][2][1][RTW89_WW][0][71] = 20, + [2][1][2][1][RTW89_WW][1][71] = 20, + [2][1][2][1][RTW89_WW][2][71] = 58, + [2][1][2][1][RTW89_WW][0][78] = 20, + [2][1][2][1][RTW89_WW][1][78] = 20, + [2][1][2][1][RTW89_WW][2][78] = 58, + [2][1][2][1][RTW89_WW][0][86] = 20, + [2][1][2][1][RTW89_WW][1][86] = 20, + [2][1][2][1][RTW89_WW][2][86] = 0, + [2][1][2][1][RTW89_WW][0][93] = 22, + [2][1][2][1][RTW89_WW][1][93] = 22, + [2][1][2][1][RTW89_WW][2][93] = 0, + [2][1][2][1][RTW89_WW][0][101] = 22, + [2][1][2][1][RTW89_WW][1][101] = 22, + [2][1][2][1][RTW89_WW][2][101] = 0, + [2][1][2][1][RTW89_WW][0][108] = 0, + [2][1][2][1][RTW89_WW][1][108] = 0, + [2][1][2][1][RTW89_WW][2][108] = 0, + [2][1][2][1][RTW89_WW][0][116] = 0, + [2][1][2][1][RTW89_WW][1][116] = 0, + [2][1][2][1][RTW89_WW][2][116] = 0, + [3][0][2][0][RTW89_WW][0][7] = 22, + [3][0][2][0][RTW89_WW][1][7] = 42, + [3][0][2][0][RTW89_WW][2][7] = 52, + [3][0][2][0][RTW89_WW][0][22] = 20, + [3][0][2][0][RTW89_WW][1][22] = 42, + [3][0][2][0][RTW89_WW][2][22] = 52, + [3][0][2][0][RTW89_WW][0][37] = 20, + [3][0][2][0][RTW89_WW][1][37] = 42, + [3][0][2][0][RTW89_WW][2][37] = 52, + [3][0][2][0][RTW89_WW][0][52] = 54, + [3][0][2][0][RTW89_WW][1][52] = 54, + [3][0][2][0][RTW89_WW][2][52] = 0, + [3][0][2][0][RTW89_WW][0][67] = 54, + [3][0][2][0][RTW89_WW][1][67] = 54, + [3][0][2][0][RTW89_WW][2][67] = 54, + [3][0][2][0][RTW89_WW][0][82] = 26, + [3][0][2][0][RTW89_WW][1][82] = 26, + [3][0][2][0][RTW89_WW][2][82] = 0, + [3][0][2][0][RTW89_WW][0][97] = 26, + [3][0][2][0][RTW89_WW][1][97] = 26, + [3][0][2][0][RTW89_WW][2][97] = 0, + [3][0][2][0][RTW89_WW][0][112] = 0, + [3][0][2][0][RTW89_WW][1][112] = 0, + [3][0][2][0][RTW89_WW][2][112] = 0, + [3][1][2][0][RTW89_WW][0][7] = 10, + [3][1][2][0][RTW89_WW][1][7] = 32, + [3][1][2][0][RTW89_WW][2][7] = 46, + [3][1][2][0][RTW89_WW][0][22] = 8, + [3][1][2][0][RTW89_WW][1][22] = 30, + [3][1][2][0][RTW89_WW][2][22] = 52, + [3][1][2][0][RTW89_WW][0][37] = 8, + [3][1][2][0][RTW89_WW][1][37] = 30, + [3][1][2][0][RTW89_WW][2][37] = 52, + [3][1][2][0][RTW89_WW][0][52] = 30, + [3][1][2][0][RTW89_WW][1][52] = 30, + [3][1][2][0][RTW89_WW][2][52] = 0, + [3][1][2][0][RTW89_WW][0][67] = 32, + [3][1][2][0][RTW89_WW][1][67] = 32, + [3][1][2][0][RTW89_WW][2][67] = 54, + [3][1][2][0][RTW89_WW][0][82] = 24, + [3][1][2][0][RTW89_WW][1][82] = 24, + [3][1][2][0][RTW89_WW][2][82] = 0, + [3][1][2][0][RTW89_WW][0][97] = 24, + [3][1][2][0][RTW89_WW][1][97] = 24, + [3][1][2][0][RTW89_WW][2][97] = 0, + [3][1][2][0][RTW89_WW][0][112] = 0, + [3][1][2][0][RTW89_WW][1][112] = 0, + [3][1][2][0][RTW89_WW][2][112] = 0, + [3][1][2][1][RTW89_WW][0][7] = 6, + [3][1][2][1][RTW89_WW][1][7] = 32, + [3][1][2][1][RTW89_WW][2][7] = 46, + [3][1][2][1][RTW89_WW][0][22] = 6, + [3][1][2][1][RTW89_WW][1][22] = 30, + [3][1][2][1][RTW89_WW][2][22] = 52, + [3][1][2][1][RTW89_WW][0][37] = 6, + [3][1][2][1][RTW89_WW][1][37] = 30, + [3][1][2][1][RTW89_WW][2][37] = 52, + [3][1][2][1][RTW89_WW][0][52] = 30, + [3][1][2][1][RTW89_WW][1][52] = 30, + [3][1][2][1][RTW89_WW][2][52] = 0, + [3][1][2][1][RTW89_WW][0][67] = 32, + [3][1][2][1][RTW89_WW][1][67] = 32, + [3][1][2][1][RTW89_WW][2][67] = 54, + [3][1][2][1][RTW89_WW][0][82] = 24, + [3][1][2][1][RTW89_WW][1][82] = 24, + [3][1][2][1][RTW89_WW][2][82] = 0, + [3][1][2][1][RTW89_WW][0][97] = 24, + [3][1][2][1][RTW89_WW][1][97] = 24, + [3][1][2][1][RTW89_WW][2][97] = 0, + [3][1][2][1][RTW89_WW][0][112] = 0, + [3][1][2][1][RTW89_WW][1][112] = 0, + [3][1][2][1][RTW89_WW][2][112] = 0, + [0][0][1][0][RTW89_FCC][1][0] = 24, + [0][0][1][0][RTW89_FCC][2][0] = 56, + [0][0][1][0][RTW89_ETSI][1][0] = 66, + [0][0][1][0][RTW89_ETSI][0][0] = 28, + [0][0][1][0][RTW89_MKK][1][0] = 66, + [0][0][1][0][RTW89_MKK][0][0] = 26, + [0][0][1][0][RTW89_IC][1][0] = 24, + [0][0][1][0][RTW89_KCC][1][0] = 24, + [0][0][1][0][RTW89_KCC][0][0] = 24, + [0][0][1][0][RTW89_ACMA][1][0] = 66, + [0][0][1][0][RTW89_ACMA][0][0] = 28, + [0][0][1][0][RTW89_CHILE][1][0] = 24, + [0][0][1][0][RTW89_QATAR][1][0] = 66, + [0][0][1][0][RTW89_QATAR][0][0] = 28, + [0][0][1][0][RTW89_UK][1][0] = 66, + [0][0][1][0][RTW89_UK][0][0] = 28, + [0][0][1][0][RTW89_FCC][1][2] = 22, + [0][0][1][0][RTW89_FCC][2][2] = 56, + [0][0][1][0][RTW89_ETSI][1][2] = 66, + [0][0][1][0][RTW89_ETSI][0][2] = 28, + [0][0][1][0][RTW89_MKK][1][2] = 66, + [0][0][1][0][RTW89_MKK][0][2] = 26, + [0][0][1][0][RTW89_IC][1][2] = 22, + [0][0][1][0][RTW89_KCC][1][2] = 24, + [0][0][1][0][RTW89_KCC][0][2] = 24, + [0][0][1][0][RTW89_ACMA][1][2] = 66, + [0][0][1][0][RTW89_ACMA][0][2] = 28, + [0][0][1][0][RTW89_CHILE][1][2] = 22, + [0][0][1][0][RTW89_QATAR][1][2] = 66, + [0][0][1][0][RTW89_QATAR][0][2] = 28, + [0][0][1][0][RTW89_UK][1][2] = 66, + [0][0][1][0][RTW89_UK][0][2] = 28, + [0][0][1][0][RTW89_FCC][1][4] = 22, + [0][0][1][0][RTW89_FCC][2][4] = 56, + [0][0][1][0][RTW89_ETSI][1][4] = 66, + [0][0][1][0][RTW89_ETSI][0][4] = 28, + [0][0][1][0][RTW89_MKK][1][4] = 66, + [0][0][1][0][RTW89_MKK][0][4] = 26, + [0][0][1][0][RTW89_IC][1][4] = 22, + [0][0][1][0][RTW89_KCC][1][4] = 24, + [0][0][1][0][RTW89_KCC][0][4] = 24, + [0][0][1][0][RTW89_ACMA][1][4] = 66, + [0][0][1][0][RTW89_ACMA][0][4] = 28, + [0][0][1][0][RTW89_CHILE][1][4] = 22, + [0][0][1][0][RTW89_QATAR][1][4] = 66, + [0][0][1][0][RTW89_QATAR][0][4] = 28, + [0][0][1][0][RTW89_UK][1][4] = 66, + [0][0][1][0][RTW89_UK][0][4] = 28, + [0][0][1][0][RTW89_FCC][1][6] = 22, + [0][0][1][0][RTW89_FCC][2][6] = 56, + [0][0][1][0][RTW89_ETSI][1][6] = 66, + [0][0][1][0][RTW89_ETSI][0][6] = 28, + [0][0][1][0][RTW89_MKK][1][6] = 66, + [0][0][1][0][RTW89_MKK][0][6] = 26, + [0][0][1][0][RTW89_IC][1][6] = 22, + [0][0][1][0][RTW89_KCC][1][6] = 24, + [0][0][1][0][RTW89_KCC][0][6] = 24, + [0][0][1][0][RTW89_ACMA][1][6] = 66, + [0][0][1][0][RTW89_ACMA][0][6] = 28, + [0][0][1][0][RTW89_CHILE][1][6] = 22, + [0][0][1][0][RTW89_QATAR][1][6] = 66, + [0][0][1][0][RTW89_QATAR][0][6] = 28, + [0][0][1][0][RTW89_UK][1][6] = 66, + [0][0][1][0][RTW89_UK][0][6] = 28, + [0][0][1][0][RTW89_FCC][1][8] = 22, + [0][0][1][0][RTW89_FCC][2][8] = 56, + [0][0][1][0][RTW89_ETSI][1][8] = 66, + [0][0][1][0][RTW89_ETSI][0][8] = 28, + [0][0][1][0][RTW89_MKK][1][8] = 66, + [0][0][1][0][RTW89_MKK][0][8] = 26, + [0][0][1][0][RTW89_IC][1][8] = 22, + [0][0][1][0][RTW89_KCC][1][8] = 24, + [0][0][1][0][RTW89_KCC][0][8] = 24, + [0][0][1][0][RTW89_ACMA][1][8] = 66, + [0][0][1][0][RTW89_ACMA][0][8] = 28, + [0][0][1][0][RTW89_CHILE][1][8] = 22, + [0][0][1][0][RTW89_QATAR][1][8] = 66, + [0][0][1][0][RTW89_QATAR][0][8] = 28, + [0][0][1][0][RTW89_UK][1][8] = 66, + [0][0][1][0][RTW89_UK][0][8] = 28, + [0][0][1][0][RTW89_FCC][1][10] = 22, + [0][0][1][0][RTW89_FCC][2][10] = 56, + [0][0][1][0][RTW89_ETSI][1][10] = 66, + [0][0][1][0][RTW89_ETSI][0][10] = 28, + [0][0][1][0][RTW89_MKK][1][10] = 66, + [0][0][1][0][RTW89_MKK][0][10] = 26, + [0][0][1][0][RTW89_IC][1][10] = 22, + [0][0][1][0][RTW89_KCC][1][10] = 24, + [0][0][1][0][RTW89_KCC][0][10] = 24, + [0][0][1][0][RTW89_ACMA][1][10] = 66, + [0][0][1][0][RTW89_ACMA][0][10] = 28, + [0][0][1][0][RTW89_CHILE][1][10] = 22, + [0][0][1][0][RTW89_QATAR][1][10] = 66, + [0][0][1][0][RTW89_QATAR][0][10] = 28, + [0][0][1][0][RTW89_UK][1][10] = 66, + [0][0][1][0][RTW89_UK][0][10] = 28, + [0][0][1][0][RTW89_FCC][1][12] = 22, + [0][0][1][0][RTW89_FCC][2][12] = 56, + [0][0][1][0][RTW89_ETSI][1][12] = 66, + [0][0][1][0][RTW89_ETSI][0][12] = 28, + [0][0][1][0][RTW89_MKK][1][12] = 66, + [0][0][1][0][RTW89_MKK][0][12] = 26, + [0][0][1][0][RTW89_IC][1][12] = 22, + [0][0][1][0][RTW89_KCC][1][12] = 24, + [0][0][1][0][RTW89_KCC][0][12] = 24, + [0][0][1][0][RTW89_ACMA][1][12] = 66, + [0][0][1][0][RTW89_ACMA][0][12] = 28, + [0][0][1][0][RTW89_CHILE][1][12] = 22, + [0][0][1][0][RTW89_QATAR][1][12] = 66, + [0][0][1][0][RTW89_QATAR][0][12] = 28, + [0][0][1][0][RTW89_UK][1][12] = 66, + [0][0][1][0][RTW89_UK][0][12] = 28, + [0][0][1][0][RTW89_FCC][1][14] = 22, + [0][0][1][0][RTW89_FCC][2][14] = 56, + [0][0][1][0][RTW89_ETSI][1][14] = 66, + [0][0][1][0][RTW89_ETSI][0][14] = 28, + [0][0][1][0][RTW89_MKK][1][14] = 66, + [0][0][1][0][RTW89_MKK][0][14] = 26, + [0][0][1][0][RTW89_IC][1][14] = 22, + [0][0][1][0][RTW89_KCC][1][14] = 24, + [0][0][1][0][RTW89_KCC][0][14] = 24, + [0][0][1][0][RTW89_ACMA][1][14] = 66, + [0][0][1][0][RTW89_ACMA][0][14] = 28, + [0][0][1][0][RTW89_CHILE][1][14] = 22, + [0][0][1][0][RTW89_QATAR][1][14] = 66, + [0][0][1][0][RTW89_QATAR][0][14] = 28, + [0][0][1][0][RTW89_UK][1][14] = 66, + [0][0][1][0][RTW89_UK][0][14] = 28, + [0][0][1][0][RTW89_FCC][1][15] = 22, + [0][0][1][0][RTW89_FCC][2][15] = 56, + [0][0][1][0][RTW89_ETSI][1][15] = 66, + [0][0][1][0][RTW89_ETSI][0][15] = 28, + [0][0][1][0][RTW89_MKK][1][15] = 66, + [0][0][1][0][RTW89_MKK][0][15] = 26, + [0][0][1][0][RTW89_IC][1][15] = 22, + [0][0][1][0][RTW89_KCC][1][15] = 24, + [0][0][1][0][RTW89_KCC][0][15] = 24, + [0][0][1][0][RTW89_ACMA][1][15] = 66, + [0][0][1][0][RTW89_ACMA][0][15] = 28, + [0][0][1][0][RTW89_CHILE][1][15] = 22, + [0][0][1][0][RTW89_QATAR][1][15] = 66, + [0][0][1][0][RTW89_QATAR][0][15] = 28, + [0][0][1][0][RTW89_UK][1][15] = 66, + [0][0][1][0][RTW89_UK][0][15] = 28, + [0][0][1][0][RTW89_FCC][1][17] = 22, + [0][0][1][0][RTW89_FCC][2][17] = 56, + [0][0][1][0][RTW89_ETSI][1][17] = 66, + [0][0][1][0][RTW89_ETSI][0][17] = 28, + [0][0][1][0][RTW89_MKK][1][17] = 66, + [0][0][1][0][RTW89_MKK][0][17] = 26, + [0][0][1][0][RTW89_IC][1][17] = 22, + [0][0][1][0][RTW89_KCC][1][17] = 24, + [0][0][1][0][RTW89_KCC][0][17] = 24, + [0][0][1][0][RTW89_ACMA][1][17] = 66, + [0][0][1][0][RTW89_ACMA][0][17] = 28, + [0][0][1][0][RTW89_CHILE][1][17] = 22, + [0][0][1][0][RTW89_QATAR][1][17] = 66, + [0][0][1][0][RTW89_QATAR][0][17] = 28, + [0][0][1][0][RTW89_UK][1][17] = 66, + [0][0][1][0][RTW89_UK][0][17] = 28, + [0][0][1][0][RTW89_FCC][1][19] = 22, + [0][0][1][0][RTW89_FCC][2][19] = 56, + [0][0][1][0][RTW89_ETSI][1][19] = 66, + [0][0][1][0][RTW89_ETSI][0][19] = 28, + [0][0][1][0][RTW89_MKK][1][19] = 66, + [0][0][1][0][RTW89_MKK][0][19] = 26, + [0][0][1][0][RTW89_IC][1][19] = 22, + [0][0][1][0][RTW89_KCC][1][19] = 24, + [0][0][1][0][RTW89_KCC][0][19] = 24, + [0][0][1][0][RTW89_ACMA][1][19] = 66, + [0][0][1][0][RTW89_ACMA][0][19] = 28, + [0][0][1][0][RTW89_CHILE][1][19] = 22, + [0][0][1][0][RTW89_QATAR][1][19] = 66, + [0][0][1][0][RTW89_QATAR][0][19] = 28, + [0][0][1][0][RTW89_UK][1][19] = 66, + [0][0][1][0][RTW89_UK][0][19] = 28, + [0][0][1][0][RTW89_FCC][1][21] = 22, + [0][0][1][0][RTW89_FCC][2][21] = 56, + [0][0][1][0][RTW89_ETSI][1][21] = 66, + [0][0][1][0][RTW89_ETSI][0][21] = 28, + [0][0][1][0][RTW89_MKK][1][21] = 66, + [0][0][1][0][RTW89_MKK][0][21] = 26, + [0][0][1][0][RTW89_IC][1][21] = 22, + [0][0][1][0][RTW89_KCC][1][21] = 24, + [0][0][1][0][RTW89_KCC][0][21] = 24, + [0][0][1][0][RTW89_ACMA][1][21] = 66, + [0][0][1][0][RTW89_ACMA][0][21] = 28, + [0][0][1][0][RTW89_CHILE][1][21] = 22, + [0][0][1][0][RTW89_QATAR][1][21] = 66, + [0][0][1][0][RTW89_QATAR][0][21] = 28, + [0][0][1][0][RTW89_UK][1][21] = 66, + [0][0][1][0][RTW89_UK][0][21] = 28, + [0][0][1][0][RTW89_FCC][1][23] = 22, + [0][0][1][0][RTW89_FCC][2][23] = 70, + [0][0][1][0][RTW89_ETSI][1][23] = 66, + [0][0][1][0][RTW89_ETSI][0][23] = 28, + [0][0][1][0][RTW89_MKK][1][23] = 66, + [0][0][1][0][RTW89_MKK][0][23] = 26, + [0][0][1][0][RTW89_IC][1][23] = 22, + [0][0][1][0][RTW89_KCC][1][23] = 24, + [0][0][1][0][RTW89_KCC][0][23] = 26, + [0][0][1][0][RTW89_ACMA][1][23] = 66, + [0][0][1][0][RTW89_ACMA][0][23] = 28, + [0][0][1][0][RTW89_CHILE][1][23] = 22, + [0][0][1][0][RTW89_QATAR][1][23] = 66, + [0][0][1][0][RTW89_QATAR][0][23] = 28, + [0][0][1][0][RTW89_UK][1][23] = 66, + [0][0][1][0][RTW89_UK][0][23] = 28, + [0][0][1][0][RTW89_FCC][1][25] = 22, + [0][0][1][0][RTW89_FCC][2][25] = 70, + [0][0][1][0][RTW89_ETSI][1][25] = 66, + [0][0][1][0][RTW89_ETSI][0][25] = 28, + [0][0][1][0][RTW89_MKK][1][25] = 66, + [0][0][1][0][RTW89_MKK][0][25] = 26, + [0][0][1][0][RTW89_IC][1][25] = 22, + [0][0][1][0][RTW89_KCC][1][25] = 24, + [0][0][1][0][RTW89_KCC][0][25] = 26, + [0][0][1][0][RTW89_ACMA][1][25] = 66, + [0][0][1][0][RTW89_ACMA][0][25] = 28, + [0][0][1][0][RTW89_CHILE][1][25] = 22, + [0][0][1][0][RTW89_QATAR][1][25] = 66, + [0][0][1][0][RTW89_QATAR][0][25] = 28, + [0][0][1][0][RTW89_UK][1][25] = 66, + [0][0][1][0][RTW89_UK][0][25] = 28, + [0][0][1][0][RTW89_FCC][1][27] = 22, + [0][0][1][0][RTW89_FCC][2][27] = 70, + [0][0][1][0][RTW89_ETSI][1][27] = 66, + [0][0][1][0][RTW89_ETSI][0][27] = 28, + [0][0][1][0][RTW89_MKK][1][27] = 66, + [0][0][1][0][RTW89_MKK][0][27] = 26, + [0][0][1][0][RTW89_IC][1][27] = 22, + [0][0][1][0][RTW89_KCC][1][27] = 24, + [0][0][1][0][RTW89_KCC][0][27] = 26, + [0][0][1][0][RTW89_ACMA][1][27] = 66, + [0][0][1][0][RTW89_ACMA][0][27] = 28, + [0][0][1][0][RTW89_CHILE][1][27] = 22, + [0][0][1][0][RTW89_QATAR][1][27] = 66, + [0][0][1][0][RTW89_QATAR][0][27] = 28, + [0][0][1][0][RTW89_UK][1][27] = 66, + [0][0][1][0][RTW89_UK][0][27] = 28, + [0][0][1][0][RTW89_FCC][1][29] = 22, + [0][0][1][0][RTW89_FCC][2][29] = 70, + [0][0][1][0][RTW89_ETSI][1][29] = 66, + [0][0][1][0][RTW89_ETSI][0][29] = 28, + [0][0][1][0][RTW89_MKK][1][29] = 66, + [0][0][1][0][RTW89_MKK][0][29] = 26, + [0][0][1][0][RTW89_IC][1][29] = 22, + [0][0][1][0][RTW89_KCC][1][29] = 24, + [0][0][1][0][RTW89_KCC][0][29] = 26, + [0][0][1][0][RTW89_ACMA][1][29] = 66, + [0][0][1][0][RTW89_ACMA][0][29] = 28, + [0][0][1][0][RTW89_CHILE][1][29] = 22, + [0][0][1][0][RTW89_QATAR][1][29] = 66, + [0][0][1][0][RTW89_QATAR][0][29] = 28, + [0][0][1][0][RTW89_UK][1][29] = 66, + [0][0][1][0][RTW89_UK][0][29] = 28, + [0][0][1][0][RTW89_FCC][1][30] = 22, + [0][0][1][0][RTW89_FCC][2][30] = 70, + [0][0][1][0][RTW89_ETSI][1][30] = 66, + [0][0][1][0][RTW89_ETSI][0][30] = 28, + [0][0][1][0][RTW89_MKK][1][30] = 66, + [0][0][1][0][RTW89_MKK][0][30] = 26, + [0][0][1][0][RTW89_IC][1][30] = 22, + [0][0][1][0][RTW89_KCC][1][30] = 24, + [0][0][1][0][RTW89_KCC][0][30] = 26, + [0][0][1][0][RTW89_ACMA][1][30] = 66, + [0][0][1][0][RTW89_ACMA][0][30] = 28, + [0][0][1][0][RTW89_CHILE][1][30] = 22, + [0][0][1][0][RTW89_QATAR][1][30] = 66, + [0][0][1][0][RTW89_QATAR][0][30] = 28, + [0][0][1][0][RTW89_UK][1][30] = 66, + [0][0][1][0][RTW89_UK][0][30] = 28, + [0][0][1][0][RTW89_FCC][1][32] = 22, + [0][0][1][0][RTW89_FCC][2][32] = 70, + [0][0][1][0][RTW89_ETSI][1][32] = 66, + [0][0][1][0][RTW89_ETSI][0][32] = 28, + [0][0][1][0][RTW89_MKK][1][32] = 66, + [0][0][1][0][RTW89_MKK][0][32] = 26, + [0][0][1][0][RTW89_IC][1][32] = 22, + [0][0][1][0][RTW89_KCC][1][32] = 24, + [0][0][1][0][RTW89_KCC][0][32] = 26, + [0][0][1][0][RTW89_ACMA][1][32] = 66, + [0][0][1][0][RTW89_ACMA][0][32] = 28, + [0][0][1][0][RTW89_CHILE][1][32] = 22, + [0][0][1][0][RTW89_QATAR][1][32] = 66, + [0][0][1][0][RTW89_QATAR][0][32] = 28, + [0][0][1][0][RTW89_UK][1][32] = 66, + [0][0][1][0][RTW89_UK][0][32] = 28, + [0][0][1][0][RTW89_FCC][1][34] = 22, + [0][0][1][0][RTW89_FCC][2][34] = 70, + [0][0][1][0][RTW89_ETSI][1][34] = 66, + [0][0][1][0][RTW89_ETSI][0][34] = 28, + [0][0][1][0][RTW89_MKK][1][34] = 66, + [0][0][1][0][RTW89_MKK][0][34] = 26, + [0][0][1][0][RTW89_IC][1][34] = 22, + [0][0][1][0][RTW89_KCC][1][34] = 24, + [0][0][1][0][RTW89_KCC][0][34] = 26, + [0][0][1][0][RTW89_ACMA][1][34] = 66, + [0][0][1][0][RTW89_ACMA][0][34] = 28, + [0][0][1][0][RTW89_CHILE][1][34] = 22, + [0][0][1][0][RTW89_QATAR][1][34] = 66, + [0][0][1][0][RTW89_QATAR][0][34] = 28, + [0][0][1][0][RTW89_UK][1][34] = 66, + [0][0][1][0][RTW89_UK][0][34] = 28, + [0][0][1][0][RTW89_FCC][1][36] = 22, + [0][0][1][0][RTW89_FCC][2][36] = 70, + [0][0][1][0][RTW89_ETSI][1][36] = 66, + [0][0][1][0][RTW89_ETSI][0][36] = 28, + [0][0][1][0][RTW89_MKK][1][36] = 66, + [0][0][1][0][RTW89_MKK][0][36] = 26, + [0][0][1][0][RTW89_IC][1][36] = 22, + [0][0][1][0][RTW89_KCC][1][36] = 24, + [0][0][1][0][RTW89_KCC][0][36] = 26, + [0][0][1][0][RTW89_ACMA][1][36] = 66, + [0][0][1][0][RTW89_ACMA][0][36] = 28, + [0][0][1][0][RTW89_CHILE][1][36] = 22, + [0][0][1][0][RTW89_QATAR][1][36] = 66, + [0][0][1][0][RTW89_QATAR][0][36] = 28, + [0][0][1][0][RTW89_UK][1][36] = 66, + [0][0][1][0][RTW89_UK][0][36] = 28, + [0][0][1][0][RTW89_FCC][1][38] = 22, + [0][0][1][0][RTW89_FCC][2][38] = 70, + [0][0][1][0][RTW89_ETSI][1][38] = 66, + [0][0][1][0][RTW89_ETSI][0][38] = 28, + [0][0][1][0][RTW89_MKK][1][38] = 66, + [0][0][1][0][RTW89_MKK][0][38] = 26, + [0][0][1][0][RTW89_IC][1][38] = 22, + [0][0][1][0][RTW89_KCC][1][38] = 24, + [0][0][1][0][RTW89_KCC][0][38] = 26, + [0][0][1][0][RTW89_ACMA][1][38] = 66, + [0][0][1][0][RTW89_ACMA][0][38] = 28, + [0][0][1][0][RTW89_CHILE][1][38] = 22, + [0][0][1][0][RTW89_QATAR][1][38] = 66, + [0][0][1][0][RTW89_QATAR][0][38] = 28, + [0][0][1][0][RTW89_UK][1][38] = 66, + [0][0][1][0][RTW89_UK][0][38] = 28, + [0][0][1][0][RTW89_FCC][1][40] = 22, + [0][0][1][0][RTW89_FCC][2][40] = 70, + [0][0][1][0][RTW89_ETSI][1][40] = 66, + [0][0][1][0][RTW89_ETSI][0][40] = 28, + [0][0][1][0][RTW89_MKK][1][40] = 66, + [0][0][1][0][RTW89_MKK][0][40] = 26, + [0][0][1][0][RTW89_IC][1][40] = 22, + [0][0][1][0][RTW89_KCC][1][40] = 24, + [0][0][1][0][RTW89_KCC][0][40] = 26, + [0][0][1][0][RTW89_ACMA][1][40] = 66, + [0][0][1][0][RTW89_ACMA][0][40] = 28, + [0][0][1][0][RTW89_CHILE][1][40] = 22, + [0][0][1][0][RTW89_QATAR][1][40] = 66, + [0][0][1][0][RTW89_QATAR][0][40] = 28, + [0][0][1][0][RTW89_UK][1][40] = 66, + [0][0][1][0][RTW89_UK][0][40] = 28, + [0][0][1][0][RTW89_FCC][1][42] = 22, + [0][0][1][0][RTW89_FCC][2][42] = 70, + [0][0][1][0][RTW89_ETSI][1][42] = 66, + [0][0][1][0][RTW89_ETSI][0][42] = 28, + [0][0][1][0][RTW89_MKK][1][42] = 66, + [0][0][1][0][RTW89_MKK][0][42] = 26, + [0][0][1][0][RTW89_IC][1][42] = 22, + [0][0][1][0][RTW89_KCC][1][42] = 24, + [0][0][1][0][RTW89_KCC][0][42] = 26, + [0][0][1][0][RTW89_ACMA][1][42] = 66, + [0][0][1][0][RTW89_ACMA][0][42] = 28, + [0][0][1][0][RTW89_CHILE][1][42] = 22, + [0][0][1][0][RTW89_QATAR][1][42] = 66, + [0][0][1][0][RTW89_QATAR][0][42] = 28, + [0][0][1][0][RTW89_UK][1][42] = 66, + [0][0][1][0][RTW89_UK][0][42] = 28, + [0][0][1][0][RTW89_FCC][1][44] = 22, + [0][0][1][0][RTW89_FCC][2][44] = 70, + [0][0][1][0][RTW89_ETSI][1][44] = 66, + [0][0][1][0][RTW89_ETSI][0][44] = 30, + [0][0][1][0][RTW89_MKK][1][44] = 44, + [0][0][1][0][RTW89_MKK][0][44] = 28, + [0][0][1][0][RTW89_IC][1][44] = 22, + [0][0][1][0][RTW89_KCC][1][44] = 24, + [0][0][1][0][RTW89_KCC][0][44] = 26, + [0][0][1][0][RTW89_ACMA][1][44] = 66, + [0][0][1][0][RTW89_ACMA][0][44] = 30, + [0][0][1][0][RTW89_CHILE][1][44] = 22, + [0][0][1][0][RTW89_QATAR][1][44] = 66, + [0][0][1][0][RTW89_QATAR][0][44] = 30, + [0][0][1][0][RTW89_UK][1][44] = 66, + [0][0][1][0][RTW89_UK][0][44] = 30, + [0][0][1][0][RTW89_FCC][1][45] = 22, + [0][0][1][0][RTW89_FCC][2][45] = 127, + [0][0][1][0][RTW89_ETSI][1][45] = 127, + [0][0][1][0][RTW89_ETSI][0][45] = 127, + [0][0][1][0][RTW89_MKK][1][45] = 127, + [0][0][1][0][RTW89_MKK][0][45] = 127, + [0][0][1][0][RTW89_IC][1][45] = 22, + [0][0][1][0][RTW89_KCC][1][45] = 24, + [0][0][1][0][RTW89_KCC][0][45] = 127, + [0][0][1][0][RTW89_ACMA][1][45] = 127, + [0][0][1][0][RTW89_ACMA][0][45] = 127, + [0][0][1][0][RTW89_CHILE][1][45] = 22, + [0][0][1][0][RTW89_QATAR][1][45] = 127, + [0][0][1][0][RTW89_QATAR][0][45] = 127, + [0][0][1][0][RTW89_UK][1][45] = 127, + [0][0][1][0][RTW89_UK][0][45] = 127, + [0][0][1][0][RTW89_FCC][1][47] = 22, + [0][0][1][0][RTW89_FCC][2][47] = 127, + [0][0][1][0][RTW89_ETSI][1][47] = 127, + [0][0][1][0][RTW89_ETSI][0][47] = 127, + [0][0][1][0][RTW89_MKK][1][47] = 127, + [0][0][1][0][RTW89_MKK][0][47] = 127, + [0][0][1][0][RTW89_IC][1][47] = 22, + [0][0][1][0][RTW89_KCC][1][47] = 24, + [0][0][1][0][RTW89_KCC][0][47] = 127, + [0][0][1][0][RTW89_ACMA][1][47] = 127, + [0][0][1][0][RTW89_ACMA][0][47] = 127, + [0][0][1][0][RTW89_CHILE][1][47] = 22, + [0][0][1][0][RTW89_QATAR][1][47] = 127, + [0][0][1][0][RTW89_QATAR][0][47] = 127, + [0][0][1][0][RTW89_UK][1][47] = 127, + [0][0][1][0][RTW89_UK][0][47] = 127, + [0][0][1][0][RTW89_FCC][1][49] = 24, + [0][0][1][0][RTW89_FCC][2][49] = 127, + [0][0][1][0][RTW89_ETSI][1][49] = 127, + [0][0][1][0][RTW89_ETSI][0][49] = 127, + [0][0][1][0][RTW89_MKK][1][49] = 127, + [0][0][1][0][RTW89_MKK][0][49] = 127, + [0][0][1][0][RTW89_IC][1][49] = 24, + [0][0][1][0][RTW89_KCC][1][49] = 24, + [0][0][1][0][RTW89_KCC][0][49] = 127, + [0][0][1][0][RTW89_ACMA][1][49] = 127, + [0][0][1][0][RTW89_ACMA][0][49] = 127, + [0][0][1][0][RTW89_CHILE][1][49] = 24, + [0][0][1][0][RTW89_QATAR][1][49] = 127, + [0][0][1][0][RTW89_QATAR][0][49] = 127, + [0][0][1][0][RTW89_UK][1][49] = 127, + [0][0][1][0][RTW89_UK][0][49] = 127, + [0][0][1][0][RTW89_FCC][1][51] = 22, + [0][0][1][0][RTW89_FCC][2][51] = 127, + [0][0][1][0][RTW89_ETSI][1][51] = 127, + [0][0][1][0][RTW89_ETSI][0][51] = 127, + [0][0][1][0][RTW89_MKK][1][51] = 127, + [0][0][1][0][RTW89_MKK][0][51] = 127, + [0][0][1][0][RTW89_IC][1][51] = 22, + [0][0][1][0][RTW89_KCC][1][51] = 24, + [0][0][1][0][RTW89_KCC][0][51] = 127, + [0][0][1][0][RTW89_ACMA][1][51] = 127, + [0][0][1][0][RTW89_ACMA][0][51] = 127, + [0][0][1][0][RTW89_CHILE][1][51] = 22, + [0][0][1][0][RTW89_QATAR][1][51] = 127, + [0][0][1][0][RTW89_QATAR][0][51] = 127, + [0][0][1][0][RTW89_UK][1][51] = 127, + [0][0][1][0][RTW89_UK][0][51] = 127, + [0][0][1][0][RTW89_FCC][1][53] = 22, + [0][0][1][0][RTW89_FCC][2][53] = 127, + [0][0][1][0][RTW89_ETSI][1][53] = 127, + [0][0][1][0][RTW89_ETSI][0][53] = 127, + [0][0][1][0][RTW89_MKK][1][53] = 127, + [0][0][1][0][RTW89_MKK][0][53] = 127, + [0][0][1][0][RTW89_IC][1][53] = 22, + [0][0][1][0][RTW89_KCC][1][53] = 24, + [0][0][1][0][RTW89_KCC][0][53] = 127, + [0][0][1][0][RTW89_ACMA][1][53] = 127, + [0][0][1][0][RTW89_ACMA][0][53] = 127, + [0][0][1][0][RTW89_CHILE][1][53] = 22, + [0][0][1][0][RTW89_QATAR][1][53] = 127, + [0][0][1][0][RTW89_QATAR][0][53] = 127, + [0][0][1][0][RTW89_UK][1][53] = 127, + [0][0][1][0][RTW89_UK][0][53] = 127, + [0][0][1][0][RTW89_FCC][1][55] = 22, + [0][0][1][0][RTW89_FCC][2][55] = 68, + [0][0][1][0][RTW89_ETSI][1][55] = 127, + [0][0][1][0][RTW89_ETSI][0][55] = 127, + [0][0][1][0][RTW89_MKK][1][55] = 127, + [0][0][1][0][RTW89_MKK][0][55] = 127, + [0][0][1][0][RTW89_IC][1][55] = 22, + [0][0][1][0][RTW89_KCC][1][55] = 26, + [0][0][1][0][RTW89_KCC][0][55] = 127, + [0][0][1][0][RTW89_ACMA][1][55] = 127, + [0][0][1][0][RTW89_ACMA][0][55] = 127, + [0][0][1][0][RTW89_CHILE][1][55] = 22, + [0][0][1][0][RTW89_QATAR][1][55] = 127, + [0][0][1][0][RTW89_QATAR][0][55] = 127, + [0][0][1][0][RTW89_UK][1][55] = 127, + [0][0][1][0][RTW89_UK][0][55] = 127, + [0][0][1][0][RTW89_FCC][1][57] = 22, + [0][0][1][0][RTW89_FCC][2][57] = 68, + [0][0][1][0][RTW89_ETSI][1][57] = 127, + [0][0][1][0][RTW89_ETSI][0][57] = 127, + [0][0][1][0][RTW89_MKK][1][57] = 127, + [0][0][1][0][RTW89_MKK][0][57] = 127, + [0][0][1][0][RTW89_IC][1][57] = 22, + [0][0][1][0][RTW89_KCC][1][57] = 26, + [0][0][1][0][RTW89_KCC][0][57] = 127, + [0][0][1][0][RTW89_ACMA][1][57] = 127, + [0][0][1][0][RTW89_ACMA][0][57] = 127, + [0][0][1][0][RTW89_CHILE][1][57] = 22, + [0][0][1][0][RTW89_QATAR][1][57] = 127, + [0][0][1][0][RTW89_QATAR][0][57] = 127, + [0][0][1][0][RTW89_UK][1][57] = 127, + [0][0][1][0][RTW89_UK][0][57] = 127, + [0][0][1][0][RTW89_FCC][1][59] = 22, + [0][0][1][0][RTW89_FCC][2][59] = 68, + [0][0][1][0][RTW89_ETSI][1][59] = 127, + [0][0][1][0][RTW89_ETSI][0][59] = 127, + [0][0][1][0][RTW89_MKK][1][59] = 127, + [0][0][1][0][RTW89_MKK][0][59] = 127, + [0][0][1][0][RTW89_IC][1][59] = 22, + [0][0][1][0][RTW89_KCC][1][59] = 26, + [0][0][1][0][RTW89_KCC][0][59] = 127, + [0][0][1][0][RTW89_ACMA][1][59] = 127, + [0][0][1][0][RTW89_ACMA][0][59] = 127, + [0][0][1][0][RTW89_CHILE][1][59] = 22, + [0][0][1][0][RTW89_QATAR][1][59] = 127, + [0][0][1][0][RTW89_QATAR][0][59] = 127, + [0][0][1][0][RTW89_UK][1][59] = 127, + [0][0][1][0][RTW89_UK][0][59] = 127, + [0][0][1][0][RTW89_FCC][1][60] = 22, + [0][0][1][0][RTW89_FCC][2][60] = 68, + [0][0][1][0][RTW89_ETSI][1][60] = 127, + [0][0][1][0][RTW89_ETSI][0][60] = 127, + [0][0][1][0][RTW89_MKK][1][60] = 127, + [0][0][1][0][RTW89_MKK][0][60] = 127, + [0][0][1][0][RTW89_IC][1][60] = 22, + [0][0][1][0][RTW89_KCC][1][60] = 26, + [0][0][1][0][RTW89_KCC][0][60] = 127, + [0][0][1][0][RTW89_ACMA][1][60] = 127, + [0][0][1][0][RTW89_ACMA][0][60] = 127, + [0][0][1][0][RTW89_CHILE][1][60] = 22, + [0][0][1][0][RTW89_QATAR][1][60] = 127, + [0][0][1][0][RTW89_QATAR][0][60] = 127, + [0][0][1][0][RTW89_UK][1][60] = 127, + [0][0][1][0][RTW89_UK][0][60] = 127, + [0][0][1][0][RTW89_FCC][1][62] = 22, + [0][0][1][0][RTW89_FCC][2][62] = 68, + [0][0][1][0][RTW89_ETSI][1][62] = 127, + [0][0][1][0][RTW89_ETSI][0][62] = 127, + [0][0][1][0][RTW89_MKK][1][62] = 127, + [0][0][1][0][RTW89_MKK][0][62] = 127, + [0][0][1][0][RTW89_IC][1][62] = 22, + [0][0][1][0][RTW89_KCC][1][62] = 26, + [0][0][1][0][RTW89_KCC][0][62] = 127, + [0][0][1][0][RTW89_ACMA][1][62] = 127, + [0][0][1][0][RTW89_ACMA][0][62] = 127, + [0][0][1][0][RTW89_CHILE][1][62] = 22, + [0][0][1][0][RTW89_QATAR][1][62] = 127, + [0][0][1][0][RTW89_QATAR][0][62] = 127, + [0][0][1][0][RTW89_UK][1][62] = 127, + [0][0][1][0][RTW89_UK][0][62] = 127, + [0][0][1][0][RTW89_FCC][1][64] = 22, + [0][0][1][0][RTW89_FCC][2][64] = 68, + [0][0][1][0][RTW89_ETSI][1][64] = 127, + [0][0][1][0][RTW89_ETSI][0][64] = 127, + [0][0][1][0][RTW89_MKK][1][64] = 127, + [0][0][1][0][RTW89_MKK][0][64] = 127, + [0][0][1][0][RTW89_IC][1][64] = 22, + [0][0][1][0][RTW89_KCC][1][64] = 26, + [0][0][1][0][RTW89_KCC][0][64] = 127, + [0][0][1][0][RTW89_ACMA][1][64] = 127, + [0][0][1][0][RTW89_ACMA][0][64] = 127, + [0][0][1][0][RTW89_CHILE][1][64] = 22, + [0][0][1][0][RTW89_QATAR][1][64] = 127, + [0][0][1][0][RTW89_QATAR][0][64] = 127, + [0][0][1][0][RTW89_UK][1][64] = 127, + [0][0][1][0][RTW89_UK][0][64] = 127, + [0][0][1][0][RTW89_FCC][1][66] = 22, + [0][0][1][0][RTW89_FCC][2][66] = 68, + [0][0][1][0][RTW89_ETSI][1][66] = 127, + [0][0][1][0][RTW89_ETSI][0][66] = 127, + [0][0][1][0][RTW89_MKK][1][66] = 127, + [0][0][1][0][RTW89_MKK][0][66] = 127, + [0][0][1][0][RTW89_IC][1][66] = 22, + [0][0][1][0][RTW89_KCC][1][66] = 26, + [0][0][1][0][RTW89_KCC][0][66] = 127, + [0][0][1][0][RTW89_ACMA][1][66] = 127, + [0][0][1][0][RTW89_ACMA][0][66] = 127, + [0][0][1][0][RTW89_CHILE][1][66] = 22, + [0][0][1][0][RTW89_QATAR][1][66] = 127, + [0][0][1][0][RTW89_QATAR][0][66] = 127, + [0][0][1][0][RTW89_UK][1][66] = 127, + [0][0][1][0][RTW89_UK][0][66] = 127, + [0][0][1][0][RTW89_FCC][1][68] = 22, + [0][0][1][0][RTW89_FCC][2][68] = 68, + [0][0][1][0][RTW89_ETSI][1][68] = 127, + [0][0][1][0][RTW89_ETSI][0][68] = 127, + [0][0][1][0][RTW89_MKK][1][68] = 127, + [0][0][1][0][RTW89_MKK][0][68] = 127, + [0][0][1][0][RTW89_IC][1][68] = 22, + [0][0][1][0][RTW89_KCC][1][68] = 26, + [0][0][1][0][RTW89_KCC][0][68] = 127, + [0][0][1][0][RTW89_ACMA][1][68] = 127, + [0][0][1][0][RTW89_ACMA][0][68] = 127, + [0][0][1][0][RTW89_CHILE][1][68] = 22, + [0][0][1][0][RTW89_QATAR][1][68] = 127, + [0][0][1][0][RTW89_QATAR][0][68] = 127, + [0][0][1][0][RTW89_UK][1][68] = 127, + [0][0][1][0][RTW89_UK][0][68] = 127, + [0][0][1][0][RTW89_FCC][1][70] = 24, + [0][0][1][0][RTW89_FCC][2][70] = 68, + [0][0][1][0][RTW89_ETSI][1][70] = 127, + [0][0][1][0][RTW89_ETSI][0][70] = 127, + [0][0][1][0][RTW89_MKK][1][70] = 127, + [0][0][1][0][RTW89_MKK][0][70] = 127, + [0][0][1][0][RTW89_IC][1][70] = 24, + [0][0][1][0][RTW89_KCC][1][70] = 26, + [0][0][1][0][RTW89_KCC][0][70] = 127, + [0][0][1][0][RTW89_ACMA][1][70] = 127, + [0][0][1][0][RTW89_ACMA][0][70] = 127, + [0][0][1][0][RTW89_CHILE][1][70] = 24, + [0][0][1][0][RTW89_QATAR][1][70] = 127, + [0][0][1][0][RTW89_QATAR][0][70] = 127, + [0][0][1][0][RTW89_UK][1][70] = 127, + [0][0][1][0][RTW89_UK][0][70] = 127, + [0][0][1][0][RTW89_FCC][1][72] = 22, + [0][0][1][0][RTW89_FCC][2][72] = 68, + [0][0][1][0][RTW89_ETSI][1][72] = 127, + [0][0][1][0][RTW89_ETSI][0][72] = 127, + [0][0][1][0][RTW89_MKK][1][72] = 127, + [0][0][1][0][RTW89_MKK][0][72] = 127, + [0][0][1][0][RTW89_IC][1][72] = 22, + [0][0][1][0][RTW89_KCC][1][72] = 26, + [0][0][1][0][RTW89_KCC][0][72] = 127, + [0][0][1][0][RTW89_ACMA][1][72] = 127, + [0][0][1][0][RTW89_ACMA][0][72] = 127, + [0][0][1][0][RTW89_CHILE][1][72] = 22, + [0][0][1][0][RTW89_QATAR][1][72] = 127, + [0][0][1][0][RTW89_QATAR][0][72] = 127, + [0][0][1][0][RTW89_UK][1][72] = 127, + [0][0][1][0][RTW89_UK][0][72] = 127, + [0][0][1][0][RTW89_FCC][1][74] = 22, + [0][0][1][0][RTW89_FCC][2][74] = 68, + [0][0][1][0][RTW89_ETSI][1][74] = 127, + [0][0][1][0][RTW89_ETSI][0][74] = 127, + [0][0][1][0][RTW89_MKK][1][74] = 127, + [0][0][1][0][RTW89_MKK][0][74] = 127, + [0][0][1][0][RTW89_IC][1][74] = 22, + [0][0][1][0][RTW89_KCC][1][74] = 26, + [0][0][1][0][RTW89_KCC][0][74] = 127, + [0][0][1][0][RTW89_ACMA][1][74] = 127, + [0][0][1][0][RTW89_ACMA][0][74] = 127, + [0][0][1][0][RTW89_CHILE][1][74] = 22, + [0][0][1][0][RTW89_QATAR][1][74] = 127, + [0][0][1][0][RTW89_QATAR][0][74] = 127, + [0][0][1][0][RTW89_UK][1][74] = 127, + [0][0][1][0][RTW89_UK][0][74] = 127, + [0][0][1][0][RTW89_FCC][1][75] = 22, + [0][0][1][0][RTW89_FCC][2][75] = 68, + [0][0][1][0][RTW89_ETSI][1][75] = 127, + [0][0][1][0][RTW89_ETSI][0][75] = 127, + [0][0][1][0][RTW89_MKK][1][75] = 127, + [0][0][1][0][RTW89_MKK][0][75] = 127, + [0][0][1][0][RTW89_IC][1][75] = 22, + [0][0][1][0][RTW89_KCC][1][75] = 26, + [0][0][1][0][RTW89_KCC][0][75] = 127, + [0][0][1][0][RTW89_ACMA][1][75] = 127, + [0][0][1][0][RTW89_ACMA][0][75] = 127, + [0][0][1][0][RTW89_CHILE][1][75] = 22, + [0][0][1][0][RTW89_QATAR][1][75] = 127, + [0][0][1][0][RTW89_QATAR][0][75] = 127, + [0][0][1][0][RTW89_UK][1][75] = 127, + [0][0][1][0][RTW89_UK][0][75] = 127, + [0][0][1][0][RTW89_FCC][1][77] = 22, + [0][0][1][0][RTW89_FCC][2][77] = 68, + [0][0][1][0][RTW89_ETSI][1][77] = 127, + [0][0][1][0][RTW89_ETSI][0][77] = 127, + [0][0][1][0][RTW89_MKK][1][77] = 127, + [0][0][1][0][RTW89_MKK][0][77] = 127, + [0][0][1][0][RTW89_IC][1][77] = 22, + [0][0][1][0][RTW89_KCC][1][77] = 26, + [0][0][1][0][RTW89_KCC][0][77] = 127, + [0][0][1][0][RTW89_ACMA][1][77] = 127, + [0][0][1][0][RTW89_ACMA][0][77] = 127, + [0][0][1][0][RTW89_CHILE][1][77] = 22, + [0][0][1][0][RTW89_QATAR][1][77] = 127, + [0][0][1][0][RTW89_QATAR][0][77] = 127, + [0][0][1][0][RTW89_UK][1][77] = 127, + [0][0][1][0][RTW89_UK][0][77] = 127, + [0][0][1][0][RTW89_FCC][1][79] = 22, + [0][0][1][0][RTW89_FCC][2][79] = 68, + [0][0][1][0][RTW89_ETSI][1][79] = 127, + [0][0][1][0][RTW89_ETSI][0][79] = 127, + [0][0][1][0][RTW89_MKK][1][79] = 127, + [0][0][1][0][RTW89_MKK][0][79] = 127, + [0][0][1][0][RTW89_IC][1][79] = 22, + [0][0][1][0][RTW89_KCC][1][79] = 26, + [0][0][1][0][RTW89_KCC][0][79] = 127, + [0][0][1][0][RTW89_ACMA][1][79] = 127, + [0][0][1][0][RTW89_ACMA][0][79] = 127, + [0][0][1][0][RTW89_CHILE][1][79] = 22, + [0][0][1][0][RTW89_QATAR][1][79] = 127, + [0][0][1][0][RTW89_QATAR][0][79] = 127, + [0][0][1][0][RTW89_UK][1][79] = 127, + [0][0][1][0][RTW89_UK][0][79] = 127, + [0][0][1][0][RTW89_FCC][1][81] = 22, + [0][0][1][0][RTW89_FCC][2][81] = 68, + [0][0][1][0][RTW89_ETSI][1][81] = 127, + [0][0][1][0][RTW89_ETSI][0][81] = 127, + [0][0][1][0][RTW89_MKK][1][81] = 127, + [0][0][1][0][RTW89_MKK][0][81] = 127, + [0][0][1][0][RTW89_IC][1][81] = 22, + [0][0][1][0][RTW89_KCC][1][81] = 26, + [0][0][1][0][RTW89_KCC][0][81] = 127, + [0][0][1][0][RTW89_ACMA][1][81] = 127, + [0][0][1][0][RTW89_ACMA][0][81] = 127, + [0][0][1][0][RTW89_CHILE][1][81] = 22, + [0][0][1][0][RTW89_QATAR][1][81] = 127, + [0][0][1][0][RTW89_QATAR][0][81] = 127, + [0][0][1][0][RTW89_UK][1][81] = 127, + [0][0][1][0][RTW89_UK][0][81] = 127, + [0][0][1][0][RTW89_FCC][1][83] = 22, + [0][0][1][0][RTW89_FCC][2][83] = 68, + [0][0][1][0][RTW89_ETSI][1][83] = 127, + [0][0][1][0][RTW89_ETSI][0][83] = 127, + [0][0][1][0][RTW89_MKK][1][83] = 127, + [0][0][1][0][RTW89_MKK][0][83] = 127, + [0][0][1][0][RTW89_IC][1][83] = 22, + [0][0][1][0][RTW89_KCC][1][83] = 32, + [0][0][1][0][RTW89_KCC][0][83] = 127, + [0][0][1][0][RTW89_ACMA][1][83] = 127, + [0][0][1][0][RTW89_ACMA][0][83] = 127, + [0][0][1][0][RTW89_CHILE][1][83] = 22, + [0][0][1][0][RTW89_QATAR][1][83] = 127, + [0][0][1][0][RTW89_QATAR][0][83] = 127, + [0][0][1][0][RTW89_UK][1][83] = 127, + [0][0][1][0][RTW89_UK][0][83] = 127, + [0][0][1][0][RTW89_FCC][1][85] = 22, + [0][0][1][0][RTW89_FCC][2][85] = 68, + [0][0][1][0][RTW89_ETSI][1][85] = 127, + [0][0][1][0][RTW89_ETSI][0][85] = 127, + [0][0][1][0][RTW89_MKK][1][85] = 127, + [0][0][1][0][RTW89_MKK][0][85] = 127, + [0][0][1][0][RTW89_IC][1][85] = 22, + [0][0][1][0][RTW89_KCC][1][85] = 32, + [0][0][1][0][RTW89_KCC][0][85] = 127, + [0][0][1][0][RTW89_ACMA][1][85] = 127, + [0][0][1][0][RTW89_ACMA][0][85] = 127, + [0][0][1][0][RTW89_CHILE][1][85] = 22, + [0][0][1][0][RTW89_QATAR][1][85] = 127, + [0][0][1][0][RTW89_QATAR][0][85] = 127, + [0][0][1][0][RTW89_UK][1][85] = 127, + [0][0][1][0][RTW89_UK][0][85] = 127, + [0][0][1][0][RTW89_FCC][1][87] = 22, + [0][0][1][0][RTW89_FCC][2][87] = 127, + [0][0][1][0][RTW89_ETSI][1][87] = 127, + [0][0][1][0][RTW89_ETSI][0][87] = 127, + [0][0][1][0][RTW89_MKK][1][87] = 127, + [0][0][1][0][RTW89_MKK][0][87] = 127, + [0][0][1][0][RTW89_IC][1][87] = 22, + [0][0][1][0][RTW89_KCC][1][87] = 32, + [0][0][1][0][RTW89_KCC][0][87] = 127, + [0][0][1][0][RTW89_ACMA][1][87] = 127, + [0][0][1][0][RTW89_ACMA][0][87] = 127, + [0][0][1][0][RTW89_CHILE][1][87] = 22, + [0][0][1][0][RTW89_QATAR][1][87] = 127, + [0][0][1][0][RTW89_QATAR][0][87] = 127, + [0][0][1][0][RTW89_UK][1][87] = 127, + [0][0][1][0][RTW89_UK][0][87] = 127, + [0][0][1][0][RTW89_FCC][1][89] = 22, + [0][0][1][0][RTW89_FCC][2][89] = 127, + [0][0][1][0][RTW89_ETSI][1][89] = 127, + [0][0][1][0][RTW89_ETSI][0][89] = 127, + [0][0][1][0][RTW89_MKK][1][89] = 127, + [0][0][1][0][RTW89_MKK][0][89] = 127, + [0][0][1][0][RTW89_IC][1][89] = 22, + [0][0][1][0][RTW89_KCC][1][89] = 32, + [0][0][1][0][RTW89_KCC][0][89] = 127, + [0][0][1][0][RTW89_ACMA][1][89] = 127, + [0][0][1][0][RTW89_ACMA][0][89] = 127, + [0][0][1][0][RTW89_CHILE][1][89] = 22, + [0][0][1][0][RTW89_QATAR][1][89] = 127, + [0][0][1][0][RTW89_QATAR][0][89] = 127, + [0][0][1][0][RTW89_UK][1][89] = 127, + [0][0][1][0][RTW89_UK][0][89] = 127, + [0][0][1][0][RTW89_FCC][1][90] = 22, + [0][0][1][0][RTW89_FCC][2][90] = 127, + [0][0][1][0][RTW89_ETSI][1][90] = 127, + [0][0][1][0][RTW89_ETSI][0][90] = 127, + [0][0][1][0][RTW89_MKK][1][90] = 127, + [0][0][1][0][RTW89_MKK][0][90] = 127, + [0][0][1][0][RTW89_IC][1][90] = 22, + [0][0][1][0][RTW89_KCC][1][90] = 32, + [0][0][1][0][RTW89_KCC][0][90] = 127, + [0][0][1][0][RTW89_ACMA][1][90] = 127, + [0][0][1][0][RTW89_ACMA][0][90] = 127, + [0][0][1][0][RTW89_CHILE][1][90] = 22, + [0][0][1][0][RTW89_QATAR][1][90] = 127, + [0][0][1][0][RTW89_QATAR][0][90] = 127, + [0][0][1][0][RTW89_UK][1][90] = 127, + [0][0][1][0][RTW89_UK][0][90] = 127, + [0][0][1][0][RTW89_FCC][1][92] = 22, + [0][0][1][0][RTW89_FCC][2][92] = 127, + [0][0][1][0][RTW89_ETSI][1][92] = 127, + [0][0][1][0][RTW89_ETSI][0][92] = 127, + [0][0][1][0][RTW89_MKK][1][92] = 127, + [0][0][1][0][RTW89_MKK][0][92] = 127, + [0][0][1][0][RTW89_IC][1][92] = 22, + [0][0][1][0][RTW89_KCC][1][92] = 32, + [0][0][1][0][RTW89_KCC][0][92] = 127, + [0][0][1][0][RTW89_ACMA][1][92] = 127, + [0][0][1][0][RTW89_ACMA][0][92] = 127, + [0][0][1][0][RTW89_CHILE][1][92] = 22, + [0][0][1][0][RTW89_QATAR][1][92] = 127, + [0][0][1][0][RTW89_QATAR][0][92] = 127, + [0][0][1][0][RTW89_UK][1][92] = 127, + [0][0][1][0][RTW89_UK][0][92] = 127, + [0][0][1][0][RTW89_FCC][1][94] = 22, + [0][0][1][0][RTW89_FCC][2][94] = 127, + [0][0][1][0][RTW89_ETSI][1][94] = 127, + [0][0][1][0][RTW89_ETSI][0][94] = 127, + [0][0][1][0][RTW89_MKK][1][94] = 127, + [0][0][1][0][RTW89_MKK][0][94] = 127, + [0][0][1][0][RTW89_IC][1][94] = 22, + [0][0][1][0][RTW89_KCC][1][94] = 32, + [0][0][1][0][RTW89_KCC][0][94] = 127, + [0][0][1][0][RTW89_ACMA][1][94] = 127, + [0][0][1][0][RTW89_ACMA][0][94] = 127, + [0][0][1][0][RTW89_CHILE][1][94] = 22, + [0][0][1][0][RTW89_QATAR][1][94] = 127, + [0][0][1][0][RTW89_QATAR][0][94] = 127, + [0][0][1][0][RTW89_UK][1][94] = 127, + [0][0][1][0][RTW89_UK][0][94] = 127, + [0][0][1][0][RTW89_FCC][1][96] = 22, + [0][0][1][0][RTW89_FCC][2][96] = 127, + [0][0][1][0][RTW89_ETSI][1][96] = 127, + [0][0][1][0][RTW89_ETSI][0][96] = 127, + [0][0][1][0][RTW89_MKK][1][96] = 127, + [0][0][1][0][RTW89_MKK][0][96] = 127, + [0][0][1][0][RTW89_IC][1][96] = 22, + [0][0][1][0][RTW89_KCC][1][96] = 32, + [0][0][1][0][RTW89_KCC][0][96] = 127, + [0][0][1][0][RTW89_ACMA][1][96] = 127, + [0][0][1][0][RTW89_ACMA][0][96] = 127, + [0][0][1][0][RTW89_CHILE][1][96] = 22, + [0][0][1][0][RTW89_QATAR][1][96] = 127, + [0][0][1][0][RTW89_QATAR][0][96] = 127, + [0][0][1][0][RTW89_UK][1][96] = 127, + [0][0][1][0][RTW89_UK][0][96] = 127, + [0][0][1][0][RTW89_FCC][1][98] = 22, + [0][0][1][0][RTW89_FCC][2][98] = 127, + [0][0][1][0][RTW89_ETSI][1][98] = 127, + [0][0][1][0][RTW89_ETSI][0][98] = 127, + [0][0][1][0][RTW89_MKK][1][98] = 127, + [0][0][1][0][RTW89_MKK][0][98] = 127, + [0][0][1][0][RTW89_IC][1][98] = 22, + [0][0][1][0][RTW89_KCC][1][98] = 32, + [0][0][1][0][RTW89_KCC][0][98] = 127, + [0][0][1][0][RTW89_ACMA][1][98] = 127, + [0][0][1][0][RTW89_ACMA][0][98] = 127, + [0][0][1][0][RTW89_CHILE][1][98] = 22, + [0][0][1][0][RTW89_QATAR][1][98] = 127, + [0][0][1][0][RTW89_QATAR][0][98] = 127, + [0][0][1][0][RTW89_UK][1][98] = 127, + [0][0][1][0][RTW89_UK][0][98] = 127, + [0][0][1][0][RTW89_FCC][1][100] = 22, + [0][0][1][0][RTW89_FCC][2][100] = 127, + [0][0][1][0][RTW89_ETSI][1][100] = 127, + [0][0][1][0][RTW89_ETSI][0][100] = 127, + [0][0][1][0][RTW89_MKK][1][100] = 127, + [0][0][1][0][RTW89_MKK][0][100] = 127, + [0][0][1][0][RTW89_IC][1][100] = 22, + [0][0][1][0][RTW89_KCC][1][100] = 32, + [0][0][1][0][RTW89_KCC][0][100] = 127, + [0][0][1][0][RTW89_ACMA][1][100] = 127, + [0][0][1][0][RTW89_ACMA][0][100] = 127, + [0][0][1][0][RTW89_CHILE][1][100] = 22, + [0][0][1][0][RTW89_QATAR][1][100] = 127, + [0][0][1][0][RTW89_QATAR][0][100] = 127, + [0][0][1][0][RTW89_UK][1][100] = 127, + [0][0][1][0][RTW89_UK][0][100] = 127, + [0][0][1][0][RTW89_FCC][1][102] = 22, + [0][0][1][0][RTW89_FCC][2][102] = 127, + [0][0][1][0][RTW89_ETSI][1][102] = 127, + [0][0][1][0][RTW89_ETSI][0][102] = 127, + [0][0][1][0][RTW89_MKK][1][102] = 127, + [0][0][1][0][RTW89_MKK][0][102] = 127, + [0][0][1][0][RTW89_IC][1][102] = 22, + [0][0][1][0][RTW89_KCC][1][102] = 32, + [0][0][1][0][RTW89_KCC][0][102] = 127, + [0][0][1][0][RTW89_ACMA][1][102] = 127, + [0][0][1][0][RTW89_ACMA][0][102] = 127, + [0][0][1][0][RTW89_CHILE][1][102] = 22, + [0][0][1][0][RTW89_QATAR][1][102] = 127, + [0][0][1][0][RTW89_QATAR][0][102] = 127, + [0][0][1][0][RTW89_UK][1][102] = 127, + [0][0][1][0][RTW89_UK][0][102] = 127, + [0][0][1][0][RTW89_FCC][1][104] = 22, + [0][0][1][0][RTW89_FCC][2][104] = 127, + [0][0][1][0][RTW89_ETSI][1][104] = 127, + [0][0][1][0][RTW89_ETSI][0][104] = 127, + [0][0][1][0][RTW89_MKK][1][104] = 127, + [0][0][1][0][RTW89_MKK][0][104] = 127, + [0][0][1][0][RTW89_IC][1][104] = 22, + [0][0][1][0][RTW89_KCC][1][104] = 32, + [0][0][1][0][RTW89_KCC][0][104] = 127, + [0][0][1][0][RTW89_ACMA][1][104] = 127, + [0][0][1][0][RTW89_ACMA][0][104] = 127, + [0][0][1][0][RTW89_CHILE][1][104] = 22, + [0][0][1][0][RTW89_QATAR][1][104] = 127, + [0][0][1][0][RTW89_QATAR][0][104] = 127, + [0][0][1][0][RTW89_UK][1][104] = 127, + [0][0][1][0][RTW89_UK][0][104] = 127, + [0][0][1][0][RTW89_FCC][1][105] = 22, + [0][0][1][0][RTW89_FCC][2][105] = 127, + [0][0][1][0][RTW89_ETSI][1][105] = 127, + [0][0][1][0][RTW89_ETSI][0][105] = 127, + [0][0][1][0][RTW89_MKK][1][105] = 127, + [0][0][1][0][RTW89_MKK][0][105] = 127, + [0][0][1][0][RTW89_IC][1][105] = 22, + [0][0][1][0][RTW89_KCC][1][105] = 32, + [0][0][1][0][RTW89_KCC][0][105] = 127, + [0][0][1][0][RTW89_ACMA][1][105] = 127, + [0][0][1][0][RTW89_ACMA][0][105] = 127, + [0][0][1][0][RTW89_CHILE][1][105] = 22, + [0][0][1][0][RTW89_QATAR][1][105] = 127, + [0][0][1][0][RTW89_QATAR][0][105] = 127, + [0][0][1][0][RTW89_UK][1][105] = 127, + [0][0][1][0][RTW89_UK][0][105] = 127, + [0][0][1][0][RTW89_FCC][1][107] = 24, + [0][0][1][0][RTW89_FCC][2][107] = 127, + [0][0][1][0][RTW89_ETSI][1][107] = 127, + [0][0][1][0][RTW89_ETSI][0][107] = 127, + [0][0][1][0][RTW89_MKK][1][107] = 127, + [0][0][1][0][RTW89_MKK][0][107] = 127, + [0][0][1][0][RTW89_IC][1][107] = 24, + [0][0][1][0][RTW89_KCC][1][107] = 32, + [0][0][1][0][RTW89_KCC][0][107] = 127, + [0][0][1][0][RTW89_ACMA][1][107] = 127, + [0][0][1][0][RTW89_ACMA][0][107] = 127, + [0][0][1][0][RTW89_CHILE][1][107] = 24, + [0][0][1][0][RTW89_QATAR][1][107] = 127, + [0][0][1][0][RTW89_QATAR][0][107] = 127, + [0][0][1][0][RTW89_UK][1][107] = 127, + [0][0][1][0][RTW89_UK][0][107] = 127, + [0][0][1][0][RTW89_FCC][1][109] = 24, + [0][0][1][0][RTW89_FCC][2][109] = 127, + [0][0][1][0][RTW89_ETSI][1][109] = 127, + [0][0][1][0][RTW89_ETSI][0][109] = 127, + [0][0][1][0][RTW89_MKK][1][109] = 127, + [0][0][1][0][RTW89_MKK][0][109] = 127, + [0][0][1][0][RTW89_IC][1][109] = 24, + [0][0][1][0][RTW89_KCC][1][109] = 32, + [0][0][1][0][RTW89_KCC][0][109] = 127, + [0][0][1][0][RTW89_ACMA][1][109] = 127, + [0][0][1][0][RTW89_ACMA][0][109] = 127, + [0][0][1][0][RTW89_CHILE][1][109] = 24, + [0][0][1][0][RTW89_QATAR][1][109] = 127, + [0][0][1][0][RTW89_QATAR][0][109] = 127, + [0][0][1][0][RTW89_UK][1][109] = 127, + [0][0][1][0][RTW89_UK][0][109] = 127, + [0][0][1][0][RTW89_FCC][1][111] = 127, + [0][0][1][0][RTW89_FCC][2][111] = 127, + [0][0][1][0][RTW89_ETSI][1][111] = 127, + [0][0][1][0][RTW89_ETSI][0][111] = 127, + [0][0][1][0][RTW89_MKK][1][111] = 127, + [0][0][1][0][RTW89_MKK][0][111] = 127, + [0][0][1][0][RTW89_IC][1][111] = 127, + [0][0][1][0][RTW89_KCC][1][111] = 127, + [0][0][1][0][RTW89_KCC][0][111] = 127, + [0][0][1][0][RTW89_ACMA][1][111] = 127, + [0][0][1][0][RTW89_ACMA][0][111] = 127, + [0][0][1][0][RTW89_CHILE][1][111] = 127, + [0][0][1][0][RTW89_QATAR][1][111] = 127, + [0][0][1][0][RTW89_QATAR][0][111] = 127, + [0][0][1][0][RTW89_UK][1][111] = 127, + [0][0][1][0][RTW89_UK][0][111] = 127, + [0][0][1][0][RTW89_FCC][1][113] = 127, + [0][0][1][0][RTW89_FCC][2][113] = 127, + [0][0][1][0][RTW89_ETSI][1][113] = 127, + [0][0][1][0][RTW89_ETSI][0][113] = 127, + [0][0][1][0][RTW89_MKK][1][113] = 127, + [0][0][1][0][RTW89_MKK][0][113] = 127, + [0][0][1][0][RTW89_IC][1][113] = 127, + [0][0][1][0][RTW89_KCC][1][113] = 127, + [0][0][1][0][RTW89_KCC][0][113] = 127, + [0][0][1][0][RTW89_ACMA][1][113] = 127, + [0][0][1][0][RTW89_ACMA][0][113] = 127, + [0][0][1][0][RTW89_CHILE][1][113] = 127, + [0][0][1][0][RTW89_QATAR][1][113] = 127, + [0][0][1][0][RTW89_QATAR][0][113] = 127, + [0][0][1][0][RTW89_UK][1][113] = 127, + [0][0][1][0][RTW89_UK][0][113] = 127, + [0][0][1][0][RTW89_FCC][1][115] = 127, + [0][0][1][0][RTW89_FCC][2][115] = 127, + [0][0][1][0][RTW89_ETSI][1][115] = 127, + [0][0][1][0][RTW89_ETSI][0][115] = 127, + [0][0][1][0][RTW89_MKK][1][115] = 127, + [0][0][1][0][RTW89_MKK][0][115] = 127, + [0][0][1][0][RTW89_IC][1][115] = 127, + [0][0][1][0][RTW89_KCC][1][115] = 127, + [0][0][1][0][RTW89_KCC][0][115] = 127, + [0][0][1][0][RTW89_ACMA][1][115] = 127, + [0][0][1][0][RTW89_ACMA][0][115] = 127, + [0][0][1][0][RTW89_CHILE][1][115] = 127, + [0][0][1][0][RTW89_QATAR][1][115] = 127, + [0][0][1][0][RTW89_QATAR][0][115] = 127, + [0][0][1][0][RTW89_UK][1][115] = 127, + [0][0][1][0][RTW89_UK][0][115] = 127, + [0][0][1][0][RTW89_FCC][1][117] = 127, + [0][0][1][0][RTW89_FCC][2][117] = 127, + [0][0][1][0][RTW89_ETSI][1][117] = 127, + [0][0][1][0][RTW89_ETSI][0][117] = 127, + [0][0][1][0][RTW89_MKK][1][117] = 127, + [0][0][1][0][RTW89_MKK][0][117] = 127, + [0][0][1][0][RTW89_IC][1][117] = 127, + [0][0][1][0][RTW89_KCC][1][117] = 127, + [0][0][1][0][RTW89_KCC][0][117] = 127, + [0][0][1][0][RTW89_ACMA][1][117] = 127, + [0][0][1][0][RTW89_ACMA][0][117] = 127, + [0][0][1][0][RTW89_CHILE][1][117] = 127, + [0][0][1][0][RTW89_QATAR][1][117] = 127, + [0][0][1][0][RTW89_QATAR][0][117] = 127, + [0][0][1][0][RTW89_UK][1][117] = 127, + [0][0][1][0][RTW89_UK][0][117] = 127, + [0][0][1][0][RTW89_FCC][1][119] = 127, + [0][0][1][0][RTW89_FCC][2][119] = 127, + [0][0][1][0][RTW89_ETSI][1][119] = 127, + [0][0][1][0][RTW89_ETSI][0][119] = 127, + [0][0][1][0][RTW89_MKK][1][119] = 127, + [0][0][1][0][RTW89_MKK][0][119] = 127, + [0][0][1][0][RTW89_IC][1][119] = 127, + [0][0][1][0][RTW89_KCC][1][119] = 127, + [0][0][1][0][RTW89_KCC][0][119] = 127, + [0][0][1][0][RTW89_ACMA][1][119] = 127, + [0][0][1][0][RTW89_ACMA][0][119] = 127, + [0][0][1][0][RTW89_CHILE][1][119] = 127, + [0][0][1][0][RTW89_QATAR][1][119] = 127, + [0][0][1][0][RTW89_QATAR][0][119] = 127, + [0][0][1][0][RTW89_UK][1][119] = 127, + [0][0][1][0][RTW89_UK][0][119] = 127, + [0][1][1][0][RTW89_FCC][1][0] = -2, + [0][1][1][0][RTW89_FCC][2][0] = 54, + [0][1][1][0][RTW89_ETSI][1][0] = 54, + [0][1][1][0][RTW89_ETSI][0][0] = 18, + [0][1][1][0][RTW89_MKK][1][0] = 56, + [0][1][1][0][RTW89_MKK][0][0] = 16, + [0][1][1][0][RTW89_IC][1][0] = -2, + [0][1][1][0][RTW89_KCC][1][0] = 12, + [0][1][1][0][RTW89_KCC][0][0] = 10, + [0][1][1][0][RTW89_ACMA][1][0] = 54, + [0][1][1][0][RTW89_ACMA][0][0] = 18, + [0][1][1][0][RTW89_CHILE][1][0] = -2, + [0][1][1][0][RTW89_QATAR][1][0] = 54, + [0][1][1][0][RTW89_QATAR][0][0] = 18, + [0][1][1][0][RTW89_UK][1][0] = 54, + [0][1][1][0][RTW89_UK][0][0] = 18, + [0][1][1][0][RTW89_FCC][1][2] = -4, + [0][1][1][0][RTW89_FCC][2][2] = 54, + [0][1][1][0][RTW89_ETSI][1][2] = 54, + [0][1][1][0][RTW89_ETSI][0][2] = 18, + [0][1][1][0][RTW89_MKK][1][2] = 54, + [0][1][1][0][RTW89_MKK][0][2] = 16, + [0][1][1][0][RTW89_IC][1][2] = -4, + [0][1][1][0][RTW89_KCC][1][2] = 12, + [0][1][1][0][RTW89_KCC][0][2] = 12, + [0][1][1][0][RTW89_ACMA][1][2] = 54, + [0][1][1][0][RTW89_ACMA][0][2] = 18, + [0][1][1][0][RTW89_CHILE][1][2] = -4, + [0][1][1][0][RTW89_QATAR][1][2] = 54, + [0][1][1][0][RTW89_QATAR][0][2] = 18, + [0][1][1][0][RTW89_UK][1][2] = 54, + [0][1][1][0][RTW89_UK][0][2] = 18, + [0][1][1][0][RTW89_FCC][1][4] = -4, + [0][1][1][0][RTW89_FCC][2][4] = 54, + [0][1][1][0][RTW89_ETSI][1][4] = 54, + [0][1][1][0][RTW89_ETSI][0][4] = 18, + [0][1][1][0][RTW89_MKK][1][4] = 54, + [0][1][1][0][RTW89_MKK][0][4] = 16, + [0][1][1][0][RTW89_IC][1][4] = -4, + [0][1][1][0][RTW89_KCC][1][4] = 12, + [0][1][1][0][RTW89_KCC][0][4] = 12, + [0][1][1][0][RTW89_ACMA][1][4] = 54, + [0][1][1][0][RTW89_ACMA][0][4] = 18, + [0][1][1][0][RTW89_CHILE][1][4] = -4, + [0][1][1][0][RTW89_QATAR][1][4] = 54, + [0][1][1][0][RTW89_QATAR][0][4] = 18, + [0][1][1][0][RTW89_UK][1][4] = 54, + [0][1][1][0][RTW89_UK][0][4] = 18, + [0][1][1][0][RTW89_FCC][1][6] = -4, + [0][1][1][0][RTW89_FCC][2][6] = 54, + [0][1][1][0][RTW89_ETSI][1][6] = 54, + [0][1][1][0][RTW89_ETSI][0][6] = 18, + [0][1][1][0][RTW89_MKK][1][6] = 54, + [0][1][1][0][RTW89_MKK][0][6] = 16, + [0][1][1][0][RTW89_IC][1][6] = -4, + [0][1][1][0][RTW89_KCC][1][6] = 12, + [0][1][1][0][RTW89_KCC][0][6] = 12, + [0][1][1][0][RTW89_ACMA][1][6] = 54, + [0][1][1][0][RTW89_ACMA][0][6] = 18, + [0][1][1][0][RTW89_CHILE][1][6] = -4, + [0][1][1][0][RTW89_QATAR][1][6] = 54, + [0][1][1][0][RTW89_QATAR][0][6] = 18, + [0][1][1][0][RTW89_UK][1][6] = 54, + [0][1][1][0][RTW89_UK][0][6] = 18, + [0][1][1][0][RTW89_FCC][1][8] = -4, + [0][1][1][0][RTW89_FCC][2][8] = 54, + [0][1][1][0][RTW89_ETSI][1][8] = 54, + [0][1][1][0][RTW89_ETSI][0][8] = 18, + [0][1][1][0][RTW89_MKK][1][8] = 54, + [0][1][1][0][RTW89_MKK][0][8] = 16, + [0][1][1][0][RTW89_IC][1][8] = -4, + [0][1][1][0][RTW89_KCC][1][8] = 12, + [0][1][1][0][RTW89_KCC][0][8] = 12, + [0][1][1][0][RTW89_ACMA][1][8] = 54, + [0][1][1][0][RTW89_ACMA][0][8] = 18, + [0][1][1][0][RTW89_CHILE][1][8] = -4, + [0][1][1][0][RTW89_QATAR][1][8] = 54, + [0][1][1][0][RTW89_QATAR][0][8] = 18, + [0][1][1][0][RTW89_UK][1][8] = 54, + [0][1][1][0][RTW89_UK][0][8] = 18, + [0][1][1][0][RTW89_FCC][1][10] = -4, + [0][1][1][0][RTW89_FCC][2][10] = 54, + [0][1][1][0][RTW89_ETSI][1][10] = 54, + [0][1][1][0][RTW89_ETSI][0][10] = 18, + [0][1][1][0][RTW89_MKK][1][10] = 54, + [0][1][1][0][RTW89_MKK][0][10] = 16, + [0][1][1][0][RTW89_IC][1][10] = -4, + [0][1][1][0][RTW89_KCC][1][10] = 12, + [0][1][1][0][RTW89_KCC][0][10] = 12, + [0][1][1][0][RTW89_ACMA][1][10] = 54, + [0][1][1][0][RTW89_ACMA][0][10] = 18, + [0][1][1][0][RTW89_CHILE][1][10] = -4, + [0][1][1][0][RTW89_QATAR][1][10] = 54, + [0][1][1][0][RTW89_QATAR][0][10] = 18, + [0][1][1][0][RTW89_UK][1][10] = 54, + [0][1][1][0][RTW89_UK][0][10] = 18, + [0][1][1][0][RTW89_FCC][1][12] = -4, + [0][1][1][0][RTW89_FCC][2][12] = 54, + [0][1][1][0][RTW89_ETSI][1][12] = 54, + [0][1][1][0][RTW89_ETSI][0][12] = 18, + [0][1][1][0][RTW89_MKK][1][12] = 54, + [0][1][1][0][RTW89_MKK][0][12] = 16, + [0][1][1][0][RTW89_IC][1][12] = -4, + [0][1][1][0][RTW89_KCC][1][12] = 12, + [0][1][1][0][RTW89_KCC][0][12] = 12, + [0][1][1][0][RTW89_ACMA][1][12] = 54, + [0][1][1][0][RTW89_ACMA][0][12] = 18, + [0][1][1][0][RTW89_CHILE][1][12] = -4, + [0][1][1][0][RTW89_QATAR][1][12] = 54, + [0][1][1][0][RTW89_QATAR][0][12] = 18, + [0][1][1][0][RTW89_UK][1][12] = 54, + [0][1][1][0][RTW89_UK][0][12] = 18, + [0][1][1][0][RTW89_FCC][1][14] = -4, + [0][1][1][0][RTW89_FCC][2][14] = 54, + [0][1][1][0][RTW89_ETSI][1][14] = 54, + [0][1][1][0][RTW89_ETSI][0][14] = 18, + [0][1][1][0][RTW89_MKK][1][14] = 54, + [0][1][1][0][RTW89_MKK][0][14] = 16, + [0][1][1][0][RTW89_IC][1][14] = -4, + [0][1][1][0][RTW89_KCC][1][14] = 12, + [0][1][1][0][RTW89_KCC][0][14] = 12, + [0][1][1][0][RTW89_ACMA][1][14] = 54, + [0][1][1][0][RTW89_ACMA][0][14] = 18, + [0][1][1][0][RTW89_CHILE][1][14] = -4, + [0][1][1][0][RTW89_QATAR][1][14] = 54, + [0][1][1][0][RTW89_QATAR][0][14] = 18, + [0][1][1][0][RTW89_UK][1][14] = 54, + [0][1][1][0][RTW89_UK][0][14] = 18, + [0][1][1][0][RTW89_FCC][1][15] = -4, + [0][1][1][0][RTW89_FCC][2][15] = 54, + [0][1][1][0][RTW89_ETSI][1][15] = 54, + [0][1][1][0][RTW89_ETSI][0][15] = 18, + [0][1][1][0][RTW89_MKK][1][15] = 54, + [0][1][1][0][RTW89_MKK][0][15] = 16, + [0][1][1][0][RTW89_IC][1][15] = -4, + [0][1][1][0][RTW89_KCC][1][15] = 12, + [0][1][1][0][RTW89_KCC][0][15] = 12, + [0][1][1][0][RTW89_ACMA][1][15] = 54, + [0][1][1][0][RTW89_ACMA][0][15] = 18, + [0][1][1][0][RTW89_CHILE][1][15] = -4, + [0][1][1][0][RTW89_QATAR][1][15] = 54, + [0][1][1][0][RTW89_QATAR][0][15] = 18, + [0][1][1][0][RTW89_UK][1][15] = 54, + [0][1][1][0][RTW89_UK][0][15] = 18, + [0][1][1][0][RTW89_FCC][1][17] = -4, + [0][1][1][0][RTW89_FCC][2][17] = 54, + [0][1][1][0][RTW89_ETSI][1][17] = 54, + [0][1][1][0][RTW89_ETSI][0][17] = 18, + [0][1][1][0][RTW89_MKK][1][17] = 54, + [0][1][1][0][RTW89_MKK][0][17] = 16, + [0][1][1][0][RTW89_IC][1][17] = -4, + [0][1][1][0][RTW89_KCC][1][17] = 12, + [0][1][1][0][RTW89_KCC][0][17] = 12, + [0][1][1][0][RTW89_ACMA][1][17] = 54, + [0][1][1][0][RTW89_ACMA][0][17] = 18, + [0][1][1][0][RTW89_CHILE][1][17] = -4, + [0][1][1][0][RTW89_QATAR][1][17] = 54, + [0][1][1][0][RTW89_QATAR][0][17] = 18, + [0][1][1][0][RTW89_UK][1][17] = 54, + [0][1][1][0][RTW89_UK][0][17] = 18, + [0][1][1][0][RTW89_FCC][1][19] = -4, + [0][1][1][0][RTW89_FCC][2][19] = 54, + [0][1][1][0][RTW89_ETSI][1][19] = 54, + [0][1][1][0][RTW89_ETSI][0][19] = 18, + [0][1][1][0][RTW89_MKK][1][19] = 54, + [0][1][1][0][RTW89_MKK][0][19] = 16, + [0][1][1][0][RTW89_IC][1][19] = -4, + [0][1][1][0][RTW89_KCC][1][19] = 12, + [0][1][1][0][RTW89_KCC][0][19] = 12, + [0][1][1][0][RTW89_ACMA][1][19] = 54, + [0][1][1][0][RTW89_ACMA][0][19] = 18, + [0][1][1][0][RTW89_CHILE][1][19] = -4, + [0][1][1][0][RTW89_QATAR][1][19] = 54, + [0][1][1][0][RTW89_QATAR][0][19] = 18, + [0][1][1][0][RTW89_UK][1][19] = 54, + [0][1][1][0][RTW89_UK][0][19] = 18, + [0][1][1][0][RTW89_FCC][1][21] = -4, + [0][1][1][0][RTW89_FCC][2][21] = 54, + [0][1][1][0][RTW89_ETSI][1][21] = 54, + [0][1][1][0][RTW89_ETSI][0][21] = 18, + [0][1][1][0][RTW89_MKK][1][21] = 54, + [0][1][1][0][RTW89_MKK][0][21] = 16, + [0][1][1][0][RTW89_IC][1][21] = -4, + [0][1][1][0][RTW89_KCC][1][21] = 12, + [0][1][1][0][RTW89_KCC][0][21] = 12, + [0][1][1][0][RTW89_ACMA][1][21] = 54, + [0][1][1][0][RTW89_ACMA][0][21] = 18, + [0][1][1][0][RTW89_CHILE][1][21] = -4, + [0][1][1][0][RTW89_QATAR][1][21] = 54, + [0][1][1][0][RTW89_QATAR][0][21] = 18, + [0][1][1][0][RTW89_UK][1][21] = 54, + [0][1][1][0][RTW89_UK][0][21] = 18, + [0][1][1][0][RTW89_FCC][1][23] = -4, + [0][1][1][0][RTW89_FCC][2][23] = 68, + [0][1][1][0][RTW89_ETSI][1][23] = 54, + [0][1][1][0][RTW89_ETSI][0][23] = 18, + [0][1][1][0][RTW89_MKK][1][23] = 54, + [0][1][1][0][RTW89_MKK][0][23] = 16, + [0][1][1][0][RTW89_IC][1][23] = -4, + [0][1][1][0][RTW89_KCC][1][23] = 12, + [0][1][1][0][RTW89_KCC][0][23] = 10, + [0][1][1][0][RTW89_ACMA][1][23] = 54, + [0][1][1][0][RTW89_ACMA][0][23] = 18, + [0][1][1][0][RTW89_CHILE][1][23] = -4, + [0][1][1][0][RTW89_QATAR][1][23] = 54, + [0][1][1][0][RTW89_QATAR][0][23] = 18, + [0][1][1][0][RTW89_UK][1][23] = 54, + [0][1][1][0][RTW89_UK][0][23] = 18, + [0][1][1][0][RTW89_FCC][1][25] = -4, + [0][1][1][0][RTW89_FCC][2][25] = 68, + [0][1][1][0][RTW89_ETSI][1][25] = 54, + [0][1][1][0][RTW89_ETSI][0][25] = 18, + [0][1][1][0][RTW89_MKK][1][25] = 54, + [0][1][1][0][RTW89_MKK][0][25] = 16, + [0][1][1][0][RTW89_IC][1][25] = -4, + [0][1][1][0][RTW89_KCC][1][25] = 12, + [0][1][1][0][RTW89_KCC][0][25] = 14, + [0][1][1][0][RTW89_ACMA][1][25] = 54, + [0][1][1][0][RTW89_ACMA][0][25] = 18, + [0][1][1][0][RTW89_CHILE][1][25] = -4, + [0][1][1][0][RTW89_QATAR][1][25] = 54, + [0][1][1][0][RTW89_QATAR][0][25] = 18, + [0][1][1][0][RTW89_UK][1][25] = 54, + [0][1][1][0][RTW89_UK][0][25] = 18, + [0][1][1][0][RTW89_FCC][1][27] = -4, + [0][1][1][0][RTW89_FCC][2][27] = 68, + [0][1][1][0][RTW89_ETSI][1][27] = 54, + [0][1][1][0][RTW89_ETSI][0][27] = 18, + [0][1][1][0][RTW89_MKK][1][27] = 54, + [0][1][1][0][RTW89_MKK][0][27] = 16, + [0][1][1][0][RTW89_IC][1][27] = -4, + [0][1][1][0][RTW89_KCC][1][27] = 12, + [0][1][1][0][RTW89_KCC][0][27] = 14, + [0][1][1][0][RTW89_ACMA][1][27] = 54, + [0][1][1][0][RTW89_ACMA][0][27] = 18, + [0][1][1][0][RTW89_CHILE][1][27] = -4, + [0][1][1][0][RTW89_QATAR][1][27] = 54, + [0][1][1][0][RTW89_QATAR][0][27] = 18, + [0][1][1][0][RTW89_UK][1][27] = 54, + [0][1][1][0][RTW89_UK][0][27] = 18, + [0][1][1][0][RTW89_FCC][1][29] = -4, + [0][1][1][0][RTW89_FCC][2][29] = 68, + [0][1][1][0][RTW89_ETSI][1][29] = 54, + [0][1][1][0][RTW89_ETSI][0][29] = 18, + [0][1][1][0][RTW89_MKK][1][29] = 54, + [0][1][1][0][RTW89_MKK][0][29] = 16, + [0][1][1][0][RTW89_IC][1][29] = -4, + [0][1][1][0][RTW89_KCC][1][29] = 12, + [0][1][1][0][RTW89_KCC][0][29] = 14, + [0][1][1][0][RTW89_ACMA][1][29] = 54, + [0][1][1][0][RTW89_ACMA][0][29] = 18, + [0][1][1][0][RTW89_CHILE][1][29] = -4, + [0][1][1][0][RTW89_QATAR][1][29] = 54, + [0][1][1][0][RTW89_QATAR][0][29] = 18, + [0][1][1][0][RTW89_UK][1][29] = 54, + [0][1][1][0][RTW89_UK][0][29] = 18, + [0][1][1][0][RTW89_FCC][1][30] = -4, + [0][1][1][0][RTW89_FCC][2][30] = 68, + [0][1][1][0][RTW89_ETSI][1][30] = 54, + [0][1][1][0][RTW89_ETSI][0][30] = 18, + [0][1][1][0][RTW89_MKK][1][30] = 54, + [0][1][1][0][RTW89_MKK][0][30] = 16, + [0][1][1][0][RTW89_IC][1][30] = -4, + [0][1][1][0][RTW89_KCC][1][30] = 12, + [0][1][1][0][RTW89_KCC][0][30] = 14, + [0][1][1][0][RTW89_ACMA][1][30] = 54, + [0][1][1][0][RTW89_ACMA][0][30] = 18, + [0][1][1][0][RTW89_CHILE][1][30] = -4, + [0][1][1][0][RTW89_QATAR][1][30] = 54, + [0][1][1][0][RTW89_QATAR][0][30] = 18, + [0][1][1][0][RTW89_UK][1][30] = 54, + [0][1][1][0][RTW89_UK][0][30] = 18, + [0][1][1][0][RTW89_FCC][1][32] = -4, + [0][1][1][0][RTW89_FCC][2][32] = 68, + [0][1][1][0][RTW89_ETSI][1][32] = 54, + [0][1][1][0][RTW89_ETSI][0][32] = 18, + [0][1][1][0][RTW89_MKK][1][32] = 54, + [0][1][1][0][RTW89_MKK][0][32] = 16, + [0][1][1][0][RTW89_IC][1][32] = -4, + [0][1][1][0][RTW89_KCC][1][32] = 12, + [0][1][1][0][RTW89_KCC][0][32] = 14, + [0][1][1][0][RTW89_ACMA][1][32] = 54, + [0][1][1][0][RTW89_ACMA][0][32] = 18, + [0][1][1][0][RTW89_CHILE][1][32] = -4, + [0][1][1][0][RTW89_QATAR][1][32] = 54, + [0][1][1][0][RTW89_QATAR][0][32] = 18, + [0][1][1][0][RTW89_UK][1][32] = 54, + [0][1][1][0][RTW89_UK][0][32] = 18, + [0][1][1][0][RTW89_FCC][1][34] = -4, + [0][1][1][0][RTW89_FCC][2][34] = 68, + [0][1][1][0][RTW89_ETSI][1][34] = 54, + [0][1][1][0][RTW89_ETSI][0][34] = 18, + [0][1][1][0][RTW89_MKK][1][34] = 54, + [0][1][1][0][RTW89_MKK][0][34] = 16, + [0][1][1][0][RTW89_IC][1][34] = -4, + [0][1][1][0][RTW89_KCC][1][34] = 12, + [0][1][1][0][RTW89_KCC][0][34] = 14, + [0][1][1][0][RTW89_ACMA][1][34] = 54, + [0][1][1][0][RTW89_ACMA][0][34] = 18, + [0][1][1][0][RTW89_CHILE][1][34] = -4, + [0][1][1][0][RTW89_QATAR][1][34] = 54, + [0][1][1][0][RTW89_QATAR][0][34] = 18, + [0][1][1][0][RTW89_UK][1][34] = 54, + [0][1][1][0][RTW89_UK][0][34] = 18, + [0][1][1][0][RTW89_FCC][1][36] = -4, + [0][1][1][0][RTW89_FCC][2][36] = 68, + [0][1][1][0][RTW89_ETSI][1][36] = 54, + [0][1][1][0][RTW89_ETSI][0][36] = 18, + [0][1][1][0][RTW89_MKK][1][36] = 54, + [0][1][1][0][RTW89_MKK][0][36] = 16, + [0][1][1][0][RTW89_IC][1][36] = -4, + [0][1][1][0][RTW89_KCC][1][36] = 12, + [0][1][1][0][RTW89_KCC][0][36] = 14, + [0][1][1][0][RTW89_ACMA][1][36] = 54, + [0][1][1][0][RTW89_ACMA][0][36] = 18, + [0][1][1][0][RTW89_CHILE][1][36] = -4, + [0][1][1][0][RTW89_QATAR][1][36] = 54, + [0][1][1][0][RTW89_QATAR][0][36] = 18, + [0][1][1][0][RTW89_UK][1][36] = 54, + [0][1][1][0][RTW89_UK][0][36] = 18, + [0][1][1][0][RTW89_FCC][1][38] = -4, + [0][1][1][0][RTW89_FCC][2][38] = 68, + [0][1][1][0][RTW89_ETSI][1][38] = 54, + [0][1][1][0][RTW89_ETSI][0][38] = 18, + [0][1][1][0][RTW89_MKK][1][38] = 54, + [0][1][1][0][RTW89_MKK][0][38] = 16, + [0][1][1][0][RTW89_IC][1][38] = -4, + [0][1][1][0][RTW89_KCC][1][38] = 12, + [0][1][1][0][RTW89_KCC][0][38] = 14, + [0][1][1][0][RTW89_ACMA][1][38] = 54, + [0][1][1][0][RTW89_ACMA][0][38] = 18, + [0][1][1][0][RTW89_CHILE][1][38] = -4, + [0][1][1][0][RTW89_QATAR][1][38] = 54, + [0][1][1][0][RTW89_QATAR][0][38] = 18, + [0][1][1][0][RTW89_UK][1][38] = 54, + [0][1][1][0][RTW89_UK][0][38] = 18, + [0][1][1][0][RTW89_FCC][1][40] = -4, + [0][1][1][0][RTW89_FCC][2][40] = 68, + [0][1][1][0][RTW89_ETSI][1][40] = 54, + [0][1][1][0][RTW89_ETSI][0][40] = 18, + [0][1][1][0][RTW89_MKK][1][40] = 54, + [0][1][1][0][RTW89_MKK][0][40] = 16, + [0][1][1][0][RTW89_IC][1][40] = -4, + [0][1][1][0][RTW89_KCC][1][40] = 12, + [0][1][1][0][RTW89_KCC][0][40] = 14, + [0][1][1][0][RTW89_ACMA][1][40] = 54, + [0][1][1][0][RTW89_ACMA][0][40] = 18, + [0][1][1][0][RTW89_CHILE][1][40] = -4, + [0][1][1][0][RTW89_QATAR][1][40] = 54, + [0][1][1][0][RTW89_QATAR][0][40] = 18, + [0][1][1][0][RTW89_UK][1][40] = 54, + [0][1][1][0][RTW89_UK][0][40] = 18, + [0][1][1][0][RTW89_FCC][1][42] = -4, + [0][1][1][0][RTW89_FCC][2][42] = 68, + [0][1][1][0][RTW89_ETSI][1][42] = 54, + [0][1][1][0][RTW89_ETSI][0][42] = 18, + [0][1][1][0][RTW89_MKK][1][42] = 54, + [0][1][1][0][RTW89_MKK][0][42] = 16, + [0][1][1][0][RTW89_IC][1][42] = -4, + [0][1][1][0][RTW89_KCC][1][42] = 12, + [0][1][1][0][RTW89_KCC][0][42] = 14, + [0][1][1][0][RTW89_ACMA][1][42] = 54, + [0][1][1][0][RTW89_ACMA][0][42] = 18, + [0][1][1][0][RTW89_CHILE][1][42] = -4, + [0][1][1][0][RTW89_QATAR][1][42] = 54, + [0][1][1][0][RTW89_QATAR][0][42] = 18, + [0][1][1][0][RTW89_UK][1][42] = 54, + [0][1][1][0][RTW89_UK][0][42] = 18, + [0][1][1][0][RTW89_FCC][1][44] = -2, + [0][1][1][0][RTW89_FCC][2][44] = 68, + [0][1][1][0][RTW89_ETSI][1][44] = 54, + [0][1][1][0][RTW89_ETSI][0][44] = 18, + [0][1][1][0][RTW89_MKK][1][44] = 34, + [0][1][1][0][RTW89_MKK][0][44] = 16, + [0][1][1][0][RTW89_IC][1][44] = -2, + [0][1][1][0][RTW89_KCC][1][44] = 12, + [0][1][1][0][RTW89_KCC][0][44] = 12, + [0][1][1][0][RTW89_ACMA][1][44] = 54, + [0][1][1][0][RTW89_ACMA][0][44] = 18, + [0][1][1][0][RTW89_CHILE][1][44] = -2, + [0][1][1][0][RTW89_QATAR][1][44] = 54, + [0][1][1][0][RTW89_QATAR][0][44] = 18, + [0][1][1][0][RTW89_UK][1][44] = 54, + [0][1][1][0][RTW89_UK][0][44] = 18, + [0][1][1][0][RTW89_FCC][1][45] = -2, + [0][1][1][0][RTW89_FCC][2][45] = 127, + [0][1][1][0][RTW89_ETSI][1][45] = 127, + [0][1][1][0][RTW89_ETSI][0][45] = 127, + [0][1][1][0][RTW89_MKK][1][45] = 127, + [0][1][1][0][RTW89_MKK][0][45] = 127, + [0][1][1][0][RTW89_IC][1][45] = -2, + [0][1][1][0][RTW89_KCC][1][45] = 12, + [0][1][1][0][RTW89_KCC][0][45] = 127, + [0][1][1][0][RTW89_ACMA][1][45] = 127, + [0][1][1][0][RTW89_ACMA][0][45] = 127, + [0][1][1][0][RTW89_CHILE][1][45] = -2, + [0][1][1][0][RTW89_QATAR][1][45] = 127, + [0][1][1][0][RTW89_QATAR][0][45] = 127, + [0][1][1][0][RTW89_UK][1][45] = 127, + [0][1][1][0][RTW89_UK][0][45] = 127, + [0][1][1][0][RTW89_FCC][1][47] = -2, + [0][1][1][0][RTW89_FCC][2][47] = 127, + [0][1][1][0][RTW89_ETSI][1][47] = 127, + [0][1][1][0][RTW89_ETSI][0][47] = 127, + [0][1][1][0][RTW89_MKK][1][47] = 127, + [0][1][1][0][RTW89_MKK][0][47] = 127, + [0][1][1][0][RTW89_IC][1][47] = -2, + [0][1][1][0][RTW89_KCC][1][47] = 12, + [0][1][1][0][RTW89_KCC][0][47] = 127, + [0][1][1][0][RTW89_ACMA][1][47] = 127, + [0][1][1][0][RTW89_ACMA][0][47] = 127, + [0][1][1][0][RTW89_CHILE][1][47] = -2, + [0][1][1][0][RTW89_QATAR][1][47] = 127, + [0][1][1][0][RTW89_QATAR][0][47] = 127, + [0][1][1][0][RTW89_UK][1][47] = 127, + [0][1][1][0][RTW89_UK][0][47] = 127, + [0][1][1][0][RTW89_FCC][1][49] = -2, + [0][1][1][0][RTW89_FCC][2][49] = 127, + [0][1][1][0][RTW89_ETSI][1][49] = 127, + [0][1][1][0][RTW89_ETSI][0][49] = 127, + [0][1][1][0][RTW89_MKK][1][49] = 127, + [0][1][1][0][RTW89_MKK][0][49] = 127, + [0][1][1][0][RTW89_IC][1][49] = -2, + [0][1][1][0][RTW89_KCC][1][49] = 12, + [0][1][1][0][RTW89_KCC][0][49] = 127, + [0][1][1][0][RTW89_ACMA][1][49] = 127, + [0][1][1][0][RTW89_ACMA][0][49] = 127, + [0][1][1][0][RTW89_CHILE][1][49] = -2, + [0][1][1][0][RTW89_QATAR][1][49] = 127, + [0][1][1][0][RTW89_QATAR][0][49] = 127, + [0][1][1][0][RTW89_UK][1][49] = 127, + [0][1][1][0][RTW89_UK][0][49] = 127, + [0][1][1][0][RTW89_FCC][1][51] = -2, + [0][1][1][0][RTW89_FCC][2][51] = 127, + [0][1][1][0][RTW89_ETSI][1][51] = 127, + [0][1][1][0][RTW89_ETSI][0][51] = 127, + [0][1][1][0][RTW89_MKK][1][51] = 127, + [0][1][1][0][RTW89_MKK][0][51] = 127, + [0][1][1][0][RTW89_IC][1][51] = -2, + [0][1][1][0][RTW89_KCC][1][51] = 12, + [0][1][1][0][RTW89_KCC][0][51] = 127, + [0][1][1][0][RTW89_ACMA][1][51] = 127, + [0][1][1][0][RTW89_ACMA][0][51] = 127, + [0][1][1][0][RTW89_CHILE][1][51] = -2, + [0][1][1][0][RTW89_QATAR][1][51] = 127, + [0][1][1][0][RTW89_QATAR][0][51] = 127, + [0][1][1][0][RTW89_UK][1][51] = 127, + [0][1][1][0][RTW89_UK][0][51] = 127, + [0][1][1][0][RTW89_FCC][1][53] = -2, + [0][1][1][0][RTW89_FCC][2][53] = 127, + [0][1][1][0][RTW89_ETSI][1][53] = 127, + [0][1][1][0][RTW89_ETSI][0][53] = 127, + [0][1][1][0][RTW89_MKK][1][53] = 127, + [0][1][1][0][RTW89_MKK][0][53] = 127, + [0][1][1][0][RTW89_IC][1][53] = -2, + [0][1][1][0][RTW89_KCC][1][53] = 12, + [0][1][1][0][RTW89_KCC][0][53] = 127, + [0][1][1][0][RTW89_ACMA][1][53] = 127, + [0][1][1][0][RTW89_ACMA][0][53] = 127, + [0][1][1][0][RTW89_CHILE][1][53] = -2, + [0][1][1][0][RTW89_QATAR][1][53] = 127, + [0][1][1][0][RTW89_QATAR][0][53] = 127, + [0][1][1][0][RTW89_UK][1][53] = 127, + [0][1][1][0][RTW89_UK][0][53] = 127, + [0][1][1][0][RTW89_FCC][1][55] = -2, + [0][1][1][0][RTW89_FCC][2][55] = 68, + [0][1][1][0][RTW89_ETSI][1][55] = 127, + [0][1][1][0][RTW89_ETSI][0][55] = 127, + [0][1][1][0][RTW89_MKK][1][55] = 127, + [0][1][1][0][RTW89_MKK][0][55] = 127, + [0][1][1][0][RTW89_IC][1][55] = -2, + [0][1][1][0][RTW89_KCC][1][55] = 12, + [0][1][1][0][RTW89_KCC][0][55] = 127, + [0][1][1][0][RTW89_ACMA][1][55] = 127, + [0][1][1][0][RTW89_ACMA][0][55] = 127, + [0][1][1][0][RTW89_CHILE][1][55] = -2, + [0][1][1][0][RTW89_QATAR][1][55] = 127, + [0][1][1][0][RTW89_QATAR][0][55] = 127, + [0][1][1][0][RTW89_UK][1][55] = 127, + [0][1][1][0][RTW89_UK][0][55] = 127, + [0][1][1][0][RTW89_FCC][1][57] = -2, + [0][1][1][0][RTW89_FCC][2][57] = 68, + [0][1][1][0][RTW89_ETSI][1][57] = 127, + [0][1][1][0][RTW89_ETSI][0][57] = 127, + [0][1][1][0][RTW89_MKK][1][57] = 127, + [0][1][1][0][RTW89_MKK][0][57] = 127, + [0][1][1][0][RTW89_IC][1][57] = -2, + [0][1][1][0][RTW89_KCC][1][57] = 12, + [0][1][1][0][RTW89_KCC][0][57] = 127, + [0][1][1][0][RTW89_ACMA][1][57] = 127, + [0][1][1][0][RTW89_ACMA][0][57] = 127, + [0][1][1][0][RTW89_CHILE][1][57] = -2, + [0][1][1][0][RTW89_QATAR][1][57] = 127, + [0][1][1][0][RTW89_QATAR][0][57] = 127, + [0][1][1][0][RTW89_UK][1][57] = 127, + [0][1][1][0][RTW89_UK][0][57] = 127, + [0][1][1][0][RTW89_FCC][1][59] = -2, + [0][1][1][0][RTW89_FCC][2][59] = 68, + [0][1][1][0][RTW89_ETSI][1][59] = 127, + [0][1][1][0][RTW89_ETSI][0][59] = 127, + [0][1][1][0][RTW89_MKK][1][59] = 127, + [0][1][1][0][RTW89_MKK][0][59] = 127, + [0][1][1][0][RTW89_IC][1][59] = -2, + [0][1][1][0][RTW89_KCC][1][59] = 12, + [0][1][1][0][RTW89_KCC][0][59] = 127, + [0][1][1][0][RTW89_ACMA][1][59] = 127, + [0][1][1][0][RTW89_ACMA][0][59] = 127, + [0][1][1][0][RTW89_CHILE][1][59] = -2, + [0][1][1][0][RTW89_QATAR][1][59] = 127, + [0][1][1][0][RTW89_QATAR][0][59] = 127, + [0][1][1][0][RTW89_UK][1][59] = 127, + [0][1][1][0][RTW89_UK][0][59] = 127, + [0][1][1][0][RTW89_FCC][1][60] = -2, + [0][1][1][0][RTW89_FCC][2][60] = 68, + [0][1][1][0][RTW89_ETSI][1][60] = 127, + [0][1][1][0][RTW89_ETSI][0][60] = 127, + [0][1][1][0][RTW89_MKK][1][60] = 127, + [0][1][1][0][RTW89_MKK][0][60] = 127, + [0][1][1][0][RTW89_IC][1][60] = -2, + [0][1][1][0][RTW89_KCC][1][60] = 12, + [0][1][1][0][RTW89_KCC][0][60] = 127, + [0][1][1][0][RTW89_ACMA][1][60] = 127, + [0][1][1][0][RTW89_ACMA][0][60] = 127, + [0][1][1][0][RTW89_CHILE][1][60] = -2, + [0][1][1][0][RTW89_QATAR][1][60] = 127, + [0][1][1][0][RTW89_QATAR][0][60] = 127, + [0][1][1][0][RTW89_UK][1][60] = 127, + [0][1][1][0][RTW89_UK][0][60] = 127, + [0][1][1][0][RTW89_FCC][1][62] = -2, + [0][1][1][0][RTW89_FCC][2][62] = 68, + [0][1][1][0][RTW89_ETSI][1][62] = 127, + [0][1][1][0][RTW89_ETSI][0][62] = 127, + [0][1][1][0][RTW89_MKK][1][62] = 127, + [0][1][1][0][RTW89_MKK][0][62] = 127, + [0][1][1][0][RTW89_IC][1][62] = -2, + [0][1][1][0][RTW89_KCC][1][62] = 12, + [0][1][1][0][RTW89_KCC][0][62] = 127, + [0][1][1][0][RTW89_ACMA][1][62] = 127, + [0][1][1][0][RTW89_ACMA][0][62] = 127, + [0][1][1][0][RTW89_CHILE][1][62] = -2, + [0][1][1][0][RTW89_QATAR][1][62] = 127, + [0][1][1][0][RTW89_QATAR][0][62] = 127, + [0][1][1][0][RTW89_UK][1][62] = 127, + [0][1][1][0][RTW89_UK][0][62] = 127, + [0][1][1][0][RTW89_FCC][1][64] = -2, + [0][1][1][0][RTW89_FCC][2][64] = 68, + [0][1][1][0][RTW89_ETSI][1][64] = 127, + [0][1][1][0][RTW89_ETSI][0][64] = 127, + [0][1][1][0][RTW89_MKK][1][64] = 127, + [0][1][1][0][RTW89_MKK][0][64] = 127, + [0][1][1][0][RTW89_IC][1][64] = -2, + [0][1][1][0][RTW89_KCC][1][64] = 12, + [0][1][1][0][RTW89_KCC][0][64] = 127, + [0][1][1][0][RTW89_ACMA][1][64] = 127, + [0][1][1][0][RTW89_ACMA][0][64] = 127, + [0][1][1][0][RTW89_CHILE][1][64] = -2, + [0][1][1][0][RTW89_QATAR][1][64] = 127, + [0][1][1][0][RTW89_QATAR][0][64] = 127, + [0][1][1][0][RTW89_UK][1][64] = 127, + [0][1][1][0][RTW89_UK][0][64] = 127, + [0][1][1][0][RTW89_FCC][1][66] = -2, + [0][1][1][0][RTW89_FCC][2][66] = 68, + [0][1][1][0][RTW89_ETSI][1][66] = 127, + [0][1][1][0][RTW89_ETSI][0][66] = 127, + [0][1][1][0][RTW89_MKK][1][66] = 127, + [0][1][1][0][RTW89_MKK][0][66] = 127, + [0][1][1][0][RTW89_IC][1][66] = -2, + [0][1][1][0][RTW89_KCC][1][66] = 12, + [0][1][1][0][RTW89_KCC][0][66] = 127, + [0][1][1][0][RTW89_ACMA][1][66] = 127, + [0][1][1][0][RTW89_ACMA][0][66] = 127, + [0][1][1][0][RTW89_CHILE][1][66] = -2, + [0][1][1][0][RTW89_QATAR][1][66] = 127, + [0][1][1][0][RTW89_QATAR][0][66] = 127, + [0][1][1][0][RTW89_UK][1][66] = 127, + [0][1][1][0][RTW89_UK][0][66] = 127, + [0][1][1][0][RTW89_FCC][1][68] = -2, + [0][1][1][0][RTW89_FCC][2][68] = 68, + [0][1][1][0][RTW89_ETSI][1][68] = 127, + [0][1][1][0][RTW89_ETSI][0][68] = 127, + [0][1][1][0][RTW89_MKK][1][68] = 127, + [0][1][1][0][RTW89_MKK][0][68] = 127, + [0][1][1][0][RTW89_IC][1][68] = -2, + [0][1][1][0][RTW89_KCC][1][68] = 12, + [0][1][1][0][RTW89_KCC][0][68] = 127, + [0][1][1][0][RTW89_ACMA][1][68] = 127, + [0][1][1][0][RTW89_ACMA][0][68] = 127, + [0][1][1][0][RTW89_CHILE][1][68] = -2, + [0][1][1][0][RTW89_QATAR][1][68] = 127, + [0][1][1][0][RTW89_QATAR][0][68] = 127, + [0][1][1][0][RTW89_UK][1][68] = 127, + [0][1][1][0][RTW89_UK][0][68] = 127, + [0][1][1][0][RTW89_FCC][1][70] = -2, + [0][1][1][0][RTW89_FCC][2][70] = 68, + [0][1][1][0][RTW89_ETSI][1][70] = 127, + [0][1][1][0][RTW89_ETSI][0][70] = 127, + [0][1][1][0][RTW89_MKK][1][70] = 127, + [0][1][1][0][RTW89_MKK][0][70] = 127, + [0][1][1][0][RTW89_IC][1][70] = -2, + [0][1][1][0][RTW89_KCC][1][70] = 12, + [0][1][1][0][RTW89_KCC][0][70] = 127, + [0][1][1][0][RTW89_ACMA][1][70] = 127, + [0][1][1][0][RTW89_ACMA][0][70] = 127, + [0][1][1][0][RTW89_CHILE][1][70] = -2, + [0][1][1][0][RTW89_QATAR][1][70] = 127, + [0][1][1][0][RTW89_QATAR][0][70] = 127, + [0][1][1][0][RTW89_UK][1][70] = 127, + [0][1][1][0][RTW89_UK][0][70] = 127, + [0][1][1][0][RTW89_FCC][1][72] = -2, + [0][1][1][0][RTW89_FCC][2][72] = 68, + [0][1][1][0][RTW89_ETSI][1][72] = 127, + [0][1][1][0][RTW89_ETSI][0][72] = 127, + [0][1][1][0][RTW89_MKK][1][72] = 127, + [0][1][1][0][RTW89_MKK][0][72] = 127, + [0][1][1][0][RTW89_IC][1][72] = -2, + [0][1][1][0][RTW89_KCC][1][72] = 12, + [0][1][1][0][RTW89_KCC][0][72] = 127, + [0][1][1][0][RTW89_ACMA][1][72] = 127, + [0][1][1][0][RTW89_ACMA][0][72] = 127, + [0][1][1][0][RTW89_CHILE][1][72] = -2, + [0][1][1][0][RTW89_QATAR][1][72] = 127, + [0][1][1][0][RTW89_QATAR][0][72] = 127, + [0][1][1][0][RTW89_UK][1][72] = 127, + [0][1][1][0][RTW89_UK][0][72] = 127, + [0][1][1][0][RTW89_FCC][1][74] = -2, + [0][1][1][0][RTW89_FCC][2][74] = 68, + [0][1][1][0][RTW89_ETSI][1][74] = 127, + [0][1][1][0][RTW89_ETSI][0][74] = 127, + [0][1][1][0][RTW89_MKK][1][74] = 127, + [0][1][1][0][RTW89_MKK][0][74] = 127, + [0][1][1][0][RTW89_IC][1][74] = -2, + [0][1][1][0][RTW89_KCC][1][74] = 12, + [0][1][1][0][RTW89_KCC][0][74] = 127, + [0][1][1][0][RTW89_ACMA][1][74] = 127, + [0][1][1][0][RTW89_ACMA][0][74] = 127, + [0][1][1][0][RTW89_CHILE][1][74] = -2, + [0][1][1][0][RTW89_QATAR][1][74] = 127, + [0][1][1][0][RTW89_QATAR][0][74] = 127, + [0][1][1][0][RTW89_UK][1][74] = 127, + [0][1][1][0][RTW89_UK][0][74] = 127, + [0][1][1][0][RTW89_FCC][1][75] = -2, + [0][1][1][0][RTW89_FCC][2][75] = 68, + [0][1][1][0][RTW89_ETSI][1][75] = 127, + [0][1][1][0][RTW89_ETSI][0][75] = 127, + [0][1][1][0][RTW89_MKK][1][75] = 127, + [0][1][1][0][RTW89_MKK][0][75] = 127, + [0][1][1][0][RTW89_IC][1][75] = -2, + [0][1][1][0][RTW89_KCC][1][75] = 12, + [0][1][1][0][RTW89_KCC][0][75] = 127, + [0][1][1][0][RTW89_ACMA][1][75] = 127, + [0][1][1][0][RTW89_ACMA][0][75] = 127, + [0][1][1][0][RTW89_CHILE][1][75] = -2, + [0][1][1][0][RTW89_QATAR][1][75] = 127, + [0][1][1][0][RTW89_QATAR][0][75] = 127, + [0][1][1][0][RTW89_UK][1][75] = 127, + [0][1][1][0][RTW89_UK][0][75] = 127, + [0][1][1][0][RTW89_FCC][1][77] = -2, + [0][1][1][0][RTW89_FCC][2][77] = 68, + [0][1][1][0][RTW89_ETSI][1][77] = 127, + [0][1][1][0][RTW89_ETSI][0][77] = 127, + [0][1][1][0][RTW89_MKK][1][77] = 127, + [0][1][1][0][RTW89_MKK][0][77] = 127, + [0][1][1][0][RTW89_IC][1][77] = -2, + [0][1][1][0][RTW89_KCC][1][77] = 12, + [0][1][1][0][RTW89_KCC][0][77] = 127, + [0][1][1][0][RTW89_ACMA][1][77] = 127, + [0][1][1][0][RTW89_ACMA][0][77] = 127, + [0][1][1][0][RTW89_CHILE][1][77] = -2, + [0][1][1][0][RTW89_QATAR][1][77] = 127, + [0][1][1][0][RTW89_QATAR][0][77] = 127, + [0][1][1][0][RTW89_UK][1][77] = 127, + [0][1][1][0][RTW89_UK][0][77] = 127, + [0][1][1][0][RTW89_FCC][1][79] = -2, + [0][1][1][0][RTW89_FCC][2][79] = 68, + [0][1][1][0][RTW89_ETSI][1][79] = 127, + [0][1][1][0][RTW89_ETSI][0][79] = 127, + [0][1][1][0][RTW89_MKK][1][79] = 127, + [0][1][1][0][RTW89_MKK][0][79] = 127, + [0][1][1][0][RTW89_IC][1][79] = -2, + [0][1][1][0][RTW89_KCC][1][79] = 12, + [0][1][1][0][RTW89_KCC][0][79] = 127, + [0][1][1][0][RTW89_ACMA][1][79] = 127, + [0][1][1][0][RTW89_ACMA][0][79] = 127, + [0][1][1][0][RTW89_CHILE][1][79] = -2, + [0][1][1][0][RTW89_QATAR][1][79] = 127, + [0][1][1][0][RTW89_QATAR][0][79] = 127, + [0][1][1][0][RTW89_UK][1][79] = 127, + [0][1][1][0][RTW89_UK][0][79] = 127, + [0][1][1][0][RTW89_FCC][1][81] = -2, + [0][1][1][0][RTW89_FCC][2][81] = 68, + [0][1][1][0][RTW89_ETSI][1][81] = 127, + [0][1][1][0][RTW89_ETSI][0][81] = 127, + [0][1][1][0][RTW89_MKK][1][81] = 127, + [0][1][1][0][RTW89_MKK][0][81] = 127, + [0][1][1][0][RTW89_IC][1][81] = -2, + [0][1][1][0][RTW89_KCC][1][81] = 12, + [0][1][1][0][RTW89_KCC][0][81] = 127, + [0][1][1][0][RTW89_ACMA][1][81] = 127, + [0][1][1][0][RTW89_ACMA][0][81] = 127, + [0][1][1][0][RTW89_CHILE][1][81] = -2, + [0][1][1][0][RTW89_QATAR][1][81] = 127, + [0][1][1][0][RTW89_QATAR][0][81] = 127, + [0][1][1][0][RTW89_UK][1][81] = 127, + [0][1][1][0][RTW89_UK][0][81] = 127, + [0][1][1][0][RTW89_FCC][1][83] = -2, + [0][1][1][0][RTW89_FCC][2][83] = 68, + [0][1][1][0][RTW89_ETSI][1][83] = 127, + [0][1][1][0][RTW89_ETSI][0][83] = 127, + [0][1][1][0][RTW89_MKK][1][83] = 127, + [0][1][1][0][RTW89_MKK][0][83] = 127, + [0][1][1][0][RTW89_IC][1][83] = -2, + [0][1][1][0][RTW89_KCC][1][83] = 20, + [0][1][1][0][RTW89_KCC][0][83] = 127, + [0][1][1][0][RTW89_ACMA][1][83] = 127, + [0][1][1][0][RTW89_ACMA][0][83] = 127, + [0][1][1][0][RTW89_CHILE][1][83] = -2, + [0][1][1][0][RTW89_QATAR][1][83] = 127, + [0][1][1][0][RTW89_QATAR][0][83] = 127, + [0][1][1][0][RTW89_UK][1][83] = 127, + [0][1][1][0][RTW89_UK][0][83] = 127, + [0][1][1][0][RTW89_FCC][1][85] = -2, + [0][1][1][0][RTW89_FCC][2][85] = 68, + [0][1][1][0][RTW89_ETSI][1][85] = 127, + [0][1][1][0][RTW89_ETSI][0][85] = 127, + [0][1][1][0][RTW89_MKK][1][85] = 127, + [0][1][1][0][RTW89_MKK][0][85] = 127, + [0][1][1][0][RTW89_IC][1][85] = -2, + [0][1][1][0][RTW89_KCC][1][85] = 20, + [0][1][1][0][RTW89_KCC][0][85] = 127, + [0][1][1][0][RTW89_ACMA][1][85] = 127, + [0][1][1][0][RTW89_ACMA][0][85] = 127, + [0][1][1][0][RTW89_CHILE][1][85] = -2, + [0][1][1][0][RTW89_QATAR][1][85] = 127, + [0][1][1][0][RTW89_QATAR][0][85] = 127, + [0][1][1][0][RTW89_UK][1][85] = 127, + [0][1][1][0][RTW89_UK][0][85] = 127, + [0][1][1][0][RTW89_FCC][1][87] = -2, + [0][1][1][0][RTW89_FCC][2][87] = 127, + [0][1][1][0][RTW89_ETSI][1][87] = 127, + [0][1][1][0][RTW89_ETSI][0][87] = 127, + [0][1][1][0][RTW89_MKK][1][87] = 127, + [0][1][1][0][RTW89_MKK][0][87] = 127, + [0][1][1][0][RTW89_IC][1][87] = -2, + [0][1][1][0][RTW89_KCC][1][87] = 20, + [0][1][1][0][RTW89_KCC][0][87] = 127, + [0][1][1][0][RTW89_ACMA][1][87] = 127, + [0][1][1][0][RTW89_ACMA][0][87] = 127, + [0][1][1][0][RTW89_CHILE][1][87] = -2, + [0][1][1][0][RTW89_QATAR][1][87] = 127, + [0][1][1][0][RTW89_QATAR][0][87] = 127, + [0][1][1][0][RTW89_UK][1][87] = 127, + [0][1][1][0][RTW89_UK][0][87] = 127, + [0][1][1][0][RTW89_FCC][1][89] = -2, + [0][1][1][0][RTW89_FCC][2][89] = 127, + [0][1][1][0][RTW89_ETSI][1][89] = 127, + [0][1][1][0][RTW89_ETSI][0][89] = 127, + [0][1][1][0][RTW89_MKK][1][89] = 127, + [0][1][1][0][RTW89_MKK][0][89] = 127, + [0][1][1][0][RTW89_IC][1][89] = -2, + [0][1][1][0][RTW89_KCC][1][89] = 20, + [0][1][1][0][RTW89_KCC][0][89] = 127, + [0][1][1][0][RTW89_ACMA][1][89] = 127, + [0][1][1][0][RTW89_ACMA][0][89] = 127, + [0][1][1][0][RTW89_CHILE][1][89] = -2, + [0][1][1][0][RTW89_QATAR][1][89] = 127, + [0][1][1][0][RTW89_QATAR][0][89] = 127, + [0][1][1][0][RTW89_UK][1][89] = 127, + [0][1][1][0][RTW89_UK][0][89] = 127, + [0][1][1][0][RTW89_FCC][1][90] = -2, + [0][1][1][0][RTW89_FCC][2][90] = 127, + [0][1][1][0][RTW89_ETSI][1][90] = 127, + [0][1][1][0][RTW89_ETSI][0][90] = 127, + [0][1][1][0][RTW89_MKK][1][90] = 127, + [0][1][1][0][RTW89_MKK][0][90] = 127, + [0][1][1][0][RTW89_IC][1][90] = -2, + [0][1][1][0][RTW89_KCC][1][90] = 20, + [0][1][1][0][RTW89_KCC][0][90] = 127, + [0][1][1][0][RTW89_ACMA][1][90] = 127, + [0][1][1][0][RTW89_ACMA][0][90] = 127, + [0][1][1][0][RTW89_CHILE][1][90] = -2, + [0][1][1][0][RTW89_QATAR][1][90] = 127, + [0][1][1][0][RTW89_QATAR][0][90] = 127, + [0][1][1][0][RTW89_UK][1][90] = 127, + [0][1][1][0][RTW89_UK][0][90] = 127, + [0][1][1][0][RTW89_FCC][1][92] = -2, + [0][1][1][0][RTW89_FCC][2][92] = 127, + [0][1][1][0][RTW89_ETSI][1][92] = 127, + [0][1][1][0][RTW89_ETSI][0][92] = 127, + [0][1][1][0][RTW89_MKK][1][92] = 127, + [0][1][1][0][RTW89_MKK][0][92] = 127, + [0][1][1][0][RTW89_IC][1][92] = -2, + [0][1][1][0][RTW89_KCC][1][92] = 20, + [0][1][1][0][RTW89_KCC][0][92] = 127, + [0][1][1][0][RTW89_ACMA][1][92] = 127, + [0][1][1][0][RTW89_ACMA][0][92] = 127, + [0][1][1][0][RTW89_CHILE][1][92] = -2, + [0][1][1][0][RTW89_QATAR][1][92] = 127, + [0][1][1][0][RTW89_QATAR][0][92] = 127, + [0][1][1][0][RTW89_UK][1][92] = 127, + [0][1][1][0][RTW89_UK][0][92] = 127, + [0][1][1][0][RTW89_FCC][1][94] = -2, + [0][1][1][0][RTW89_FCC][2][94] = 127, + [0][1][1][0][RTW89_ETSI][1][94] = 127, + [0][1][1][0][RTW89_ETSI][0][94] = 127, + [0][1][1][0][RTW89_MKK][1][94] = 127, + [0][1][1][0][RTW89_MKK][0][94] = 127, + [0][1][1][0][RTW89_IC][1][94] = -2, + [0][1][1][0][RTW89_KCC][1][94] = 20, + [0][1][1][0][RTW89_KCC][0][94] = 127, + [0][1][1][0][RTW89_ACMA][1][94] = 127, + [0][1][1][0][RTW89_ACMA][0][94] = 127, + [0][1][1][0][RTW89_CHILE][1][94] = -2, + [0][1][1][0][RTW89_QATAR][1][94] = 127, + [0][1][1][0][RTW89_QATAR][0][94] = 127, + [0][1][1][0][RTW89_UK][1][94] = 127, + [0][1][1][0][RTW89_UK][0][94] = 127, + [0][1][1][0][RTW89_FCC][1][96] = -2, + [0][1][1][0][RTW89_FCC][2][96] = 127, + [0][1][1][0][RTW89_ETSI][1][96] = 127, + [0][1][1][0][RTW89_ETSI][0][96] = 127, + [0][1][1][0][RTW89_MKK][1][96] = 127, + [0][1][1][0][RTW89_MKK][0][96] = 127, + [0][1][1][0][RTW89_IC][1][96] = -2, + [0][1][1][0][RTW89_KCC][1][96] = 20, + [0][1][1][0][RTW89_KCC][0][96] = 127, + [0][1][1][0][RTW89_ACMA][1][96] = 127, + [0][1][1][0][RTW89_ACMA][0][96] = 127, + [0][1][1][0][RTW89_CHILE][1][96] = -2, + [0][1][1][0][RTW89_QATAR][1][96] = 127, + [0][1][1][0][RTW89_QATAR][0][96] = 127, + [0][1][1][0][RTW89_UK][1][96] = 127, + [0][1][1][0][RTW89_UK][0][96] = 127, + [0][1][1][0][RTW89_FCC][1][98] = -2, + [0][1][1][0][RTW89_FCC][2][98] = 127, + [0][1][1][0][RTW89_ETSI][1][98] = 127, + [0][1][1][0][RTW89_ETSI][0][98] = 127, + [0][1][1][0][RTW89_MKK][1][98] = 127, + [0][1][1][0][RTW89_MKK][0][98] = 127, + [0][1][1][0][RTW89_IC][1][98] = -2, + [0][1][1][0][RTW89_KCC][1][98] = 20, + [0][1][1][0][RTW89_KCC][0][98] = 127, + [0][1][1][0][RTW89_ACMA][1][98] = 127, + [0][1][1][0][RTW89_ACMA][0][98] = 127, + [0][1][1][0][RTW89_CHILE][1][98] = -2, + [0][1][1][0][RTW89_QATAR][1][98] = 127, + [0][1][1][0][RTW89_QATAR][0][98] = 127, + [0][1][1][0][RTW89_UK][1][98] = 127, + [0][1][1][0][RTW89_UK][0][98] = 127, + [0][1][1][0][RTW89_FCC][1][100] = -2, + [0][1][1][0][RTW89_FCC][2][100] = 127, + [0][1][1][0][RTW89_ETSI][1][100] = 127, + [0][1][1][0][RTW89_ETSI][0][100] = 127, + [0][1][1][0][RTW89_MKK][1][100] = 127, + [0][1][1][0][RTW89_MKK][0][100] = 127, + [0][1][1][0][RTW89_IC][1][100] = -2, + [0][1][1][0][RTW89_KCC][1][100] = 20, + [0][1][1][0][RTW89_KCC][0][100] = 127, + [0][1][1][0][RTW89_ACMA][1][100] = 127, + [0][1][1][0][RTW89_ACMA][0][100] = 127, + [0][1][1][0][RTW89_CHILE][1][100] = -2, + [0][1][1][0][RTW89_QATAR][1][100] = 127, + [0][1][1][0][RTW89_QATAR][0][100] = 127, + [0][1][1][0][RTW89_UK][1][100] = 127, + [0][1][1][0][RTW89_UK][0][100] = 127, + [0][1][1][0][RTW89_FCC][1][102] = -2, + [0][1][1][0][RTW89_FCC][2][102] = 127, + [0][1][1][0][RTW89_ETSI][1][102] = 127, + [0][1][1][0][RTW89_ETSI][0][102] = 127, + [0][1][1][0][RTW89_MKK][1][102] = 127, + [0][1][1][0][RTW89_MKK][0][102] = 127, + [0][1][1][0][RTW89_IC][1][102] = -2, + [0][1][1][0][RTW89_KCC][1][102] = 20, + [0][1][1][0][RTW89_KCC][0][102] = 127, + [0][1][1][0][RTW89_ACMA][1][102] = 127, + [0][1][1][0][RTW89_ACMA][0][102] = 127, + [0][1][1][0][RTW89_CHILE][1][102] = -2, + [0][1][1][0][RTW89_QATAR][1][102] = 127, + [0][1][1][0][RTW89_QATAR][0][102] = 127, + [0][1][1][0][RTW89_UK][1][102] = 127, + [0][1][1][0][RTW89_UK][0][102] = 127, + [0][1][1][0][RTW89_FCC][1][104] = -2, + [0][1][1][0][RTW89_FCC][2][104] = 127, + [0][1][1][0][RTW89_ETSI][1][104] = 127, + [0][1][1][0][RTW89_ETSI][0][104] = 127, + [0][1][1][0][RTW89_MKK][1][104] = 127, + [0][1][1][0][RTW89_MKK][0][104] = 127, + [0][1][1][0][RTW89_IC][1][104] = -2, + [0][1][1][0][RTW89_KCC][1][104] = 20, + [0][1][1][0][RTW89_KCC][0][104] = 127, + [0][1][1][0][RTW89_ACMA][1][104] = 127, + [0][1][1][0][RTW89_ACMA][0][104] = 127, + [0][1][1][0][RTW89_CHILE][1][104] = -2, + [0][1][1][0][RTW89_QATAR][1][104] = 127, + [0][1][1][0][RTW89_QATAR][0][104] = 127, + [0][1][1][0][RTW89_UK][1][104] = 127, + [0][1][1][0][RTW89_UK][0][104] = 127, + [0][1][1][0][RTW89_FCC][1][105] = -2, + [0][1][1][0][RTW89_FCC][2][105] = 127, + [0][1][1][0][RTW89_ETSI][1][105] = 127, + [0][1][1][0][RTW89_ETSI][0][105] = 127, + [0][1][1][0][RTW89_MKK][1][105] = 127, + [0][1][1][0][RTW89_MKK][0][105] = 127, + [0][1][1][0][RTW89_IC][1][105] = -2, + [0][1][1][0][RTW89_KCC][1][105] = 20, + [0][1][1][0][RTW89_KCC][0][105] = 127, + [0][1][1][0][RTW89_ACMA][1][105] = 127, + [0][1][1][0][RTW89_ACMA][0][105] = 127, + [0][1][1][0][RTW89_CHILE][1][105] = -2, + [0][1][1][0][RTW89_QATAR][1][105] = 127, + [0][1][1][0][RTW89_QATAR][0][105] = 127, + [0][1][1][0][RTW89_UK][1][105] = 127, + [0][1][1][0][RTW89_UK][0][105] = 127, + [0][1][1][0][RTW89_FCC][1][107] = 1, + [0][1][1][0][RTW89_FCC][2][107] = 127, + [0][1][1][0][RTW89_ETSI][1][107] = 127, + [0][1][1][0][RTW89_ETSI][0][107] = 127, + [0][1][1][0][RTW89_MKK][1][107] = 127, + [0][1][1][0][RTW89_MKK][0][107] = 127, + [0][1][1][0][RTW89_IC][1][107] = 1, + [0][1][1][0][RTW89_KCC][1][107] = 20, + [0][1][1][0][RTW89_KCC][0][107] = 127, + [0][1][1][0][RTW89_ACMA][1][107] = 127, + [0][1][1][0][RTW89_ACMA][0][107] = 127, + [0][1][1][0][RTW89_CHILE][1][107] = 1, + [0][1][1][0][RTW89_QATAR][1][107] = 127, + [0][1][1][0][RTW89_QATAR][0][107] = 127, + [0][1][1][0][RTW89_UK][1][107] = 127, + [0][1][1][0][RTW89_UK][0][107] = 127, + [0][1][1][0][RTW89_FCC][1][109] = 1, + [0][1][1][0][RTW89_FCC][2][109] = 127, + [0][1][1][0][RTW89_ETSI][1][109] = 127, + [0][1][1][0][RTW89_ETSI][0][109] = 127, + [0][1][1][0][RTW89_MKK][1][109] = 127, + [0][1][1][0][RTW89_MKK][0][109] = 127, + [0][1][1][0][RTW89_IC][1][109] = 1, + [0][1][1][0][RTW89_KCC][1][109] = 20, + [0][1][1][0][RTW89_KCC][0][109] = 127, + [0][1][1][0][RTW89_ACMA][1][109] = 127, + [0][1][1][0][RTW89_ACMA][0][109] = 127, + [0][1][1][0][RTW89_CHILE][1][109] = 1, + [0][1][1][0][RTW89_QATAR][1][109] = 127, + [0][1][1][0][RTW89_QATAR][0][109] = 127, + [0][1][1][0][RTW89_UK][1][109] = 127, + [0][1][1][0][RTW89_UK][0][109] = 127, + [0][1][1][0][RTW89_FCC][1][111] = 127, + [0][1][1][0][RTW89_FCC][2][111] = 127, + [0][1][1][0][RTW89_ETSI][1][111] = 127, + [0][1][1][0][RTW89_ETSI][0][111] = 127, + [0][1][1][0][RTW89_MKK][1][111] = 127, + [0][1][1][0][RTW89_MKK][0][111] = 127, + [0][1][1][0][RTW89_IC][1][111] = 127, + [0][1][1][0][RTW89_KCC][1][111] = 127, + [0][1][1][0][RTW89_KCC][0][111] = 127, + [0][1][1][0][RTW89_ACMA][1][111] = 127, + [0][1][1][0][RTW89_ACMA][0][111] = 127, + [0][1][1][0][RTW89_CHILE][1][111] = 127, + [0][1][1][0][RTW89_QATAR][1][111] = 127, + [0][1][1][0][RTW89_QATAR][0][111] = 127, + [0][1][1][0][RTW89_UK][1][111] = 127, + [0][1][1][0][RTW89_UK][0][111] = 127, + [0][1][1][0][RTW89_FCC][1][113] = 127, + [0][1][1][0][RTW89_FCC][2][113] = 127, + [0][1][1][0][RTW89_ETSI][1][113] = 127, + [0][1][1][0][RTW89_ETSI][0][113] = 127, + [0][1][1][0][RTW89_MKK][1][113] = 127, + [0][1][1][0][RTW89_MKK][0][113] = 127, + [0][1][1][0][RTW89_IC][1][113] = 127, + [0][1][1][0][RTW89_KCC][1][113] = 127, + [0][1][1][0][RTW89_KCC][0][113] = 127, + [0][1][1][0][RTW89_ACMA][1][113] = 127, + [0][1][1][0][RTW89_ACMA][0][113] = 127, + [0][1][1][0][RTW89_CHILE][1][113] = 127, + [0][1][1][0][RTW89_QATAR][1][113] = 127, + [0][1][1][0][RTW89_QATAR][0][113] = 127, + [0][1][1][0][RTW89_UK][1][113] = 127, + [0][1][1][0][RTW89_UK][0][113] = 127, + [0][1][1][0][RTW89_FCC][1][115] = 127, + [0][1][1][0][RTW89_FCC][2][115] = 127, + [0][1][1][0][RTW89_ETSI][1][115] = 127, + [0][1][1][0][RTW89_ETSI][0][115] = 127, + [0][1][1][0][RTW89_MKK][1][115] = 127, + [0][1][1][0][RTW89_MKK][0][115] = 127, + [0][1][1][0][RTW89_IC][1][115] = 127, + [0][1][1][0][RTW89_KCC][1][115] = 127, + [0][1][1][0][RTW89_KCC][0][115] = 127, + [0][1][1][0][RTW89_ACMA][1][115] = 127, + [0][1][1][0][RTW89_ACMA][0][115] = 127, + [0][1][1][0][RTW89_CHILE][1][115] = 127, + [0][1][1][0][RTW89_QATAR][1][115] = 127, + [0][1][1][0][RTW89_QATAR][0][115] = 127, + [0][1][1][0][RTW89_UK][1][115] = 127, + [0][1][1][0][RTW89_UK][0][115] = 127, + [0][1][1][0][RTW89_FCC][1][117] = 127, + [0][1][1][0][RTW89_FCC][2][117] = 127, + [0][1][1][0][RTW89_ETSI][1][117] = 127, + [0][1][1][0][RTW89_ETSI][0][117] = 127, + [0][1][1][0][RTW89_MKK][1][117] = 127, + [0][1][1][0][RTW89_MKK][0][117] = 127, + [0][1][1][0][RTW89_IC][1][117] = 127, + [0][1][1][0][RTW89_KCC][1][117] = 127, + [0][1][1][0][RTW89_KCC][0][117] = 127, + [0][1][1][0][RTW89_ACMA][1][117] = 127, + [0][1][1][0][RTW89_ACMA][0][117] = 127, + [0][1][1][0][RTW89_CHILE][1][117] = 127, + [0][1][1][0][RTW89_QATAR][1][117] = 127, + [0][1][1][0][RTW89_QATAR][0][117] = 127, + [0][1][1][0][RTW89_UK][1][117] = 127, + [0][1][1][0][RTW89_UK][0][117] = 127, + [0][1][1][0][RTW89_FCC][1][119] = 127, + [0][1][1][0][RTW89_FCC][2][119] = 127, + [0][1][1][0][RTW89_ETSI][1][119] = 127, + [0][1][1][0][RTW89_ETSI][0][119] = 127, + [0][1][1][0][RTW89_MKK][1][119] = 127, + [0][1][1][0][RTW89_MKK][0][119] = 127, + [0][1][1][0][RTW89_IC][1][119] = 127, + [0][1][1][0][RTW89_KCC][1][119] = 127, + [0][1][1][0][RTW89_KCC][0][119] = 127, + [0][1][1][0][RTW89_ACMA][1][119] = 127, + [0][1][1][0][RTW89_ACMA][0][119] = 127, + [0][1][1][0][RTW89_CHILE][1][119] = 127, + [0][1][1][0][RTW89_QATAR][1][119] = 127, + [0][1][1][0][RTW89_QATAR][0][119] = 127, + [0][1][1][0][RTW89_UK][1][119] = 127, + [0][1][1][0][RTW89_UK][0][119] = 127, + [0][0][2][0][RTW89_FCC][1][0] = 24, + [0][0][2][0][RTW89_FCC][2][0] = 56, + [0][0][2][0][RTW89_ETSI][1][0] = 66, + [0][0][2][0][RTW89_ETSI][0][0] = 28, + [0][0][2][0][RTW89_MKK][1][0] = 66, + [0][0][2][0][RTW89_MKK][0][0] = 26, + [0][0][2][0][RTW89_IC][1][0] = 24, + [0][0][2][0][RTW89_KCC][1][0] = 24, + [0][0][2][0][RTW89_KCC][0][0] = 24, + [0][0][2][0][RTW89_ACMA][1][0] = 66, + [0][0][2][0][RTW89_ACMA][0][0] = 28, + [0][0][2][0][RTW89_CHILE][1][0] = 24, + [0][0][2][0][RTW89_QATAR][1][0] = 66, + [0][0][2][0][RTW89_QATAR][0][0] = 28, + [0][0][2][0][RTW89_UK][1][0] = 66, + [0][0][2][0][RTW89_UK][0][0] = 28, + [0][0][2][0][RTW89_FCC][1][2] = 22, + [0][0][2][0][RTW89_FCC][2][2] = 56, + [0][0][2][0][RTW89_ETSI][1][2] = 66, + [0][0][2][0][RTW89_ETSI][0][2] = 28, + [0][0][2][0][RTW89_MKK][1][2] = 66, + [0][0][2][0][RTW89_MKK][0][2] = 26, + [0][0][2][0][RTW89_IC][1][2] = 22, + [0][0][2][0][RTW89_KCC][1][2] = 24, + [0][0][2][0][RTW89_KCC][0][2] = 24, + [0][0][2][0][RTW89_ACMA][1][2] = 66, + [0][0][2][0][RTW89_ACMA][0][2] = 28, + [0][0][2][0][RTW89_CHILE][1][2] = 22, + [0][0][2][0][RTW89_QATAR][1][2] = 66, + [0][0][2][0][RTW89_QATAR][0][2] = 28, + [0][0][2][0][RTW89_UK][1][2] = 66, + [0][0][2][0][RTW89_UK][0][2] = 28, + [0][0][2][0][RTW89_FCC][1][4] = 22, + [0][0][2][0][RTW89_FCC][2][4] = 56, + [0][0][2][0][RTW89_ETSI][1][4] = 66, + [0][0][2][0][RTW89_ETSI][0][4] = 28, + [0][0][2][0][RTW89_MKK][1][4] = 66, + [0][0][2][0][RTW89_MKK][0][4] = 26, + [0][0][2][0][RTW89_IC][1][4] = 22, + [0][0][2][0][RTW89_KCC][1][4] = 24, + [0][0][2][0][RTW89_KCC][0][4] = 24, + [0][0][2][0][RTW89_ACMA][1][4] = 66, + [0][0][2][0][RTW89_ACMA][0][4] = 28, + [0][0][2][0][RTW89_CHILE][1][4] = 22, + [0][0][2][0][RTW89_QATAR][1][4] = 66, + [0][0][2][0][RTW89_QATAR][0][4] = 28, + [0][0][2][0][RTW89_UK][1][4] = 66, + [0][0][2][0][RTW89_UK][0][4] = 28, + [0][0][2][0][RTW89_FCC][1][6] = 22, + [0][0][2][0][RTW89_FCC][2][6] = 56, + [0][0][2][0][RTW89_ETSI][1][6] = 66, + [0][0][2][0][RTW89_ETSI][0][6] = 28, + [0][0][2][0][RTW89_MKK][1][6] = 66, + [0][0][2][0][RTW89_MKK][0][6] = 26, + [0][0][2][0][RTW89_IC][1][6] = 22, + [0][0][2][0][RTW89_KCC][1][6] = 24, + [0][0][2][0][RTW89_KCC][0][6] = 24, + [0][0][2][0][RTW89_ACMA][1][6] = 66, + [0][0][2][0][RTW89_ACMA][0][6] = 28, + [0][0][2][0][RTW89_CHILE][1][6] = 22, + [0][0][2][0][RTW89_QATAR][1][6] = 66, + [0][0][2][0][RTW89_QATAR][0][6] = 28, + [0][0][2][0][RTW89_UK][1][6] = 66, + [0][0][2][0][RTW89_UK][0][6] = 28, + [0][0][2][0][RTW89_FCC][1][8] = 22, + [0][0][2][0][RTW89_FCC][2][8] = 56, + [0][0][2][0][RTW89_ETSI][1][8] = 66, + [0][0][2][0][RTW89_ETSI][0][8] = 28, + [0][0][2][0][RTW89_MKK][1][8] = 66, + [0][0][2][0][RTW89_MKK][0][8] = 26, + [0][0][2][0][RTW89_IC][1][8] = 22, + [0][0][2][0][RTW89_KCC][1][8] = 24, + [0][0][2][0][RTW89_KCC][0][8] = 24, + [0][0][2][0][RTW89_ACMA][1][8] = 66, + [0][0][2][0][RTW89_ACMA][0][8] = 28, + [0][0][2][0][RTW89_CHILE][1][8] = 22, + [0][0][2][0][RTW89_QATAR][1][8] = 66, + [0][0][2][0][RTW89_QATAR][0][8] = 28, + [0][0][2][0][RTW89_UK][1][8] = 66, + [0][0][2][0][RTW89_UK][0][8] = 28, + [0][0][2][0][RTW89_FCC][1][10] = 22, + [0][0][2][0][RTW89_FCC][2][10] = 56, + [0][0][2][0][RTW89_ETSI][1][10] = 66, + [0][0][2][0][RTW89_ETSI][0][10] = 28, + [0][0][2][0][RTW89_MKK][1][10] = 66, + [0][0][2][0][RTW89_MKK][0][10] = 26, + [0][0][2][0][RTW89_IC][1][10] = 22, + [0][0][2][0][RTW89_KCC][1][10] = 24, + [0][0][2][0][RTW89_KCC][0][10] = 24, + [0][0][2][0][RTW89_ACMA][1][10] = 66, + [0][0][2][0][RTW89_ACMA][0][10] = 28, + [0][0][2][0][RTW89_CHILE][1][10] = 22, + [0][0][2][0][RTW89_QATAR][1][10] = 66, + [0][0][2][0][RTW89_QATAR][0][10] = 28, + [0][0][2][0][RTW89_UK][1][10] = 66, + [0][0][2][0][RTW89_UK][0][10] = 28, + [0][0][2][0][RTW89_FCC][1][12] = 22, + [0][0][2][0][RTW89_FCC][2][12] = 56, + [0][0][2][0][RTW89_ETSI][1][12] = 66, + [0][0][2][0][RTW89_ETSI][0][12] = 28, + [0][0][2][0][RTW89_MKK][1][12] = 66, + [0][0][2][0][RTW89_MKK][0][12] = 26, + [0][0][2][0][RTW89_IC][1][12] = 22, + [0][0][2][0][RTW89_KCC][1][12] = 24, + [0][0][2][0][RTW89_KCC][0][12] = 24, + [0][0][2][0][RTW89_ACMA][1][12] = 66, + [0][0][2][0][RTW89_ACMA][0][12] = 28, + [0][0][2][0][RTW89_CHILE][1][12] = 22, + [0][0][2][0][RTW89_QATAR][1][12] = 66, + [0][0][2][0][RTW89_QATAR][0][12] = 28, + [0][0][2][0][RTW89_UK][1][12] = 66, + [0][0][2][0][RTW89_UK][0][12] = 28, + [0][0][2][0][RTW89_FCC][1][14] = 22, + [0][0][2][0][RTW89_FCC][2][14] = 56, + [0][0][2][0][RTW89_ETSI][1][14] = 66, + [0][0][2][0][RTW89_ETSI][0][14] = 28, + [0][0][2][0][RTW89_MKK][1][14] = 66, + [0][0][2][0][RTW89_MKK][0][14] = 26, + [0][0][2][0][RTW89_IC][1][14] = 22, + [0][0][2][0][RTW89_KCC][1][14] = 24, + [0][0][2][0][RTW89_KCC][0][14] = 24, + [0][0][2][0][RTW89_ACMA][1][14] = 66, + [0][0][2][0][RTW89_ACMA][0][14] = 28, + [0][0][2][0][RTW89_CHILE][1][14] = 22, + [0][0][2][0][RTW89_QATAR][1][14] = 66, + [0][0][2][0][RTW89_QATAR][0][14] = 28, + [0][0][2][0][RTW89_UK][1][14] = 66, + [0][0][2][0][RTW89_UK][0][14] = 28, + [0][0][2][0][RTW89_FCC][1][15] = 22, + [0][0][2][0][RTW89_FCC][2][15] = 56, + [0][0][2][0][RTW89_ETSI][1][15] = 66, + [0][0][2][0][RTW89_ETSI][0][15] = 28, + [0][0][2][0][RTW89_MKK][1][15] = 66, + [0][0][2][0][RTW89_MKK][0][15] = 26, + [0][0][2][0][RTW89_IC][1][15] = 22, + [0][0][2][0][RTW89_KCC][1][15] = 24, + [0][0][2][0][RTW89_KCC][0][15] = 24, + [0][0][2][0][RTW89_ACMA][1][15] = 66, + [0][0][2][0][RTW89_ACMA][0][15] = 28, + [0][0][2][0][RTW89_CHILE][1][15] = 22, + [0][0][2][0][RTW89_QATAR][1][15] = 66, + [0][0][2][0][RTW89_QATAR][0][15] = 28, + [0][0][2][0][RTW89_UK][1][15] = 66, + [0][0][2][0][RTW89_UK][0][15] = 28, + [0][0][2][0][RTW89_FCC][1][17] = 22, + [0][0][2][0][RTW89_FCC][2][17] = 56, + [0][0][2][0][RTW89_ETSI][1][17] = 66, + [0][0][2][0][RTW89_ETSI][0][17] = 28, + [0][0][2][0][RTW89_MKK][1][17] = 66, + [0][0][2][0][RTW89_MKK][0][17] = 26, + [0][0][2][0][RTW89_IC][1][17] = 22, + [0][0][2][0][RTW89_KCC][1][17] = 24, + [0][0][2][0][RTW89_KCC][0][17] = 24, + [0][0][2][0][RTW89_ACMA][1][17] = 66, + [0][0][2][0][RTW89_ACMA][0][17] = 28, + [0][0][2][0][RTW89_CHILE][1][17] = 22, + [0][0][2][0][RTW89_QATAR][1][17] = 66, + [0][0][2][0][RTW89_QATAR][0][17] = 28, + [0][0][2][0][RTW89_UK][1][17] = 66, + [0][0][2][0][RTW89_UK][0][17] = 28, + [0][0][2][0][RTW89_FCC][1][19] = 22, + [0][0][2][0][RTW89_FCC][2][19] = 56, + [0][0][2][0][RTW89_ETSI][1][19] = 66, + [0][0][2][0][RTW89_ETSI][0][19] = 28, + [0][0][2][0][RTW89_MKK][1][19] = 66, + [0][0][2][0][RTW89_MKK][0][19] = 26, + [0][0][2][0][RTW89_IC][1][19] = 22, + [0][0][2][0][RTW89_KCC][1][19] = 24, + [0][0][2][0][RTW89_KCC][0][19] = 24, + [0][0][2][0][RTW89_ACMA][1][19] = 66, + [0][0][2][0][RTW89_ACMA][0][19] = 28, + [0][0][2][0][RTW89_CHILE][1][19] = 22, + [0][0][2][0][RTW89_QATAR][1][19] = 66, + [0][0][2][0][RTW89_QATAR][0][19] = 28, + [0][0][2][0][RTW89_UK][1][19] = 66, + [0][0][2][0][RTW89_UK][0][19] = 28, + [0][0][2][0][RTW89_FCC][1][21] = 22, + [0][0][2][0][RTW89_FCC][2][21] = 56, + [0][0][2][0][RTW89_ETSI][1][21] = 66, + [0][0][2][0][RTW89_ETSI][0][21] = 28, + [0][0][2][0][RTW89_MKK][1][21] = 66, + [0][0][2][0][RTW89_MKK][0][21] = 26, + [0][0][2][0][RTW89_IC][1][21] = 22, + [0][0][2][0][RTW89_KCC][1][21] = 24, + [0][0][2][0][RTW89_KCC][0][21] = 24, + [0][0][2][0][RTW89_ACMA][1][21] = 66, + [0][0][2][0][RTW89_ACMA][0][21] = 28, + [0][0][2][0][RTW89_CHILE][1][21] = 22, + [0][0][2][0][RTW89_QATAR][1][21] = 66, + [0][0][2][0][RTW89_QATAR][0][21] = 28, + [0][0][2][0][RTW89_UK][1][21] = 66, + [0][0][2][0][RTW89_UK][0][21] = 28, + [0][0][2][0][RTW89_FCC][1][23] = 22, + [0][0][2][0][RTW89_FCC][2][23] = 70, + [0][0][2][0][RTW89_ETSI][1][23] = 66, + [0][0][2][0][RTW89_ETSI][0][23] = 28, + [0][0][2][0][RTW89_MKK][1][23] = 66, + [0][0][2][0][RTW89_MKK][0][23] = 26, + [0][0][2][0][RTW89_IC][1][23] = 22, + [0][0][2][0][RTW89_KCC][1][23] = 24, + [0][0][2][0][RTW89_KCC][0][23] = 26, + [0][0][2][0][RTW89_ACMA][1][23] = 66, + [0][0][2][0][RTW89_ACMA][0][23] = 28, + [0][0][2][0][RTW89_CHILE][1][23] = 22, + [0][0][2][0][RTW89_QATAR][1][23] = 66, + [0][0][2][0][RTW89_QATAR][0][23] = 28, + [0][0][2][0][RTW89_UK][1][23] = 66, + [0][0][2][0][RTW89_UK][0][23] = 28, + [0][0][2][0][RTW89_FCC][1][25] = 22, + [0][0][2][0][RTW89_FCC][2][25] = 70, + [0][0][2][0][RTW89_ETSI][1][25] = 66, + [0][0][2][0][RTW89_ETSI][0][25] = 28, + [0][0][2][0][RTW89_MKK][1][25] = 66, + [0][0][2][0][RTW89_MKK][0][25] = 26, + [0][0][2][0][RTW89_IC][1][25] = 22, + [0][0][2][0][RTW89_KCC][1][25] = 24, + [0][0][2][0][RTW89_KCC][0][25] = 26, + [0][0][2][0][RTW89_ACMA][1][25] = 66, + [0][0][2][0][RTW89_ACMA][0][25] = 28, + [0][0][2][0][RTW89_CHILE][1][25] = 22, + [0][0][2][0][RTW89_QATAR][1][25] = 66, + [0][0][2][0][RTW89_QATAR][0][25] = 28, + [0][0][2][0][RTW89_UK][1][25] = 66, + [0][0][2][0][RTW89_UK][0][25] = 28, + [0][0][2][0][RTW89_FCC][1][27] = 22, + [0][0][2][0][RTW89_FCC][2][27] = 70, + [0][0][2][0][RTW89_ETSI][1][27] = 66, + [0][0][2][0][RTW89_ETSI][0][27] = 28, + [0][0][2][0][RTW89_MKK][1][27] = 66, + [0][0][2][0][RTW89_MKK][0][27] = 26, + [0][0][2][0][RTW89_IC][1][27] = 22, + [0][0][2][0][RTW89_KCC][1][27] = 24, + [0][0][2][0][RTW89_KCC][0][27] = 26, + [0][0][2][0][RTW89_ACMA][1][27] = 66, + [0][0][2][0][RTW89_ACMA][0][27] = 28, + [0][0][2][0][RTW89_CHILE][1][27] = 22, + [0][0][2][0][RTW89_QATAR][1][27] = 66, + [0][0][2][0][RTW89_QATAR][0][27] = 28, + [0][0][2][0][RTW89_UK][1][27] = 66, + [0][0][2][0][RTW89_UK][0][27] = 28, + [0][0][2][0][RTW89_FCC][1][29] = 22, + [0][0][2][0][RTW89_FCC][2][29] = 70, + [0][0][2][0][RTW89_ETSI][1][29] = 66, + [0][0][2][0][RTW89_ETSI][0][29] = 28, + [0][0][2][0][RTW89_MKK][1][29] = 66, + [0][0][2][0][RTW89_MKK][0][29] = 26, + [0][0][2][0][RTW89_IC][1][29] = 22, + [0][0][2][0][RTW89_KCC][1][29] = 24, + [0][0][2][0][RTW89_KCC][0][29] = 26, + [0][0][2][0][RTW89_ACMA][1][29] = 66, + [0][0][2][0][RTW89_ACMA][0][29] = 28, + [0][0][2][0][RTW89_CHILE][1][29] = 22, + [0][0][2][0][RTW89_QATAR][1][29] = 66, + [0][0][2][0][RTW89_QATAR][0][29] = 28, + [0][0][2][0][RTW89_UK][1][29] = 66, + [0][0][2][0][RTW89_UK][0][29] = 28, + [0][0][2][0][RTW89_FCC][1][30] = 22, + [0][0][2][0][RTW89_FCC][2][30] = 70, + [0][0][2][0][RTW89_ETSI][1][30] = 66, + [0][0][2][0][RTW89_ETSI][0][30] = 28, + [0][0][2][0][RTW89_MKK][1][30] = 66, + [0][0][2][0][RTW89_MKK][0][30] = 26, + [0][0][2][0][RTW89_IC][1][30] = 22, + [0][0][2][0][RTW89_KCC][1][30] = 24, + [0][0][2][0][RTW89_KCC][0][30] = 26, + [0][0][2][0][RTW89_ACMA][1][30] = 66, + [0][0][2][0][RTW89_ACMA][0][30] = 28, + [0][0][2][0][RTW89_CHILE][1][30] = 22, + [0][0][2][0][RTW89_QATAR][1][30] = 66, + [0][0][2][0][RTW89_QATAR][0][30] = 28, + [0][0][2][0][RTW89_UK][1][30] = 66, + [0][0][2][0][RTW89_UK][0][30] = 28, + [0][0][2][0][RTW89_FCC][1][32] = 22, + [0][0][2][0][RTW89_FCC][2][32] = 70, + [0][0][2][0][RTW89_ETSI][1][32] = 66, + [0][0][2][0][RTW89_ETSI][0][32] = 28, + [0][0][2][0][RTW89_MKK][1][32] = 66, + [0][0][2][0][RTW89_MKK][0][32] = 26, + [0][0][2][0][RTW89_IC][1][32] = 22, + [0][0][2][0][RTW89_KCC][1][32] = 24, + [0][0][2][0][RTW89_KCC][0][32] = 26, + [0][0][2][0][RTW89_ACMA][1][32] = 66, + [0][0][2][0][RTW89_ACMA][0][32] = 28, + [0][0][2][0][RTW89_CHILE][1][32] = 22, + [0][0][2][0][RTW89_QATAR][1][32] = 66, + [0][0][2][0][RTW89_QATAR][0][32] = 28, + [0][0][2][0][RTW89_UK][1][32] = 66, + [0][0][2][0][RTW89_UK][0][32] = 28, + [0][0][2][0][RTW89_FCC][1][34] = 22, + [0][0][2][0][RTW89_FCC][2][34] = 70, + [0][0][2][0][RTW89_ETSI][1][34] = 66, + [0][0][2][0][RTW89_ETSI][0][34] = 28, + [0][0][2][0][RTW89_MKK][1][34] = 66, + [0][0][2][0][RTW89_MKK][0][34] = 26, + [0][0][2][0][RTW89_IC][1][34] = 22, + [0][0][2][0][RTW89_KCC][1][34] = 24, + [0][0][2][0][RTW89_KCC][0][34] = 26, + [0][0][2][0][RTW89_ACMA][1][34] = 66, + [0][0][2][0][RTW89_ACMA][0][34] = 28, + [0][0][2][0][RTW89_CHILE][1][34] = 22, + [0][0][2][0][RTW89_QATAR][1][34] = 66, + [0][0][2][0][RTW89_QATAR][0][34] = 28, + [0][0][2][0][RTW89_UK][1][34] = 66, + [0][0][2][0][RTW89_UK][0][34] = 28, + [0][0][2][0][RTW89_FCC][1][36] = 22, + [0][0][2][0][RTW89_FCC][2][36] = 70, + [0][0][2][0][RTW89_ETSI][1][36] = 66, + [0][0][2][0][RTW89_ETSI][0][36] = 28, + [0][0][2][0][RTW89_MKK][1][36] = 66, + [0][0][2][0][RTW89_MKK][0][36] = 26, + [0][0][2][0][RTW89_IC][1][36] = 22, + [0][0][2][0][RTW89_KCC][1][36] = 24, + [0][0][2][0][RTW89_KCC][0][36] = 26, + [0][0][2][0][RTW89_ACMA][1][36] = 66, + [0][0][2][0][RTW89_ACMA][0][36] = 28, + [0][0][2][0][RTW89_CHILE][1][36] = 22, + [0][0][2][0][RTW89_QATAR][1][36] = 66, + [0][0][2][0][RTW89_QATAR][0][36] = 28, + [0][0][2][0][RTW89_UK][1][36] = 66, + [0][0][2][0][RTW89_UK][0][36] = 28, + [0][0][2][0][RTW89_FCC][1][38] = 22, + [0][0][2][0][RTW89_FCC][2][38] = 70, + [0][0][2][0][RTW89_ETSI][1][38] = 66, + [0][0][2][0][RTW89_ETSI][0][38] = 28, + [0][0][2][0][RTW89_MKK][1][38] = 66, + [0][0][2][0][RTW89_MKK][0][38] = 26, + [0][0][2][0][RTW89_IC][1][38] = 22, + [0][0][2][0][RTW89_KCC][1][38] = 24, + [0][0][2][0][RTW89_KCC][0][38] = 26, + [0][0][2][0][RTW89_ACMA][1][38] = 66, + [0][0][2][0][RTW89_ACMA][0][38] = 28, + [0][0][2][0][RTW89_CHILE][1][38] = 22, + [0][0][2][0][RTW89_QATAR][1][38] = 66, + [0][0][2][0][RTW89_QATAR][0][38] = 28, + [0][0][2][0][RTW89_UK][1][38] = 66, + [0][0][2][0][RTW89_UK][0][38] = 28, + [0][0][2][0][RTW89_FCC][1][40] = 22, + [0][0][2][0][RTW89_FCC][2][40] = 70, + [0][0][2][0][RTW89_ETSI][1][40] = 66, + [0][0][2][0][RTW89_ETSI][0][40] = 28, + [0][0][2][0][RTW89_MKK][1][40] = 66, + [0][0][2][0][RTW89_MKK][0][40] = 26, + [0][0][2][0][RTW89_IC][1][40] = 22, + [0][0][2][0][RTW89_KCC][1][40] = 24, + [0][0][2][0][RTW89_KCC][0][40] = 26, + [0][0][2][0][RTW89_ACMA][1][40] = 66, + [0][0][2][0][RTW89_ACMA][0][40] = 28, + [0][0][2][0][RTW89_CHILE][1][40] = 22, + [0][0][2][0][RTW89_QATAR][1][40] = 66, + [0][0][2][0][RTW89_QATAR][0][40] = 28, + [0][0][2][0][RTW89_UK][1][40] = 66, + [0][0][2][0][RTW89_UK][0][40] = 28, + [0][0][2][0][RTW89_FCC][1][42] = 22, + [0][0][2][0][RTW89_FCC][2][42] = 70, + [0][0][2][0][RTW89_ETSI][1][42] = 66, + [0][0][2][0][RTW89_ETSI][0][42] = 28, + [0][0][2][0][RTW89_MKK][1][42] = 66, + [0][0][2][0][RTW89_MKK][0][42] = 26, + [0][0][2][0][RTW89_IC][1][42] = 22, + [0][0][2][0][RTW89_KCC][1][42] = 24, + [0][0][2][0][RTW89_KCC][0][42] = 26, + [0][0][2][0][RTW89_ACMA][1][42] = 66, + [0][0][2][0][RTW89_ACMA][0][42] = 28, + [0][0][2][0][RTW89_CHILE][1][42] = 22, + [0][0][2][0][RTW89_QATAR][1][42] = 66, + [0][0][2][0][RTW89_QATAR][0][42] = 28, + [0][0][2][0][RTW89_UK][1][42] = 66, + [0][0][2][0][RTW89_UK][0][42] = 28, + [0][0][2][0][RTW89_FCC][1][44] = 22, + [0][0][2][0][RTW89_FCC][2][44] = 70, + [0][0][2][0][RTW89_ETSI][1][44] = 66, + [0][0][2][0][RTW89_ETSI][0][44] = 30, + [0][0][2][0][RTW89_MKK][1][44] = 44, + [0][0][2][0][RTW89_MKK][0][44] = 28, + [0][0][2][0][RTW89_IC][1][44] = 22, + [0][0][2][0][RTW89_KCC][1][44] = 24, + [0][0][2][0][RTW89_KCC][0][44] = 26, + [0][0][2][0][RTW89_ACMA][1][44] = 66, + [0][0][2][0][RTW89_ACMA][0][44] = 30, + [0][0][2][0][RTW89_CHILE][1][44] = 22, + [0][0][2][0][RTW89_QATAR][1][44] = 66, + [0][0][2][0][RTW89_QATAR][0][44] = 30, + [0][0][2][0][RTW89_UK][1][44] = 66, + [0][0][2][0][RTW89_UK][0][44] = 30, + [0][0][2][0][RTW89_FCC][1][45] = 22, + [0][0][2][0][RTW89_FCC][2][45] = 127, + [0][0][2][0][RTW89_ETSI][1][45] = 127, + [0][0][2][0][RTW89_ETSI][0][45] = 127, + [0][0][2][0][RTW89_MKK][1][45] = 127, + [0][0][2][0][RTW89_MKK][0][45] = 127, + [0][0][2][0][RTW89_IC][1][45] = 22, + [0][0][2][0][RTW89_KCC][1][45] = 24, + [0][0][2][0][RTW89_KCC][0][45] = 127, + [0][0][2][0][RTW89_ACMA][1][45] = 127, + [0][0][2][0][RTW89_ACMA][0][45] = 127, + [0][0][2][0][RTW89_CHILE][1][45] = 22, + [0][0][2][0][RTW89_QATAR][1][45] = 127, + [0][0][2][0][RTW89_QATAR][0][45] = 127, + [0][0][2][0][RTW89_UK][1][45] = 127, + [0][0][2][0][RTW89_UK][0][45] = 127, + [0][0][2][0][RTW89_FCC][1][47] = 22, + [0][0][2][0][RTW89_FCC][2][47] = 127, + [0][0][2][0][RTW89_ETSI][1][47] = 127, + [0][0][2][0][RTW89_ETSI][0][47] = 127, + [0][0][2][0][RTW89_MKK][1][47] = 127, + [0][0][2][0][RTW89_MKK][0][47] = 127, + [0][0][2][0][RTW89_IC][1][47] = 22, + [0][0][2][0][RTW89_KCC][1][47] = 24, + [0][0][2][0][RTW89_KCC][0][47] = 127, + [0][0][2][0][RTW89_ACMA][1][47] = 127, + [0][0][2][0][RTW89_ACMA][0][47] = 127, + [0][0][2][0][RTW89_CHILE][1][47] = 22, + [0][0][2][0][RTW89_QATAR][1][47] = 127, + [0][0][2][0][RTW89_QATAR][0][47] = 127, + [0][0][2][0][RTW89_UK][1][47] = 127, + [0][0][2][0][RTW89_UK][0][47] = 127, + [0][0][2][0][RTW89_FCC][1][49] = 24, + [0][0][2][0][RTW89_FCC][2][49] = 127, + [0][0][2][0][RTW89_ETSI][1][49] = 127, + [0][0][2][0][RTW89_ETSI][0][49] = 127, + [0][0][2][0][RTW89_MKK][1][49] = 127, + [0][0][2][0][RTW89_MKK][0][49] = 127, + [0][0][2][0][RTW89_IC][1][49] = 24, + [0][0][2][0][RTW89_KCC][1][49] = 24, + [0][0][2][0][RTW89_KCC][0][49] = 127, + [0][0][2][0][RTW89_ACMA][1][49] = 127, + [0][0][2][0][RTW89_ACMA][0][49] = 127, + [0][0][2][0][RTW89_CHILE][1][49] = 24, + [0][0][2][0][RTW89_QATAR][1][49] = 127, + [0][0][2][0][RTW89_QATAR][0][49] = 127, + [0][0][2][0][RTW89_UK][1][49] = 127, + [0][0][2][0][RTW89_UK][0][49] = 127, + [0][0][2][0][RTW89_FCC][1][51] = 22, + [0][0][2][0][RTW89_FCC][2][51] = 127, + [0][0][2][0][RTW89_ETSI][1][51] = 127, + [0][0][2][0][RTW89_ETSI][0][51] = 127, + [0][0][2][0][RTW89_MKK][1][51] = 127, + [0][0][2][0][RTW89_MKK][0][51] = 127, + [0][0][2][0][RTW89_IC][1][51] = 22, + [0][0][2][0][RTW89_KCC][1][51] = 24, + [0][0][2][0][RTW89_KCC][0][51] = 127, + [0][0][2][0][RTW89_ACMA][1][51] = 127, + [0][0][2][0][RTW89_ACMA][0][51] = 127, + [0][0][2][0][RTW89_CHILE][1][51] = 22, + [0][0][2][0][RTW89_QATAR][1][51] = 127, + [0][0][2][0][RTW89_QATAR][0][51] = 127, + [0][0][2][0][RTW89_UK][1][51] = 127, + [0][0][2][0][RTW89_UK][0][51] = 127, + [0][0][2][0][RTW89_FCC][1][53] = 22, + [0][0][2][0][RTW89_FCC][2][53] = 127, + [0][0][2][0][RTW89_ETSI][1][53] = 127, + [0][0][2][0][RTW89_ETSI][0][53] = 127, + [0][0][2][0][RTW89_MKK][1][53] = 127, + [0][0][2][0][RTW89_MKK][0][53] = 127, + [0][0][2][0][RTW89_IC][1][53] = 22, + [0][0][2][0][RTW89_KCC][1][53] = 24, + [0][0][2][0][RTW89_KCC][0][53] = 127, + [0][0][2][0][RTW89_ACMA][1][53] = 127, + [0][0][2][0][RTW89_ACMA][0][53] = 127, + [0][0][2][0][RTW89_CHILE][1][53] = 22, + [0][0][2][0][RTW89_QATAR][1][53] = 127, + [0][0][2][0][RTW89_QATAR][0][53] = 127, + [0][0][2][0][RTW89_UK][1][53] = 127, + [0][0][2][0][RTW89_UK][0][53] = 127, + [0][0][2][0][RTW89_FCC][1][55] = 22, + [0][0][2][0][RTW89_FCC][2][55] = 68, + [0][0][2][0][RTW89_ETSI][1][55] = 127, + [0][0][2][0][RTW89_ETSI][0][55] = 127, + [0][0][2][0][RTW89_MKK][1][55] = 127, + [0][0][2][0][RTW89_MKK][0][55] = 127, + [0][0][2][0][RTW89_IC][1][55] = 22, + [0][0][2][0][RTW89_KCC][1][55] = 26, + [0][0][2][0][RTW89_KCC][0][55] = 127, + [0][0][2][0][RTW89_ACMA][1][55] = 127, + [0][0][2][0][RTW89_ACMA][0][55] = 127, + [0][0][2][0][RTW89_CHILE][1][55] = 22, + [0][0][2][0][RTW89_QATAR][1][55] = 127, + [0][0][2][0][RTW89_QATAR][0][55] = 127, + [0][0][2][0][RTW89_UK][1][55] = 127, + [0][0][2][0][RTW89_UK][0][55] = 127, + [0][0][2][0][RTW89_FCC][1][57] = 22, + [0][0][2][0][RTW89_FCC][2][57] = 68, + [0][0][2][0][RTW89_ETSI][1][57] = 127, + [0][0][2][0][RTW89_ETSI][0][57] = 127, + [0][0][2][0][RTW89_MKK][1][57] = 127, + [0][0][2][0][RTW89_MKK][0][57] = 127, + [0][0][2][0][RTW89_IC][1][57] = 22, + [0][0][2][0][RTW89_KCC][1][57] = 26, + [0][0][2][0][RTW89_KCC][0][57] = 127, + [0][0][2][0][RTW89_ACMA][1][57] = 127, + [0][0][2][0][RTW89_ACMA][0][57] = 127, + [0][0][2][0][RTW89_CHILE][1][57] = 22, + [0][0][2][0][RTW89_QATAR][1][57] = 127, + [0][0][2][0][RTW89_QATAR][0][57] = 127, + [0][0][2][0][RTW89_UK][1][57] = 127, + [0][0][2][0][RTW89_UK][0][57] = 127, + [0][0][2][0][RTW89_FCC][1][59] = 22, + [0][0][2][0][RTW89_FCC][2][59] = 68, + [0][0][2][0][RTW89_ETSI][1][59] = 127, + [0][0][2][0][RTW89_ETSI][0][59] = 127, + [0][0][2][0][RTW89_MKK][1][59] = 127, + [0][0][2][0][RTW89_MKK][0][59] = 127, + [0][0][2][0][RTW89_IC][1][59] = 22, + [0][0][2][0][RTW89_KCC][1][59] = 26, + [0][0][2][0][RTW89_KCC][0][59] = 127, + [0][0][2][0][RTW89_ACMA][1][59] = 127, + [0][0][2][0][RTW89_ACMA][0][59] = 127, + [0][0][2][0][RTW89_CHILE][1][59] = 22, + [0][0][2][0][RTW89_QATAR][1][59] = 127, + [0][0][2][0][RTW89_QATAR][0][59] = 127, + [0][0][2][0][RTW89_UK][1][59] = 127, + [0][0][2][0][RTW89_UK][0][59] = 127, + [0][0][2][0][RTW89_FCC][1][60] = 22, + [0][0][2][0][RTW89_FCC][2][60] = 68, + [0][0][2][0][RTW89_ETSI][1][60] = 127, + [0][0][2][0][RTW89_ETSI][0][60] = 127, + [0][0][2][0][RTW89_MKK][1][60] = 127, + [0][0][2][0][RTW89_MKK][0][60] = 127, + [0][0][2][0][RTW89_IC][1][60] = 22, + [0][0][2][0][RTW89_KCC][1][60] = 26, + [0][0][2][0][RTW89_KCC][0][60] = 127, + [0][0][2][0][RTW89_ACMA][1][60] = 127, + [0][0][2][0][RTW89_ACMA][0][60] = 127, + [0][0][2][0][RTW89_CHILE][1][60] = 22, + [0][0][2][0][RTW89_QATAR][1][60] = 127, + [0][0][2][0][RTW89_QATAR][0][60] = 127, + [0][0][2][0][RTW89_UK][1][60] = 127, + [0][0][2][0][RTW89_UK][0][60] = 127, + [0][0][2][0][RTW89_FCC][1][62] = 22, + [0][0][2][0][RTW89_FCC][2][62] = 68, + [0][0][2][0][RTW89_ETSI][1][62] = 127, + [0][0][2][0][RTW89_ETSI][0][62] = 127, + [0][0][2][0][RTW89_MKK][1][62] = 127, + [0][0][2][0][RTW89_MKK][0][62] = 127, + [0][0][2][0][RTW89_IC][1][62] = 22, + [0][0][2][0][RTW89_KCC][1][62] = 26, + [0][0][2][0][RTW89_KCC][0][62] = 127, + [0][0][2][0][RTW89_ACMA][1][62] = 127, + [0][0][2][0][RTW89_ACMA][0][62] = 127, + [0][0][2][0][RTW89_CHILE][1][62] = 22, + [0][0][2][0][RTW89_QATAR][1][62] = 127, + [0][0][2][0][RTW89_QATAR][0][62] = 127, + [0][0][2][0][RTW89_UK][1][62] = 127, + [0][0][2][0][RTW89_UK][0][62] = 127, + [0][0][2][0][RTW89_FCC][1][64] = 22, + [0][0][2][0][RTW89_FCC][2][64] = 68, + [0][0][2][0][RTW89_ETSI][1][64] = 127, + [0][0][2][0][RTW89_ETSI][0][64] = 127, + [0][0][2][0][RTW89_MKK][1][64] = 127, + [0][0][2][0][RTW89_MKK][0][64] = 127, + [0][0][2][0][RTW89_IC][1][64] = 22, + [0][0][2][0][RTW89_KCC][1][64] = 26, + [0][0][2][0][RTW89_KCC][0][64] = 127, + [0][0][2][0][RTW89_ACMA][1][64] = 127, + [0][0][2][0][RTW89_ACMA][0][64] = 127, + [0][0][2][0][RTW89_CHILE][1][64] = 22, + [0][0][2][0][RTW89_QATAR][1][64] = 127, + [0][0][2][0][RTW89_QATAR][0][64] = 127, + [0][0][2][0][RTW89_UK][1][64] = 127, + [0][0][2][0][RTW89_UK][0][64] = 127, + [0][0][2][0][RTW89_FCC][1][66] = 22, + [0][0][2][0][RTW89_FCC][2][66] = 68, + [0][0][2][0][RTW89_ETSI][1][66] = 127, + [0][0][2][0][RTW89_ETSI][0][66] = 127, + [0][0][2][0][RTW89_MKK][1][66] = 127, + [0][0][2][0][RTW89_MKK][0][66] = 127, + [0][0][2][0][RTW89_IC][1][66] = 22, + [0][0][2][0][RTW89_KCC][1][66] = 26, + [0][0][2][0][RTW89_KCC][0][66] = 127, + [0][0][2][0][RTW89_ACMA][1][66] = 127, + [0][0][2][0][RTW89_ACMA][0][66] = 127, + [0][0][2][0][RTW89_CHILE][1][66] = 22, + [0][0][2][0][RTW89_QATAR][1][66] = 127, + [0][0][2][0][RTW89_QATAR][0][66] = 127, + [0][0][2][0][RTW89_UK][1][66] = 127, + [0][0][2][0][RTW89_UK][0][66] = 127, + [0][0][2][0][RTW89_FCC][1][68] = 22, + [0][0][2][0][RTW89_FCC][2][68] = 68, + [0][0][2][0][RTW89_ETSI][1][68] = 127, + [0][0][2][0][RTW89_ETSI][0][68] = 127, + [0][0][2][0][RTW89_MKK][1][68] = 127, + [0][0][2][0][RTW89_MKK][0][68] = 127, + [0][0][2][0][RTW89_IC][1][68] = 22, + [0][0][2][0][RTW89_KCC][1][68] = 26, + [0][0][2][0][RTW89_KCC][0][68] = 127, + [0][0][2][0][RTW89_ACMA][1][68] = 127, + [0][0][2][0][RTW89_ACMA][0][68] = 127, + [0][0][2][0][RTW89_CHILE][1][68] = 22, + [0][0][2][0][RTW89_QATAR][1][68] = 127, + [0][0][2][0][RTW89_QATAR][0][68] = 127, + [0][0][2][0][RTW89_UK][1][68] = 127, + [0][0][2][0][RTW89_UK][0][68] = 127, + [0][0][2][0][RTW89_FCC][1][70] = 24, + [0][0][2][0][RTW89_FCC][2][70] = 68, + [0][0][2][0][RTW89_ETSI][1][70] = 127, + [0][0][2][0][RTW89_ETSI][0][70] = 127, + [0][0][2][0][RTW89_MKK][1][70] = 127, + [0][0][2][0][RTW89_MKK][0][70] = 127, + [0][0][2][0][RTW89_IC][1][70] = 24, + [0][0][2][0][RTW89_KCC][1][70] = 26, + [0][0][2][0][RTW89_KCC][0][70] = 127, + [0][0][2][0][RTW89_ACMA][1][70] = 127, + [0][0][2][0][RTW89_ACMA][0][70] = 127, + [0][0][2][0][RTW89_CHILE][1][70] = 24, + [0][0][2][0][RTW89_QATAR][1][70] = 127, + [0][0][2][0][RTW89_QATAR][0][70] = 127, + [0][0][2][0][RTW89_UK][1][70] = 127, + [0][0][2][0][RTW89_UK][0][70] = 127, + [0][0][2][0][RTW89_FCC][1][72] = 22, + [0][0][2][0][RTW89_FCC][2][72] = 68, + [0][0][2][0][RTW89_ETSI][1][72] = 127, + [0][0][2][0][RTW89_ETSI][0][72] = 127, + [0][0][2][0][RTW89_MKK][1][72] = 127, + [0][0][2][0][RTW89_MKK][0][72] = 127, + [0][0][2][0][RTW89_IC][1][72] = 22, + [0][0][2][0][RTW89_KCC][1][72] = 26, + [0][0][2][0][RTW89_KCC][0][72] = 127, + [0][0][2][0][RTW89_ACMA][1][72] = 127, + [0][0][2][0][RTW89_ACMA][0][72] = 127, + [0][0][2][0][RTW89_CHILE][1][72] = 22, + [0][0][2][0][RTW89_QATAR][1][72] = 127, + [0][0][2][0][RTW89_QATAR][0][72] = 127, + [0][0][2][0][RTW89_UK][1][72] = 127, + [0][0][2][0][RTW89_UK][0][72] = 127, + [0][0][2][0][RTW89_FCC][1][74] = 22, + [0][0][2][0][RTW89_FCC][2][74] = 68, + [0][0][2][0][RTW89_ETSI][1][74] = 127, + [0][0][2][0][RTW89_ETSI][0][74] = 127, + [0][0][2][0][RTW89_MKK][1][74] = 127, + [0][0][2][0][RTW89_MKK][0][74] = 127, + [0][0][2][0][RTW89_IC][1][74] = 22, + [0][0][2][0][RTW89_KCC][1][74] = 26, + [0][0][2][0][RTW89_KCC][0][74] = 127, + [0][0][2][0][RTW89_ACMA][1][74] = 127, + [0][0][2][0][RTW89_ACMA][0][74] = 127, + [0][0][2][0][RTW89_CHILE][1][74] = 22, + [0][0][2][0][RTW89_QATAR][1][74] = 127, + [0][0][2][0][RTW89_QATAR][0][74] = 127, + [0][0][2][0][RTW89_UK][1][74] = 127, + [0][0][2][0][RTW89_UK][0][74] = 127, + [0][0][2][0][RTW89_FCC][1][75] = 22, + [0][0][2][0][RTW89_FCC][2][75] = 68, + [0][0][2][0][RTW89_ETSI][1][75] = 127, + [0][0][2][0][RTW89_ETSI][0][75] = 127, + [0][0][2][0][RTW89_MKK][1][75] = 127, + [0][0][2][0][RTW89_MKK][0][75] = 127, + [0][0][2][0][RTW89_IC][1][75] = 22, + [0][0][2][0][RTW89_KCC][1][75] = 26, + [0][0][2][0][RTW89_KCC][0][75] = 127, + [0][0][2][0][RTW89_ACMA][1][75] = 127, + [0][0][2][0][RTW89_ACMA][0][75] = 127, + [0][0][2][0][RTW89_CHILE][1][75] = 22, + [0][0][2][0][RTW89_QATAR][1][75] = 127, + [0][0][2][0][RTW89_QATAR][0][75] = 127, + [0][0][2][0][RTW89_UK][1][75] = 127, + [0][0][2][0][RTW89_UK][0][75] = 127, + [0][0][2][0][RTW89_FCC][1][77] = 22, + [0][0][2][0][RTW89_FCC][2][77] = 68, + [0][0][2][0][RTW89_ETSI][1][77] = 127, + [0][0][2][0][RTW89_ETSI][0][77] = 127, + [0][0][2][0][RTW89_MKK][1][77] = 127, + [0][0][2][0][RTW89_MKK][0][77] = 127, + [0][0][2][0][RTW89_IC][1][77] = 22, + [0][0][2][0][RTW89_KCC][1][77] = 26, + [0][0][2][0][RTW89_KCC][0][77] = 127, + [0][0][2][0][RTW89_ACMA][1][77] = 127, + [0][0][2][0][RTW89_ACMA][0][77] = 127, + [0][0][2][0][RTW89_CHILE][1][77] = 22, + [0][0][2][0][RTW89_QATAR][1][77] = 127, + [0][0][2][0][RTW89_QATAR][0][77] = 127, + [0][0][2][0][RTW89_UK][1][77] = 127, + [0][0][2][0][RTW89_UK][0][77] = 127, + [0][0][2][0][RTW89_FCC][1][79] = 22, + [0][0][2][0][RTW89_FCC][2][79] = 68, + [0][0][2][0][RTW89_ETSI][1][79] = 127, + [0][0][2][0][RTW89_ETSI][0][79] = 127, + [0][0][2][0][RTW89_MKK][1][79] = 127, + [0][0][2][0][RTW89_MKK][0][79] = 127, + [0][0][2][0][RTW89_IC][1][79] = 22, + [0][0][2][0][RTW89_KCC][1][79] = 26, + [0][0][2][0][RTW89_KCC][0][79] = 127, + [0][0][2][0][RTW89_ACMA][1][79] = 127, + [0][0][2][0][RTW89_ACMA][0][79] = 127, + [0][0][2][0][RTW89_CHILE][1][79] = 22, + [0][0][2][0][RTW89_QATAR][1][79] = 127, + [0][0][2][0][RTW89_QATAR][0][79] = 127, + [0][0][2][0][RTW89_UK][1][79] = 127, + [0][0][2][0][RTW89_UK][0][79] = 127, + [0][0][2][0][RTW89_FCC][1][81] = 22, + [0][0][2][0][RTW89_FCC][2][81] = 68, + [0][0][2][0][RTW89_ETSI][1][81] = 127, + [0][0][2][0][RTW89_ETSI][0][81] = 127, + [0][0][2][0][RTW89_MKK][1][81] = 127, + [0][0][2][0][RTW89_MKK][0][81] = 127, + [0][0][2][0][RTW89_IC][1][81] = 22, + [0][0][2][0][RTW89_KCC][1][81] = 26, + [0][0][2][0][RTW89_KCC][0][81] = 127, + [0][0][2][0][RTW89_ACMA][1][81] = 127, + [0][0][2][0][RTW89_ACMA][0][81] = 127, + [0][0][2][0][RTW89_CHILE][1][81] = 22, + [0][0][2][0][RTW89_QATAR][1][81] = 127, + [0][0][2][0][RTW89_QATAR][0][81] = 127, + [0][0][2][0][RTW89_UK][1][81] = 127, + [0][0][2][0][RTW89_UK][0][81] = 127, + [0][0][2][0][RTW89_FCC][1][83] = 22, + [0][0][2][0][RTW89_FCC][2][83] = 68, + [0][0][2][0][RTW89_ETSI][1][83] = 127, + [0][0][2][0][RTW89_ETSI][0][83] = 127, + [0][0][2][0][RTW89_MKK][1][83] = 127, + [0][0][2][0][RTW89_MKK][0][83] = 127, + [0][0][2][0][RTW89_IC][1][83] = 22, + [0][0][2][0][RTW89_KCC][1][83] = 32, + [0][0][2][0][RTW89_KCC][0][83] = 127, + [0][0][2][0][RTW89_ACMA][1][83] = 127, + [0][0][2][0][RTW89_ACMA][0][83] = 127, + [0][0][2][0][RTW89_CHILE][1][83] = 22, + [0][0][2][0][RTW89_QATAR][1][83] = 127, + [0][0][2][0][RTW89_QATAR][0][83] = 127, + [0][0][2][0][RTW89_UK][1][83] = 127, + [0][0][2][0][RTW89_UK][0][83] = 127, + [0][0][2][0][RTW89_FCC][1][85] = 22, + [0][0][2][0][RTW89_FCC][2][85] = 68, + [0][0][2][0][RTW89_ETSI][1][85] = 127, + [0][0][2][0][RTW89_ETSI][0][85] = 127, + [0][0][2][0][RTW89_MKK][1][85] = 127, + [0][0][2][0][RTW89_MKK][0][85] = 127, + [0][0][2][0][RTW89_IC][1][85] = 22, + [0][0][2][0][RTW89_KCC][1][85] = 32, + [0][0][2][0][RTW89_KCC][0][85] = 127, + [0][0][2][0][RTW89_ACMA][1][85] = 127, + [0][0][2][0][RTW89_ACMA][0][85] = 127, + [0][0][2][0][RTW89_CHILE][1][85] = 22, + [0][0][2][0][RTW89_QATAR][1][85] = 127, + [0][0][2][0][RTW89_QATAR][0][85] = 127, + [0][0][2][0][RTW89_UK][1][85] = 127, + [0][0][2][0][RTW89_UK][0][85] = 127, + [0][0][2][0][RTW89_FCC][1][87] = 22, + [0][0][2][0][RTW89_FCC][2][87] = 127, + [0][0][2][0][RTW89_ETSI][1][87] = 127, + [0][0][2][0][RTW89_ETSI][0][87] = 127, + [0][0][2][0][RTW89_MKK][1][87] = 127, + [0][0][2][0][RTW89_MKK][0][87] = 127, + [0][0][2][0][RTW89_IC][1][87] = 22, + [0][0][2][0][RTW89_KCC][1][87] = 32, + [0][0][2][0][RTW89_KCC][0][87] = 127, + [0][0][2][0][RTW89_ACMA][1][87] = 127, + [0][0][2][0][RTW89_ACMA][0][87] = 127, + [0][0][2][0][RTW89_CHILE][1][87] = 22, + [0][0][2][0][RTW89_QATAR][1][87] = 127, + [0][0][2][0][RTW89_QATAR][0][87] = 127, + [0][0][2][0][RTW89_UK][1][87] = 127, + [0][0][2][0][RTW89_UK][0][87] = 127, + [0][0][2][0][RTW89_FCC][1][89] = 22, + [0][0][2][0][RTW89_FCC][2][89] = 127, + [0][0][2][0][RTW89_ETSI][1][89] = 127, + [0][0][2][0][RTW89_ETSI][0][89] = 127, + [0][0][2][0][RTW89_MKK][1][89] = 127, + [0][0][2][0][RTW89_MKK][0][89] = 127, + [0][0][2][0][RTW89_IC][1][89] = 22, + [0][0][2][0][RTW89_KCC][1][89] = 32, + [0][0][2][0][RTW89_KCC][0][89] = 127, + [0][0][2][0][RTW89_ACMA][1][89] = 127, + [0][0][2][0][RTW89_ACMA][0][89] = 127, + [0][0][2][0][RTW89_CHILE][1][89] = 22, + [0][0][2][0][RTW89_QATAR][1][89] = 127, + [0][0][2][0][RTW89_QATAR][0][89] = 127, + [0][0][2][0][RTW89_UK][1][89] = 127, + [0][0][2][0][RTW89_UK][0][89] = 127, + [0][0][2][0][RTW89_FCC][1][90] = 22, + [0][0][2][0][RTW89_FCC][2][90] = 127, + [0][0][2][0][RTW89_ETSI][1][90] = 127, + [0][0][2][0][RTW89_ETSI][0][90] = 127, + [0][0][2][0][RTW89_MKK][1][90] = 127, + [0][0][2][0][RTW89_MKK][0][90] = 127, + [0][0][2][0][RTW89_IC][1][90] = 22, + [0][0][2][0][RTW89_KCC][1][90] = 32, + [0][0][2][0][RTW89_KCC][0][90] = 127, + [0][0][2][0][RTW89_ACMA][1][90] = 127, + [0][0][2][0][RTW89_ACMA][0][90] = 127, + [0][0][2][0][RTW89_CHILE][1][90] = 22, + [0][0][2][0][RTW89_QATAR][1][90] = 127, + [0][0][2][0][RTW89_QATAR][0][90] = 127, + [0][0][2][0][RTW89_UK][1][90] = 127, + [0][0][2][0][RTW89_UK][0][90] = 127, + [0][0][2][0][RTW89_FCC][1][92] = 22, + [0][0][2][0][RTW89_FCC][2][92] = 127, + [0][0][2][0][RTW89_ETSI][1][92] = 127, + [0][0][2][0][RTW89_ETSI][0][92] = 127, + [0][0][2][0][RTW89_MKK][1][92] = 127, + [0][0][2][0][RTW89_MKK][0][92] = 127, + [0][0][2][0][RTW89_IC][1][92] = 22, + [0][0][2][0][RTW89_KCC][1][92] = 32, + [0][0][2][0][RTW89_KCC][0][92] = 127, + [0][0][2][0][RTW89_ACMA][1][92] = 127, + [0][0][2][0][RTW89_ACMA][0][92] = 127, + [0][0][2][0][RTW89_CHILE][1][92] = 22, + [0][0][2][0][RTW89_QATAR][1][92] = 127, + [0][0][2][0][RTW89_QATAR][0][92] = 127, + [0][0][2][0][RTW89_UK][1][92] = 127, + [0][0][2][0][RTW89_UK][0][92] = 127, + [0][0][2][0][RTW89_FCC][1][94] = 22, + [0][0][2][0][RTW89_FCC][2][94] = 127, + [0][0][2][0][RTW89_ETSI][1][94] = 127, + [0][0][2][0][RTW89_ETSI][0][94] = 127, + [0][0][2][0][RTW89_MKK][1][94] = 127, + [0][0][2][0][RTW89_MKK][0][94] = 127, + [0][0][2][0][RTW89_IC][1][94] = 22, + [0][0][2][0][RTW89_KCC][1][94] = 32, + [0][0][2][0][RTW89_KCC][0][94] = 127, + [0][0][2][0][RTW89_ACMA][1][94] = 127, + [0][0][2][0][RTW89_ACMA][0][94] = 127, + [0][0][2][0][RTW89_CHILE][1][94] = 22, + [0][0][2][0][RTW89_QATAR][1][94] = 127, + [0][0][2][0][RTW89_QATAR][0][94] = 127, + [0][0][2][0][RTW89_UK][1][94] = 127, + [0][0][2][0][RTW89_UK][0][94] = 127, + [0][0][2][0][RTW89_FCC][1][96] = 22, + [0][0][2][0][RTW89_FCC][2][96] = 127, + [0][0][2][0][RTW89_ETSI][1][96] = 127, + [0][0][2][0][RTW89_ETSI][0][96] = 127, + [0][0][2][0][RTW89_MKK][1][96] = 127, + [0][0][2][0][RTW89_MKK][0][96] = 127, + [0][0][2][0][RTW89_IC][1][96] = 22, + [0][0][2][0][RTW89_KCC][1][96] = 32, + [0][0][2][0][RTW89_KCC][0][96] = 127, + [0][0][2][0][RTW89_ACMA][1][96] = 127, + [0][0][2][0][RTW89_ACMA][0][96] = 127, + [0][0][2][0][RTW89_CHILE][1][96] = 22, + [0][0][2][0][RTW89_QATAR][1][96] = 127, + [0][0][2][0][RTW89_QATAR][0][96] = 127, + [0][0][2][0][RTW89_UK][1][96] = 127, + [0][0][2][0][RTW89_UK][0][96] = 127, + [0][0][2][0][RTW89_FCC][1][98] = 22, + [0][0][2][0][RTW89_FCC][2][98] = 127, + [0][0][2][0][RTW89_ETSI][1][98] = 127, + [0][0][2][0][RTW89_ETSI][0][98] = 127, + [0][0][2][0][RTW89_MKK][1][98] = 127, + [0][0][2][0][RTW89_MKK][0][98] = 127, + [0][0][2][0][RTW89_IC][1][98] = 22, + [0][0][2][0][RTW89_KCC][1][98] = 32, + [0][0][2][0][RTW89_KCC][0][98] = 127, + [0][0][2][0][RTW89_ACMA][1][98] = 127, + [0][0][2][0][RTW89_ACMA][0][98] = 127, + [0][0][2][0][RTW89_CHILE][1][98] = 22, + [0][0][2][0][RTW89_QATAR][1][98] = 127, + [0][0][2][0][RTW89_QATAR][0][98] = 127, + [0][0][2][0][RTW89_UK][1][98] = 127, + [0][0][2][0][RTW89_UK][0][98] = 127, + [0][0][2][0][RTW89_FCC][1][100] = 22, + [0][0][2][0][RTW89_FCC][2][100] = 127, + [0][0][2][0][RTW89_ETSI][1][100] = 127, + [0][0][2][0][RTW89_ETSI][0][100] = 127, + [0][0][2][0][RTW89_MKK][1][100] = 127, + [0][0][2][0][RTW89_MKK][0][100] = 127, + [0][0][2][0][RTW89_IC][1][100] = 22, + [0][0][2][0][RTW89_KCC][1][100] = 32, + [0][0][2][0][RTW89_KCC][0][100] = 127, + [0][0][2][0][RTW89_ACMA][1][100] = 127, + [0][0][2][0][RTW89_ACMA][0][100] = 127, + [0][0][2][0][RTW89_CHILE][1][100] = 22, + [0][0][2][0][RTW89_QATAR][1][100] = 127, + [0][0][2][0][RTW89_QATAR][0][100] = 127, + [0][0][2][0][RTW89_UK][1][100] = 127, + [0][0][2][0][RTW89_UK][0][100] = 127, + [0][0][2][0][RTW89_FCC][1][102] = 22, + [0][0][2][0][RTW89_FCC][2][102] = 127, + [0][0][2][0][RTW89_ETSI][1][102] = 127, + [0][0][2][0][RTW89_ETSI][0][102] = 127, + [0][0][2][0][RTW89_MKK][1][102] = 127, + [0][0][2][0][RTW89_MKK][0][102] = 127, + [0][0][2][0][RTW89_IC][1][102] = 22, + [0][0][2][0][RTW89_KCC][1][102] = 32, + [0][0][2][0][RTW89_KCC][0][102] = 127, + [0][0][2][0][RTW89_ACMA][1][102] = 127, + [0][0][2][0][RTW89_ACMA][0][102] = 127, + [0][0][2][0][RTW89_CHILE][1][102] = 22, + [0][0][2][0][RTW89_QATAR][1][102] = 127, + [0][0][2][0][RTW89_QATAR][0][102] = 127, + [0][0][2][0][RTW89_UK][1][102] = 127, + [0][0][2][0][RTW89_UK][0][102] = 127, + [0][0][2][0][RTW89_FCC][1][104] = 22, + [0][0][2][0][RTW89_FCC][2][104] = 127, + [0][0][2][0][RTW89_ETSI][1][104] = 127, + [0][0][2][0][RTW89_ETSI][0][104] = 127, + [0][0][2][0][RTW89_MKK][1][104] = 127, + [0][0][2][0][RTW89_MKK][0][104] = 127, + [0][0][2][0][RTW89_IC][1][104] = 22, + [0][0][2][0][RTW89_KCC][1][104] = 32, + [0][0][2][0][RTW89_KCC][0][104] = 127, + [0][0][2][0][RTW89_ACMA][1][104] = 127, + [0][0][2][0][RTW89_ACMA][0][104] = 127, + [0][0][2][0][RTW89_CHILE][1][104] = 22, + [0][0][2][0][RTW89_QATAR][1][104] = 127, + [0][0][2][0][RTW89_QATAR][0][104] = 127, + [0][0][2][0][RTW89_UK][1][104] = 127, + [0][0][2][0][RTW89_UK][0][104] = 127, + [0][0][2][0][RTW89_FCC][1][105] = 22, + [0][0][2][0][RTW89_FCC][2][105] = 127, + [0][0][2][0][RTW89_ETSI][1][105] = 127, + [0][0][2][0][RTW89_ETSI][0][105] = 127, + [0][0][2][0][RTW89_MKK][1][105] = 127, + [0][0][2][0][RTW89_MKK][0][105] = 127, + [0][0][2][0][RTW89_IC][1][105] = 22, + [0][0][2][0][RTW89_KCC][1][105] = 32, + [0][0][2][0][RTW89_KCC][0][105] = 127, + [0][0][2][0][RTW89_ACMA][1][105] = 127, + [0][0][2][0][RTW89_ACMA][0][105] = 127, + [0][0][2][0][RTW89_CHILE][1][105] = 22, + [0][0][2][0][RTW89_QATAR][1][105] = 127, + [0][0][2][0][RTW89_QATAR][0][105] = 127, + [0][0][2][0][RTW89_UK][1][105] = 127, + [0][0][2][0][RTW89_UK][0][105] = 127, + [0][0][2][0][RTW89_FCC][1][107] = 24, + [0][0][2][0][RTW89_FCC][2][107] = 127, + [0][0][2][0][RTW89_ETSI][1][107] = 127, + [0][0][2][0][RTW89_ETSI][0][107] = 127, + [0][0][2][0][RTW89_MKK][1][107] = 127, + [0][0][2][0][RTW89_MKK][0][107] = 127, + [0][0][2][0][RTW89_IC][1][107] = 24, + [0][0][2][0][RTW89_KCC][1][107] = 32, + [0][0][2][0][RTW89_KCC][0][107] = 127, + [0][0][2][0][RTW89_ACMA][1][107] = 127, + [0][0][2][0][RTW89_ACMA][0][107] = 127, + [0][0][2][0][RTW89_CHILE][1][107] = 24, + [0][0][2][0][RTW89_QATAR][1][107] = 127, + [0][0][2][0][RTW89_QATAR][0][107] = 127, + [0][0][2][0][RTW89_UK][1][107] = 127, + [0][0][2][0][RTW89_UK][0][107] = 127, + [0][0][2][0][RTW89_FCC][1][109] = 24, + [0][0][2][0][RTW89_FCC][2][109] = 127, + [0][0][2][0][RTW89_ETSI][1][109] = 127, + [0][0][2][0][RTW89_ETSI][0][109] = 127, + [0][0][2][0][RTW89_MKK][1][109] = 127, + [0][0][2][0][RTW89_MKK][0][109] = 127, + [0][0][2][0][RTW89_IC][1][109] = 24, + [0][0][2][0][RTW89_KCC][1][109] = 32, + [0][0][2][0][RTW89_KCC][0][109] = 127, + [0][0][2][0][RTW89_ACMA][1][109] = 127, + [0][0][2][0][RTW89_ACMA][0][109] = 127, + [0][0][2][0][RTW89_CHILE][1][109] = 24, + [0][0][2][0][RTW89_QATAR][1][109] = 127, + [0][0][2][0][RTW89_QATAR][0][109] = 127, + [0][0][2][0][RTW89_UK][1][109] = 127, + [0][0][2][0][RTW89_UK][0][109] = 127, + [0][0][2][0][RTW89_FCC][1][111] = 127, + [0][0][2][0][RTW89_FCC][2][111] = 127, + [0][0][2][0][RTW89_ETSI][1][111] = 127, + [0][0][2][0][RTW89_ETSI][0][111] = 127, + [0][0][2][0][RTW89_MKK][1][111] = 127, + [0][0][2][0][RTW89_MKK][0][111] = 127, + [0][0][2][0][RTW89_IC][1][111] = 127, + [0][0][2][0][RTW89_KCC][1][111] = 127, + [0][0][2][0][RTW89_KCC][0][111] = 127, + [0][0][2][0][RTW89_ACMA][1][111] = 127, + [0][0][2][0][RTW89_ACMA][0][111] = 127, + [0][0][2][0][RTW89_CHILE][1][111] = 127, + [0][0][2][0][RTW89_QATAR][1][111] = 127, + [0][0][2][0][RTW89_QATAR][0][111] = 127, + [0][0][2][0][RTW89_UK][1][111] = 127, + [0][0][2][0][RTW89_UK][0][111] = 127, + [0][0][2][0][RTW89_FCC][1][113] = 127, + [0][0][2][0][RTW89_FCC][2][113] = 127, + [0][0][2][0][RTW89_ETSI][1][113] = 127, + [0][0][2][0][RTW89_ETSI][0][113] = 127, + [0][0][2][0][RTW89_MKK][1][113] = 127, + [0][0][2][0][RTW89_MKK][0][113] = 127, + [0][0][2][0][RTW89_IC][1][113] = 127, + [0][0][2][0][RTW89_KCC][1][113] = 127, + [0][0][2][0][RTW89_KCC][0][113] = 127, + [0][0][2][0][RTW89_ACMA][1][113] = 127, + [0][0][2][0][RTW89_ACMA][0][113] = 127, + [0][0][2][0][RTW89_CHILE][1][113] = 127, + [0][0][2][0][RTW89_QATAR][1][113] = 127, + [0][0][2][0][RTW89_QATAR][0][113] = 127, + [0][0][2][0][RTW89_UK][1][113] = 127, + [0][0][2][0][RTW89_UK][0][113] = 127, + [0][0][2][0][RTW89_FCC][1][115] = 127, + [0][0][2][0][RTW89_FCC][2][115] = 127, + [0][0][2][0][RTW89_ETSI][1][115] = 127, + [0][0][2][0][RTW89_ETSI][0][115] = 127, + [0][0][2][0][RTW89_MKK][1][115] = 127, + [0][0][2][0][RTW89_MKK][0][115] = 127, + [0][0][2][0][RTW89_IC][1][115] = 127, + [0][0][2][0][RTW89_KCC][1][115] = 127, + [0][0][2][0][RTW89_KCC][0][115] = 127, + [0][0][2][0][RTW89_ACMA][1][115] = 127, + [0][0][2][0][RTW89_ACMA][0][115] = 127, + [0][0][2][0][RTW89_CHILE][1][115] = 127, + [0][0][2][0][RTW89_QATAR][1][115] = 127, + [0][0][2][0][RTW89_QATAR][0][115] = 127, + [0][0][2][0][RTW89_UK][1][115] = 127, + [0][0][2][0][RTW89_UK][0][115] = 127, + [0][0][2][0][RTW89_FCC][1][117] = 127, + [0][0][2][0][RTW89_FCC][2][117] = 127, + [0][0][2][0][RTW89_ETSI][1][117] = 127, + [0][0][2][0][RTW89_ETSI][0][117] = 127, + [0][0][2][0][RTW89_MKK][1][117] = 127, + [0][0][2][0][RTW89_MKK][0][117] = 127, + [0][0][2][0][RTW89_IC][1][117] = 127, + [0][0][2][0][RTW89_KCC][1][117] = 127, + [0][0][2][0][RTW89_KCC][0][117] = 127, + [0][0][2][0][RTW89_ACMA][1][117] = 127, + [0][0][2][0][RTW89_ACMA][0][117] = 127, + [0][0][2][0][RTW89_CHILE][1][117] = 127, + [0][0][2][0][RTW89_QATAR][1][117] = 127, + [0][0][2][0][RTW89_QATAR][0][117] = 127, + [0][0][2][0][RTW89_UK][1][117] = 127, + [0][0][2][0][RTW89_UK][0][117] = 127, + [0][0][2][0][RTW89_FCC][1][119] = 127, + [0][0][2][0][RTW89_FCC][2][119] = 127, + [0][0][2][0][RTW89_ETSI][1][119] = 127, + [0][0][2][0][RTW89_ETSI][0][119] = 127, + [0][0][2][0][RTW89_MKK][1][119] = 127, + [0][0][2][0][RTW89_MKK][0][119] = 127, + [0][0][2][0][RTW89_IC][1][119] = 127, + [0][0][2][0][RTW89_KCC][1][119] = 127, + [0][0][2][0][RTW89_KCC][0][119] = 127, + [0][0][2][0][RTW89_ACMA][1][119] = 127, + [0][0][2][0][RTW89_ACMA][0][119] = 127, + [0][0][2][0][RTW89_CHILE][1][119] = 127, + [0][0][2][0][RTW89_QATAR][1][119] = 127, + [0][0][2][0][RTW89_QATAR][0][119] = 127, + [0][0][2][0][RTW89_UK][1][119] = 127, + [0][0][2][0][RTW89_UK][0][119] = 127, + [0][1][2][0][RTW89_FCC][1][0] = -2, + [0][1][2][0][RTW89_FCC][2][0] = 54, + [0][1][2][0][RTW89_ETSI][1][0] = 54, + [0][1][2][0][RTW89_ETSI][0][0] = 18, + [0][1][2][0][RTW89_MKK][1][0] = 56, + [0][1][2][0][RTW89_MKK][0][0] = 16, + [0][1][2][0][RTW89_IC][1][0] = -2, + [0][1][2][0][RTW89_KCC][1][0] = 12, + [0][1][2][0][RTW89_KCC][0][0] = 10, + [0][1][2][0][RTW89_ACMA][1][0] = 54, + [0][1][2][0][RTW89_ACMA][0][0] = 18, + [0][1][2][0][RTW89_CHILE][1][0] = -2, + [0][1][2][0][RTW89_QATAR][1][0] = 54, + [0][1][2][0][RTW89_QATAR][0][0] = 18, + [0][1][2][0][RTW89_UK][1][0] = 54, + [0][1][2][0][RTW89_UK][0][0] = 18, + [0][1][2][0][RTW89_FCC][1][2] = -4, + [0][1][2][0][RTW89_FCC][2][2] = 54, + [0][1][2][0][RTW89_ETSI][1][2] = 54, + [0][1][2][0][RTW89_ETSI][0][2] = 18, + [0][1][2][0][RTW89_MKK][1][2] = 54, + [0][1][2][0][RTW89_MKK][0][2] = 16, + [0][1][2][0][RTW89_IC][1][2] = -4, + [0][1][2][0][RTW89_KCC][1][2] = 12, + [0][1][2][0][RTW89_KCC][0][2] = 12, + [0][1][2][0][RTW89_ACMA][1][2] = 54, + [0][1][2][0][RTW89_ACMA][0][2] = 18, + [0][1][2][0][RTW89_CHILE][1][2] = -4, + [0][1][2][0][RTW89_QATAR][1][2] = 54, + [0][1][2][0][RTW89_QATAR][0][2] = 18, + [0][1][2][0][RTW89_UK][1][2] = 54, + [0][1][2][0][RTW89_UK][0][2] = 18, + [0][1][2][0][RTW89_FCC][1][4] = -4, + [0][1][2][0][RTW89_FCC][2][4] = 54, + [0][1][2][0][RTW89_ETSI][1][4] = 54, + [0][1][2][0][RTW89_ETSI][0][4] = 18, + [0][1][2][0][RTW89_MKK][1][4] = 54, + [0][1][2][0][RTW89_MKK][0][4] = 16, + [0][1][2][0][RTW89_IC][1][4] = -4, + [0][1][2][0][RTW89_KCC][1][4] = 12, + [0][1][2][0][RTW89_KCC][0][4] = 12, + [0][1][2][0][RTW89_ACMA][1][4] = 54, + [0][1][2][0][RTW89_ACMA][0][4] = 18, + [0][1][2][0][RTW89_CHILE][1][4] = -4, + [0][1][2][0][RTW89_QATAR][1][4] = 54, + [0][1][2][0][RTW89_QATAR][0][4] = 18, + [0][1][2][0][RTW89_UK][1][4] = 54, + [0][1][2][0][RTW89_UK][0][4] = 18, + [0][1][2][0][RTW89_FCC][1][6] = -4, + [0][1][2][0][RTW89_FCC][2][6] = 54, + [0][1][2][0][RTW89_ETSI][1][6] = 54, + [0][1][2][0][RTW89_ETSI][0][6] = 18, + [0][1][2][0][RTW89_MKK][1][6] = 54, + [0][1][2][0][RTW89_MKK][0][6] = 16, + [0][1][2][0][RTW89_IC][1][6] = -4, + [0][1][2][0][RTW89_KCC][1][6] = 12, + [0][1][2][0][RTW89_KCC][0][6] = 12, + [0][1][2][0][RTW89_ACMA][1][6] = 54, + [0][1][2][0][RTW89_ACMA][0][6] = 18, + [0][1][2][0][RTW89_CHILE][1][6] = -4, + [0][1][2][0][RTW89_QATAR][1][6] = 54, + [0][1][2][0][RTW89_QATAR][0][6] = 18, + [0][1][2][0][RTW89_UK][1][6] = 54, + [0][1][2][0][RTW89_UK][0][6] = 18, + [0][1][2][0][RTW89_FCC][1][8] = -4, + [0][1][2][0][RTW89_FCC][2][8] = 54, + [0][1][2][0][RTW89_ETSI][1][8] = 54, + [0][1][2][0][RTW89_ETSI][0][8] = 18, + [0][1][2][0][RTW89_MKK][1][8] = 54, + [0][1][2][0][RTW89_MKK][0][8] = 16, + [0][1][2][0][RTW89_IC][1][8] = -4, + [0][1][2][0][RTW89_KCC][1][8] = 12, + [0][1][2][0][RTW89_KCC][0][8] = 12, + [0][1][2][0][RTW89_ACMA][1][8] = 54, + [0][1][2][0][RTW89_ACMA][0][8] = 18, + [0][1][2][0][RTW89_CHILE][1][8] = -4, + [0][1][2][0][RTW89_QATAR][1][8] = 54, + [0][1][2][0][RTW89_QATAR][0][8] = 18, + [0][1][2][0][RTW89_UK][1][8] = 54, + [0][1][2][0][RTW89_UK][0][8] = 18, + [0][1][2][0][RTW89_FCC][1][10] = -4, + [0][1][2][0][RTW89_FCC][2][10] = 54, + [0][1][2][0][RTW89_ETSI][1][10] = 54, + [0][1][2][0][RTW89_ETSI][0][10] = 18, + [0][1][2][0][RTW89_MKK][1][10] = 54, + [0][1][2][0][RTW89_MKK][0][10] = 16, + [0][1][2][0][RTW89_IC][1][10] = -4, + [0][1][2][0][RTW89_KCC][1][10] = 12, + [0][1][2][0][RTW89_KCC][0][10] = 12, + [0][1][2][0][RTW89_ACMA][1][10] = 54, + [0][1][2][0][RTW89_ACMA][0][10] = 18, + [0][1][2][0][RTW89_CHILE][1][10] = -4, + [0][1][2][0][RTW89_QATAR][1][10] = 54, + [0][1][2][0][RTW89_QATAR][0][10] = 18, + [0][1][2][0][RTW89_UK][1][10] = 54, + [0][1][2][0][RTW89_UK][0][10] = 18, + [0][1][2][0][RTW89_FCC][1][12] = -4, + [0][1][2][0][RTW89_FCC][2][12] = 54, + [0][1][2][0][RTW89_ETSI][1][12] = 54, + [0][1][2][0][RTW89_ETSI][0][12] = 18, + [0][1][2][0][RTW89_MKK][1][12] = 54, + [0][1][2][0][RTW89_MKK][0][12] = 16, + [0][1][2][0][RTW89_IC][1][12] = -4, + [0][1][2][0][RTW89_KCC][1][12] = 12, + [0][1][2][0][RTW89_KCC][0][12] = 12, + [0][1][2][0][RTW89_ACMA][1][12] = 54, + [0][1][2][0][RTW89_ACMA][0][12] = 18, + [0][1][2][0][RTW89_CHILE][1][12] = -4, + [0][1][2][0][RTW89_QATAR][1][12] = 54, + [0][1][2][0][RTW89_QATAR][0][12] = 18, + [0][1][2][0][RTW89_UK][1][12] = 54, + [0][1][2][0][RTW89_UK][0][12] = 18, + [0][1][2][0][RTW89_FCC][1][14] = -4, + [0][1][2][0][RTW89_FCC][2][14] = 54, + [0][1][2][0][RTW89_ETSI][1][14] = 54, + [0][1][2][0][RTW89_ETSI][0][14] = 18, + [0][1][2][0][RTW89_MKK][1][14] = 54, + [0][1][2][0][RTW89_MKK][0][14] = 16, + [0][1][2][0][RTW89_IC][1][14] = -4, + [0][1][2][0][RTW89_KCC][1][14] = 12, + [0][1][2][0][RTW89_KCC][0][14] = 12, + [0][1][2][0][RTW89_ACMA][1][14] = 54, + [0][1][2][0][RTW89_ACMA][0][14] = 18, + [0][1][2][0][RTW89_CHILE][1][14] = -4, + [0][1][2][0][RTW89_QATAR][1][14] = 54, + [0][1][2][0][RTW89_QATAR][0][14] = 18, + [0][1][2][0][RTW89_UK][1][14] = 54, + [0][1][2][0][RTW89_UK][0][14] = 18, + [0][1][2][0][RTW89_FCC][1][15] = -4, + [0][1][2][0][RTW89_FCC][2][15] = 54, + [0][1][2][0][RTW89_ETSI][1][15] = 54, + [0][1][2][0][RTW89_ETSI][0][15] = 18, + [0][1][2][0][RTW89_MKK][1][15] = 54, + [0][1][2][0][RTW89_MKK][0][15] = 16, + [0][1][2][0][RTW89_IC][1][15] = -4, + [0][1][2][0][RTW89_KCC][1][15] = 12, + [0][1][2][0][RTW89_KCC][0][15] = 12, + [0][1][2][0][RTW89_ACMA][1][15] = 54, + [0][1][2][0][RTW89_ACMA][0][15] = 18, + [0][1][2][0][RTW89_CHILE][1][15] = -4, + [0][1][2][0][RTW89_QATAR][1][15] = 54, + [0][1][2][0][RTW89_QATAR][0][15] = 18, + [0][1][2][0][RTW89_UK][1][15] = 54, + [0][1][2][0][RTW89_UK][0][15] = 18, + [0][1][2][0][RTW89_FCC][1][17] = -4, + [0][1][2][0][RTW89_FCC][2][17] = 54, + [0][1][2][0][RTW89_ETSI][1][17] = 54, + [0][1][2][0][RTW89_ETSI][0][17] = 18, + [0][1][2][0][RTW89_MKK][1][17] = 54, + [0][1][2][0][RTW89_MKK][0][17] = 16, + [0][1][2][0][RTW89_IC][1][17] = -4, + [0][1][2][0][RTW89_KCC][1][17] = 12, + [0][1][2][0][RTW89_KCC][0][17] = 12, + [0][1][2][0][RTW89_ACMA][1][17] = 54, + [0][1][2][0][RTW89_ACMA][0][17] = 18, + [0][1][2][0][RTW89_CHILE][1][17] = -4, + [0][1][2][0][RTW89_QATAR][1][17] = 54, + [0][1][2][0][RTW89_QATAR][0][17] = 18, + [0][1][2][0][RTW89_UK][1][17] = 54, + [0][1][2][0][RTW89_UK][0][17] = 18, + [0][1][2][0][RTW89_FCC][1][19] = -4, + [0][1][2][0][RTW89_FCC][2][19] = 54, + [0][1][2][0][RTW89_ETSI][1][19] = 54, + [0][1][2][0][RTW89_ETSI][0][19] = 18, + [0][1][2][0][RTW89_MKK][1][19] = 54, + [0][1][2][0][RTW89_MKK][0][19] = 16, + [0][1][2][0][RTW89_IC][1][19] = -4, + [0][1][2][0][RTW89_KCC][1][19] = 12, + [0][1][2][0][RTW89_KCC][0][19] = 12, + [0][1][2][0][RTW89_ACMA][1][19] = 54, + [0][1][2][0][RTW89_ACMA][0][19] = 18, + [0][1][2][0][RTW89_CHILE][1][19] = -4, + [0][1][2][0][RTW89_QATAR][1][19] = 54, + [0][1][2][0][RTW89_QATAR][0][19] = 18, + [0][1][2][0][RTW89_UK][1][19] = 54, + [0][1][2][0][RTW89_UK][0][19] = 18, + [0][1][2][0][RTW89_FCC][1][21] = -4, + [0][1][2][0][RTW89_FCC][2][21] = 54, + [0][1][2][0][RTW89_ETSI][1][21] = 54, + [0][1][2][0][RTW89_ETSI][0][21] = 18, + [0][1][2][0][RTW89_MKK][1][21] = 54, + [0][1][2][0][RTW89_MKK][0][21] = 16, + [0][1][2][0][RTW89_IC][1][21] = -4, + [0][1][2][0][RTW89_KCC][1][21] = 12, + [0][1][2][0][RTW89_KCC][0][21] = 12, + [0][1][2][0][RTW89_ACMA][1][21] = 54, + [0][1][2][0][RTW89_ACMA][0][21] = 18, + [0][1][2][0][RTW89_CHILE][1][21] = -4, + [0][1][2][0][RTW89_QATAR][1][21] = 54, + [0][1][2][0][RTW89_QATAR][0][21] = 18, + [0][1][2][0][RTW89_UK][1][21] = 54, + [0][1][2][0][RTW89_UK][0][21] = 18, + [0][1][2][0][RTW89_FCC][1][23] = -4, + [0][1][2][0][RTW89_FCC][2][23] = 68, + [0][1][2][0][RTW89_ETSI][1][23] = 54, + [0][1][2][0][RTW89_ETSI][0][23] = 18, + [0][1][2][0][RTW89_MKK][1][23] = 54, + [0][1][2][0][RTW89_MKK][0][23] = 16, + [0][1][2][0][RTW89_IC][1][23] = -4, + [0][1][2][0][RTW89_KCC][1][23] = 12, + [0][1][2][0][RTW89_KCC][0][23] = 10, + [0][1][2][0][RTW89_ACMA][1][23] = 54, + [0][1][2][0][RTW89_ACMA][0][23] = 18, + [0][1][2][0][RTW89_CHILE][1][23] = -4, + [0][1][2][0][RTW89_QATAR][1][23] = 54, + [0][1][2][0][RTW89_QATAR][0][23] = 18, + [0][1][2][0][RTW89_UK][1][23] = 54, + [0][1][2][0][RTW89_UK][0][23] = 18, + [0][1][2][0][RTW89_FCC][1][25] = -4, + [0][1][2][0][RTW89_FCC][2][25] = 68, + [0][1][2][0][RTW89_ETSI][1][25] = 54, + [0][1][2][0][RTW89_ETSI][0][25] = 18, + [0][1][2][0][RTW89_MKK][1][25] = 54, + [0][1][2][0][RTW89_MKK][0][25] = 16, + [0][1][2][0][RTW89_IC][1][25] = -4, + [0][1][2][0][RTW89_KCC][1][25] = 12, + [0][1][2][0][RTW89_KCC][0][25] = 14, + [0][1][2][0][RTW89_ACMA][1][25] = 54, + [0][1][2][0][RTW89_ACMA][0][25] = 18, + [0][1][2][0][RTW89_CHILE][1][25] = -4, + [0][1][2][0][RTW89_QATAR][1][25] = 54, + [0][1][2][0][RTW89_QATAR][0][25] = 18, + [0][1][2][0][RTW89_UK][1][25] = 54, + [0][1][2][0][RTW89_UK][0][25] = 18, + [0][1][2][0][RTW89_FCC][1][27] = -4, + [0][1][2][0][RTW89_FCC][2][27] = 68, + [0][1][2][0][RTW89_ETSI][1][27] = 54, + [0][1][2][0][RTW89_ETSI][0][27] = 18, + [0][1][2][0][RTW89_MKK][1][27] = 54, + [0][1][2][0][RTW89_MKK][0][27] = 16, + [0][1][2][0][RTW89_IC][1][27] = -4, + [0][1][2][0][RTW89_KCC][1][27] = 12, + [0][1][2][0][RTW89_KCC][0][27] = 14, + [0][1][2][0][RTW89_ACMA][1][27] = 54, + [0][1][2][0][RTW89_ACMA][0][27] = 18, + [0][1][2][0][RTW89_CHILE][1][27] = -4, + [0][1][2][0][RTW89_QATAR][1][27] = 54, + [0][1][2][0][RTW89_QATAR][0][27] = 18, + [0][1][2][0][RTW89_UK][1][27] = 54, + [0][1][2][0][RTW89_UK][0][27] = 18, + [0][1][2][0][RTW89_FCC][1][29] = -4, + [0][1][2][0][RTW89_FCC][2][29] = 68, + [0][1][2][0][RTW89_ETSI][1][29] = 54, + [0][1][2][0][RTW89_ETSI][0][29] = 18, + [0][1][2][0][RTW89_MKK][1][29] = 54, + [0][1][2][0][RTW89_MKK][0][29] = 16, + [0][1][2][0][RTW89_IC][1][29] = -4, + [0][1][2][0][RTW89_KCC][1][29] = 12, + [0][1][2][0][RTW89_KCC][0][29] = 14, + [0][1][2][0][RTW89_ACMA][1][29] = 54, + [0][1][2][0][RTW89_ACMA][0][29] = 18, + [0][1][2][0][RTW89_CHILE][1][29] = -4, + [0][1][2][0][RTW89_QATAR][1][29] = 54, + [0][1][2][0][RTW89_QATAR][0][29] = 18, + [0][1][2][0][RTW89_UK][1][29] = 54, + [0][1][2][0][RTW89_UK][0][29] = 18, + [0][1][2][0][RTW89_FCC][1][30] = -4, + [0][1][2][0][RTW89_FCC][2][30] = 68, + [0][1][2][0][RTW89_ETSI][1][30] = 54, + [0][1][2][0][RTW89_ETSI][0][30] = 18, + [0][1][2][0][RTW89_MKK][1][30] = 54, + [0][1][2][0][RTW89_MKK][0][30] = 16, + [0][1][2][0][RTW89_IC][1][30] = -4, + [0][1][2][0][RTW89_KCC][1][30] = 12, + [0][1][2][0][RTW89_KCC][0][30] = 14, + [0][1][2][0][RTW89_ACMA][1][30] = 54, + [0][1][2][0][RTW89_ACMA][0][30] = 18, + [0][1][2][0][RTW89_CHILE][1][30] = -4, + [0][1][2][0][RTW89_QATAR][1][30] = 54, + [0][1][2][0][RTW89_QATAR][0][30] = 18, + [0][1][2][0][RTW89_UK][1][30] = 54, + [0][1][2][0][RTW89_UK][0][30] = 18, + [0][1][2][0][RTW89_FCC][1][32] = -4, + [0][1][2][0][RTW89_FCC][2][32] = 68, + [0][1][2][0][RTW89_ETSI][1][32] = 54, + [0][1][2][0][RTW89_ETSI][0][32] = 18, + [0][1][2][0][RTW89_MKK][1][32] = 54, + [0][1][2][0][RTW89_MKK][0][32] = 16, + [0][1][2][0][RTW89_IC][1][32] = -4, + [0][1][2][0][RTW89_KCC][1][32] = 12, + [0][1][2][0][RTW89_KCC][0][32] = 14, + [0][1][2][0][RTW89_ACMA][1][32] = 54, + [0][1][2][0][RTW89_ACMA][0][32] = 18, + [0][1][2][0][RTW89_CHILE][1][32] = -4, + [0][1][2][0][RTW89_QATAR][1][32] = 54, + [0][1][2][0][RTW89_QATAR][0][32] = 18, + [0][1][2][0][RTW89_UK][1][32] = 54, + [0][1][2][0][RTW89_UK][0][32] = 18, + [0][1][2][0][RTW89_FCC][1][34] = -4, + [0][1][2][0][RTW89_FCC][2][34] = 68, + [0][1][2][0][RTW89_ETSI][1][34] = 54, + [0][1][2][0][RTW89_ETSI][0][34] = 18, + [0][1][2][0][RTW89_MKK][1][34] = 54, + [0][1][2][0][RTW89_MKK][0][34] = 16, + [0][1][2][0][RTW89_IC][1][34] = -4, + [0][1][2][0][RTW89_KCC][1][34] = 12, + [0][1][2][0][RTW89_KCC][0][34] = 14, + [0][1][2][0][RTW89_ACMA][1][34] = 54, + [0][1][2][0][RTW89_ACMA][0][34] = 18, + [0][1][2][0][RTW89_CHILE][1][34] = -4, + [0][1][2][0][RTW89_QATAR][1][34] = 54, + [0][1][2][0][RTW89_QATAR][0][34] = 18, + [0][1][2][0][RTW89_UK][1][34] = 54, + [0][1][2][0][RTW89_UK][0][34] = 18, + [0][1][2][0][RTW89_FCC][1][36] = -4, + [0][1][2][0][RTW89_FCC][2][36] = 68, + [0][1][2][0][RTW89_ETSI][1][36] = 54, + [0][1][2][0][RTW89_ETSI][0][36] = 18, + [0][1][2][0][RTW89_MKK][1][36] = 54, + [0][1][2][0][RTW89_MKK][0][36] = 16, + [0][1][2][0][RTW89_IC][1][36] = -4, + [0][1][2][0][RTW89_KCC][1][36] = 12, + [0][1][2][0][RTW89_KCC][0][36] = 14, + [0][1][2][0][RTW89_ACMA][1][36] = 54, + [0][1][2][0][RTW89_ACMA][0][36] = 18, + [0][1][2][0][RTW89_CHILE][1][36] = -4, + [0][1][2][0][RTW89_QATAR][1][36] = 54, + [0][1][2][0][RTW89_QATAR][0][36] = 18, + [0][1][2][0][RTW89_UK][1][36] = 54, + [0][1][2][0][RTW89_UK][0][36] = 18, + [0][1][2][0][RTW89_FCC][1][38] = -4, + [0][1][2][0][RTW89_FCC][2][38] = 68, + [0][1][2][0][RTW89_ETSI][1][38] = 54, + [0][1][2][0][RTW89_ETSI][0][38] = 18, + [0][1][2][0][RTW89_MKK][1][38] = 54, + [0][1][2][0][RTW89_MKK][0][38] = 16, + [0][1][2][0][RTW89_IC][1][38] = -4, + [0][1][2][0][RTW89_KCC][1][38] = 12, + [0][1][2][0][RTW89_KCC][0][38] = 14, + [0][1][2][0][RTW89_ACMA][1][38] = 54, + [0][1][2][0][RTW89_ACMA][0][38] = 18, + [0][1][2][0][RTW89_CHILE][1][38] = -4, + [0][1][2][0][RTW89_QATAR][1][38] = 54, + [0][1][2][0][RTW89_QATAR][0][38] = 18, + [0][1][2][0][RTW89_UK][1][38] = 54, + [0][1][2][0][RTW89_UK][0][38] = 18, + [0][1][2][0][RTW89_FCC][1][40] = -4, + [0][1][2][0][RTW89_FCC][2][40] = 68, + [0][1][2][0][RTW89_ETSI][1][40] = 54, + [0][1][2][0][RTW89_ETSI][0][40] = 18, + [0][1][2][0][RTW89_MKK][1][40] = 54, + [0][1][2][0][RTW89_MKK][0][40] = 16, + [0][1][2][0][RTW89_IC][1][40] = -4, + [0][1][2][0][RTW89_KCC][1][40] = 12, + [0][1][2][0][RTW89_KCC][0][40] = 14, + [0][1][2][0][RTW89_ACMA][1][40] = 54, + [0][1][2][0][RTW89_ACMA][0][40] = 18, + [0][1][2][0][RTW89_CHILE][1][40] = -4, + [0][1][2][0][RTW89_QATAR][1][40] = 54, + [0][1][2][0][RTW89_QATAR][0][40] = 18, + [0][1][2][0][RTW89_UK][1][40] = 54, + [0][1][2][0][RTW89_UK][0][40] = 18, + [0][1][2][0][RTW89_FCC][1][42] = -4, + [0][1][2][0][RTW89_FCC][2][42] = 68, + [0][1][2][0][RTW89_ETSI][1][42] = 54, + [0][1][2][0][RTW89_ETSI][0][42] = 18, + [0][1][2][0][RTW89_MKK][1][42] = 54, + [0][1][2][0][RTW89_MKK][0][42] = 16, + [0][1][2][0][RTW89_IC][1][42] = -4, + [0][1][2][0][RTW89_KCC][1][42] = 12, + [0][1][2][0][RTW89_KCC][0][42] = 14, + [0][1][2][0][RTW89_ACMA][1][42] = 54, + [0][1][2][0][RTW89_ACMA][0][42] = 18, + [0][1][2][0][RTW89_CHILE][1][42] = -4, + [0][1][2][0][RTW89_QATAR][1][42] = 54, + [0][1][2][0][RTW89_QATAR][0][42] = 18, + [0][1][2][0][RTW89_UK][1][42] = 54, + [0][1][2][0][RTW89_UK][0][42] = 18, + [0][1][2][0][RTW89_FCC][1][44] = -2, + [0][1][2][0][RTW89_FCC][2][44] = 68, + [0][1][2][0][RTW89_ETSI][1][44] = 54, + [0][1][2][0][RTW89_ETSI][0][44] = 18, + [0][1][2][0][RTW89_MKK][1][44] = 34, + [0][1][2][0][RTW89_MKK][0][44] = 16, + [0][1][2][0][RTW89_IC][1][44] = -2, + [0][1][2][0][RTW89_KCC][1][44] = 12, + [0][1][2][0][RTW89_KCC][0][44] = 12, + [0][1][2][0][RTW89_ACMA][1][44] = 54, + [0][1][2][0][RTW89_ACMA][0][44] = 18, + [0][1][2][0][RTW89_CHILE][1][44] = -2, + [0][1][2][0][RTW89_QATAR][1][44] = 54, + [0][1][2][0][RTW89_QATAR][0][44] = 18, + [0][1][2][0][RTW89_UK][1][44] = 54, + [0][1][2][0][RTW89_UK][0][44] = 18, + [0][1][2][0][RTW89_FCC][1][45] = -2, + [0][1][2][0][RTW89_FCC][2][45] = 127, + [0][1][2][0][RTW89_ETSI][1][45] = 127, + [0][1][2][0][RTW89_ETSI][0][45] = 127, + [0][1][2][0][RTW89_MKK][1][45] = 127, + [0][1][2][0][RTW89_MKK][0][45] = 127, + [0][1][2][0][RTW89_IC][1][45] = -2, + [0][1][2][0][RTW89_KCC][1][45] = 12, + [0][1][2][0][RTW89_KCC][0][45] = 127, + [0][1][2][0][RTW89_ACMA][1][45] = 127, + [0][1][2][0][RTW89_ACMA][0][45] = 127, + [0][1][2][0][RTW89_CHILE][1][45] = -2, + [0][1][2][0][RTW89_QATAR][1][45] = 127, + [0][1][2][0][RTW89_QATAR][0][45] = 127, + [0][1][2][0][RTW89_UK][1][45] = 127, + [0][1][2][0][RTW89_UK][0][45] = 127, + [0][1][2][0][RTW89_FCC][1][47] = -2, + [0][1][2][0][RTW89_FCC][2][47] = 127, + [0][1][2][0][RTW89_ETSI][1][47] = 127, + [0][1][2][0][RTW89_ETSI][0][47] = 127, + [0][1][2][0][RTW89_MKK][1][47] = 127, + [0][1][2][0][RTW89_MKK][0][47] = 127, + [0][1][2][0][RTW89_IC][1][47] = -2, + [0][1][2][0][RTW89_KCC][1][47] = 12, + [0][1][2][0][RTW89_KCC][0][47] = 127, + [0][1][2][0][RTW89_ACMA][1][47] = 127, + [0][1][2][0][RTW89_ACMA][0][47] = 127, + [0][1][2][0][RTW89_CHILE][1][47] = -2, + [0][1][2][0][RTW89_QATAR][1][47] = 127, + [0][1][2][0][RTW89_QATAR][0][47] = 127, + [0][1][2][0][RTW89_UK][1][47] = 127, + [0][1][2][0][RTW89_UK][0][47] = 127, + [0][1][2][0][RTW89_FCC][1][49] = -2, + [0][1][2][0][RTW89_FCC][2][49] = 127, + [0][1][2][0][RTW89_ETSI][1][49] = 127, + [0][1][2][0][RTW89_ETSI][0][49] = 127, + [0][1][2][0][RTW89_MKK][1][49] = 127, + [0][1][2][0][RTW89_MKK][0][49] = 127, + [0][1][2][0][RTW89_IC][1][49] = -2, + [0][1][2][0][RTW89_KCC][1][49] = 12, + [0][1][2][0][RTW89_KCC][0][49] = 127, + [0][1][2][0][RTW89_ACMA][1][49] = 127, + [0][1][2][0][RTW89_ACMA][0][49] = 127, + [0][1][2][0][RTW89_CHILE][1][49] = -2, + [0][1][2][0][RTW89_QATAR][1][49] = 127, + [0][1][2][0][RTW89_QATAR][0][49] = 127, + [0][1][2][0][RTW89_UK][1][49] = 127, + [0][1][2][0][RTW89_UK][0][49] = 127, + [0][1][2][0][RTW89_FCC][1][51] = -2, + [0][1][2][0][RTW89_FCC][2][51] = 127, + [0][1][2][0][RTW89_ETSI][1][51] = 127, + [0][1][2][0][RTW89_ETSI][0][51] = 127, + [0][1][2][0][RTW89_MKK][1][51] = 127, + [0][1][2][0][RTW89_MKK][0][51] = 127, + [0][1][2][0][RTW89_IC][1][51] = -2, + [0][1][2][0][RTW89_KCC][1][51] = 12, + [0][1][2][0][RTW89_KCC][0][51] = 127, + [0][1][2][0][RTW89_ACMA][1][51] = 127, + [0][1][2][0][RTW89_ACMA][0][51] = 127, + [0][1][2][0][RTW89_CHILE][1][51] = -2, + [0][1][2][0][RTW89_QATAR][1][51] = 127, + [0][1][2][0][RTW89_QATAR][0][51] = 127, + [0][1][2][0][RTW89_UK][1][51] = 127, + [0][1][2][0][RTW89_UK][0][51] = 127, + [0][1][2][0][RTW89_FCC][1][53] = -2, + [0][1][2][0][RTW89_FCC][2][53] = 127, + [0][1][2][0][RTW89_ETSI][1][53] = 127, + [0][1][2][0][RTW89_ETSI][0][53] = 127, + [0][1][2][0][RTW89_MKK][1][53] = 127, + [0][1][2][0][RTW89_MKK][0][53] = 127, + [0][1][2][0][RTW89_IC][1][53] = -2, + [0][1][2][0][RTW89_KCC][1][53] = 12, + [0][1][2][0][RTW89_KCC][0][53] = 127, + [0][1][2][0][RTW89_ACMA][1][53] = 127, + [0][1][2][0][RTW89_ACMA][0][53] = 127, + [0][1][2][0][RTW89_CHILE][1][53] = -2, + [0][1][2][0][RTW89_QATAR][1][53] = 127, + [0][1][2][0][RTW89_QATAR][0][53] = 127, + [0][1][2][0][RTW89_UK][1][53] = 127, + [0][1][2][0][RTW89_UK][0][53] = 127, + [0][1][2][0][RTW89_FCC][1][55] = -2, + [0][1][2][0][RTW89_FCC][2][55] = 68, + [0][1][2][0][RTW89_ETSI][1][55] = 127, + [0][1][2][0][RTW89_ETSI][0][55] = 127, + [0][1][2][0][RTW89_MKK][1][55] = 127, + [0][1][2][0][RTW89_MKK][0][55] = 127, + [0][1][2][0][RTW89_IC][1][55] = -2, + [0][1][2][0][RTW89_KCC][1][55] = 12, + [0][1][2][0][RTW89_KCC][0][55] = 127, + [0][1][2][0][RTW89_ACMA][1][55] = 127, + [0][1][2][0][RTW89_ACMA][0][55] = 127, + [0][1][2][0][RTW89_CHILE][1][55] = -2, + [0][1][2][0][RTW89_QATAR][1][55] = 127, + [0][1][2][0][RTW89_QATAR][0][55] = 127, + [0][1][2][0][RTW89_UK][1][55] = 127, + [0][1][2][0][RTW89_UK][0][55] = 127, + [0][1][2][0][RTW89_FCC][1][57] = -2, + [0][1][2][0][RTW89_FCC][2][57] = 68, + [0][1][2][0][RTW89_ETSI][1][57] = 127, + [0][1][2][0][RTW89_ETSI][0][57] = 127, + [0][1][2][0][RTW89_MKK][1][57] = 127, + [0][1][2][0][RTW89_MKK][0][57] = 127, + [0][1][2][0][RTW89_IC][1][57] = -2, + [0][1][2][0][RTW89_KCC][1][57] = 12, + [0][1][2][0][RTW89_KCC][0][57] = 127, + [0][1][2][0][RTW89_ACMA][1][57] = 127, + [0][1][2][0][RTW89_ACMA][0][57] = 127, + [0][1][2][0][RTW89_CHILE][1][57] = -2, + [0][1][2][0][RTW89_QATAR][1][57] = 127, + [0][1][2][0][RTW89_QATAR][0][57] = 127, + [0][1][2][0][RTW89_UK][1][57] = 127, + [0][1][2][0][RTW89_UK][0][57] = 127, + [0][1][2][0][RTW89_FCC][1][59] = -2, + [0][1][2][0][RTW89_FCC][2][59] = 68, + [0][1][2][0][RTW89_ETSI][1][59] = 127, + [0][1][2][0][RTW89_ETSI][0][59] = 127, + [0][1][2][0][RTW89_MKK][1][59] = 127, + [0][1][2][0][RTW89_MKK][0][59] = 127, + [0][1][2][0][RTW89_IC][1][59] = -2, + [0][1][2][0][RTW89_KCC][1][59] = 12, + [0][1][2][0][RTW89_KCC][0][59] = 127, + [0][1][2][0][RTW89_ACMA][1][59] = 127, + [0][1][2][0][RTW89_ACMA][0][59] = 127, + [0][1][2][0][RTW89_CHILE][1][59] = -2, + [0][1][2][0][RTW89_QATAR][1][59] = 127, + [0][1][2][0][RTW89_QATAR][0][59] = 127, + [0][1][2][0][RTW89_UK][1][59] = 127, + [0][1][2][0][RTW89_UK][0][59] = 127, + [0][1][2][0][RTW89_FCC][1][60] = -2, + [0][1][2][0][RTW89_FCC][2][60] = 68, + [0][1][2][0][RTW89_ETSI][1][60] = 127, + [0][1][2][0][RTW89_ETSI][0][60] = 127, + [0][1][2][0][RTW89_MKK][1][60] = 127, + [0][1][2][0][RTW89_MKK][0][60] = 127, + [0][1][2][0][RTW89_IC][1][60] = -2, + [0][1][2][0][RTW89_KCC][1][60] = 12, + [0][1][2][0][RTW89_KCC][0][60] = 127, + [0][1][2][0][RTW89_ACMA][1][60] = 127, + [0][1][2][0][RTW89_ACMA][0][60] = 127, + [0][1][2][0][RTW89_CHILE][1][60] = -2, + [0][1][2][0][RTW89_QATAR][1][60] = 127, + [0][1][2][0][RTW89_QATAR][0][60] = 127, + [0][1][2][0][RTW89_UK][1][60] = 127, + [0][1][2][0][RTW89_UK][0][60] = 127, + [0][1][2][0][RTW89_FCC][1][62] = -2, + [0][1][2][0][RTW89_FCC][2][62] = 68, + [0][1][2][0][RTW89_ETSI][1][62] = 127, + [0][1][2][0][RTW89_ETSI][0][62] = 127, + [0][1][2][0][RTW89_MKK][1][62] = 127, + [0][1][2][0][RTW89_MKK][0][62] = 127, + [0][1][2][0][RTW89_IC][1][62] = -2, + [0][1][2][0][RTW89_KCC][1][62] = 12, + [0][1][2][0][RTW89_KCC][0][62] = 127, + [0][1][2][0][RTW89_ACMA][1][62] = 127, + [0][1][2][0][RTW89_ACMA][0][62] = 127, + [0][1][2][0][RTW89_CHILE][1][62] = -2, + [0][1][2][0][RTW89_QATAR][1][62] = 127, + [0][1][2][0][RTW89_QATAR][0][62] = 127, + [0][1][2][0][RTW89_UK][1][62] = 127, + [0][1][2][0][RTW89_UK][0][62] = 127, + [0][1][2][0][RTW89_FCC][1][64] = -2, + [0][1][2][0][RTW89_FCC][2][64] = 68, + [0][1][2][0][RTW89_ETSI][1][64] = 127, + [0][1][2][0][RTW89_ETSI][0][64] = 127, + [0][1][2][0][RTW89_MKK][1][64] = 127, + [0][1][2][0][RTW89_MKK][0][64] = 127, + [0][1][2][0][RTW89_IC][1][64] = -2, + [0][1][2][0][RTW89_KCC][1][64] = 12, + [0][1][2][0][RTW89_KCC][0][64] = 127, + [0][1][2][0][RTW89_ACMA][1][64] = 127, + [0][1][2][0][RTW89_ACMA][0][64] = 127, + [0][1][2][0][RTW89_CHILE][1][64] = -2, + [0][1][2][0][RTW89_QATAR][1][64] = 127, + [0][1][2][0][RTW89_QATAR][0][64] = 127, + [0][1][2][0][RTW89_UK][1][64] = 127, + [0][1][2][0][RTW89_UK][0][64] = 127, + [0][1][2][0][RTW89_FCC][1][66] = -2, + [0][1][2][0][RTW89_FCC][2][66] = 68, + [0][1][2][0][RTW89_ETSI][1][66] = 127, + [0][1][2][0][RTW89_ETSI][0][66] = 127, + [0][1][2][0][RTW89_MKK][1][66] = 127, + [0][1][2][0][RTW89_MKK][0][66] = 127, + [0][1][2][0][RTW89_IC][1][66] = -2, + [0][1][2][0][RTW89_KCC][1][66] = 12, + [0][1][2][0][RTW89_KCC][0][66] = 127, + [0][1][2][0][RTW89_ACMA][1][66] = 127, + [0][1][2][0][RTW89_ACMA][0][66] = 127, + [0][1][2][0][RTW89_CHILE][1][66] = -2, + [0][1][2][0][RTW89_QATAR][1][66] = 127, + [0][1][2][0][RTW89_QATAR][0][66] = 127, + [0][1][2][0][RTW89_UK][1][66] = 127, + [0][1][2][0][RTW89_UK][0][66] = 127, + [0][1][2][0][RTW89_FCC][1][68] = -2, + [0][1][2][0][RTW89_FCC][2][68] = 68, + [0][1][2][0][RTW89_ETSI][1][68] = 127, + [0][1][2][0][RTW89_ETSI][0][68] = 127, + [0][1][2][0][RTW89_MKK][1][68] = 127, + [0][1][2][0][RTW89_MKK][0][68] = 127, + [0][1][2][0][RTW89_IC][1][68] = -2, + [0][1][2][0][RTW89_KCC][1][68] = 12, + [0][1][2][0][RTW89_KCC][0][68] = 127, + [0][1][2][0][RTW89_ACMA][1][68] = 127, + [0][1][2][0][RTW89_ACMA][0][68] = 127, + [0][1][2][0][RTW89_CHILE][1][68] = -2, + [0][1][2][0][RTW89_QATAR][1][68] = 127, + [0][1][2][0][RTW89_QATAR][0][68] = 127, + [0][1][2][0][RTW89_UK][1][68] = 127, + [0][1][2][0][RTW89_UK][0][68] = 127, + [0][1][2][0][RTW89_FCC][1][70] = -2, + [0][1][2][0][RTW89_FCC][2][70] = 68, + [0][1][2][0][RTW89_ETSI][1][70] = 127, + [0][1][2][0][RTW89_ETSI][0][70] = 127, + [0][1][2][0][RTW89_MKK][1][70] = 127, + [0][1][2][0][RTW89_MKK][0][70] = 127, + [0][1][2][0][RTW89_IC][1][70] = -2, + [0][1][2][0][RTW89_KCC][1][70] = 12, + [0][1][2][0][RTW89_KCC][0][70] = 127, + [0][1][2][0][RTW89_ACMA][1][70] = 127, + [0][1][2][0][RTW89_ACMA][0][70] = 127, + [0][1][2][0][RTW89_CHILE][1][70] = -2, + [0][1][2][0][RTW89_QATAR][1][70] = 127, + [0][1][2][0][RTW89_QATAR][0][70] = 127, + [0][1][2][0][RTW89_UK][1][70] = 127, + [0][1][2][0][RTW89_UK][0][70] = 127, + [0][1][2][0][RTW89_FCC][1][72] = -2, + [0][1][2][0][RTW89_FCC][2][72] = 68, + [0][1][2][0][RTW89_ETSI][1][72] = 127, + [0][1][2][0][RTW89_ETSI][0][72] = 127, + [0][1][2][0][RTW89_MKK][1][72] = 127, + [0][1][2][0][RTW89_MKK][0][72] = 127, + [0][1][2][0][RTW89_IC][1][72] = -2, + [0][1][2][0][RTW89_KCC][1][72] = 12, + [0][1][2][0][RTW89_KCC][0][72] = 127, + [0][1][2][0][RTW89_ACMA][1][72] = 127, + [0][1][2][0][RTW89_ACMA][0][72] = 127, + [0][1][2][0][RTW89_CHILE][1][72] = -2, + [0][1][2][0][RTW89_QATAR][1][72] = 127, + [0][1][2][0][RTW89_QATAR][0][72] = 127, + [0][1][2][0][RTW89_UK][1][72] = 127, + [0][1][2][0][RTW89_UK][0][72] = 127, + [0][1][2][0][RTW89_FCC][1][74] = -2, + [0][1][2][0][RTW89_FCC][2][74] = 68, + [0][1][2][0][RTW89_ETSI][1][74] = 127, + [0][1][2][0][RTW89_ETSI][0][74] = 127, + [0][1][2][0][RTW89_MKK][1][74] = 127, + [0][1][2][0][RTW89_MKK][0][74] = 127, + [0][1][2][0][RTW89_IC][1][74] = -2, + [0][1][2][0][RTW89_KCC][1][74] = 12, + [0][1][2][0][RTW89_KCC][0][74] = 127, + [0][1][2][0][RTW89_ACMA][1][74] = 127, + [0][1][2][0][RTW89_ACMA][0][74] = 127, + [0][1][2][0][RTW89_CHILE][1][74] = -2, + [0][1][2][0][RTW89_QATAR][1][74] = 127, + [0][1][2][0][RTW89_QATAR][0][74] = 127, + [0][1][2][0][RTW89_UK][1][74] = 127, + [0][1][2][0][RTW89_UK][0][74] = 127, + [0][1][2][0][RTW89_FCC][1][75] = -2, + [0][1][2][0][RTW89_FCC][2][75] = 68, + [0][1][2][0][RTW89_ETSI][1][75] = 127, + [0][1][2][0][RTW89_ETSI][0][75] = 127, + [0][1][2][0][RTW89_MKK][1][75] = 127, + [0][1][2][0][RTW89_MKK][0][75] = 127, + [0][1][2][0][RTW89_IC][1][75] = -2, + [0][1][2][0][RTW89_KCC][1][75] = 12, + [0][1][2][0][RTW89_KCC][0][75] = 127, + [0][1][2][0][RTW89_ACMA][1][75] = 127, + [0][1][2][0][RTW89_ACMA][0][75] = 127, + [0][1][2][0][RTW89_CHILE][1][75] = -2, + [0][1][2][0][RTW89_QATAR][1][75] = 127, + [0][1][2][0][RTW89_QATAR][0][75] = 127, + [0][1][2][0][RTW89_UK][1][75] = 127, + [0][1][2][0][RTW89_UK][0][75] = 127, + [0][1][2][0][RTW89_FCC][1][77] = -2, + [0][1][2][0][RTW89_FCC][2][77] = 68, + [0][1][2][0][RTW89_ETSI][1][77] = 127, + [0][1][2][0][RTW89_ETSI][0][77] = 127, + [0][1][2][0][RTW89_MKK][1][77] = 127, + [0][1][2][0][RTW89_MKK][0][77] = 127, + [0][1][2][0][RTW89_IC][1][77] = -2, + [0][1][2][0][RTW89_KCC][1][77] = 12, + [0][1][2][0][RTW89_KCC][0][77] = 127, + [0][1][2][0][RTW89_ACMA][1][77] = 127, + [0][1][2][0][RTW89_ACMA][0][77] = 127, + [0][1][2][0][RTW89_CHILE][1][77] = -2, + [0][1][2][0][RTW89_QATAR][1][77] = 127, + [0][1][2][0][RTW89_QATAR][0][77] = 127, + [0][1][2][0][RTW89_UK][1][77] = 127, + [0][1][2][0][RTW89_UK][0][77] = 127, + [0][1][2][0][RTW89_FCC][1][79] = -2, + [0][1][2][0][RTW89_FCC][2][79] = 68, + [0][1][2][0][RTW89_ETSI][1][79] = 127, + [0][1][2][0][RTW89_ETSI][0][79] = 127, + [0][1][2][0][RTW89_MKK][1][79] = 127, + [0][1][2][0][RTW89_MKK][0][79] = 127, + [0][1][2][0][RTW89_IC][1][79] = -2, + [0][1][2][0][RTW89_KCC][1][79] = 12, + [0][1][2][0][RTW89_KCC][0][79] = 127, + [0][1][2][0][RTW89_ACMA][1][79] = 127, + [0][1][2][0][RTW89_ACMA][0][79] = 127, + [0][1][2][0][RTW89_CHILE][1][79] = -2, + [0][1][2][0][RTW89_QATAR][1][79] = 127, + [0][1][2][0][RTW89_QATAR][0][79] = 127, + [0][1][2][0][RTW89_UK][1][79] = 127, + [0][1][2][0][RTW89_UK][0][79] = 127, + [0][1][2][0][RTW89_FCC][1][81] = -2, + [0][1][2][0][RTW89_FCC][2][81] = 68, + [0][1][2][0][RTW89_ETSI][1][81] = 127, + [0][1][2][0][RTW89_ETSI][0][81] = 127, + [0][1][2][0][RTW89_MKK][1][81] = 127, + [0][1][2][0][RTW89_MKK][0][81] = 127, + [0][1][2][0][RTW89_IC][1][81] = -2, + [0][1][2][0][RTW89_KCC][1][81] = 12, + [0][1][2][0][RTW89_KCC][0][81] = 127, + [0][1][2][0][RTW89_ACMA][1][81] = 127, + [0][1][2][0][RTW89_ACMA][0][81] = 127, + [0][1][2][0][RTW89_CHILE][1][81] = -2, + [0][1][2][0][RTW89_QATAR][1][81] = 127, + [0][1][2][0][RTW89_QATAR][0][81] = 127, + [0][1][2][0][RTW89_UK][1][81] = 127, + [0][1][2][0][RTW89_UK][0][81] = 127, + [0][1][2][0][RTW89_FCC][1][83] = -2, + [0][1][2][0][RTW89_FCC][2][83] = 68, + [0][1][2][0][RTW89_ETSI][1][83] = 127, + [0][1][2][0][RTW89_ETSI][0][83] = 127, + [0][1][2][0][RTW89_MKK][1][83] = 127, + [0][1][2][0][RTW89_MKK][0][83] = 127, + [0][1][2][0][RTW89_IC][1][83] = -2, + [0][1][2][0][RTW89_KCC][1][83] = 20, + [0][1][2][0][RTW89_KCC][0][83] = 127, + [0][1][2][0][RTW89_ACMA][1][83] = 127, + [0][1][2][0][RTW89_ACMA][0][83] = 127, + [0][1][2][0][RTW89_CHILE][1][83] = -2, + [0][1][2][0][RTW89_QATAR][1][83] = 127, + [0][1][2][0][RTW89_QATAR][0][83] = 127, + [0][1][2][0][RTW89_UK][1][83] = 127, + [0][1][2][0][RTW89_UK][0][83] = 127, + [0][1][2][0][RTW89_FCC][1][85] = -2, + [0][1][2][0][RTW89_FCC][2][85] = 68, + [0][1][2][0][RTW89_ETSI][1][85] = 127, + [0][1][2][0][RTW89_ETSI][0][85] = 127, + [0][1][2][0][RTW89_MKK][1][85] = 127, + [0][1][2][0][RTW89_MKK][0][85] = 127, + [0][1][2][0][RTW89_IC][1][85] = -2, + [0][1][2][0][RTW89_KCC][1][85] = 20, + [0][1][2][0][RTW89_KCC][0][85] = 127, + [0][1][2][0][RTW89_ACMA][1][85] = 127, + [0][1][2][0][RTW89_ACMA][0][85] = 127, + [0][1][2][0][RTW89_CHILE][1][85] = -2, + [0][1][2][0][RTW89_QATAR][1][85] = 127, + [0][1][2][0][RTW89_QATAR][0][85] = 127, + [0][1][2][0][RTW89_UK][1][85] = 127, + [0][1][2][0][RTW89_UK][0][85] = 127, + [0][1][2][0][RTW89_FCC][1][87] = -2, + [0][1][2][0][RTW89_FCC][2][87] = 127, + [0][1][2][0][RTW89_ETSI][1][87] = 127, + [0][1][2][0][RTW89_ETSI][0][87] = 127, + [0][1][2][0][RTW89_MKK][1][87] = 127, + [0][1][2][0][RTW89_MKK][0][87] = 127, + [0][1][2][0][RTW89_IC][1][87] = -2, + [0][1][2][0][RTW89_KCC][1][87] = 20, + [0][1][2][0][RTW89_KCC][0][87] = 127, + [0][1][2][0][RTW89_ACMA][1][87] = 127, + [0][1][2][0][RTW89_ACMA][0][87] = 127, + [0][1][2][0][RTW89_CHILE][1][87] = -2, + [0][1][2][0][RTW89_QATAR][1][87] = 127, + [0][1][2][0][RTW89_QATAR][0][87] = 127, + [0][1][2][0][RTW89_UK][1][87] = 127, + [0][1][2][0][RTW89_UK][0][87] = 127, + [0][1][2][0][RTW89_FCC][1][89] = -2, + [0][1][2][0][RTW89_FCC][2][89] = 127, + [0][1][2][0][RTW89_ETSI][1][89] = 127, + [0][1][2][0][RTW89_ETSI][0][89] = 127, + [0][1][2][0][RTW89_MKK][1][89] = 127, + [0][1][2][0][RTW89_MKK][0][89] = 127, + [0][1][2][0][RTW89_IC][1][89] = -2, + [0][1][2][0][RTW89_KCC][1][89] = 20, + [0][1][2][0][RTW89_KCC][0][89] = 127, + [0][1][2][0][RTW89_ACMA][1][89] = 127, + [0][1][2][0][RTW89_ACMA][0][89] = 127, + [0][1][2][0][RTW89_CHILE][1][89] = -2, + [0][1][2][0][RTW89_QATAR][1][89] = 127, + [0][1][2][0][RTW89_QATAR][0][89] = 127, + [0][1][2][0][RTW89_UK][1][89] = 127, + [0][1][2][0][RTW89_UK][0][89] = 127, + [0][1][2][0][RTW89_FCC][1][90] = -2, + [0][1][2][0][RTW89_FCC][2][90] = 127, + [0][1][2][0][RTW89_ETSI][1][90] = 127, + [0][1][2][0][RTW89_ETSI][0][90] = 127, + [0][1][2][0][RTW89_MKK][1][90] = 127, + [0][1][2][0][RTW89_MKK][0][90] = 127, + [0][1][2][0][RTW89_IC][1][90] = -2, + [0][1][2][0][RTW89_KCC][1][90] = 20, + [0][1][2][0][RTW89_KCC][0][90] = 127, + [0][1][2][0][RTW89_ACMA][1][90] = 127, + [0][1][2][0][RTW89_ACMA][0][90] = 127, + [0][1][2][0][RTW89_CHILE][1][90] = -2, + [0][1][2][0][RTW89_QATAR][1][90] = 127, + [0][1][2][0][RTW89_QATAR][0][90] = 127, + [0][1][2][0][RTW89_UK][1][90] = 127, + [0][1][2][0][RTW89_UK][0][90] = 127, + [0][1][2][0][RTW89_FCC][1][92] = -2, + [0][1][2][0][RTW89_FCC][2][92] = 127, + [0][1][2][0][RTW89_ETSI][1][92] = 127, + [0][1][2][0][RTW89_ETSI][0][92] = 127, + [0][1][2][0][RTW89_MKK][1][92] = 127, + [0][1][2][0][RTW89_MKK][0][92] = 127, + [0][1][2][0][RTW89_IC][1][92] = -2, + [0][1][2][0][RTW89_KCC][1][92] = 20, + [0][1][2][0][RTW89_KCC][0][92] = 127, + [0][1][2][0][RTW89_ACMA][1][92] = 127, + [0][1][2][0][RTW89_ACMA][0][92] = 127, + [0][1][2][0][RTW89_CHILE][1][92] = -2, + [0][1][2][0][RTW89_QATAR][1][92] = 127, + [0][1][2][0][RTW89_QATAR][0][92] = 127, + [0][1][2][0][RTW89_UK][1][92] = 127, + [0][1][2][0][RTW89_UK][0][92] = 127, + [0][1][2][0][RTW89_FCC][1][94] = -2, + [0][1][2][0][RTW89_FCC][2][94] = 127, + [0][1][2][0][RTW89_ETSI][1][94] = 127, + [0][1][2][0][RTW89_ETSI][0][94] = 127, + [0][1][2][0][RTW89_MKK][1][94] = 127, + [0][1][2][0][RTW89_MKK][0][94] = 127, + [0][1][2][0][RTW89_IC][1][94] = -2, + [0][1][2][0][RTW89_KCC][1][94] = 20, + [0][1][2][0][RTW89_KCC][0][94] = 127, + [0][1][2][0][RTW89_ACMA][1][94] = 127, + [0][1][2][0][RTW89_ACMA][0][94] = 127, + [0][1][2][0][RTW89_CHILE][1][94] = -2, + [0][1][2][0][RTW89_QATAR][1][94] = 127, + [0][1][2][0][RTW89_QATAR][0][94] = 127, + [0][1][2][0][RTW89_UK][1][94] = 127, + [0][1][2][0][RTW89_UK][0][94] = 127, + [0][1][2][0][RTW89_FCC][1][96] = -2, + [0][1][2][0][RTW89_FCC][2][96] = 127, + [0][1][2][0][RTW89_ETSI][1][96] = 127, + [0][1][2][0][RTW89_ETSI][0][96] = 127, + [0][1][2][0][RTW89_MKK][1][96] = 127, + [0][1][2][0][RTW89_MKK][0][96] = 127, + [0][1][2][0][RTW89_IC][1][96] = -2, + [0][1][2][0][RTW89_KCC][1][96] = 20, + [0][1][2][0][RTW89_KCC][0][96] = 127, + [0][1][2][0][RTW89_ACMA][1][96] = 127, + [0][1][2][0][RTW89_ACMA][0][96] = 127, + [0][1][2][0][RTW89_CHILE][1][96] = -2, + [0][1][2][0][RTW89_QATAR][1][96] = 127, + [0][1][2][0][RTW89_QATAR][0][96] = 127, + [0][1][2][0][RTW89_UK][1][96] = 127, + [0][1][2][0][RTW89_UK][0][96] = 127, + [0][1][2][0][RTW89_FCC][1][98] = -2, + [0][1][2][0][RTW89_FCC][2][98] = 127, + [0][1][2][0][RTW89_ETSI][1][98] = 127, + [0][1][2][0][RTW89_ETSI][0][98] = 127, + [0][1][2][0][RTW89_MKK][1][98] = 127, + [0][1][2][0][RTW89_MKK][0][98] = 127, + [0][1][2][0][RTW89_IC][1][98] = -2, + [0][1][2][0][RTW89_KCC][1][98] = 20, + [0][1][2][0][RTW89_KCC][0][98] = 127, + [0][1][2][0][RTW89_ACMA][1][98] = 127, + [0][1][2][0][RTW89_ACMA][0][98] = 127, + [0][1][2][0][RTW89_CHILE][1][98] = -2, + [0][1][2][0][RTW89_QATAR][1][98] = 127, + [0][1][2][0][RTW89_QATAR][0][98] = 127, + [0][1][2][0][RTW89_UK][1][98] = 127, + [0][1][2][0][RTW89_UK][0][98] = 127, + [0][1][2][0][RTW89_FCC][1][100] = -2, + [0][1][2][0][RTW89_FCC][2][100] = 127, + [0][1][2][0][RTW89_ETSI][1][100] = 127, + [0][1][2][0][RTW89_ETSI][0][100] = 127, + [0][1][2][0][RTW89_MKK][1][100] = 127, + [0][1][2][0][RTW89_MKK][0][100] = 127, + [0][1][2][0][RTW89_IC][1][100] = -2, + [0][1][2][0][RTW89_KCC][1][100] = 20, + [0][1][2][0][RTW89_KCC][0][100] = 127, + [0][1][2][0][RTW89_ACMA][1][100] = 127, + [0][1][2][0][RTW89_ACMA][0][100] = 127, + [0][1][2][0][RTW89_CHILE][1][100] = -2, + [0][1][2][0][RTW89_QATAR][1][100] = 127, + [0][1][2][0][RTW89_QATAR][0][100] = 127, + [0][1][2][0][RTW89_UK][1][100] = 127, + [0][1][2][0][RTW89_UK][0][100] = 127, + [0][1][2][0][RTW89_FCC][1][102] = -2, + [0][1][2][0][RTW89_FCC][2][102] = 127, + [0][1][2][0][RTW89_ETSI][1][102] = 127, + [0][1][2][0][RTW89_ETSI][0][102] = 127, + [0][1][2][0][RTW89_MKK][1][102] = 127, + [0][1][2][0][RTW89_MKK][0][102] = 127, + [0][1][2][0][RTW89_IC][1][102] = -2, + [0][1][2][0][RTW89_KCC][1][102] = 20, + [0][1][2][0][RTW89_KCC][0][102] = 127, + [0][1][2][0][RTW89_ACMA][1][102] = 127, + [0][1][2][0][RTW89_ACMA][0][102] = 127, + [0][1][2][0][RTW89_CHILE][1][102] = -2, + [0][1][2][0][RTW89_QATAR][1][102] = 127, + [0][1][2][0][RTW89_QATAR][0][102] = 127, + [0][1][2][0][RTW89_UK][1][102] = 127, + [0][1][2][0][RTW89_UK][0][102] = 127, + [0][1][2][0][RTW89_FCC][1][104] = -2, + [0][1][2][0][RTW89_FCC][2][104] = 127, + [0][1][2][0][RTW89_ETSI][1][104] = 127, + [0][1][2][0][RTW89_ETSI][0][104] = 127, + [0][1][2][0][RTW89_MKK][1][104] = 127, + [0][1][2][0][RTW89_MKK][0][104] = 127, + [0][1][2][0][RTW89_IC][1][104] = -2, + [0][1][2][0][RTW89_KCC][1][104] = 20, + [0][1][2][0][RTW89_KCC][0][104] = 127, + [0][1][2][0][RTW89_ACMA][1][104] = 127, + [0][1][2][0][RTW89_ACMA][0][104] = 127, + [0][1][2][0][RTW89_CHILE][1][104] = -2, + [0][1][2][0][RTW89_QATAR][1][104] = 127, + [0][1][2][0][RTW89_QATAR][0][104] = 127, + [0][1][2][0][RTW89_UK][1][104] = 127, + [0][1][2][0][RTW89_UK][0][104] = 127, + [0][1][2][0][RTW89_FCC][1][105] = -2, + [0][1][2][0][RTW89_FCC][2][105] = 127, + [0][1][2][0][RTW89_ETSI][1][105] = 127, + [0][1][2][0][RTW89_ETSI][0][105] = 127, + [0][1][2][0][RTW89_MKK][1][105] = 127, + [0][1][2][0][RTW89_MKK][0][105] = 127, + [0][1][2][0][RTW89_IC][1][105] = -2, + [0][1][2][0][RTW89_KCC][1][105] = 20, + [0][1][2][0][RTW89_KCC][0][105] = 127, + [0][1][2][0][RTW89_ACMA][1][105] = 127, + [0][1][2][0][RTW89_ACMA][0][105] = 127, + [0][1][2][0][RTW89_CHILE][1][105] = -2, + [0][1][2][0][RTW89_QATAR][1][105] = 127, + [0][1][2][0][RTW89_QATAR][0][105] = 127, + [0][1][2][0][RTW89_UK][1][105] = 127, + [0][1][2][0][RTW89_UK][0][105] = 127, + [0][1][2][0][RTW89_FCC][1][107] = 1, + [0][1][2][0][RTW89_FCC][2][107] = 127, + [0][1][2][0][RTW89_ETSI][1][107] = 127, + [0][1][2][0][RTW89_ETSI][0][107] = 127, + [0][1][2][0][RTW89_MKK][1][107] = 127, + [0][1][2][0][RTW89_MKK][0][107] = 127, + [0][1][2][0][RTW89_IC][1][107] = 1, + [0][1][2][0][RTW89_KCC][1][107] = 20, + [0][1][2][0][RTW89_KCC][0][107] = 127, + [0][1][2][0][RTW89_ACMA][1][107] = 127, + [0][1][2][0][RTW89_ACMA][0][107] = 127, + [0][1][2][0][RTW89_CHILE][1][107] = 1, + [0][1][2][0][RTW89_QATAR][1][107] = 127, + [0][1][2][0][RTW89_QATAR][0][107] = 127, + [0][1][2][0][RTW89_UK][1][107] = 127, + [0][1][2][0][RTW89_UK][0][107] = 127, + [0][1][2][0][RTW89_FCC][1][109] = 1, + [0][1][2][0][RTW89_FCC][2][109] = 127, + [0][1][2][0][RTW89_ETSI][1][109] = 127, + [0][1][2][0][RTW89_ETSI][0][109] = 127, + [0][1][2][0][RTW89_MKK][1][109] = 127, + [0][1][2][0][RTW89_MKK][0][109] = 127, + [0][1][2][0][RTW89_IC][1][109] = 1, + [0][1][2][0][RTW89_KCC][1][109] = 20, + [0][1][2][0][RTW89_KCC][0][109] = 127, + [0][1][2][0][RTW89_ACMA][1][109] = 127, + [0][1][2][0][RTW89_ACMA][0][109] = 127, + [0][1][2][0][RTW89_CHILE][1][109] = 1, + [0][1][2][0][RTW89_QATAR][1][109] = 127, + [0][1][2][0][RTW89_QATAR][0][109] = 127, + [0][1][2][0][RTW89_UK][1][109] = 127, + [0][1][2][0][RTW89_UK][0][109] = 127, + [0][1][2][0][RTW89_FCC][1][111] = 127, + [0][1][2][0][RTW89_FCC][2][111] = 127, + [0][1][2][0][RTW89_ETSI][1][111] = 127, + [0][1][2][0][RTW89_ETSI][0][111] = 127, + [0][1][2][0][RTW89_MKK][1][111] = 127, + [0][1][2][0][RTW89_MKK][0][111] = 127, + [0][1][2][0][RTW89_IC][1][111] = 127, + [0][1][2][0][RTW89_KCC][1][111] = 127, + [0][1][2][0][RTW89_KCC][0][111] = 127, + [0][1][2][0][RTW89_ACMA][1][111] = 127, + [0][1][2][0][RTW89_ACMA][0][111] = 127, + [0][1][2][0][RTW89_CHILE][1][111] = 127, + [0][1][2][0][RTW89_QATAR][1][111] = 127, + [0][1][2][0][RTW89_QATAR][0][111] = 127, + [0][1][2][0][RTW89_UK][1][111] = 127, + [0][1][2][0][RTW89_UK][0][111] = 127, + [0][1][2][0][RTW89_FCC][1][113] = 127, + [0][1][2][0][RTW89_FCC][2][113] = 127, + [0][1][2][0][RTW89_ETSI][1][113] = 127, + [0][1][2][0][RTW89_ETSI][0][113] = 127, + [0][1][2][0][RTW89_MKK][1][113] = 127, + [0][1][2][0][RTW89_MKK][0][113] = 127, + [0][1][2][0][RTW89_IC][1][113] = 127, + [0][1][2][0][RTW89_KCC][1][113] = 127, + [0][1][2][0][RTW89_KCC][0][113] = 127, + [0][1][2][0][RTW89_ACMA][1][113] = 127, + [0][1][2][0][RTW89_ACMA][0][113] = 127, + [0][1][2][0][RTW89_CHILE][1][113] = 127, + [0][1][2][0][RTW89_QATAR][1][113] = 127, + [0][1][2][0][RTW89_QATAR][0][113] = 127, + [0][1][2][0][RTW89_UK][1][113] = 127, + [0][1][2][0][RTW89_UK][0][113] = 127, + [0][1][2][0][RTW89_FCC][1][115] = 127, + [0][1][2][0][RTW89_FCC][2][115] = 127, + [0][1][2][0][RTW89_ETSI][1][115] = 127, + [0][1][2][0][RTW89_ETSI][0][115] = 127, + [0][1][2][0][RTW89_MKK][1][115] = 127, + [0][1][2][0][RTW89_MKK][0][115] = 127, + [0][1][2][0][RTW89_IC][1][115] = 127, + [0][1][2][0][RTW89_KCC][1][115] = 127, + [0][1][2][0][RTW89_KCC][0][115] = 127, + [0][1][2][0][RTW89_ACMA][1][115] = 127, + [0][1][2][0][RTW89_ACMA][0][115] = 127, + [0][1][2][0][RTW89_CHILE][1][115] = 127, + [0][1][2][0][RTW89_QATAR][1][115] = 127, + [0][1][2][0][RTW89_QATAR][0][115] = 127, + [0][1][2][0][RTW89_UK][1][115] = 127, + [0][1][2][0][RTW89_UK][0][115] = 127, + [0][1][2][0][RTW89_FCC][1][117] = 127, + [0][1][2][0][RTW89_FCC][2][117] = 127, + [0][1][2][0][RTW89_ETSI][1][117] = 127, + [0][1][2][0][RTW89_ETSI][0][117] = 127, + [0][1][2][0][RTW89_MKK][1][117] = 127, + [0][1][2][0][RTW89_MKK][0][117] = 127, + [0][1][2][0][RTW89_IC][1][117] = 127, + [0][1][2][0][RTW89_KCC][1][117] = 127, + [0][1][2][0][RTW89_KCC][0][117] = 127, + [0][1][2][0][RTW89_ACMA][1][117] = 127, + [0][1][2][0][RTW89_ACMA][0][117] = 127, + [0][1][2][0][RTW89_CHILE][1][117] = 127, + [0][1][2][0][RTW89_QATAR][1][117] = 127, + [0][1][2][0][RTW89_QATAR][0][117] = 127, + [0][1][2][0][RTW89_UK][1][117] = 127, + [0][1][2][0][RTW89_UK][0][117] = 127, + [0][1][2][0][RTW89_FCC][1][119] = 127, + [0][1][2][0][RTW89_FCC][2][119] = 127, + [0][1][2][0][RTW89_ETSI][1][119] = 127, + [0][1][2][0][RTW89_ETSI][0][119] = 127, + [0][1][2][0][RTW89_MKK][1][119] = 127, + [0][1][2][0][RTW89_MKK][0][119] = 127, + [0][1][2][0][RTW89_IC][1][119] = 127, + [0][1][2][0][RTW89_KCC][1][119] = 127, + [0][1][2][0][RTW89_KCC][0][119] = 127, + [0][1][2][0][RTW89_ACMA][1][119] = 127, + [0][1][2][0][RTW89_ACMA][0][119] = 127, + [0][1][2][0][RTW89_CHILE][1][119] = 127, + [0][1][2][0][RTW89_QATAR][1][119] = 127, + [0][1][2][0][RTW89_QATAR][0][119] = 127, + [0][1][2][0][RTW89_UK][1][119] = 127, + [0][1][2][0][RTW89_UK][0][119] = 127, + [0][1][2][1][RTW89_FCC][1][0] = -2, + [0][1][2][1][RTW89_FCC][2][0] = 54, + [0][1][2][1][RTW89_ETSI][1][0] = 42, + [0][1][2][1][RTW89_ETSI][0][0] = 6, + [0][1][2][1][RTW89_MKK][1][0] = 56, + [0][1][2][1][RTW89_MKK][0][0] = 16, + [0][1][2][1][RTW89_IC][1][0] = -2, + [0][1][2][1][RTW89_KCC][1][0] = 12, + [0][1][2][1][RTW89_KCC][0][0] = 10, + [0][1][2][1][RTW89_ACMA][1][0] = 42, + [0][1][2][1][RTW89_ACMA][0][0] = 6, + [0][1][2][1][RTW89_CHILE][1][0] = -2, + [0][1][2][1][RTW89_QATAR][1][0] = 42, + [0][1][2][1][RTW89_QATAR][0][0] = 6, + [0][1][2][1][RTW89_UK][1][0] = 42, + [0][1][2][1][RTW89_UK][0][0] = 6, + [0][1][2][1][RTW89_FCC][1][2] = -4, + [0][1][2][1][RTW89_FCC][2][2] = 54, + [0][1][2][1][RTW89_ETSI][1][2] = 42, + [0][1][2][1][RTW89_ETSI][0][2] = 6, + [0][1][2][1][RTW89_MKK][1][2] = 54, + [0][1][2][1][RTW89_MKK][0][2] = 16, + [0][1][2][1][RTW89_IC][1][2] = -4, + [0][1][2][1][RTW89_KCC][1][2] = 12, + [0][1][2][1][RTW89_KCC][0][2] = 12, + [0][1][2][1][RTW89_ACMA][1][2] = 42, + [0][1][2][1][RTW89_ACMA][0][2] = 6, + [0][1][2][1][RTW89_CHILE][1][2] = -4, + [0][1][2][1][RTW89_QATAR][1][2] = 42, + [0][1][2][1][RTW89_QATAR][0][2] = 6, + [0][1][2][1][RTW89_UK][1][2] = 42, + [0][1][2][1][RTW89_UK][0][2] = 6, + [0][1][2][1][RTW89_FCC][1][4] = -4, + [0][1][2][1][RTW89_FCC][2][4] = 54, + [0][1][2][1][RTW89_ETSI][1][4] = 42, + [0][1][2][1][RTW89_ETSI][0][4] = 6, + [0][1][2][1][RTW89_MKK][1][4] = 54, + [0][1][2][1][RTW89_MKK][0][4] = 16, + [0][1][2][1][RTW89_IC][1][4] = -4, + [0][1][2][1][RTW89_KCC][1][4] = 12, + [0][1][2][1][RTW89_KCC][0][4] = 12, + [0][1][2][1][RTW89_ACMA][1][4] = 42, + [0][1][2][1][RTW89_ACMA][0][4] = 6, + [0][1][2][1][RTW89_CHILE][1][4] = -4, + [0][1][2][1][RTW89_QATAR][1][4] = 42, + [0][1][2][1][RTW89_QATAR][0][4] = 6, + [0][1][2][1][RTW89_UK][1][4] = 42, + [0][1][2][1][RTW89_UK][0][4] = 6, + [0][1][2][1][RTW89_FCC][1][6] = -4, + [0][1][2][1][RTW89_FCC][2][6] = 54, + [0][1][2][1][RTW89_ETSI][1][6] = 42, + [0][1][2][1][RTW89_ETSI][0][6] = 6, + [0][1][2][1][RTW89_MKK][1][6] = 54, + [0][1][2][1][RTW89_MKK][0][6] = 16, + [0][1][2][1][RTW89_IC][1][6] = -4, + [0][1][2][1][RTW89_KCC][1][6] = 12, + [0][1][2][1][RTW89_KCC][0][6] = 12, + [0][1][2][1][RTW89_ACMA][1][6] = 42, + [0][1][2][1][RTW89_ACMA][0][6] = 6, + [0][1][2][1][RTW89_CHILE][1][6] = -4, + [0][1][2][1][RTW89_QATAR][1][6] = 42, + [0][1][2][1][RTW89_QATAR][0][6] = 6, + [0][1][2][1][RTW89_UK][1][6] = 42, + [0][1][2][1][RTW89_UK][0][6] = 6, + [0][1][2][1][RTW89_FCC][1][8] = -4, + [0][1][2][1][RTW89_FCC][2][8] = 54, + [0][1][2][1][RTW89_ETSI][1][8] = 42, + [0][1][2][1][RTW89_ETSI][0][8] = 6, + [0][1][2][1][RTW89_MKK][1][8] = 54, + [0][1][2][1][RTW89_MKK][0][8] = 16, + [0][1][2][1][RTW89_IC][1][8] = -4, + [0][1][2][1][RTW89_KCC][1][8] = 12, + [0][1][2][1][RTW89_KCC][0][8] = 12, + [0][1][2][1][RTW89_ACMA][1][8] = 42, + [0][1][2][1][RTW89_ACMA][0][8] = 6, + [0][1][2][1][RTW89_CHILE][1][8] = -4, + [0][1][2][1][RTW89_QATAR][1][8] = 42, + [0][1][2][1][RTW89_QATAR][0][8] = 6, + [0][1][2][1][RTW89_UK][1][8] = 42, + [0][1][2][1][RTW89_UK][0][8] = 6, + [0][1][2][1][RTW89_FCC][1][10] = -4, + [0][1][2][1][RTW89_FCC][2][10] = 54, + [0][1][2][1][RTW89_ETSI][1][10] = 42, + [0][1][2][1][RTW89_ETSI][0][10] = 6, + [0][1][2][1][RTW89_MKK][1][10] = 54, + [0][1][2][1][RTW89_MKK][0][10] = 16, + [0][1][2][1][RTW89_IC][1][10] = -4, + [0][1][2][1][RTW89_KCC][1][10] = 12, + [0][1][2][1][RTW89_KCC][0][10] = 12, + [0][1][2][1][RTW89_ACMA][1][10] = 42, + [0][1][2][1][RTW89_ACMA][0][10] = 6, + [0][1][2][1][RTW89_CHILE][1][10] = -4, + [0][1][2][1][RTW89_QATAR][1][10] = 42, + [0][1][2][1][RTW89_QATAR][0][10] = 6, + [0][1][2][1][RTW89_UK][1][10] = 42, + [0][1][2][1][RTW89_UK][0][10] = 6, + [0][1][2][1][RTW89_FCC][1][12] = -4, + [0][1][2][1][RTW89_FCC][2][12] = 54, + [0][1][2][1][RTW89_ETSI][1][12] = 42, + [0][1][2][1][RTW89_ETSI][0][12] = 6, + [0][1][2][1][RTW89_MKK][1][12] = 54, + [0][1][2][1][RTW89_MKK][0][12] = 16, + [0][1][2][1][RTW89_IC][1][12] = -4, + [0][1][2][1][RTW89_KCC][1][12] = 12, + [0][1][2][1][RTW89_KCC][0][12] = 12, + [0][1][2][1][RTW89_ACMA][1][12] = 42, + [0][1][2][1][RTW89_ACMA][0][12] = 6, + [0][1][2][1][RTW89_CHILE][1][12] = -4, + [0][1][2][1][RTW89_QATAR][1][12] = 42, + [0][1][2][1][RTW89_QATAR][0][12] = 6, + [0][1][2][1][RTW89_UK][1][12] = 42, + [0][1][2][1][RTW89_UK][0][12] = 6, + [0][1][2][1][RTW89_FCC][1][14] = -4, + [0][1][2][1][RTW89_FCC][2][14] = 54, + [0][1][2][1][RTW89_ETSI][1][14] = 42, + [0][1][2][1][RTW89_ETSI][0][14] = 6, + [0][1][2][1][RTW89_MKK][1][14] = 54, + [0][1][2][1][RTW89_MKK][0][14] = 16, + [0][1][2][1][RTW89_IC][1][14] = -4, + [0][1][2][1][RTW89_KCC][1][14] = 12, + [0][1][2][1][RTW89_KCC][0][14] = 12, + [0][1][2][1][RTW89_ACMA][1][14] = 42, + [0][1][2][1][RTW89_ACMA][0][14] = 6, + [0][1][2][1][RTW89_CHILE][1][14] = -4, + [0][1][2][1][RTW89_QATAR][1][14] = 42, + [0][1][2][1][RTW89_QATAR][0][14] = 6, + [0][1][2][1][RTW89_UK][1][14] = 42, + [0][1][2][1][RTW89_UK][0][14] = 6, + [0][1][2][1][RTW89_FCC][1][15] = -4, + [0][1][2][1][RTW89_FCC][2][15] = 54, + [0][1][2][1][RTW89_ETSI][1][15] = 42, + [0][1][2][1][RTW89_ETSI][0][15] = 6, + [0][1][2][1][RTW89_MKK][1][15] = 54, + [0][1][2][1][RTW89_MKK][0][15] = 16, + [0][1][2][1][RTW89_IC][1][15] = -4, + [0][1][2][1][RTW89_KCC][1][15] = 12, + [0][1][2][1][RTW89_KCC][0][15] = 12, + [0][1][2][1][RTW89_ACMA][1][15] = 42, + [0][1][2][1][RTW89_ACMA][0][15] = 6, + [0][1][2][1][RTW89_CHILE][1][15] = -4, + [0][1][2][1][RTW89_QATAR][1][15] = 42, + [0][1][2][1][RTW89_QATAR][0][15] = 6, + [0][1][2][1][RTW89_UK][1][15] = 42, + [0][1][2][1][RTW89_UK][0][15] = 6, + [0][1][2][1][RTW89_FCC][1][17] = -4, + [0][1][2][1][RTW89_FCC][2][17] = 54, + [0][1][2][1][RTW89_ETSI][1][17] = 42, + [0][1][2][1][RTW89_ETSI][0][17] = 6, + [0][1][2][1][RTW89_MKK][1][17] = 54, + [0][1][2][1][RTW89_MKK][0][17] = 16, + [0][1][2][1][RTW89_IC][1][17] = -4, + [0][1][2][1][RTW89_KCC][1][17] = 12, + [0][1][2][1][RTW89_KCC][0][17] = 12, + [0][1][2][1][RTW89_ACMA][1][17] = 42, + [0][1][2][1][RTW89_ACMA][0][17] = 6, + [0][1][2][1][RTW89_CHILE][1][17] = -4, + [0][1][2][1][RTW89_QATAR][1][17] = 42, + [0][1][2][1][RTW89_QATAR][0][17] = 6, + [0][1][2][1][RTW89_UK][1][17] = 42, + [0][1][2][1][RTW89_UK][0][17] = 6, + [0][1][2][1][RTW89_FCC][1][19] = -4, + [0][1][2][1][RTW89_FCC][2][19] = 54, + [0][1][2][1][RTW89_ETSI][1][19] = 42, + [0][1][2][1][RTW89_ETSI][0][19] = 6, + [0][1][2][1][RTW89_MKK][1][19] = 54, + [0][1][2][1][RTW89_MKK][0][19] = 16, + [0][1][2][1][RTW89_IC][1][19] = -4, + [0][1][2][1][RTW89_KCC][1][19] = 12, + [0][1][2][1][RTW89_KCC][0][19] = 12, + [0][1][2][1][RTW89_ACMA][1][19] = 42, + [0][1][2][1][RTW89_ACMA][0][19] = 6, + [0][1][2][1][RTW89_CHILE][1][19] = -4, + [0][1][2][1][RTW89_QATAR][1][19] = 42, + [0][1][2][1][RTW89_QATAR][0][19] = 6, + [0][1][2][1][RTW89_UK][1][19] = 42, + [0][1][2][1][RTW89_UK][0][19] = 6, + [0][1][2][1][RTW89_FCC][1][21] = -4, + [0][1][2][1][RTW89_FCC][2][21] = 54, + [0][1][2][1][RTW89_ETSI][1][21] = 42, + [0][1][2][1][RTW89_ETSI][0][21] = 6, + [0][1][2][1][RTW89_MKK][1][21] = 54, + [0][1][2][1][RTW89_MKK][0][21] = 16, + [0][1][2][1][RTW89_IC][1][21] = -4, + [0][1][2][1][RTW89_KCC][1][21] = 12, + [0][1][2][1][RTW89_KCC][0][21] = 12, + [0][1][2][1][RTW89_ACMA][1][21] = 42, + [0][1][2][1][RTW89_ACMA][0][21] = 6, + [0][1][2][1][RTW89_CHILE][1][21] = -4, + [0][1][2][1][RTW89_QATAR][1][21] = 42, + [0][1][2][1][RTW89_QATAR][0][21] = 6, + [0][1][2][1][RTW89_UK][1][21] = 42, + [0][1][2][1][RTW89_UK][0][21] = 6, + [0][1][2][1][RTW89_FCC][1][23] = -4, + [0][1][2][1][RTW89_FCC][2][23] = 68, + [0][1][2][1][RTW89_ETSI][1][23] = 42, + [0][1][2][1][RTW89_ETSI][0][23] = 6, + [0][1][2][1][RTW89_MKK][1][23] = 54, + [0][1][2][1][RTW89_MKK][0][23] = 16, + [0][1][2][1][RTW89_IC][1][23] = -4, + [0][1][2][1][RTW89_KCC][1][23] = 12, + [0][1][2][1][RTW89_KCC][0][23] = 10, + [0][1][2][1][RTW89_ACMA][1][23] = 42, + [0][1][2][1][RTW89_ACMA][0][23] = 6, + [0][1][2][1][RTW89_CHILE][1][23] = -4, + [0][1][2][1][RTW89_QATAR][1][23] = 42, + [0][1][2][1][RTW89_QATAR][0][23] = 6, + [0][1][2][1][RTW89_UK][1][23] = 42, + [0][1][2][1][RTW89_UK][0][23] = 6, + [0][1][2][1][RTW89_FCC][1][25] = -4, + [0][1][2][1][RTW89_FCC][2][25] = 68, + [0][1][2][1][RTW89_ETSI][1][25] = 42, + [0][1][2][1][RTW89_ETSI][0][25] = 6, + [0][1][2][1][RTW89_MKK][1][25] = 54, + [0][1][2][1][RTW89_MKK][0][25] = 16, + [0][1][2][1][RTW89_IC][1][25] = -4, + [0][1][2][1][RTW89_KCC][1][25] = 12, + [0][1][2][1][RTW89_KCC][0][25] = 14, + [0][1][2][1][RTW89_ACMA][1][25] = 42, + [0][1][2][1][RTW89_ACMA][0][25] = 6, + [0][1][2][1][RTW89_CHILE][1][25] = -4, + [0][1][2][1][RTW89_QATAR][1][25] = 42, + [0][1][2][1][RTW89_QATAR][0][25] = 6, + [0][1][2][1][RTW89_UK][1][25] = 42, + [0][1][2][1][RTW89_UK][0][25] = 6, + [0][1][2][1][RTW89_FCC][1][27] = -4, + [0][1][2][1][RTW89_FCC][2][27] = 68, + [0][1][2][1][RTW89_ETSI][1][27] = 42, + [0][1][2][1][RTW89_ETSI][0][27] = 6, + [0][1][2][1][RTW89_MKK][1][27] = 54, + [0][1][2][1][RTW89_MKK][0][27] = 16, + [0][1][2][1][RTW89_IC][1][27] = -4, + [0][1][2][1][RTW89_KCC][1][27] = 12, + [0][1][2][1][RTW89_KCC][0][27] = 14, + [0][1][2][1][RTW89_ACMA][1][27] = 42, + [0][1][2][1][RTW89_ACMA][0][27] = 6, + [0][1][2][1][RTW89_CHILE][1][27] = -4, + [0][1][2][1][RTW89_QATAR][1][27] = 42, + [0][1][2][1][RTW89_QATAR][0][27] = 6, + [0][1][2][1][RTW89_UK][1][27] = 42, + [0][1][2][1][RTW89_UK][0][27] = 6, + [0][1][2][1][RTW89_FCC][1][29] = -4, + [0][1][2][1][RTW89_FCC][2][29] = 68, + [0][1][2][1][RTW89_ETSI][1][29] = 42, + [0][1][2][1][RTW89_ETSI][0][29] = 6, + [0][1][2][1][RTW89_MKK][1][29] = 54, + [0][1][2][1][RTW89_MKK][0][29] = 16, + [0][1][2][1][RTW89_IC][1][29] = -4, + [0][1][2][1][RTW89_KCC][1][29] = 12, + [0][1][2][1][RTW89_KCC][0][29] = 14, + [0][1][2][1][RTW89_ACMA][1][29] = 42, + [0][1][2][1][RTW89_ACMA][0][29] = 6, + [0][1][2][1][RTW89_CHILE][1][29] = -4, + [0][1][2][1][RTW89_QATAR][1][29] = 42, + [0][1][2][1][RTW89_QATAR][0][29] = 6, + [0][1][2][1][RTW89_UK][1][29] = 42, + [0][1][2][1][RTW89_UK][0][29] = 6, + [0][1][2][1][RTW89_FCC][1][30] = -4, + [0][1][2][1][RTW89_FCC][2][30] = 68, + [0][1][2][1][RTW89_ETSI][1][30] = 42, + [0][1][2][1][RTW89_ETSI][0][30] = 6, + [0][1][2][1][RTW89_MKK][1][30] = 54, + [0][1][2][1][RTW89_MKK][0][30] = 16, + [0][1][2][1][RTW89_IC][1][30] = -4, + [0][1][2][1][RTW89_KCC][1][30] = 12, + [0][1][2][1][RTW89_KCC][0][30] = 14, + [0][1][2][1][RTW89_ACMA][1][30] = 42, + [0][1][2][1][RTW89_ACMA][0][30] = 6, + [0][1][2][1][RTW89_CHILE][1][30] = -4, + [0][1][2][1][RTW89_QATAR][1][30] = 42, + [0][1][2][1][RTW89_QATAR][0][30] = 6, + [0][1][2][1][RTW89_UK][1][30] = 42, + [0][1][2][1][RTW89_UK][0][30] = 6, + [0][1][2][1][RTW89_FCC][1][32] = -4, + [0][1][2][1][RTW89_FCC][2][32] = 68, + [0][1][2][1][RTW89_ETSI][1][32] = 42, + [0][1][2][1][RTW89_ETSI][0][32] = 6, + [0][1][2][1][RTW89_MKK][1][32] = 54, + [0][1][2][1][RTW89_MKK][0][32] = 16, + [0][1][2][1][RTW89_IC][1][32] = -4, + [0][1][2][1][RTW89_KCC][1][32] = 12, + [0][1][2][1][RTW89_KCC][0][32] = 14, + [0][1][2][1][RTW89_ACMA][1][32] = 42, + [0][1][2][1][RTW89_ACMA][0][32] = 6, + [0][1][2][1][RTW89_CHILE][1][32] = -4, + [0][1][2][1][RTW89_QATAR][1][32] = 42, + [0][1][2][1][RTW89_QATAR][0][32] = 6, + [0][1][2][1][RTW89_UK][1][32] = 42, + [0][1][2][1][RTW89_UK][0][32] = 6, + [0][1][2][1][RTW89_FCC][1][34] = -4, + [0][1][2][1][RTW89_FCC][2][34] = 68, + [0][1][2][1][RTW89_ETSI][1][34] = 42, + [0][1][2][1][RTW89_ETSI][0][34] = 6, + [0][1][2][1][RTW89_MKK][1][34] = 54, + [0][1][2][1][RTW89_MKK][0][34] = 16, + [0][1][2][1][RTW89_IC][1][34] = -4, + [0][1][2][1][RTW89_KCC][1][34] = 12, + [0][1][2][1][RTW89_KCC][0][34] = 14, + [0][1][2][1][RTW89_ACMA][1][34] = 42, + [0][1][2][1][RTW89_ACMA][0][34] = 6, + [0][1][2][1][RTW89_CHILE][1][34] = -4, + [0][1][2][1][RTW89_QATAR][1][34] = 42, + [0][1][2][1][RTW89_QATAR][0][34] = 6, + [0][1][2][1][RTW89_UK][1][34] = 42, + [0][1][2][1][RTW89_UK][0][34] = 6, + [0][1][2][1][RTW89_FCC][1][36] = -4, + [0][1][2][1][RTW89_FCC][2][36] = 68, + [0][1][2][1][RTW89_ETSI][1][36] = 42, + [0][1][2][1][RTW89_ETSI][0][36] = 6, + [0][1][2][1][RTW89_MKK][1][36] = 54, + [0][1][2][1][RTW89_MKK][0][36] = 16, + [0][1][2][1][RTW89_IC][1][36] = -4, + [0][1][2][1][RTW89_KCC][1][36] = 12, + [0][1][2][1][RTW89_KCC][0][36] = 14, + [0][1][2][1][RTW89_ACMA][1][36] = 42, + [0][1][2][1][RTW89_ACMA][0][36] = 6, + [0][1][2][1][RTW89_CHILE][1][36] = -4, + [0][1][2][1][RTW89_QATAR][1][36] = 42, + [0][1][2][1][RTW89_QATAR][0][36] = 6, + [0][1][2][1][RTW89_UK][1][36] = 42, + [0][1][2][1][RTW89_UK][0][36] = 6, + [0][1][2][1][RTW89_FCC][1][38] = -4, + [0][1][2][1][RTW89_FCC][2][38] = 68, + [0][1][2][1][RTW89_ETSI][1][38] = 42, + [0][1][2][1][RTW89_ETSI][0][38] = 6, + [0][1][2][1][RTW89_MKK][1][38] = 54, + [0][1][2][1][RTW89_MKK][0][38] = 16, + [0][1][2][1][RTW89_IC][1][38] = -4, + [0][1][2][1][RTW89_KCC][1][38] = 12, + [0][1][2][1][RTW89_KCC][0][38] = 14, + [0][1][2][1][RTW89_ACMA][1][38] = 42, + [0][1][2][1][RTW89_ACMA][0][38] = 6, + [0][1][2][1][RTW89_CHILE][1][38] = -4, + [0][1][2][1][RTW89_QATAR][1][38] = 42, + [0][1][2][1][RTW89_QATAR][0][38] = 6, + [0][1][2][1][RTW89_UK][1][38] = 42, + [0][1][2][1][RTW89_UK][0][38] = 6, + [0][1][2][1][RTW89_FCC][1][40] = -4, + [0][1][2][1][RTW89_FCC][2][40] = 68, + [0][1][2][1][RTW89_ETSI][1][40] = 42, + [0][1][2][1][RTW89_ETSI][0][40] = 6, + [0][1][2][1][RTW89_MKK][1][40] = 54, + [0][1][2][1][RTW89_MKK][0][40] = 16, + [0][1][2][1][RTW89_IC][1][40] = -4, + [0][1][2][1][RTW89_KCC][1][40] = 12, + [0][1][2][1][RTW89_KCC][0][40] = 14, + [0][1][2][1][RTW89_ACMA][1][40] = 42, + [0][1][2][1][RTW89_ACMA][0][40] = 6, + [0][1][2][1][RTW89_CHILE][1][40] = -4, + [0][1][2][1][RTW89_QATAR][1][40] = 42, + [0][1][2][1][RTW89_QATAR][0][40] = 6, + [0][1][2][1][RTW89_UK][1][40] = 42, + [0][1][2][1][RTW89_UK][0][40] = 6, + [0][1][2][1][RTW89_FCC][1][42] = -4, + [0][1][2][1][RTW89_FCC][2][42] = 68, + [0][1][2][1][RTW89_ETSI][1][42] = 42, + [0][1][2][1][RTW89_ETSI][0][42] = 6, + [0][1][2][1][RTW89_MKK][1][42] = 54, + [0][1][2][1][RTW89_MKK][0][42] = 16, + [0][1][2][1][RTW89_IC][1][42] = -4, + [0][1][2][1][RTW89_KCC][1][42] = 12, + [0][1][2][1][RTW89_KCC][0][42] = 14, + [0][1][2][1][RTW89_ACMA][1][42] = 42, + [0][1][2][1][RTW89_ACMA][0][42] = 6, + [0][1][2][1][RTW89_CHILE][1][42] = -4, + [0][1][2][1][RTW89_QATAR][1][42] = 42, + [0][1][2][1][RTW89_QATAR][0][42] = 6, + [0][1][2][1][RTW89_UK][1][42] = 42, + [0][1][2][1][RTW89_UK][0][42] = 6, + [0][1][2][1][RTW89_FCC][1][44] = -2, + [0][1][2][1][RTW89_FCC][2][44] = 68, + [0][1][2][1][RTW89_ETSI][1][44] = 42, + [0][1][2][1][RTW89_ETSI][0][44] = 6, + [0][1][2][1][RTW89_MKK][1][44] = 34, + [0][1][2][1][RTW89_MKK][0][44] = 16, + [0][1][2][1][RTW89_IC][1][44] = -2, + [0][1][2][1][RTW89_KCC][1][44] = 12, + [0][1][2][1][RTW89_KCC][0][44] = 12, + [0][1][2][1][RTW89_ACMA][1][44] = 42, + [0][1][2][1][RTW89_ACMA][0][44] = 6, + [0][1][2][1][RTW89_CHILE][1][44] = -2, + [0][1][2][1][RTW89_QATAR][1][44] = 42, + [0][1][2][1][RTW89_QATAR][0][44] = 6, + [0][1][2][1][RTW89_UK][1][44] = 42, + [0][1][2][1][RTW89_UK][0][44] = 6, + [0][1][2][1][RTW89_FCC][1][45] = -2, + [0][1][2][1][RTW89_FCC][2][45] = 127, + [0][1][2][1][RTW89_ETSI][1][45] = 127, + [0][1][2][1][RTW89_ETSI][0][45] = 127, + [0][1][2][1][RTW89_MKK][1][45] = 127, + [0][1][2][1][RTW89_MKK][0][45] = 127, + [0][1][2][1][RTW89_IC][1][45] = -2, + [0][1][2][1][RTW89_KCC][1][45] = 12, + [0][1][2][1][RTW89_KCC][0][45] = 127, + [0][1][2][1][RTW89_ACMA][1][45] = 127, + [0][1][2][1][RTW89_ACMA][0][45] = 127, + [0][1][2][1][RTW89_CHILE][1][45] = -2, + [0][1][2][1][RTW89_QATAR][1][45] = 127, + [0][1][2][1][RTW89_QATAR][0][45] = 127, + [0][1][2][1][RTW89_UK][1][45] = 127, + [0][1][2][1][RTW89_UK][0][45] = 127, + [0][1][2][1][RTW89_FCC][1][47] = -2, + [0][1][2][1][RTW89_FCC][2][47] = 127, + [0][1][2][1][RTW89_ETSI][1][47] = 127, + [0][1][2][1][RTW89_ETSI][0][47] = 127, + [0][1][2][1][RTW89_MKK][1][47] = 127, + [0][1][2][1][RTW89_MKK][0][47] = 127, + [0][1][2][1][RTW89_IC][1][47] = -2, + [0][1][2][1][RTW89_KCC][1][47] = 12, + [0][1][2][1][RTW89_KCC][0][47] = 127, + [0][1][2][1][RTW89_ACMA][1][47] = 127, + [0][1][2][1][RTW89_ACMA][0][47] = 127, + [0][1][2][1][RTW89_CHILE][1][47] = -2, + [0][1][2][1][RTW89_QATAR][1][47] = 127, + [0][1][2][1][RTW89_QATAR][0][47] = 127, + [0][1][2][1][RTW89_UK][1][47] = 127, + [0][1][2][1][RTW89_UK][0][47] = 127, + [0][1][2][1][RTW89_FCC][1][49] = -2, + [0][1][2][1][RTW89_FCC][2][49] = 127, + [0][1][2][1][RTW89_ETSI][1][49] = 127, + [0][1][2][1][RTW89_ETSI][0][49] = 127, + [0][1][2][1][RTW89_MKK][1][49] = 127, + [0][1][2][1][RTW89_MKK][0][49] = 127, + [0][1][2][1][RTW89_IC][1][49] = -2, + [0][1][2][1][RTW89_KCC][1][49] = 12, + [0][1][2][1][RTW89_KCC][0][49] = 127, + [0][1][2][1][RTW89_ACMA][1][49] = 127, + [0][1][2][1][RTW89_ACMA][0][49] = 127, + [0][1][2][1][RTW89_CHILE][1][49] = -2, + [0][1][2][1][RTW89_QATAR][1][49] = 127, + [0][1][2][1][RTW89_QATAR][0][49] = 127, + [0][1][2][1][RTW89_UK][1][49] = 127, + [0][1][2][1][RTW89_UK][0][49] = 127, + [0][1][2][1][RTW89_FCC][1][51] = -2, + [0][1][2][1][RTW89_FCC][2][51] = 127, + [0][1][2][1][RTW89_ETSI][1][51] = 127, + [0][1][2][1][RTW89_ETSI][0][51] = 127, + [0][1][2][1][RTW89_MKK][1][51] = 127, + [0][1][2][1][RTW89_MKK][0][51] = 127, + [0][1][2][1][RTW89_IC][1][51] = -2, + [0][1][2][1][RTW89_KCC][1][51] = 12, + [0][1][2][1][RTW89_KCC][0][51] = 127, + [0][1][2][1][RTW89_ACMA][1][51] = 127, + [0][1][2][1][RTW89_ACMA][0][51] = 127, + [0][1][2][1][RTW89_CHILE][1][51] = -2, + [0][1][2][1][RTW89_QATAR][1][51] = 127, + [0][1][2][1][RTW89_QATAR][0][51] = 127, + [0][1][2][1][RTW89_UK][1][51] = 127, + [0][1][2][1][RTW89_UK][0][51] = 127, + [0][1][2][1][RTW89_FCC][1][53] = -2, + [0][1][2][1][RTW89_FCC][2][53] = 127, + [0][1][2][1][RTW89_ETSI][1][53] = 127, + [0][1][2][1][RTW89_ETSI][0][53] = 127, + [0][1][2][1][RTW89_MKK][1][53] = 127, + [0][1][2][1][RTW89_MKK][0][53] = 127, + [0][1][2][1][RTW89_IC][1][53] = -2, + [0][1][2][1][RTW89_KCC][1][53] = 12, + [0][1][2][1][RTW89_KCC][0][53] = 127, + [0][1][2][1][RTW89_ACMA][1][53] = 127, + [0][1][2][1][RTW89_ACMA][0][53] = 127, + [0][1][2][1][RTW89_CHILE][1][53] = -2, + [0][1][2][1][RTW89_QATAR][1][53] = 127, + [0][1][2][1][RTW89_QATAR][0][53] = 127, + [0][1][2][1][RTW89_UK][1][53] = 127, + [0][1][2][1][RTW89_UK][0][53] = 127, + [0][1][2][1][RTW89_FCC][1][55] = -2, + [0][1][2][1][RTW89_FCC][2][55] = 68, + [0][1][2][1][RTW89_ETSI][1][55] = 127, + [0][1][2][1][RTW89_ETSI][0][55] = 127, + [0][1][2][1][RTW89_MKK][1][55] = 127, + [0][1][2][1][RTW89_MKK][0][55] = 127, + [0][1][2][1][RTW89_IC][1][55] = -2, + [0][1][2][1][RTW89_KCC][1][55] = 12, + [0][1][2][1][RTW89_KCC][0][55] = 127, + [0][1][2][1][RTW89_ACMA][1][55] = 127, + [0][1][2][1][RTW89_ACMA][0][55] = 127, + [0][1][2][1][RTW89_CHILE][1][55] = -2, + [0][1][2][1][RTW89_QATAR][1][55] = 127, + [0][1][2][1][RTW89_QATAR][0][55] = 127, + [0][1][2][1][RTW89_UK][1][55] = 127, + [0][1][2][1][RTW89_UK][0][55] = 127, + [0][1][2][1][RTW89_FCC][1][57] = -2, + [0][1][2][1][RTW89_FCC][2][57] = 68, + [0][1][2][1][RTW89_ETSI][1][57] = 127, + [0][1][2][1][RTW89_ETSI][0][57] = 127, + [0][1][2][1][RTW89_MKK][1][57] = 127, + [0][1][2][1][RTW89_MKK][0][57] = 127, + [0][1][2][1][RTW89_IC][1][57] = -2, + [0][1][2][1][RTW89_KCC][1][57] = 12, + [0][1][2][1][RTW89_KCC][0][57] = 127, + [0][1][2][1][RTW89_ACMA][1][57] = 127, + [0][1][2][1][RTW89_ACMA][0][57] = 127, + [0][1][2][1][RTW89_CHILE][1][57] = -2, + [0][1][2][1][RTW89_QATAR][1][57] = 127, + [0][1][2][1][RTW89_QATAR][0][57] = 127, + [0][1][2][1][RTW89_UK][1][57] = 127, + [0][1][2][1][RTW89_UK][0][57] = 127, + [0][1][2][1][RTW89_FCC][1][59] = -2, + [0][1][2][1][RTW89_FCC][2][59] = 68, + [0][1][2][1][RTW89_ETSI][1][59] = 127, + [0][1][2][1][RTW89_ETSI][0][59] = 127, + [0][1][2][1][RTW89_MKK][1][59] = 127, + [0][1][2][1][RTW89_MKK][0][59] = 127, + [0][1][2][1][RTW89_IC][1][59] = -2, + [0][1][2][1][RTW89_KCC][1][59] = 12, + [0][1][2][1][RTW89_KCC][0][59] = 127, + [0][1][2][1][RTW89_ACMA][1][59] = 127, + [0][1][2][1][RTW89_ACMA][0][59] = 127, + [0][1][2][1][RTW89_CHILE][1][59] = -2, + [0][1][2][1][RTW89_QATAR][1][59] = 127, + [0][1][2][1][RTW89_QATAR][0][59] = 127, + [0][1][2][1][RTW89_UK][1][59] = 127, + [0][1][2][1][RTW89_UK][0][59] = 127, + [0][1][2][1][RTW89_FCC][1][60] = -2, + [0][1][2][1][RTW89_FCC][2][60] = 68, + [0][1][2][1][RTW89_ETSI][1][60] = 127, + [0][1][2][1][RTW89_ETSI][0][60] = 127, + [0][1][2][1][RTW89_MKK][1][60] = 127, + [0][1][2][1][RTW89_MKK][0][60] = 127, + [0][1][2][1][RTW89_IC][1][60] = -2, + [0][1][2][1][RTW89_KCC][1][60] = 12, + [0][1][2][1][RTW89_KCC][0][60] = 127, + [0][1][2][1][RTW89_ACMA][1][60] = 127, + [0][1][2][1][RTW89_ACMA][0][60] = 127, + [0][1][2][1][RTW89_CHILE][1][60] = -2, + [0][1][2][1][RTW89_QATAR][1][60] = 127, + [0][1][2][1][RTW89_QATAR][0][60] = 127, + [0][1][2][1][RTW89_UK][1][60] = 127, + [0][1][2][1][RTW89_UK][0][60] = 127, + [0][1][2][1][RTW89_FCC][1][62] = -2, + [0][1][2][1][RTW89_FCC][2][62] = 68, + [0][1][2][1][RTW89_ETSI][1][62] = 127, + [0][1][2][1][RTW89_ETSI][0][62] = 127, + [0][1][2][1][RTW89_MKK][1][62] = 127, + [0][1][2][1][RTW89_MKK][0][62] = 127, + [0][1][2][1][RTW89_IC][1][62] = -2, + [0][1][2][1][RTW89_KCC][1][62] = 12, + [0][1][2][1][RTW89_KCC][0][62] = 127, + [0][1][2][1][RTW89_ACMA][1][62] = 127, + [0][1][2][1][RTW89_ACMA][0][62] = 127, + [0][1][2][1][RTW89_CHILE][1][62] = -2, + [0][1][2][1][RTW89_QATAR][1][62] = 127, + [0][1][2][1][RTW89_QATAR][0][62] = 127, + [0][1][2][1][RTW89_UK][1][62] = 127, + [0][1][2][1][RTW89_UK][0][62] = 127, + [0][1][2][1][RTW89_FCC][1][64] = -2, + [0][1][2][1][RTW89_FCC][2][64] = 68, + [0][1][2][1][RTW89_ETSI][1][64] = 127, + [0][1][2][1][RTW89_ETSI][0][64] = 127, + [0][1][2][1][RTW89_MKK][1][64] = 127, + [0][1][2][1][RTW89_MKK][0][64] = 127, + [0][1][2][1][RTW89_IC][1][64] = -2, + [0][1][2][1][RTW89_KCC][1][64] = 12, + [0][1][2][1][RTW89_KCC][0][64] = 127, + [0][1][2][1][RTW89_ACMA][1][64] = 127, + [0][1][2][1][RTW89_ACMA][0][64] = 127, + [0][1][2][1][RTW89_CHILE][1][64] = -2, + [0][1][2][1][RTW89_QATAR][1][64] = 127, + [0][1][2][1][RTW89_QATAR][0][64] = 127, + [0][1][2][1][RTW89_UK][1][64] = 127, + [0][1][2][1][RTW89_UK][0][64] = 127, + [0][1][2][1][RTW89_FCC][1][66] = -2, + [0][1][2][1][RTW89_FCC][2][66] = 68, + [0][1][2][1][RTW89_ETSI][1][66] = 127, + [0][1][2][1][RTW89_ETSI][0][66] = 127, + [0][1][2][1][RTW89_MKK][1][66] = 127, + [0][1][2][1][RTW89_MKK][0][66] = 127, + [0][1][2][1][RTW89_IC][1][66] = -2, + [0][1][2][1][RTW89_KCC][1][66] = 12, + [0][1][2][1][RTW89_KCC][0][66] = 127, + [0][1][2][1][RTW89_ACMA][1][66] = 127, + [0][1][2][1][RTW89_ACMA][0][66] = 127, + [0][1][2][1][RTW89_CHILE][1][66] = -2, + [0][1][2][1][RTW89_QATAR][1][66] = 127, + [0][1][2][1][RTW89_QATAR][0][66] = 127, + [0][1][2][1][RTW89_UK][1][66] = 127, + [0][1][2][1][RTW89_UK][0][66] = 127, + [0][1][2][1][RTW89_FCC][1][68] = -2, + [0][1][2][1][RTW89_FCC][2][68] = 68, + [0][1][2][1][RTW89_ETSI][1][68] = 127, + [0][1][2][1][RTW89_ETSI][0][68] = 127, + [0][1][2][1][RTW89_MKK][1][68] = 127, + [0][1][2][1][RTW89_MKK][0][68] = 127, + [0][1][2][1][RTW89_IC][1][68] = -2, + [0][1][2][1][RTW89_KCC][1][68] = 12, + [0][1][2][1][RTW89_KCC][0][68] = 127, + [0][1][2][1][RTW89_ACMA][1][68] = 127, + [0][1][2][1][RTW89_ACMA][0][68] = 127, + [0][1][2][1][RTW89_CHILE][1][68] = -2, + [0][1][2][1][RTW89_QATAR][1][68] = 127, + [0][1][2][1][RTW89_QATAR][0][68] = 127, + [0][1][2][1][RTW89_UK][1][68] = 127, + [0][1][2][1][RTW89_UK][0][68] = 127, + [0][1][2][1][RTW89_FCC][1][70] = -2, + [0][1][2][1][RTW89_FCC][2][70] = 68, + [0][1][2][1][RTW89_ETSI][1][70] = 127, + [0][1][2][1][RTW89_ETSI][0][70] = 127, + [0][1][2][1][RTW89_MKK][1][70] = 127, + [0][1][2][1][RTW89_MKK][0][70] = 127, + [0][1][2][1][RTW89_IC][1][70] = -2, + [0][1][2][1][RTW89_KCC][1][70] = 12, + [0][1][2][1][RTW89_KCC][0][70] = 127, + [0][1][2][1][RTW89_ACMA][1][70] = 127, + [0][1][2][1][RTW89_ACMA][0][70] = 127, + [0][1][2][1][RTW89_CHILE][1][70] = -2, + [0][1][2][1][RTW89_QATAR][1][70] = 127, + [0][1][2][1][RTW89_QATAR][0][70] = 127, + [0][1][2][1][RTW89_UK][1][70] = 127, + [0][1][2][1][RTW89_UK][0][70] = 127, + [0][1][2][1][RTW89_FCC][1][72] = -2, + [0][1][2][1][RTW89_FCC][2][72] = 68, + [0][1][2][1][RTW89_ETSI][1][72] = 127, + [0][1][2][1][RTW89_ETSI][0][72] = 127, + [0][1][2][1][RTW89_MKK][1][72] = 127, + [0][1][2][1][RTW89_MKK][0][72] = 127, + [0][1][2][1][RTW89_IC][1][72] = -2, + [0][1][2][1][RTW89_KCC][1][72] = 12, + [0][1][2][1][RTW89_KCC][0][72] = 127, + [0][1][2][1][RTW89_ACMA][1][72] = 127, + [0][1][2][1][RTW89_ACMA][0][72] = 127, + [0][1][2][1][RTW89_CHILE][1][72] = -2, + [0][1][2][1][RTW89_QATAR][1][72] = 127, + [0][1][2][1][RTW89_QATAR][0][72] = 127, + [0][1][2][1][RTW89_UK][1][72] = 127, + [0][1][2][1][RTW89_UK][0][72] = 127, + [0][1][2][1][RTW89_FCC][1][74] = -2, + [0][1][2][1][RTW89_FCC][2][74] = 68, + [0][1][2][1][RTW89_ETSI][1][74] = 127, + [0][1][2][1][RTW89_ETSI][0][74] = 127, + [0][1][2][1][RTW89_MKK][1][74] = 127, + [0][1][2][1][RTW89_MKK][0][74] = 127, + [0][1][2][1][RTW89_IC][1][74] = -2, + [0][1][2][1][RTW89_KCC][1][74] = 12, + [0][1][2][1][RTW89_KCC][0][74] = 127, + [0][1][2][1][RTW89_ACMA][1][74] = 127, + [0][1][2][1][RTW89_ACMA][0][74] = 127, + [0][1][2][1][RTW89_CHILE][1][74] = -2, + [0][1][2][1][RTW89_QATAR][1][74] = 127, + [0][1][2][1][RTW89_QATAR][0][74] = 127, + [0][1][2][1][RTW89_UK][1][74] = 127, + [0][1][2][1][RTW89_UK][0][74] = 127, + [0][1][2][1][RTW89_FCC][1][75] = -2, + [0][1][2][1][RTW89_FCC][2][75] = 68, + [0][1][2][1][RTW89_ETSI][1][75] = 127, + [0][1][2][1][RTW89_ETSI][0][75] = 127, + [0][1][2][1][RTW89_MKK][1][75] = 127, + [0][1][2][1][RTW89_MKK][0][75] = 127, + [0][1][2][1][RTW89_IC][1][75] = -2, + [0][1][2][1][RTW89_KCC][1][75] = 12, + [0][1][2][1][RTW89_KCC][0][75] = 127, + [0][1][2][1][RTW89_ACMA][1][75] = 127, + [0][1][2][1][RTW89_ACMA][0][75] = 127, + [0][1][2][1][RTW89_CHILE][1][75] = -2, + [0][1][2][1][RTW89_QATAR][1][75] = 127, + [0][1][2][1][RTW89_QATAR][0][75] = 127, + [0][1][2][1][RTW89_UK][1][75] = 127, + [0][1][2][1][RTW89_UK][0][75] = 127, + [0][1][2][1][RTW89_FCC][1][77] = -2, + [0][1][2][1][RTW89_FCC][2][77] = 68, + [0][1][2][1][RTW89_ETSI][1][77] = 127, + [0][1][2][1][RTW89_ETSI][0][77] = 127, + [0][1][2][1][RTW89_MKK][1][77] = 127, + [0][1][2][1][RTW89_MKK][0][77] = 127, + [0][1][2][1][RTW89_IC][1][77] = -2, + [0][1][2][1][RTW89_KCC][1][77] = 12, + [0][1][2][1][RTW89_KCC][0][77] = 127, + [0][1][2][1][RTW89_ACMA][1][77] = 127, + [0][1][2][1][RTW89_ACMA][0][77] = 127, + [0][1][2][1][RTW89_CHILE][1][77] = -2, + [0][1][2][1][RTW89_QATAR][1][77] = 127, + [0][1][2][1][RTW89_QATAR][0][77] = 127, + [0][1][2][1][RTW89_UK][1][77] = 127, + [0][1][2][1][RTW89_UK][0][77] = 127, + [0][1][2][1][RTW89_FCC][1][79] = -2, + [0][1][2][1][RTW89_FCC][2][79] = 68, + [0][1][2][1][RTW89_ETSI][1][79] = 127, + [0][1][2][1][RTW89_ETSI][0][79] = 127, + [0][1][2][1][RTW89_MKK][1][79] = 127, + [0][1][2][1][RTW89_MKK][0][79] = 127, + [0][1][2][1][RTW89_IC][1][79] = -2, + [0][1][2][1][RTW89_KCC][1][79] = 12, + [0][1][2][1][RTW89_KCC][0][79] = 127, + [0][1][2][1][RTW89_ACMA][1][79] = 127, + [0][1][2][1][RTW89_ACMA][0][79] = 127, + [0][1][2][1][RTW89_CHILE][1][79] = -2, + [0][1][2][1][RTW89_QATAR][1][79] = 127, + [0][1][2][1][RTW89_QATAR][0][79] = 127, + [0][1][2][1][RTW89_UK][1][79] = 127, + [0][1][2][1][RTW89_UK][0][79] = 127, + [0][1][2][1][RTW89_FCC][1][81] = -2, + [0][1][2][1][RTW89_FCC][2][81] = 68, + [0][1][2][1][RTW89_ETSI][1][81] = 127, + [0][1][2][1][RTW89_ETSI][0][81] = 127, + [0][1][2][1][RTW89_MKK][1][81] = 127, + [0][1][2][1][RTW89_MKK][0][81] = 127, + [0][1][2][1][RTW89_IC][1][81] = -2, + [0][1][2][1][RTW89_KCC][1][81] = 12, + [0][1][2][1][RTW89_KCC][0][81] = 127, + [0][1][2][1][RTW89_ACMA][1][81] = 127, + [0][1][2][1][RTW89_ACMA][0][81] = 127, + [0][1][2][1][RTW89_CHILE][1][81] = -2, + [0][1][2][1][RTW89_QATAR][1][81] = 127, + [0][1][2][1][RTW89_QATAR][0][81] = 127, + [0][1][2][1][RTW89_UK][1][81] = 127, + [0][1][2][1][RTW89_UK][0][81] = 127, + [0][1][2][1][RTW89_FCC][1][83] = -2, + [0][1][2][1][RTW89_FCC][2][83] = 68, + [0][1][2][1][RTW89_ETSI][1][83] = 127, + [0][1][2][1][RTW89_ETSI][0][83] = 127, + [0][1][2][1][RTW89_MKK][1][83] = 127, + [0][1][2][1][RTW89_MKK][0][83] = 127, + [0][1][2][1][RTW89_IC][1][83] = -2, + [0][1][2][1][RTW89_KCC][1][83] = 20, + [0][1][2][1][RTW89_KCC][0][83] = 127, + [0][1][2][1][RTW89_ACMA][1][83] = 127, + [0][1][2][1][RTW89_ACMA][0][83] = 127, + [0][1][2][1][RTW89_CHILE][1][83] = -2, + [0][1][2][1][RTW89_QATAR][1][83] = 127, + [0][1][2][1][RTW89_QATAR][0][83] = 127, + [0][1][2][1][RTW89_UK][1][83] = 127, + [0][1][2][1][RTW89_UK][0][83] = 127, + [0][1][2][1][RTW89_FCC][1][85] = -2, + [0][1][2][1][RTW89_FCC][2][85] = 68, + [0][1][2][1][RTW89_ETSI][1][85] = 127, + [0][1][2][1][RTW89_ETSI][0][85] = 127, + [0][1][2][1][RTW89_MKK][1][85] = 127, + [0][1][2][1][RTW89_MKK][0][85] = 127, + [0][1][2][1][RTW89_IC][1][85] = -2, + [0][1][2][1][RTW89_KCC][1][85] = 20, + [0][1][2][1][RTW89_KCC][0][85] = 127, + [0][1][2][1][RTW89_ACMA][1][85] = 127, + [0][1][2][1][RTW89_ACMA][0][85] = 127, + [0][1][2][1][RTW89_CHILE][1][85] = -2, + [0][1][2][1][RTW89_QATAR][1][85] = 127, + [0][1][2][1][RTW89_QATAR][0][85] = 127, + [0][1][2][1][RTW89_UK][1][85] = 127, + [0][1][2][1][RTW89_UK][0][85] = 127, + [0][1][2][1][RTW89_FCC][1][87] = -2, + [0][1][2][1][RTW89_FCC][2][87] = 127, + [0][1][2][1][RTW89_ETSI][1][87] = 127, + [0][1][2][1][RTW89_ETSI][0][87] = 127, + [0][1][2][1][RTW89_MKK][1][87] = 127, + [0][1][2][1][RTW89_MKK][0][87] = 127, + [0][1][2][1][RTW89_IC][1][87] = -2, + [0][1][2][1][RTW89_KCC][1][87] = 20, + [0][1][2][1][RTW89_KCC][0][87] = 127, + [0][1][2][1][RTW89_ACMA][1][87] = 127, + [0][1][2][1][RTW89_ACMA][0][87] = 127, + [0][1][2][1][RTW89_CHILE][1][87] = -2, + [0][1][2][1][RTW89_QATAR][1][87] = 127, + [0][1][2][1][RTW89_QATAR][0][87] = 127, + [0][1][2][1][RTW89_UK][1][87] = 127, + [0][1][2][1][RTW89_UK][0][87] = 127, + [0][1][2][1][RTW89_FCC][1][89] = -2, + [0][1][2][1][RTW89_FCC][2][89] = 127, + [0][1][2][1][RTW89_ETSI][1][89] = 127, + [0][1][2][1][RTW89_ETSI][0][89] = 127, + [0][1][2][1][RTW89_MKK][1][89] = 127, + [0][1][2][1][RTW89_MKK][0][89] = 127, + [0][1][2][1][RTW89_IC][1][89] = -2, + [0][1][2][1][RTW89_KCC][1][89] = 20, + [0][1][2][1][RTW89_KCC][0][89] = 127, + [0][1][2][1][RTW89_ACMA][1][89] = 127, + [0][1][2][1][RTW89_ACMA][0][89] = 127, + [0][1][2][1][RTW89_CHILE][1][89] = -2, + [0][1][2][1][RTW89_QATAR][1][89] = 127, + [0][1][2][1][RTW89_QATAR][0][89] = 127, + [0][1][2][1][RTW89_UK][1][89] = 127, + [0][1][2][1][RTW89_UK][0][89] = 127, + [0][1][2][1][RTW89_FCC][1][90] = -2, + [0][1][2][1][RTW89_FCC][2][90] = 127, + [0][1][2][1][RTW89_ETSI][1][90] = 127, + [0][1][2][1][RTW89_ETSI][0][90] = 127, + [0][1][2][1][RTW89_MKK][1][90] = 127, + [0][1][2][1][RTW89_MKK][0][90] = 127, + [0][1][2][1][RTW89_IC][1][90] = -2, + [0][1][2][1][RTW89_KCC][1][90] = 20, + [0][1][2][1][RTW89_KCC][0][90] = 127, + [0][1][2][1][RTW89_ACMA][1][90] = 127, + [0][1][2][1][RTW89_ACMA][0][90] = 127, + [0][1][2][1][RTW89_CHILE][1][90] = -2, + [0][1][2][1][RTW89_QATAR][1][90] = 127, + [0][1][2][1][RTW89_QATAR][0][90] = 127, + [0][1][2][1][RTW89_UK][1][90] = 127, + [0][1][2][1][RTW89_UK][0][90] = 127, + [0][1][2][1][RTW89_FCC][1][92] = -2, + [0][1][2][1][RTW89_FCC][2][92] = 127, + [0][1][2][1][RTW89_ETSI][1][92] = 127, + [0][1][2][1][RTW89_ETSI][0][92] = 127, + [0][1][2][1][RTW89_MKK][1][92] = 127, + [0][1][2][1][RTW89_MKK][0][92] = 127, + [0][1][2][1][RTW89_IC][1][92] = -2, + [0][1][2][1][RTW89_KCC][1][92] = 20, + [0][1][2][1][RTW89_KCC][0][92] = 127, + [0][1][2][1][RTW89_ACMA][1][92] = 127, + [0][1][2][1][RTW89_ACMA][0][92] = 127, + [0][1][2][1][RTW89_CHILE][1][92] = -2, + [0][1][2][1][RTW89_QATAR][1][92] = 127, + [0][1][2][1][RTW89_QATAR][0][92] = 127, + [0][1][2][1][RTW89_UK][1][92] = 127, + [0][1][2][1][RTW89_UK][0][92] = 127, + [0][1][2][1][RTW89_FCC][1][94] = -2, + [0][1][2][1][RTW89_FCC][2][94] = 127, + [0][1][2][1][RTW89_ETSI][1][94] = 127, + [0][1][2][1][RTW89_ETSI][0][94] = 127, + [0][1][2][1][RTW89_MKK][1][94] = 127, + [0][1][2][1][RTW89_MKK][0][94] = 127, + [0][1][2][1][RTW89_IC][1][94] = -2, + [0][1][2][1][RTW89_KCC][1][94] = 20, + [0][1][2][1][RTW89_KCC][0][94] = 127, + [0][1][2][1][RTW89_ACMA][1][94] = 127, + [0][1][2][1][RTW89_ACMA][0][94] = 127, + [0][1][2][1][RTW89_CHILE][1][94] = -2, + [0][1][2][1][RTW89_QATAR][1][94] = 127, + [0][1][2][1][RTW89_QATAR][0][94] = 127, + [0][1][2][1][RTW89_UK][1][94] = 127, + [0][1][2][1][RTW89_UK][0][94] = 127, + [0][1][2][1][RTW89_FCC][1][96] = -2, + [0][1][2][1][RTW89_FCC][2][96] = 127, + [0][1][2][1][RTW89_ETSI][1][96] = 127, + [0][1][2][1][RTW89_ETSI][0][96] = 127, + [0][1][2][1][RTW89_MKK][1][96] = 127, + [0][1][2][1][RTW89_MKK][0][96] = 127, + [0][1][2][1][RTW89_IC][1][96] = -2, + [0][1][2][1][RTW89_KCC][1][96] = 20, + [0][1][2][1][RTW89_KCC][0][96] = 127, + [0][1][2][1][RTW89_ACMA][1][96] = 127, + [0][1][2][1][RTW89_ACMA][0][96] = 127, + [0][1][2][1][RTW89_CHILE][1][96] = -2, + [0][1][2][1][RTW89_QATAR][1][96] = 127, + [0][1][2][1][RTW89_QATAR][0][96] = 127, + [0][1][2][1][RTW89_UK][1][96] = 127, + [0][1][2][1][RTW89_UK][0][96] = 127, + [0][1][2][1][RTW89_FCC][1][98] = -2, + [0][1][2][1][RTW89_FCC][2][98] = 127, + [0][1][2][1][RTW89_ETSI][1][98] = 127, + [0][1][2][1][RTW89_ETSI][0][98] = 127, + [0][1][2][1][RTW89_MKK][1][98] = 127, + [0][1][2][1][RTW89_MKK][0][98] = 127, + [0][1][2][1][RTW89_IC][1][98] = -2, + [0][1][2][1][RTW89_KCC][1][98] = 20, + [0][1][2][1][RTW89_KCC][0][98] = 127, + [0][1][2][1][RTW89_ACMA][1][98] = 127, + [0][1][2][1][RTW89_ACMA][0][98] = 127, + [0][1][2][1][RTW89_CHILE][1][98] = -2, + [0][1][2][1][RTW89_QATAR][1][98] = 127, + [0][1][2][1][RTW89_QATAR][0][98] = 127, + [0][1][2][1][RTW89_UK][1][98] = 127, + [0][1][2][1][RTW89_UK][0][98] = 127, + [0][1][2][1][RTW89_FCC][1][100] = -2, + [0][1][2][1][RTW89_FCC][2][100] = 127, + [0][1][2][1][RTW89_ETSI][1][100] = 127, + [0][1][2][1][RTW89_ETSI][0][100] = 127, + [0][1][2][1][RTW89_MKK][1][100] = 127, + [0][1][2][1][RTW89_MKK][0][100] = 127, + [0][1][2][1][RTW89_IC][1][100] = -2, + [0][1][2][1][RTW89_KCC][1][100] = 20, + [0][1][2][1][RTW89_KCC][0][100] = 127, + [0][1][2][1][RTW89_ACMA][1][100] = 127, + [0][1][2][1][RTW89_ACMA][0][100] = 127, + [0][1][2][1][RTW89_CHILE][1][100] = -2, + [0][1][2][1][RTW89_QATAR][1][100] = 127, + [0][1][2][1][RTW89_QATAR][0][100] = 127, + [0][1][2][1][RTW89_UK][1][100] = 127, + [0][1][2][1][RTW89_UK][0][100] = 127, + [0][1][2][1][RTW89_FCC][1][102] = -2, + [0][1][2][1][RTW89_FCC][2][102] = 127, + [0][1][2][1][RTW89_ETSI][1][102] = 127, + [0][1][2][1][RTW89_ETSI][0][102] = 127, + [0][1][2][1][RTW89_MKK][1][102] = 127, + [0][1][2][1][RTW89_MKK][0][102] = 127, + [0][1][2][1][RTW89_IC][1][102] = -2, + [0][1][2][1][RTW89_KCC][1][102] = 20, + [0][1][2][1][RTW89_KCC][0][102] = 127, + [0][1][2][1][RTW89_ACMA][1][102] = 127, + [0][1][2][1][RTW89_ACMA][0][102] = 127, + [0][1][2][1][RTW89_CHILE][1][102] = -2, + [0][1][2][1][RTW89_QATAR][1][102] = 127, + [0][1][2][1][RTW89_QATAR][0][102] = 127, + [0][1][2][1][RTW89_UK][1][102] = 127, + [0][1][2][1][RTW89_UK][0][102] = 127, + [0][1][2][1][RTW89_FCC][1][104] = -2, + [0][1][2][1][RTW89_FCC][2][104] = 127, + [0][1][2][1][RTW89_ETSI][1][104] = 127, + [0][1][2][1][RTW89_ETSI][0][104] = 127, + [0][1][2][1][RTW89_MKK][1][104] = 127, + [0][1][2][1][RTW89_MKK][0][104] = 127, + [0][1][2][1][RTW89_IC][1][104] = -2, + [0][1][2][1][RTW89_KCC][1][104] = 20, + [0][1][2][1][RTW89_KCC][0][104] = 127, + [0][1][2][1][RTW89_ACMA][1][104] = 127, + [0][1][2][1][RTW89_ACMA][0][104] = 127, + [0][1][2][1][RTW89_CHILE][1][104] = -2, + [0][1][2][1][RTW89_QATAR][1][104] = 127, + [0][1][2][1][RTW89_QATAR][0][104] = 127, + [0][1][2][1][RTW89_UK][1][104] = 127, + [0][1][2][1][RTW89_UK][0][104] = 127, + [0][1][2][1][RTW89_FCC][1][105] = -2, + [0][1][2][1][RTW89_FCC][2][105] = 127, + [0][1][2][1][RTW89_ETSI][1][105] = 127, + [0][1][2][1][RTW89_ETSI][0][105] = 127, + [0][1][2][1][RTW89_MKK][1][105] = 127, + [0][1][2][1][RTW89_MKK][0][105] = 127, + [0][1][2][1][RTW89_IC][1][105] = -2, + [0][1][2][1][RTW89_KCC][1][105] = 20, + [0][1][2][1][RTW89_KCC][0][105] = 127, + [0][1][2][1][RTW89_ACMA][1][105] = 127, + [0][1][2][1][RTW89_ACMA][0][105] = 127, + [0][1][2][1][RTW89_CHILE][1][105] = -2, + [0][1][2][1][RTW89_QATAR][1][105] = 127, + [0][1][2][1][RTW89_QATAR][0][105] = 127, + [0][1][2][1][RTW89_UK][1][105] = 127, + [0][1][2][1][RTW89_UK][0][105] = 127, + [0][1][2][1][RTW89_FCC][1][107] = 1, + [0][1][2][1][RTW89_FCC][2][107] = 127, + [0][1][2][1][RTW89_ETSI][1][107] = 127, + [0][1][2][1][RTW89_ETSI][0][107] = 127, + [0][1][2][1][RTW89_MKK][1][107] = 127, + [0][1][2][1][RTW89_MKK][0][107] = 127, + [0][1][2][1][RTW89_IC][1][107] = 1, + [0][1][2][1][RTW89_KCC][1][107] = 20, + [0][1][2][1][RTW89_KCC][0][107] = 127, + [0][1][2][1][RTW89_ACMA][1][107] = 127, + [0][1][2][1][RTW89_ACMA][0][107] = 127, + [0][1][2][1][RTW89_CHILE][1][107] = 1, + [0][1][2][1][RTW89_QATAR][1][107] = 127, + [0][1][2][1][RTW89_QATAR][0][107] = 127, + [0][1][2][1][RTW89_UK][1][107] = 127, + [0][1][2][1][RTW89_UK][0][107] = 127, + [0][1][2][1][RTW89_FCC][1][109] = 1, + [0][1][2][1][RTW89_FCC][2][109] = 127, + [0][1][2][1][RTW89_ETSI][1][109] = 127, + [0][1][2][1][RTW89_ETSI][0][109] = 127, + [0][1][2][1][RTW89_MKK][1][109] = 127, + [0][1][2][1][RTW89_MKK][0][109] = 127, + [0][1][2][1][RTW89_IC][1][109] = 1, + [0][1][2][1][RTW89_KCC][1][109] = 20, + [0][1][2][1][RTW89_KCC][0][109] = 127, + [0][1][2][1][RTW89_ACMA][1][109] = 127, + [0][1][2][1][RTW89_ACMA][0][109] = 127, + [0][1][2][1][RTW89_CHILE][1][109] = 1, + [0][1][2][1][RTW89_QATAR][1][109] = 127, + [0][1][2][1][RTW89_QATAR][0][109] = 127, + [0][1][2][1][RTW89_UK][1][109] = 127, + [0][1][2][1][RTW89_UK][0][109] = 127, + [0][1][2][1][RTW89_FCC][1][111] = 127, + [0][1][2][1][RTW89_FCC][2][111] = 127, + [0][1][2][1][RTW89_ETSI][1][111] = 127, + [0][1][2][1][RTW89_ETSI][0][111] = 127, + [0][1][2][1][RTW89_MKK][1][111] = 127, + [0][1][2][1][RTW89_MKK][0][111] = 127, + [0][1][2][1][RTW89_IC][1][111] = 127, + [0][1][2][1][RTW89_KCC][1][111] = 127, + [0][1][2][1][RTW89_KCC][0][111] = 127, + [0][1][2][1][RTW89_ACMA][1][111] = 127, + [0][1][2][1][RTW89_ACMA][0][111] = 127, + [0][1][2][1][RTW89_CHILE][1][111] = 127, + [0][1][2][1][RTW89_QATAR][1][111] = 127, + [0][1][2][1][RTW89_QATAR][0][111] = 127, + [0][1][2][1][RTW89_UK][1][111] = 127, + [0][1][2][1][RTW89_UK][0][111] = 127, + [0][1][2][1][RTW89_FCC][1][113] = 127, + [0][1][2][1][RTW89_FCC][2][113] = 127, + [0][1][2][1][RTW89_ETSI][1][113] = 127, + [0][1][2][1][RTW89_ETSI][0][113] = 127, + [0][1][2][1][RTW89_MKK][1][113] = 127, + [0][1][2][1][RTW89_MKK][0][113] = 127, + [0][1][2][1][RTW89_IC][1][113] = 127, + [0][1][2][1][RTW89_KCC][1][113] = 127, + [0][1][2][1][RTW89_KCC][0][113] = 127, + [0][1][2][1][RTW89_ACMA][1][113] = 127, + [0][1][2][1][RTW89_ACMA][0][113] = 127, + [0][1][2][1][RTW89_CHILE][1][113] = 127, + [0][1][2][1][RTW89_QATAR][1][113] = 127, + [0][1][2][1][RTW89_QATAR][0][113] = 127, + [0][1][2][1][RTW89_UK][1][113] = 127, + [0][1][2][1][RTW89_UK][0][113] = 127, + [0][1][2][1][RTW89_FCC][1][115] = 127, + [0][1][2][1][RTW89_FCC][2][115] = 127, + [0][1][2][1][RTW89_ETSI][1][115] = 127, + [0][1][2][1][RTW89_ETSI][0][115] = 127, + [0][1][2][1][RTW89_MKK][1][115] = 127, + [0][1][2][1][RTW89_MKK][0][115] = 127, + [0][1][2][1][RTW89_IC][1][115] = 127, + [0][1][2][1][RTW89_KCC][1][115] = 127, + [0][1][2][1][RTW89_KCC][0][115] = 127, + [0][1][2][1][RTW89_ACMA][1][115] = 127, + [0][1][2][1][RTW89_ACMA][0][115] = 127, + [0][1][2][1][RTW89_CHILE][1][115] = 127, + [0][1][2][1][RTW89_QATAR][1][115] = 127, + [0][1][2][1][RTW89_QATAR][0][115] = 127, + [0][1][2][1][RTW89_UK][1][115] = 127, + [0][1][2][1][RTW89_UK][0][115] = 127, + [0][1][2][1][RTW89_FCC][1][117] = 127, + [0][1][2][1][RTW89_FCC][2][117] = 127, + [0][1][2][1][RTW89_ETSI][1][117] = 127, + [0][1][2][1][RTW89_ETSI][0][117] = 127, + [0][1][2][1][RTW89_MKK][1][117] = 127, + [0][1][2][1][RTW89_MKK][0][117] = 127, + [0][1][2][1][RTW89_IC][1][117] = 127, + [0][1][2][1][RTW89_KCC][1][117] = 127, + [0][1][2][1][RTW89_KCC][0][117] = 127, + [0][1][2][1][RTW89_ACMA][1][117] = 127, + [0][1][2][1][RTW89_ACMA][0][117] = 127, + [0][1][2][1][RTW89_CHILE][1][117] = 127, + [0][1][2][1][RTW89_QATAR][1][117] = 127, + [0][1][2][1][RTW89_QATAR][0][117] = 127, + [0][1][2][1][RTW89_UK][1][117] = 127, + [0][1][2][1][RTW89_UK][0][117] = 127, + [0][1][2][1][RTW89_FCC][1][119] = 127, + [0][1][2][1][RTW89_FCC][2][119] = 127, + [0][1][2][1][RTW89_ETSI][1][119] = 127, + [0][1][2][1][RTW89_ETSI][0][119] = 127, + [0][1][2][1][RTW89_MKK][1][119] = 127, + [0][1][2][1][RTW89_MKK][0][119] = 127, + [0][1][2][1][RTW89_IC][1][119] = 127, + [0][1][2][1][RTW89_KCC][1][119] = 127, + [0][1][2][1][RTW89_KCC][0][119] = 127, + [0][1][2][1][RTW89_ACMA][1][119] = 127, + [0][1][2][1][RTW89_ACMA][0][119] = 127, + [0][1][2][1][RTW89_CHILE][1][119] = 127, + [0][1][2][1][RTW89_QATAR][1][119] = 127, + [0][1][2][1][RTW89_QATAR][0][119] = 127, + [0][1][2][1][RTW89_UK][1][119] = 127, + [0][1][2][1][RTW89_UK][0][119] = 127, + [1][0][2][0][RTW89_FCC][1][1] = 34, + [1][0][2][0][RTW89_FCC][2][1] = 70, + [1][0][2][0][RTW89_ETSI][1][1] = 66, + [1][0][2][0][RTW89_ETSI][0][1] = 30, + [1][0][2][0][RTW89_MKK][1][1] = 62, + [1][0][2][0][RTW89_MKK][0][1] = 26, + [1][0][2][0][RTW89_IC][1][1] = 34, + [1][0][2][0][RTW89_KCC][1][1] = 40, + [1][0][2][0][RTW89_KCC][0][1] = 24, + [1][0][2][0][RTW89_ACMA][1][1] = 66, + [1][0][2][0][RTW89_ACMA][0][1] = 30, + [1][0][2][0][RTW89_CHILE][1][1] = 34, + [1][0][2][0][RTW89_QATAR][1][1] = 66, + [1][0][2][0][RTW89_QATAR][0][1] = 30, + [1][0][2][0][RTW89_UK][1][1] = 66, + [1][0][2][0][RTW89_UK][0][1] = 30, + [1][0][2][0][RTW89_FCC][1][5] = 34, + [1][0][2][0][RTW89_FCC][2][5] = 70, + [1][0][2][0][RTW89_ETSI][1][5] = 66, + [1][0][2][0][RTW89_ETSI][0][5] = 30, + [1][0][2][0][RTW89_MKK][1][5] = 62, + [1][0][2][0][RTW89_MKK][0][5] = 26, + [1][0][2][0][RTW89_IC][1][5] = 34, + [1][0][2][0][RTW89_KCC][1][5] = 40, + [1][0][2][0][RTW89_KCC][0][5] = 24, + [1][0][2][0][RTW89_ACMA][1][5] = 66, + [1][0][2][0][RTW89_ACMA][0][5] = 30, + [1][0][2][0][RTW89_CHILE][1][5] = 34, + [1][0][2][0][RTW89_QATAR][1][5] = 66, + [1][0][2][0][RTW89_QATAR][0][5] = 30, + [1][0][2][0][RTW89_UK][1][5] = 66, + [1][0][2][0][RTW89_UK][0][5] = 30, + [1][0][2][0][RTW89_FCC][1][9] = 34, + [1][0][2][0][RTW89_FCC][2][9] = 70, + [1][0][2][0][RTW89_ETSI][1][9] = 66, + [1][0][2][0][RTW89_ETSI][0][9] = 30, + [1][0][2][0][RTW89_MKK][1][9] = 62, + [1][0][2][0][RTW89_MKK][0][9] = 26, + [1][0][2][0][RTW89_IC][1][9] = 34, + [1][0][2][0][RTW89_KCC][1][9] = 40, + [1][0][2][0][RTW89_KCC][0][9] = 24, + [1][0][2][0][RTW89_ACMA][1][9] = 66, + [1][0][2][0][RTW89_ACMA][0][9] = 30, + [1][0][2][0][RTW89_CHILE][1][9] = 34, + [1][0][2][0][RTW89_QATAR][1][9] = 66, + [1][0][2][0][RTW89_QATAR][0][9] = 30, + [1][0][2][0][RTW89_UK][1][9] = 66, + [1][0][2][0][RTW89_UK][0][9] = 30, + [1][0][2][0][RTW89_FCC][1][13] = 34, + [1][0][2][0][RTW89_FCC][2][13] = 70, + [1][0][2][0][RTW89_ETSI][1][13] = 66, + [1][0][2][0][RTW89_ETSI][0][13] = 30, + [1][0][2][0][RTW89_MKK][1][13] = 62, + [1][0][2][0][RTW89_MKK][0][13] = 26, + [1][0][2][0][RTW89_IC][1][13] = 34, + [1][0][2][0][RTW89_KCC][1][13] = 40, + [1][0][2][0][RTW89_KCC][0][13] = 24, + [1][0][2][0][RTW89_ACMA][1][13] = 66, + [1][0][2][0][RTW89_ACMA][0][13] = 30, + [1][0][2][0][RTW89_CHILE][1][13] = 34, + [1][0][2][0][RTW89_QATAR][1][13] = 66, + [1][0][2][0][RTW89_QATAR][0][13] = 30, + [1][0][2][0][RTW89_UK][1][13] = 66, + [1][0][2][0][RTW89_UK][0][13] = 30, + [1][0][2][0][RTW89_FCC][1][16] = 34, + [1][0][2][0][RTW89_FCC][2][16] = 70, + [1][0][2][0][RTW89_ETSI][1][16] = 66, + [1][0][2][0][RTW89_ETSI][0][16] = 30, + [1][0][2][0][RTW89_MKK][1][16] = 62, + [1][0][2][0][RTW89_MKK][0][16] = 26, + [1][0][2][0][RTW89_IC][1][16] = 34, + [1][0][2][0][RTW89_KCC][1][16] = 40, + [1][0][2][0][RTW89_KCC][0][16] = 24, + [1][0][2][0][RTW89_ACMA][1][16] = 66, + [1][0][2][0][RTW89_ACMA][0][16] = 30, + [1][0][2][0][RTW89_CHILE][1][16] = 34, + [1][0][2][0][RTW89_QATAR][1][16] = 66, + [1][0][2][0][RTW89_QATAR][0][16] = 30, + [1][0][2][0][RTW89_UK][1][16] = 66, + [1][0][2][0][RTW89_UK][0][16] = 30, + [1][0][2][0][RTW89_FCC][1][20] = 34, + [1][0][2][0][RTW89_FCC][2][20] = 70, + [1][0][2][0][RTW89_ETSI][1][20] = 66, + [1][0][2][0][RTW89_ETSI][0][20] = 30, + [1][0][2][0][RTW89_MKK][1][20] = 62, + [1][0][2][0][RTW89_MKK][0][20] = 26, + [1][0][2][0][RTW89_IC][1][20] = 34, + [1][0][2][0][RTW89_KCC][1][20] = 40, + [1][0][2][0][RTW89_KCC][0][20] = 24, + [1][0][2][0][RTW89_ACMA][1][20] = 66, + [1][0][2][0][RTW89_ACMA][0][20] = 30, + [1][0][2][0][RTW89_CHILE][1][20] = 34, + [1][0][2][0][RTW89_QATAR][1][20] = 66, + [1][0][2][0][RTW89_QATAR][0][20] = 30, + [1][0][2][0][RTW89_UK][1][20] = 66, + [1][0][2][0][RTW89_UK][0][20] = 30, + [1][0][2][0][RTW89_FCC][1][24] = 36, + [1][0][2][0][RTW89_FCC][2][24] = 70, + [1][0][2][0][RTW89_ETSI][1][24] = 66, + [1][0][2][0][RTW89_ETSI][0][24] = 30, + [1][0][2][0][RTW89_MKK][1][24] = 64, + [1][0][2][0][RTW89_MKK][0][24] = 28, + [1][0][2][0][RTW89_IC][1][24] = 36, + [1][0][2][0][RTW89_KCC][1][24] = 40, + [1][0][2][0][RTW89_KCC][0][24] = 26, + [1][0][2][0][RTW89_ACMA][1][24] = 66, + [1][0][2][0][RTW89_ACMA][0][24] = 30, + [1][0][2][0][RTW89_CHILE][1][24] = 36, + [1][0][2][0][RTW89_QATAR][1][24] = 66, + [1][0][2][0][RTW89_QATAR][0][24] = 30, + [1][0][2][0][RTW89_UK][1][24] = 66, + [1][0][2][0][RTW89_UK][0][24] = 30, + [1][0][2][0][RTW89_FCC][1][28] = 34, + [1][0][2][0][RTW89_FCC][2][28] = 70, + [1][0][2][0][RTW89_ETSI][1][28] = 66, + [1][0][2][0][RTW89_ETSI][0][28] = 30, + [1][0][2][0][RTW89_MKK][1][28] = 64, + [1][0][2][0][RTW89_MKK][0][28] = 26, + [1][0][2][0][RTW89_IC][1][28] = 34, + [1][0][2][0][RTW89_KCC][1][28] = 40, + [1][0][2][0][RTW89_KCC][0][28] = 26, + [1][0][2][0][RTW89_ACMA][1][28] = 66, + [1][0][2][0][RTW89_ACMA][0][28] = 30, + [1][0][2][0][RTW89_CHILE][1][28] = 34, + [1][0][2][0][RTW89_QATAR][1][28] = 66, + [1][0][2][0][RTW89_QATAR][0][28] = 30, + [1][0][2][0][RTW89_UK][1][28] = 66, + [1][0][2][0][RTW89_UK][0][28] = 30, + [1][0][2][0][RTW89_FCC][1][31] = 34, + [1][0][2][0][RTW89_FCC][2][31] = 70, + [1][0][2][0][RTW89_ETSI][1][31] = 66, + [1][0][2][0][RTW89_ETSI][0][31] = 30, + [1][0][2][0][RTW89_MKK][1][31] = 64, + [1][0][2][0][RTW89_MKK][0][31] = 26, + [1][0][2][0][RTW89_IC][1][31] = 34, + [1][0][2][0][RTW89_KCC][1][31] = 40, + [1][0][2][0][RTW89_KCC][0][31] = 26, + [1][0][2][0][RTW89_ACMA][1][31] = 66, + [1][0][2][0][RTW89_ACMA][0][31] = 30, + [1][0][2][0][RTW89_CHILE][1][31] = 34, + [1][0][2][0][RTW89_QATAR][1][31] = 66, + [1][0][2][0][RTW89_QATAR][0][31] = 30, + [1][0][2][0][RTW89_UK][1][31] = 66, + [1][0][2][0][RTW89_UK][0][31] = 30, + [1][0][2][0][RTW89_FCC][1][35] = 34, + [1][0][2][0][RTW89_FCC][2][35] = 70, + [1][0][2][0][RTW89_ETSI][1][35] = 66, + [1][0][2][0][RTW89_ETSI][0][35] = 30, + [1][0][2][0][RTW89_MKK][1][35] = 64, + [1][0][2][0][RTW89_MKK][0][35] = 26, + [1][0][2][0][RTW89_IC][1][35] = 34, + [1][0][2][0][RTW89_KCC][1][35] = 40, + [1][0][2][0][RTW89_KCC][0][35] = 26, + [1][0][2][0][RTW89_ACMA][1][35] = 66, + [1][0][2][0][RTW89_ACMA][0][35] = 30, + [1][0][2][0][RTW89_CHILE][1][35] = 34, + [1][0][2][0][RTW89_QATAR][1][35] = 66, + [1][0][2][0][RTW89_QATAR][0][35] = 30, + [1][0][2][0][RTW89_UK][1][35] = 66, + [1][0][2][0][RTW89_UK][0][35] = 30, + [1][0][2][0][RTW89_FCC][1][39] = 34, + [1][0][2][0][RTW89_FCC][2][39] = 70, + [1][0][2][0][RTW89_ETSI][1][39] = 66, + [1][0][2][0][RTW89_ETSI][0][39] = 30, + [1][0][2][0][RTW89_MKK][1][39] = 64, + [1][0][2][0][RTW89_MKK][0][39] = 26, + [1][0][2][0][RTW89_IC][1][39] = 34, + [1][0][2][0][RTW89_KCC][1][39] = 40, + [1][0][2][0][RTW89_KCC][0][39] = 26, + [1][0][2][0][RTW89_ACMA][1][39] = 66, + [1][0][2][0][RTW89_ACMA][0][39] = 30, + [1][0][2][0][RTW89_CHILE][1][39] = 34, + [1][0][2][0][RTW89_QATAR][1][39] = 66, + [1][0][2][0][RTW89_QATAR][0][39] = 30, + [1][0][2][0][RTW89_UK][1][39] = 66, + [1][0][2][0][RTW89_UK][0][39] = 30, + [1][0][2][0][RTW89_FCC][1][43] = 34, + [1][0][2][0][RTW89_FCC][2][43] = 70, + [1][0][2][0][RTW89_ETSI][1][43] = 66, + [1][0][2][0][RTW89_ETSI][0][43] = 30, + [1][0][2][0][RTW89_MKK][1][43] = 64, + [1][0][2][0][RTW89_MKK][0][43] = 26, + [1][0][2][0][RTW89_IC][1][43] = 34, + [1][0][2][0][RTW89_KCC][1][43] = 40, + [1][0][2][0][RTW89_KCC][0][43] = 26, + [1][0][2][0][RTW89_ACMA][1][43] = 66, + [1][0][2][0][RTW89_ACMA][0][43] = 30, + [1][0][2][0][RTW89_CHILE][1][43] = 34, + [1][0][2][0][RTW89_QATAR][1][43] = 66, + [1][0][2][0][RTW89_QATAR][0][43] = 30, + [1][0][2][0][RTW89_UK][1][43] = 66, + [1][0][2][0][RTW89_UK][0][43] = 30, + [1][0][2][0][RTW89_FCC][1][46] = 34, + [1][0][2][0][RTW89_FCC][2][46] = 127, + [1][0][2][0][RTW89_ETSI][1][46] = 127, + [1][0][2][0][RTW89_ETSI][0][46] = 127, + [1][0][2][0][RTW89_MKK][1][46] = 127, + [1][0][2][0][RTW89_MKK][0][46] = 127, + [1][0][2][0][RTW89_IC][1][46] = 34, + [1][0][2][0][RTW89_KCC][1][46] = 40, + [1][0][2][0][RTW89_KCC][0][46] = 127, + [1][0][2][0][RTW89_ACMA][1][46] = 127, + [1][0][2][0][RTW89_ACMA][0][46] = 127, + [1][0][2][0][RTW89_CHILE][1][46] = 34, + [1][0][2][0][RTW89_QATAR][1][46] = 127, + [1][0][2][0][RTW89_QATAR][0][46] = 127, + [1][0][2][0][RTW89_UK][1][46] = 127, + [1][0][2][0][RTW89_UK][0][46] = 127, + [1][0][2][0][RTW89_FCC][1][50] = 34, + [1][0][2][0][RTW89_FCC][2][50] = 127, + [1][0][2][0][RTW89_ETSI][1][50] = 127, + [1][0][2][0][RTW89_ETSI][0][50] = 127, + [1][0][2][0][RTW89_MKK][1][50] = 127, + [1][0][2][0][RTW89_MKK][0][50] = 127, + [1][0][2][0][RTW89_IC][1][50] = 34, + [1][0][2][0][RTW89_KCC][1][50] = 40, + [1][0][2][0][RTW89_KCC][0][50] = 127, + [1][0][2][0][RTW89_ACMA][1][50] = 127, + [1][0][2][0][RTW89_ACMA][0][50] = 127, + [1][0][2][0][RTW89_CHILE][1][50] = 34, + [1][0][2][0][RTW89_QATAR][1][50] = 127, + [1][0][2][0][RTW89_QATAR][0][50] = 127, + [1][0][2][0][RTW89_UK][1][50] = 127, + [1][0][2][0][RTW89_UK][0][50] = 127, + [1][0][2][0][RTW89_FCC][1][54] = 36, + [1][0][2][0][RTW89_FCC][2][54] = 127, + [1][0][2][0][RTW89_ETSI][1][54] = 127, + [1][0][2][0][RTW89_ETSI][0][54] = 127, + [1][0][2][0][RTW89_MKK][1][54] = 127, + [1][0][2][0][RTW89_MKK][0][54] = 127, + [1][0][2][0][RTW89_IC][1][54] = 36, + [1][0][2][0][RTW89_KCC][1][54] = 40, + [1][0][2][0][RTW89_KCC][0][54] = 127, + [1][0][2][0][RTW89_ACMA][1][54] = 127, + [1][0][2][0][RTW89_ACMA][0][54] = 127, + [1][0][2][0][RTW89_CHILE][1][54] = 36, + [1][0][2][0][RTW89_QATAR][1][54] = 127, + [1][0][2][0][RTW89_QATAR][0][54] = 127, + [1][0][2][0][RTW89_UK][1][54] = 127, + [1][0][2][0][RTW89_UK][0][54] = 127, + [1][0][2][0][RTW89_FCC][1][58] = 36, + [1][0][2][0][RTW89_FCC][2][58] = 66, + [1][0][2][0][RTW89_ETSI][1][58] = 127, + [1][0][2][0][RTW89_ETSI][0][58] = 127, + [1][0][2][0][RTW89_MKK][1][58] = 127, + [1][0][2][0][RTW89_MKK][0][58] = 127, + [1][0][2][0][RTW89_IC][1][58] = 36, + [1][0][2][0][RTW89_KCC][1][58] = 40, + [1][0][2][0][RTW89_KCC][0][58] = 127, + [1][0][2][0][RTW89_ACMA][1][58] = 127, + [1][0][2][0][RTW89_ACMA][0][58] = 127, + [1][0][2][0][RTW89_CHILE][1][58] = 36, + [1][0][2][0][RTW89_QATAR][1][58] = 127, + [1][0][2][0][RTW89_QATAR][0][58] = 127, + [1][0][2][0][RTW89_UK][1][58] = 127, + [1][0][2][0][RTW89_UK][0][58] = 127, + [1][0][2][0][RTW89_FCC][1][61] = 34, + [1][0][2][0][RTW89_FCC][2][61] = 66, + [1][0][2][0][RTW89_ETSI][1][61] = 127, + [1][0][2][0][RTW89_ETSI][0][61] = 127, + [1][0][2][0][RTW89_MKK][1][61] = 127, + [1][0][2][0][RTW89_MKK][0][61] = 127, + [1][0][2][0][RTW89_IC][1][61] = 34, + [1][0][2][0][RTW89_KCC][1][61] = 40, + [1][0][2][0][RTW89_KCC][0][61] = 127, + [1][0][2][0][RTW89_ACMA][1][61] = 127, + [1][0][2][0][RTW89_ACMA][0][61] = 127, + [1][0][2][0][RTW89_CHILE][1][61] = 34, + [1][0][2][0][RTW89_QATAR][1][61] = 127, + [1][0][2][0][RTW89_QATAR][0][61] = 127, + [1][0][2][0][RTW89_UK][1][61] = 127, + [1][0][2][0][RTW89_UK][0][61] = 127, + [1][0][2][0][RTW89_FCC][1][65] = 34, + [1][0][2][0][RTW89_FCC][2][65] = 66, + [1][0][2][0][RTW89_ETSI][1][65] = 127, + [1][0][2][0][RTW89_ETSI][0][65] = 127, + [1][0][2][0][RTW89_MKK][1][65] = 127, + [1][0][2][0][RTW89_MKK][0][65] = 127, + [1][0][2][0][RTW89_IC][1][65] = 34, + [1][0][2][0][RTW89_KCC][1][65] = 40, + [1][0][2][0][RTW89_KCC][0][65] = 127, + [1][0][2][0][RTW89_ACMA][1][65] = 127, + [1][0][2][0][RTW89_ACMA][0][65] = 127, + [1][0][2][0][RTW89_CHILE][1][65] = 34, + [1][0][2][0][RTW89_QATAR][1][65] = 127, + [1][0][2][0][RTW89_QATAR][0][65] = 127, + [1][0][2][0][RTW89_UK][1][65] = 127, + [1][0][2][0][RTW89_UK][0][65] = 127, + [1][0][2][0][RTW89_FCC][1][69] = 34, + [1][0][2][0][RTW89_FCC][2][69] = 66, + [1][0][2][0][RTW89_ETSI][1][69] = 127, + [1][0][2][0][RTW89_ETSI][0][69] = 127, + [1][0][2][0][RTW89_MKK][1][69] = 127, + [1][0][2][0][RTW89_MKK][0][69] = 127, + [1][0][2][0][RTW89_IC][1][69] = 34, + [1][0][2][0][RTW89_KCC][1][69] = 40, + [1][0][2][0][RTW89_KCC][0][69] = 127, + [1][0][2][0][RTW89_ACMA][1][69] = 127, + [1][0][2][0][RTW89_ACMA][0][69] = 127, + [1][0][2][0][RTW89_CHILE][1][69] = 34, + [1][0][2][0][RTW89_QATAR][1][69] = 127, + [1][0][2][0][RTW89_QATAR][0][69] = 127, + [1][0][2][0][RTW89_UK][1][69] = 127, + [1][0][2][0][RTW89_UK][0][69] = 127, + [1][0][2][0][RTW89_FCC][1][73] = 34, + [1][0][2][0][RTW89_FCC][2][73] = 66, + [1][0][2][0][RTW89_ETSI][1][73] = 127, + [1][0][2][0][RTW89_ETSI][0][73] = 127, + [1][0][2][0][RTW89_MKK][1][73] = 127, + [1][0][2][0][RTW89_MKK][0][73] = 127, + [1][0][2][0][RTW89_IC][1][73] = 34, + [1][0][2][0][RTW89_KCC][1][73] = 40, + [1][0][2][0][RTW89_KCC][0][73] = 127, + [1][0][2][0][RTW89_ACMA][1][73] = 127, + [1][0][2][0][RTW89_ACMA][0][73] = 127, + [1][0][2][0][RTW89_CHILE][1][73] = 34, + [1][0][2][0][RTW89_QATAR][1][73] = 127, + [1][0][2][0][RTW89_QATAR][0][73] = 127, + [1][0][2][0][RTW89_UK][1][73] = 127, + [1][0][2][0][RTW89_UK][0][73] = 127, + [1][0][2][0][RTW89_FCC][1][76] = 34, + [1][0][2][0][RTW89_FCC][2][76] = 66, + [1][0][2][0][RTW89_ETSI][1][76] = 127, + [1][0][2][0][RTW89_ETSI][0][76] = 127, + [1][0][2][0][RTW89_MKK][1][76] = 127, + [1][0][2][0][RTW89_MKK][0][76] = 127, + [1][0][2][0][RTW89_IC][1][76] = 34, + [1][0][2][0][RTW89_KCC][1][76] = 40, + [1][0][2][0][RTW89_KCC][0][76] = 127, + [1][0][2][0][RTW89_ACMA][1][76] = 127, + [1][0][2][0][RTW89_ACMA][0][76] = 127, + [1][0][2][0][RTW89_CHILE][1][76] = 34, + [1][0][2][0][RTW89_QATAR][1][76] = 127, + [1][0][2][0][RTW89_QATAR][0][76] = 127, + [1][0][2][0][RTW89_UK][1][76] = 127, + [1][0][2][0][RTW89_UK][0][76] = 127, + [1][0][2][0][RTW89_FCC][1][80] = 34, + [1][0][2][0][RTW89_FCC][2][80] = 66, + [1][0][2][0][RTW89_ETSI][1][80] = 127, + [1][0][2][0][RTW89_ETSI][0][80] = 127, + [1][0][2][0][RTW89_MKK][1][80] = 127, + [1][0][2][0][RTW89_MKK][0][80] = 127, + [1][0][2][0][RTW89_IC][1][80] = 34, + [1][0][2][0][RTW89_KCC][1][80] = 42, + [1][0][2][0][RTW89_KCC][0][80] = 127, + [1][0][2][0][RTW89_ACMA][1][80] = 127, + [1][0][2][0][RTW89_ACMA][0][80] = 127, + [1][0][2][0][RTW89_CHILE][1][80] = 34, + [1][0][2][0][RTW89_QATAR][1][80] = 127, + [1][0][2][0][RTW89_QATAR][0][80] = 127, + [1][0][2][0][RTW89_UK][1][80] = 127, + [1][0][2][0][RTW89_UK][0][80] = 127, + [1][0][2][0][RTW89_FCC][1][84] = 34, + [1][0][2][0][RTW89_FCC][2][84] = 66, + [1][0][2][0][RTW89_ETSI][1][84] = 127, + [1][0][2][0][RTW89_ETSI][0][84] = 127, + [1][0][2][0][RTW89_MKK][1][84] = 127, + [1][0][2][0][RTW89_MKK][0][84] = 127, + [1][0][2][0][RTW89_IC][1][84] = 34, + [1][0][2][0][RTW89_KCC][1][84] = 42, + [1][0][2][0][RTW89_KCC][0][84] = 127, + [1][0][2][0][RTW89_ACMA][1][84] = 127, + [1][0][2][0][RTW89_ACMA][0][84] = 127, + [1][0][2][0][RTW89_CHILE][1][84] = 34, + [1][0][2][0][RTW89_QATAR][1][84] = 127, + [1][0][2][0][RTW89_QATAR][0][84] = 127, + [1][0][2][0][RTW89_UK][1][84] = 127, + [1][0][2][0][RTW89_UK][0][84] = 127, + [1][0][2][0][RTW89_FCC][1][88] = 34, + [1][0][2][0][RTW89_FCC][2][88] = 127, + [1][0][2][0][RTW89_ETSI][1][88] = 127, + [1][0][2][0][RTW89_ETSI][0][88] = 127, + [1][0][2][0][RTW89_MKK][1][88] = 127, + [1][0][2][0][RTW89_MKK][0][88] = 127, + [1][0][2][0][RTW89_IC][1][88] = 34, + [1][0][2][0][RTW89_KCC][1][88] = 42, + [1][0][2][0][RTW89_KCC][0][88] = 127, + [1][0][2][0][RTW89_ACMA][1][88] = 127, + [1][0][2][0][RTW89_ACMA][0][88] = 127, + [1][0][2][0][RTW89_CHILE][1][88] = 34, + [1][0][2][0][RTW89_QATAR][1][88] = 127, + [1][0][2][0][RTW89_QATAR][0][88] = 127, + [1][0][2][0][RTW89_UK][1][88] = 127, + [1][0][2][0][RTW89_UK][0][88] = 127, + [1][0][2][0][RTW89_FCC][1][91] = 36, + [1][0][2][0][RTW89_FCC][2][91] = 127, + [1][0][2][0][RTW89_ETSI][1][91] = 127, + [1][0][2][0][RTW89_ETSI][0][91] = 127, + [1][0][2][0][RTW89_MKK][1][91] = 127, + [1][0][2][0][RTW89_MKK][0][91] = 127, + [1][0][2][0][RTW89_IC][1][91] = 36, + [1][0][2][0][RTW89_KCC][1][91] = 42, + [1][0][2][0][RTW89_KCC][0][91] = 127, + [1][0][2][0][RTW89_ACMA][1][91] = 127, + [1][0][2][0][RTW89_ACMA][0][91] = 127, + [1][0][2][0][RTW89_CHILE][1][91] = 36, + [1][0][2][0][RTW89_QATAR][1][91] = 127, + [1][0][2][0][RTW89_QATAR][0][91] = 127, + [1][0][2][0][RTW89_UK][1][91] = 127, + [1][0][2][0][RTW89_UK][0][91] = 127, + [1][0][2][0][RTW89_FCC][1][95] = 34, + [1][0][2][0][RTW89_FCC][2][95] = 127, + [1][0][2][0][RTW89_ETSI][1][95] = 127, + [1][0][2][0][RTW89_ETSI][0][95] = 127, + [1][0][2][0][RTW89_MKK][1][95] = 127, + [1][0][2][0][RTW89_MKK][0][95] = 127, + [1][0][2][0][RTW89_IC][1][95] = 34, + [1][0][2][0][RTW89_KCC][1][95] = 42, + [1][0][2][0][RTW89_KCC][0][95] = 127, + [1][0][2][0][RTW89_ACMA][1][95] = 127, + [1][0][2][0][RTW89_ACMA][0][95] = 127, + [1][0][2][0][RTW89_CHILE][1][95] = 34, + [1][0][2][0][RTW89_QATAR][1][95] = 127, + [1][0][2][0][RTW89_QATAR][0][95] = 127, + [1][0][2][0][RTW89_UK][1][95] = 127, + [1][0][2][0][RTW89_UK][0][95] = 127, + [1][0][2][0][RTW89_FCC][1][99] = 34, + [1][0][2][0][RTW89_FCC][2][99] = 127, + [1][0][2][0][RTW89_ETSI][1][99] = 127, + [1][0][2][0][RTW89_ETSI][0][99] = 127, + [1][0][2][0][RTW89_MKK][1][99] = 127, + [1][0][2][0][RTW89_MKK][0][99] = 127, + [1][0][2][0][RTW89_IC][1][99] = 34, + [1][0][2][0][RTW89_KCC][1][99] = 42, + [1][0][2][0][RTW89_KCC][0][99] = 127, + [1][0][2][0][RTW89_ACMA][1][99] = 127, + [1][0][2][0][RTW89_ACMA][0][99] = 127, + [1][0][2][0][RTW89_CHILE][1][99] = 34, + [1][0][2][0][RTW89_QATAR][1][99] = 127, + [1][0][2][0][RTW89_QATAR][0][99] = 127, + [1][0][2][0][RTW89_UK][1][99] = 127, + [1][0][2][0][RTW89_UK][0][99] = 127, + [1][0][2][0][RTW89_FCC][1][103] = 34, + [1][0][2][0][RTW89_FCC][2][103] = 127, + [1][0][2][0][RTW89_ETSI][1][103] = 127, + [1][0][2][0][RTW89_ETSI][0][103] = 127, + [1][0][2][0][RTW89_MKK][1][103] = 127, + [1][0][2][0][RTW89_MKK][0][103] = 127, + [1][0][2][0][RTW89_IC][1][103] = 34, + [1][0][2][0][RTW89_KCC][1][103] = 42, + [1][0][2][0][RTW89_KCC][0][103] = 127, + [1][0][2][0][RTW89_ACMA][1][103] = 127, + [1][0][2][0][RTW89_ACMA][0][103] = 127, + [1][0][2][0][RTW89_CHILE][1][103] = 34, + [1][0][2][0][RTW89_QATAR][1][103] = 127, + [1][0][2][0][RTW89_QATAR][0][103] = 127, + [1][0][2][0][RTW89_UK][1][103] = 127, + [1][0][2][0][RTW89_UK][0][103] = 127, + [1][0][2][0][RTW89_FCC][1][106] = 36, + [1][0][2][0][RTW89_FCC][2][106] = 127, + [1][0][2][0][RTW89_ETSI][1][106] = 127, + [1][0][2][0][RTW89_ETSI][0][106] = 127, + [1][0][2][0][RTW89_MKK][1][106] = 127, + [1][0][2][0][RTW89_MKK][0][106] = 127, + [1][0][2][0][RTW89_IC][1][106] = 36, + [1][0][2][0][RTW89_KCC][1][106] = 42, + [1][0][2][0][RTW89_KCC][0][106] = 127, + [1][0][2][0][RTW89_ACMA][1][106] = 127, + [1][0][2][0][RTW89_ACMA][0][106] = 127, + [1][0][2][0][RTW89_CHILE][1][106] = 36, + [1][0][2][0][RTW89_QATAR][1][106] = 127, + [1][0][2][0][RTW89_QATAR][0][106] = 127, + [1][0][2][0][RTW89_UK][1][106] = 127, + [1][0][2][0][RTW89_UK][0][106] = 127, + [1][0][2][0][RTW89_FCC][1][110] = 127, + [1][0][2][0][RTW89_FCC][2][110] = 127, + [1][0][2][0][RTW89_ETSI][1][110] = 127, + [1][0][2][0][RTW89_ETSI][0][110] = 127, + [1][0][2][0][RTW89_MKK][1][110] = 127, + [1][0][2][0][RTW89_MKK][0][110] = 127, + [1][0][2][0][RTW89_IC][1][110] = 127, + [1][0][2][0][RTW89_KCC][1][110] = 127, + [1][0][2][0][RTW89_KCC][0][110] = 127, + [1][0][2][0][RTW89_ACMA][1][110] = 127, + [1][0][2][0][RTW89_ACMA][0][110] = 127, + [1][0][2][0][RTW89_CHILE][1][110] = 127, + [1][0][2][0][RTW89_QATAR][1][110] = 127, + [1][0][2][0][RTW89_QATAR][0][110] = 127, + [1][0][2][0][RTW89_UK][1][110] = 127, + [1][0][2][0][RTW89_UK][0][110] = 127, + [1][0][2][0][RTW89_FCC][1][114] = 127, + [1][0][2][0][RTW89_FCC][2][114] = 127, + [1][0][2][0][RTW89_ETSI][1][114] = 127, + [1][0][2][0][RTW89_ETSI][0][114] = 127, + [1][0][2][0][RTW89_MKK][1][114] = 127, + [1][0][2][0][RTW89_MKK][0][114] = 127, + [1][0][2][0][RTW89_IC][1][114] = 127, + [1][0][2][0][RTW89_KCC][1][114] = 127, + [1][0][2][0][RTW89_KCC][0][114] = 127, + [1][0][2][0][RTW89_ACMA][1][114] = 127, + [1][0][2][0][RTW89_ACMA][0][114] = 127, + [1][0][2][0][RTW89_CHILE][1][114] = 127, + [1][0][2][0][RTW89_QATAR][1][114] = 127, + [1][0][2][0][RTW89_QATAR][0][114] = 127, + [1][0][2][0][RTW89_UK][1][114] = 127, + [1][0][2][0][RTW89_UK][0][114] = 127, + [1][0][2][0][RTW89_FCC][1][118] = 127, + [1][0][2][0][RTW89_FCC][2][118] = 127, + [1][0][2][0][RTW89_ETSI][1][118] = 127, + [1][0][2][0][RTW89_ETSI][0][118] = 127, + [1][0][2][0][RTW89_MKK][1][118] = 127, + [1][0][2][0][RTW89_MKK][0][118] = 127, + [1][0][2][0][RTW89_IC][1][118] = 127, + [1][0][2][0][RTW89_KCC][1][118] = 127, + [1][0][2][0][RTW89_KCC][0][118] = 127, + [1][0][2][0][RTW89_ACMA][1][118] = 127, + [1][0][2][0][RTW89_ACMA][0][118] = 127, + [1][0][2][0][RTW89_CHILE][1][118] = 127, + [1][0][2][0][RTW89_QATAR][1][118] = 127, + [1][0][2][0][RTW89_QATAR][0][118] = 127, + [1][0][2][0][RTW89_UK][1][118] = 127, + [1][0][2][0][RTW89_UK][0][118] = 127, + [1][1][2][0][RTW89_FCC][1][1] = 10, + [1][1][2][0][RTW89_FCC][2][1] = 58, + [1][1][2][0][RTW89_ETSI][1][1] = 54, + [1][1][2][0][RTW89_ETSI][0][1] = 18, + [1][1][2][0][RTW89_MKK][1][1] = 52, + [1][1][2][0][RTW89_MKK][0][1] = 12, + [1][1][2][0][RTW89_IC][1][1] = 10, + [1][1][2][0][RTW89_KCC][1][1] = 28, + [1][1][2][0][RTW89_KCC][0][1] = 12, + [1][1][2][0][RTW89_ACMA][1][1] = 54, + [1][1][2][0][RTW89_ACMA][0][1] = 18, + [1][1][2][0][RTW89_CHILE][1][1] = 10, + [1][1][2][0][RTW89_QATAR][1][1] = 54, + [1][1][2][0][RTW89_QATAR][0][1] = 18, + [1][1][2][0][RTW89_UK][1][1] = 54, + [1][1][2][0][RTW89_UK][0][1] = 18, + [1][1][2][0][RTW89_FCC][1][5] = 10, + [1][1][2][0][RTW89_FCC][2][5] = 58, + [1][1][2][0][RTW89_ETSI][1][5] = 54, + [1][1][2][0][RTW89_ETSI][0][5] = 16, + [1][1][2][0][RTW89_MKK][1][5] = 52, + [1][1][2][0][RTW89_MKK][0][5] = 12, + [1][1][2][0][RTW89_IC][1][5] = 10, + [1][1][2][0][RTW89_KCC][1][5] = 28, + [1][1][2][0][RTW89_KCC][0][5] = 12, + [1][1][2][0][RTW89_ACMA][1][5] = 54, + [1][1][2][0][RTW89_ACMA][0][5] = 16, + [1][1][2][0][RTW89_CHILE][1][5] = 10, + [1][1][2][0][RTW89_QATAR][1][5] = 54, + [1][1][2][0][RTW89_QATAR][0][5] = 16, + [1][1][2][0][RTW89_UK][1][5] = 54, + [1][1][2][0][RTW89_UK][0][5] = 16, + [1][1][2][0][RTW89_FCC][1][9] = 10, + [1][1][2][0][RTW89_FCC][2][9] = 58, + [1][1][2][0][RTW89_ETSI][1][9] = 54, + [1][1][2][0][RTW89_ETSI][0][9] = 16, + [1][1][2][0][RTW89_MKK][1][9] = 52, + [1][1][2][0][RTW89_MKK][0][9] = 12, + [1][1][2][0][RTW89_IC][1][9] = 10, + [1][1][2][0][RTW89_KCC][1][9] = 28, + [1][1][2][0][RTW89_KCC][0][9] = 12, + [1][1][2][0][RTW89_ACMA][1][9] = 54, + [1][1][2][0][RTW89_ACMA][0][9] = 16, + [1][1][2][0][RTW89_CHILE][1][9] = 10, + [1][1][2][0][RTW89_QATAR][1][9] = 54, + [1][1][2][0][RTW89_QATAR][0][9] = 16, + [1][1][2][0][RTW89_UK][1][9] = 54, + [1][1][2][0][RTW89_UK][0][9] = 16, + [1][1][2][0][RTW89_FCC][1][13] = 10, + [1][1][2][0][RTW89_FCC][2][13] = 58, + [1][1][2][0][RTW89_ETSI][1][13] = 54, + [1][1][2][0][RTW89_ETSI][0][13] = 16, + [1][1][2][0][RTW89_MKK][1][13] = 52, + [1][1][2][0][RTW89_MKK][0][13] = 12, + [1][1][2][0][RTW89_IC][1][13] = 10, + [1][1][2][0][RTW89_KCC][1][13] = 28, + [1][1][2][0][RTW89_KCC][0][13] = 12, + [1][1][2][0][RTW89_ACMA][1][13] = 54, + [1][1][2][0][RTW89_ACMA][0][13] = 16, + [1][1][2][0][RTW89_CHILE][1][13] = 10, + [1][1][2][0][RTW89_QATAR][1][13] = 54, + [1][1][2][0][RTW89_QATAR][0][13] = 16, + [1][1][2][0][RTW89_UK][1][13] = 54, + [1][1][2][0][RTW89_UK][0][13] = 16, + [1][1][2][0][RTW89_FCC][1][16] = 10, + [1][1][2][0][RTW89_FCC][2][16] = 58, + [1][1][2][0][RTW89_ETSI][1][16] = 54, + [1][1][2][0][RTW89_ETSI][0][16] = 16, + [1][1][2][0][RTW89_MKK][1][16] = 52, + [1][1][2][0][RTW89_MKK][0][16] = 12, + [1][1][2][0][RTW89_IC][1][16] = 10, + [1][1][2][0][RTW89_KCC][1][16] = 28, + [1][1][2][0][RTW89_KCC][0][16] = 12, + [1][1][2][0][RTW89_ACMA][1][16] = 54, + [1][1][2][0][RTW89_ACMA][0][16] = 16, + [1][1][2][0][RTW89_CHILE][1][16] = 10, + [1][1][2][0][RTW89_QATAR][1][16] = 54, + [1][1][2][0][RTW89_QATAR][0][16] = 16, + [1][1][2][0][RTW89_UK][1][16] = 54, + [1][1][2][0][RTW89_UK][0][16] = 16, + [1][1][2][0][RTW89_FCC][1][20] = 10, + [1][1][2][0][RTW89_FCC][2][20] = 58, + [1][1][2][0][RTW89_ETSI][1][20] = 54, + [1][1][2][0][RTW89_ETSI][0][20] = 16, + [1][1][2][0][RTW89_MKK][1][20] = 52, + [1][1][2][0][RTW89_MKK][0][20] = 12, + [1][1][2][0][RTW89_IC][1][20] = 10, + [1][1][2][0][RTW89_KCC][1][20] = 28, + [1][1][2][0][RTW89_KCC][0][20] = 12, + [1][1][2][0][RTW89_ACMA][1][20] = 54, + [1][1][2][0][RTW89_ACMA][0][20] = 16, + [1][1][2][0][RTW89_CHILE][1][20] = 10, + [1][1][2][0][RTW89_QATAR][1][20] = 54, + [1][1][2][0][RTW89_QATAR][0][20] = 16, + [1][1][2][0][RTW89_UK][1][20] = 54, + [1][1][2][0][RTW89_UK][0][20] = 16, + [1][1][2][0][RTW89_FCC][1][24] = 10, + [1][1][2][0][RTW89_FCC][2][24] = 70, + [1][1][2][0][RTW89_ETSI][1][24] = 54, + [1][1][2][0][RTW89_ETSI][0][24] = 16, + [1][1][2][0][RTW89_MKK][1][24] = 54, + [1][1][2][0][RTW89_MKK][0][24] = 14, + [1][1][2][0][RTW89_IC][1][24] = 10, + [1][1][2][0][RTW89_KCC][1][24] = 28, + [1][1][2][0][RTW89_KCC][0][24] = 12, + [1][1][2][0][RTW89_ACMA][1][24] = 54, + [1][1][2][0][RTW89_ACMA][0][24] = 16, + [1][1][2][0][RTW89_CHILE][1][24] = 10, + [1][1][2][0][RTW89_QATAR][1][24] = 54, + [1][1][2][0][RTW89_QATAR][0][24] = 16, + [1][1][2][0][RTW89_UK][1][24] = 54, + [1][1][2][0][RTW89_UK][0][24] = 16, + [1][1][2][0][RTW89_FCC][1][28] = 10, + [1][1][2][0][RTW89_FCC][2][28] = 70, + [1][1][2][0][RTW89_ETSI][1][28] = 54, + [1][1][2][0][RTW89_ETSI][0][28] = 16, + [1][1][2][0][RTW89_MKK][1][28] = 52, + [1][1][2][0][RTW89_MKK][0][28] = 14, + [1][1][2][0][RTW89_IC][1][28] = 10, + [1][1][2][0][RTW89_KCC][1][28] = 28, + [1][1][2][0][RTW89_KCC][0][28] = 14, + [1][1][2][0][RTW89_ACMA][1][28] = 54, + [1][1][2][0][RTW89_ACMA][0][28] = 16, + [1][1][2][0][RTW89_CHILE][1][28] = 10, + [1][1][2][0][RTW89_QATAR][1][28] = 54, + [1][1][2][0][RTW89_QATAR][0][28] = 16, + [1][1][2][0][RTW89_UK][1][28] = 54, + [1][1][2][0][RTW89_UK][0][28] = 16, + [1][1][2][0][RTW89_FCC][1][31] = 10, + [1][1][2][0][RTW89_FCC][2][31] = 70, + [1][1][2][0][RTW89_ETSI][1][31] = 54, + [1][1][2][0][RTW89_ETSI][0][31] = 16, + [1][1][2][0][RTW89_MKK][1][31] = 52, + [1][1][2][0][RTW89_MKK][0][31] = 14, + [1][1][2][0][RTW89_IC][1][31] = 10, + [1][1][2][0][RTW89_KCC][1][31] = 28, + [1][1][2][0][RTW89_KCC][0][31] = 14, + [1][1][2][0][RTW89_ACMA][1][31] = 54, + [1][1][2][0][RTW89_ACMA][0][31] = 16, + [1][1][2][0][RTW89_CHILE][1][31] = 10, + [1][1][2][0][RTW89_QATAR][1][31] = 54, + [1][1][2][0][RTW89_QATAR][0][31] = 16, + [1][1][2][0][RTW89_UK][1][31] = 54, + [1][1][2][0][RTW89_UK][0][31] = 16, + [1][1][2][0][RTW89_FCC][1][35] = 10, + [1][1][2][0][RTW89_FCC][2][35] = 70, + [1][1][2][0][RTW89_ETSI][1][35] = 54, + [1][1][2][0][RTW89_ETSI][0][35] = 16, + [1][1][2][0][RTW89_MKK][1][35] = 52, + [1][1][2][0][RTW89_MKK][0][35] = 14, + [1][1][2][0][RTW89_IC][1][35] = 10, + [1][1][2][0][RTW89_KCC][1][35] = 28, + [1][1][2][0][RTW89_KCC][0][35] = 14, + [1][1][2][0][RTW89_ACMA][1][35] = 54, + [1][1][2][0][RTW89_ACMA][0][35] = 16, + [1][1][2][0][RTW89_CHILE][1][35] = 10, + [1][1][2][0][RTW89_QATAR][1][35] = 54, + [1][1][2][0][RTW89_QATAR][0][35] = 16, + [1][1][2][0][RTW89_UK][1][35] = 54, + [1][1][2][0][RTW89_UK][0][35] = 16, + [1][1][2][0][RTW89_FCC][1][39] = 10, + [1][1][2][0][RTW89_FCC][2][39] = 70, + [1][1][2][0][RTW89_ETSI][1][39] = 54, + [1][1][2][0][RTW89_ETSI][0][39] = 16, + [1][1][2][0][RTW89_MKK][1][39] = 52, + [1][1][2][0][RTW89_MKK][0][39] = 14, + [1][1][2][0][RTW89_IC][1][39] = 10, + [1][1][2][0][RTW89_KCC][1][39] = 28, + [1][1][2][0][RTW89_KCC][0][39] = 14, + [1][1][2][0][RTW89_ACMA][1][39] = 54, + [1][1][2][0][RTW89_ACMA][0][39] = 16, + [1][1][2][0][RTW89_CHILE][1][39] = 10, + [1][1][2][0][RTW89_QATAR][1][39] = 54, + [1][1][2][0][RTW89_QATAR][0][39] = 16, + [1][1][2][0][RTW89_UK][1][39] = 54, + [1][1][2][0][RTW89_UK][0][39] = 16, + [1][1][2][0][RTW89_FCC][1][43] = 10, + [1][1][2][0][RTW89_FCC][2][43] = 70, + [1][1][2][0][RTW89_ETSI][1][43] = 54, + [1][1][2][0][RTW89_ETSI][0][43] = 16, + [1][1][2][0][RTW89_MKK][1][43] = 52, + [1][1][2][0][RTW89_MKK][0][43] = 14, + [1][1][2][0][RTW89_IC][1][43] = 10, + [1][1][2][0][RTW89_KCC][1][43] = 28, + [1][1][2][0][RTW89_KCC][0][43] = 14, + [1][1][2][0][RTW89_ACMA][1][43] = 54, + [1][1][2][0][RTW89_ACMA][0][43] = 16, + [1][1][2][0][RTW89_CHILE][1][43] = 10, + [1][1][2][0][RTW89_QATAR][1][43] = 54, + [1][1][2][0][RTW89_QATAR][0][43] = 16, + [1][1][2][0][RTW89_UK][1][43] = 54, + [1][1][2][0][RTW89_UK][0][43] = 16, + [1][1][2][0][RTW89_FCC][1][46] = 12, + [1][1][2][0][RTW89_FCC][2][46] = 127, + [1][1][2][0][RTW89_ETSI][1][46] = 127, + [1][1][2][0][RTW89_ETSI][0][46] = 127, + [1][1][2][0][RTW89_MKK][1][46] = 127, + [1][1][2][0][RTW89_MKK][0][46] = 127, + [1][1][2][0][RTW89_IC][1][46] = 12, + [1][1][2][0][RTW89_KCC][1][46] = 28, + [1][1][2][0][RTW89_KCC][0][46] = 127, + [1][1][2][0][RTW89_ACMA][1][46] = 127, + [1][1][2][0][RTW89_ACMA][0][46] = 127, + [1][1][2][0][RTW89_CHILE][1][46] = 12, + [1][1][2][0][RTW89_QATAR][1][46] = 127, + [1][1][2][0][RTW89_QATAR][0][46] = 127, + [1][1][2][0][RTW89_UK][1][46] = 127, + [1][1][2][0][RTW89_UK][0][46] = 127, + [1][1][2][0][RTW89_FCC][1][50] = 12, + [1][1][2][0][RTW89_FCC][2][50] = 127, + [1][1][2][0][RTW89_ETSI][1][50] = 127, + [1][1][2][0][RTW89_ETSI][0][50] = 127, + [1][1][2][0][RTW89_MKK][1][50] = 127, + [1][1][2][0][RTW89_MKK][0][50] = 127, + [1][1][2][0][RTW89_IC][1][50] = 12, + [1][1][2][0][RTW89_KCC][1][50] = 28, + [1][1][2][0][RTW89_KCC][0][50] = 127, + [1][1][2][0][RTW89_ACMA][1][50] = 127, + [1][1][2][0][RTW89_ACMA][0][50] = 127, + [1][1][2][0][RTW89_CHILE][1][50] = 12, + [1][1][2][0][RTW89_QATAR][1][50] = 127, + [1][1][2][0][RTW89_QATAR][0][50] = 127, + [1][1][2][0][RTW89_UK][1][50] = 127, + [1][1][2][0][RTW89_UK][0][50] = 127, + [1][1][2][0][RTW89_FCC][1][54] = 10, + [1][1][2][0][RTW89_FCC][2][54] = 127, + [1][1][2][0][RTW89_ETSI][1][54] = 127, + [1][1][2][0][RTW89_ETSI][0][54] = 127, + [1][1][2][0][RTW89_MKK][1][54] = 127, + [1][1][2][0][RTW89_MKK][0][54] = 127, + [1][1][2][0][RTW89_IC][1][54] = 10, + [1][1][2][0][RTW89_KCC][1][54] = 28, + [1][1][2][0][RTW89_KCC][0][54] = 127, + [1][1][2][0][RTW89_ACMA][1][54] = 127, + [1][1][2][0][RTW89_ACMA][0][54] = 127, + [1][1][2][0][RTW89_CHILE][1][54] = 10, + [1][1][2][0][RTW89_QATAR][1][54] = 127, + [1][1][2][0][RTW89_QATAR][0][54] = 127, + [1][1][2][0][RTW89_UK][1][54] = 127, + [1][1][2][0][RTW89_UK][0][54] = 127, + [1][1][2][0][RTW89_FCC][1][58] = 10, + [1][1][2][0][RTW89_FCC][2][58] = 66, + [1][1][2][0][RTW89_ETSI][1][58] = 127, + [1][1][2][0][RTW89_ETSI][0][58] = 127, + [1][1][2][0][RTW89_MKK][1][58] = 127, + [1][1][2][0][RTW89_MKK][0][58] = 127, + [1][1][2][0][RTW89_IC][1][58] = 10, + [1][1][2][0][RTW89_KCC][1][58] = 28, + [1][1][2][0][RTW89_KCC][0][58] = 127, + [1][1][2][0][RTW89_ACMA][1][58] = 127, + [1][1][2][0][RTW89_ACMA][0][58] = 127, + [1][1][2][0][RTW89_CHILE][1][58] = 10, + [1][1][2][0][RTW89_QATAR][1][58] = 127, + [1][1][2][0][RTW89_QATAR][0][58] = 127, + [1][1][2][0][RTW89_UK][1][58] = 127, + [1][1][2][0][RTW89_UK][0][58] = 127, + [1][1][2][0][RTW89_FCC][1][61] = 10, + [1][1][2][0][RTW89_FCC][2][61] = 66, + [1][1][2][0][RTW89_ETSI][1][61] = 127, + [1][1][2][0][RTW89_ETSI][0][61] = 127, + [1][1][2][0][RTW89_MKK][1][61] = 127, + [1][1][2][0][RTW89_MKK][0][61] = 127, + [1][1][2][0][RTW89_IC][1][61] = 10, + [1][1][2][0][RTW89_KCC][1][61] = 28, + [1][1][2][0][RTW89_KCC][0][61] = 127, + [1][1][2][0][RTW89_ACMA][1][61] = 127, + [1][1][2][0][RTW89_ACMA][0][61] = 127, + [1][1][2][0][RTW89_CHILE][1][61] = 10, + [1][1][2][0][RTW89_QATAR][1][61] = 127, + [1][1][2][0][RTW89_QATAR][0][61] = 127, + [1][1][2][0][RTW89_UK][1][61] = 127, + [1][1][2][0][RTW89_UK][0][61] = 127, + [1][1][2][0][RTW89_FCC][1][65] = 10, + [1][1][2][0][RTW89_FCC][2][65] = 66, + [1][1][2][0][RTW89_ETSI][1][65] = 127, + [1][1][2][0][RTW89_ETSI][0][65] = 127, + [1][1][2][0][RTW89_MKK][1][65] = 127, + [1][1][2][0][RTW89_MKK][0][65] = 127, + [1][1][2][0][RTW89_IC][1][65] = 10, + [1][1][2][0][RTW89_KCC][1][65] = 28, + [1][1][2][0][RTW89_KCC][0][65] = 127, + [1][1][2][0][RTW89_ACMA][1][65] = 127, + [1][1][2][0][RTW89_ACMA][0][65] = 127, + [1][1][2][0][RTW89_CHILE][1][65] = 10, + [1][1][2][0][RTW89_QATAR][1][65] = 127, + [1][1][2][0][RTW89_QATAR][0][65] = 127, + [1][1][2][0][RTW89_UK][1][65] = 127, + [1][1][2][0][RTW89_UK][0][65] = 127, + [1][1][2][0][RTW89_FCC][1][69] = 10, + [1][1][2][0][RTW89_FCC][2][69] = 66, + [1][1][2][0][RTW89_ETSI][1][69] = 127, + [1][1][2][0][RTW89_ETSI][0][69] = 127, + [1][1][2][0][RTW89_MKK][1][69] = 127, + [1][1][2][0][RTW89_MKK][0][69] = 127, + [1][1][2][0][RTW89_IC][1][69] = 10, + [1][1][2][0][RTW89_KCC][1][69] = 28, + [1][1][2][0][RTW89_KCC][0][69] = 127, + [1][1][2][0][RTW89_ACMA][1][69] = 127, + [1][1][2][0][RTW89_ACMA][0][69] = 127, + [1][1][2][0][RTW89_CHILE][1][69] = 10, + [1][1][2][0][RTW89_QATAR][1][69] = 127, + [1][1][2][0][RTW89_QATAR][0][69] = 127, + [1][1][2][0][RTW89_UK][1][69] = 127, + [1][1][2][0][RTW89_UK][0][69] = 127, + [1][1][2][0][RTW89_FCC][1][73] = 10, + [1][1][2][0][RTW89_FCC][2][73] = 66, + [1][1][2][0][RTW89_ETSI][1][73] = 127, + [1][1][2][0][RTW89_ETSI][0][73] = 127, + [1][1][2][0][RTW89_MKK][1][73] = 127, + [1][1][2][0][RTW89_MKK][0][73] = 127, + [1][1][2][0][RTW89_IC][1][73] = 10, + [1][1][2][0][RTW89_KCC][1][73] = 28, + [1][1][2][0][RTW89_KCC][0][73] = 127, + [1][1][2][0][RTW89_ACMA][1][73] = 127, + [1][1][2][0][RTW89_ACMA][0][73] = 127, + [1][1][2][0][RTW89_CHILE][1][73] = 10, + [1][1][2][0][RTW89_QATAR][1][73] = 127, + [1][1][2][0][RTW89_QATAR][0][73] = 127, + [1][1][2][0][RTW89_UK][1][73] = 127, + [1][1][2][0][RTW89_UK][0][73] = 127, + [1][1][2][0][RTW89_FCC][1][76] = 10, + [1][1][2][0][RTW89_FCC][2][76] = 66, + [1][1][2][0][RTW89_ETSI][1][76] = 127, + [1][1][2][0][RTW89_ETSI][0][76] = 127, + [1][1][2][0][RTW89_MKK][1][76] = 127, + [1][1][2][0][RTW89_MKK][0][76] = 127, + [1][1][2][0][RTW89_IC][1][76] = 10, + [1][1][2][0][RTW89_KCC][1][76] = 28, + [1][1][2][0][RTW89_KCC][0][76] = 127, + [1][1][2][0][RTW89_ACMA][1][76] = 127, + [1][1][2][0][RTW89_ACMA][0][76] = 127, + [1][1][2][0][RTW89_CHILE][1][76] = 10, + [1][1][2][0][RTW89_QATAR][1][76] = 127, + [1][1][2][0][RTW89_QATAR][0][76] = 127, + [1][1][2][0][RTW89_UK][1][76] = 127, + [1][1][2][0][RTW89_UK][0][76] = 127, + [1][1][2][0][RTW89_FCC][1][80] = 10, + [1][1][2][0][RTW89_FCC][2][80] = 66, + [1][1][2][0][RTW89_ETSI][1][80] = 127, + [1][1][2][0][RTW89_ETSI][0][80] = 127, + [1][1][2][0][RTW89_MKK][1][80] = 127, + [1][1][2][0][RTW89_MKK][0][80] = 127, + [1][1][2][0][RTW89_IC][1][80] = 10, + [1][1][2][0][RTW89_KCC][1][80] = 32, + [1][1][2][0][RTW89_KCC][0][80] = 127, + [1][1][2][0][RTW89_ACMA][1][80] = 127, + [1][1][2][0][RTW89_ACMA][0][80] = 127, + [1][1][2][0][RTW89_CHILE][1][80] = 10, + [1][1][2][0][RTW89_QATAR][1][80] = 127, + [1][1][2][0][RTW89_QATAR][0][80] = 127, + [1][1][2][0][RTW89_UK][1][80] = 127, + [1][1][2][0][RTW89_UK][0][80] = 127, + [1][1][2][0][RTW89_FCC][1][84] = 10, + [1][1][2][0][RTW89_FCC][2][84] = 66, + [1][1][2][0][RTW89_ETSI][1][84] = 127, + [1][1][2][0][RTW89_ETSI][0][84] = 127, + [1][1][2][0][RTW89_MKK][1][84] = 127, + [1][1][2][0][RTW89_MKK][0][84] = 127, + [1][1][2][0][RTW89_IC][1][84] = 10, + [1][1][2][0][RTW89_KCC][1][84] = 32, + [1][1][2][0][RTW89_KCC][0][84] = 127, + [1][1][2][0][RTW89_ACMA][1][84] = 127, + [1][1][2][0][RTW89_ACMA][0][84] = 127, + [1][1][2][0][RTW89_CHILE][1][84] = 10, + [1][1][2][0][RTW89_QATAR][1][84] = 127, + [1][1][2][0][RTW89_QATAR][0][84] = 127, + [1][1][2][0][RTW89_UK][1][84] = 127, + [1][1][2][0][RTW89_UK][0][84] = 127, + [1][1][2][0][RTW89_FCC][1][88] = 10, + [1][1][2][0][RTW89_FCC][2][88] = 127, + [1][1][2][0][RTW89_ETSI][1][88] = 127, + [1][1][2][0][RTW89_ETSI][0][88] = 127, + [1][1][2][0][RTW89_MKK][1][88] = 127, + [1][1][2][0][RTW89_MKK][0][88] = 127, + [1][1][2][0][RTW89_IC][1][88] = 10, + [1][1][2][0][RTW89_KCC][1][88] = 32, + [1][1][2][0][RTW89_KCC][0][88] = 127, + [1][1][2][0][RTW89_ACMA][1][88] = 127, + [1][1][2][0][RTW89_ACMA][0][88] = 127, + [1][1][2][0][RTW89_CHILE][1][88] = 10, + [1][1][2][0][RTW89_QATAR][1][88] = 127, + [1][1][2][0][RTW89_QATAR][0][88] = 127, + [1][1][2][0][RTW89_UK][1][88] = 127, + [1][1][2][0][RTW89_UK][0][88] = 127, + [1][1][2][0][RTW89_FCC][1][91] = 12, + [1][1][2][0][RTW89_FCC][2][91] = 127, + [1][1][2][0][RTW89_ETSI][1][91] = 127, + [1][1][2][0][RTW89_ETSI][0][91] = 127, + [1][1][2][0][RTW89_MKK][1][91] = 127, + [1][1][2][0][RTW89_MKK][0][91] = 127, + [1][1][2][0][RTW89_IC][1][91] = 12, + [1][1][2][0][RTW89_KCC][1][91] = 32, + [1][1][2][0][RTW89_KCC][0][91] = 127, + [1][1][2][0][RTW89_ACMA][1][91] = 127, + [1][1][2][0][RTW89_ACMA][0][91] = 127, + [1][1][2][0][RTW89_CHILE][1][91] = 12, + [1][1][2][0][RTW89_QATAR][1][91] = 127, + [1][1][2][0][RTW89_QATAR][0][91] = 127, + [1][1][2][0][RTW89_UK][1][91] = 127, + [1][1][2][0][RTW89_UK][0][91] = 127, + [1][1][2][0][RTW89_FCC][1][95] = 10, + [1][1][2][0][RTW89_FCC][2][95] = 127, + [1][1][2][0][RTW89_ETSI][1][95] = 127, + [1][1][2][0][RTW89_ETSI][0][95] = 127, + [1][1][2][0][RTW89_MKK][1][95] = 127, + [1][1][2][0][RTW89_MKK][0][95] = 127, + [1][1][2][0][RTW89_IC][1][95] = 10, + [1][1][2][0][RTW89_KCC][1][95] = 32, + [1][1][2][0][RTW89_KCC][0][95] = 127, + [1][1][2][0][RTW89_ACMA][1][95] = 127, + [1][1][2][0][RTW89_ACMA][0][95] = 127, + [1][1][2][0][RTW89_CHILE][1][95] = 10, + [1][1][2][0][RTW89_QATAR][1][95] = 127, + [1][1][2][0][RTW89_QATAR][0][95] = 127, + [1][1][2][0][RTW89_UK][1][95] = 127, + [1][1][2][0][RTW89_UK][0][95] = 127, + [1][1][2][0][RTW89_FCC][1][99] = 10, + [1][1][2][0][RTW89_FCC][2][99] = 127, + [1][1][2][0][RTW89_ETSI][1][99] = 127, + [1][1][2][0][RTW89_ETSI][0][99] = 127, + [1][1][2][0][RTW89_MKK][1][99] = 127, + [1][1][2][0][RTW89_MKK][0][99] = 127, + [1][1][2][0][RTW89_IC][1][99] = 10, + [1][1][2][0][RTW89_KCC][1][99] = 32, + [1][1][2][0][RTW89_KCC][0][99] = 127, + [1][1][2][0][RTW89_ACMA][1][99] = 127, + [1][1][2][0][RTW89_ACMA][0][99] = 127, + [1][1][2][0][RTW89_CHILE][1][99] = 10, + [1][1][2][0][RTW89_QATAR][1][99] = 127, + [1][1][2][0][RTW89_QATAR][0][99] = 127, + [1][1][2][0][RTW89_UK][1][99] = 127, + [1][1][2][0][RTW89_UK][0][99] = 127, + [1][1][2][0][RTW89_FCC][1][103] = 10, + [1][1][2][0][RTW89_FCC][2][103] = 127, + [1][1][2][0][RTW89_ETSI][1][103] = 127, + [1][1][2][0][RTW89_ETSI][0][103] = 127, + [1][1][2][0][RTW89_MKK][1][103] = 127, + [1][1][2][0][RTW89_MKK][0][103] = 127, + [1][1][2][0][RTW89_IC][1][103] = 10, + [1][1][2][0][RTW89_KCC][1][103] = 32, + [1][1][2][0][RTW89_KCC][0][103] = 127, + [1][1][2][0][RTW89_ACMA][1][103] = 127, + [1][1][2][0][RTW89_ACMA][0][103] = 127, + [1][1][2][0][RTW89_CHILE][1][103] = 10, + [1][1][2][0][RTW89_QATAR][1][103] = 127, + [1][1][2][0][RTW89_QATAR][0][103] = 127, + [1][1][2][0][RTW89_UK][1][103] = 127, + [1][1][2][0][RTW89_UK][0][103] = 127, + [1][1][2][0][RTW89_FCC][1][106] = 12, + [1][1][2][0][RTW89_FCC][2][106] = 127, + [1][1][2][0][RTW89_ETSI][1][106] = 127, + [1][1][2][0][RTW89_ETSI][0][106] = 127, + [1][1][2][0][RTW89_MKK][1][106] = 127, + [1][1][2][0][RTW89_MKK][0][106] = 127, + [1][1][2][0][RTW89_IC][1][106] = 12, + [1][1][2][0][RTW89_KCC][1][106] = 32, + [1][1][2][0][RTW89_KCC][0][106] = 127, + [1][1][2][0][RTW89_ACMA][1][106] = 127, + [1][1][2][0][RTW89_ACMA][0][106] = 127, + [1][1][2][0][RTW89_CHILE][1][106] = 12, + [1][1][2][0][RTW89_QATAR][1][106] = 127, + [1][1][2][0][RTW89_QATAR][0][106] = 127, + [1][1][2][0][RTW89_UK][1][106] = 127, + [1][1][2][0][RTW89_UK][0][106] = 127, + [1][1][2][0][RTW89_FCC][1][110] = 127, + [1][1][2][0][RTW89_FCC][2][110] = 127, + [1][1][2][0][RTW89_ETSI][1][110] = 127, + [1][1][2][0][RTW89_ETSI][0][110] = 127, + [1][1][2][0][RTW89_MKK][1][110] = 127, + [1][1][2][0][RTW89_MKK][0][110] = 127, + [1][1][2][0][RTW89_IC][1][110] = 127, + [1][1][2][0][RTW89_KCC][1][110] = 127, + [1][1][2][0][RTW89_KCC][0][110] = 127, + [1][1][2][0][RTW89_ACMA][1][110] = 127, + [1][1][2][0][RTW89_ACMA][0][110] = 127, + [1][1][2][0][RTW89_CHILE][1][110] = 127, + [1][1][2][0][RTW89_QATAR][1][110] = 127, + [1][1][2][0][RTW89_QATAR][0][110] = 127, + [1][1][2][0][RTW89_UK][1][110] = 127, + [1][1][2][0][RTW89_UK][0][110] = 127, + [1][1][2][0][RTW89_FCC][1][114] = 127, + [1][1][2][0][RTW89_FCC][2][114] = 127, + [1][1][2][0][RTW89_ETSI][1][114] = 127, + [1][1][2][0][RTW89_ETSI][0][114] = 127, + [1][1][2][0][RTW89_MKK][1][114] = 127, + [1][1][2][0][RTW89_MKK][0][114] = 127, + [1][1][2][0][RTW89_IC][1][114] = 127, + [1][1][2][0][RTW89_KCC][1][114] = 127, + [1][1][2][0][RTW89_KCC][0][114] = 127, + [1][1][2][0][RTW89_ACMA][1][114] = 127, + [1][1][2][0][RTW89_ACMA][0][114] = 127, + [1][1][2][0][RTW89_CHILE][1][114] = 127, + [1][1][2][0][RTW89_QATAR][1][114] = 127, + [1][1][2][0][RTW89_QATAR][0][114] = 127, + [1][1][2][0][RTW89_UK][1][114] = 127, + [1][1][2][0][RTW89_UK][0][114] = 127, + [1][1][2][0][RTW89_FCC][1][118] = 127, + [1][1][2][0][RTW89_FCC][2][118] = 127, + [1][1][2][0][RTW89_ETSI][1][118] = 127, + [1][1][2][0][RTW89_ETSI][0][118] = 127, + [1][1][2][0][RTW89_MKK][1][118] = 127, + [1][1][2][0][RTW89_MKK][0][118] = 127, + [1][1][2][0][RTW89_IC][1][118] = 127, + [1][1][2][0][RTW89_KCC][1][118] = 127, + [1][1][2][0][RTW89_KCC][0][118] = 127, + [1][1][2][0][RTW89_ACMA][1][118] = 127, + [1][1][2][0][RTW89_ACMA][0][118] = 127, + [1][1][2][0][RTW89_CHILE][1][118] = 127, + [1][1][2][0][RTW89_QATAR][1][118] = 127, + [1][1][2][0][RTW89_QATAR][0][118] = 127, + [1][1][2][0][RTW89_UK][1][118] = 127, + [1][1][2][0][RTW89_UK][0][118] = 127, + [1][1][2][1][RTW89_FCC][1][1] = 10, + [1][1][2][1][RTW89_FCC][2][1] = 58, + [1][1][2][1][RTW89_ETSI][1][1] = 42, + [1][1][2][1][RTW89_ETSI][0][1] = 6, + [1][1][2][1][RTW89_MKK][1][1] = 52, + [1][1][2][1][RTW89_MKK][0][1] = 12, + [1][1][2][1][RTW89_IC][1][1] = 10, + [1][1][2][1][RTW89_KCC][1][1] = 28, + [1][1][2][1][RTW89_KCC][0][1] = 12, + [1][1][2][1][RTW89_ACMA][1][1] = 42, + [1][1][2][1][RTW89_ACMA][0][1] = 6, + [1][1][2][1][RTW89_CHILE][1][1] = 10, + [1][1][2][1][RTW89_QATAR][1][1] = 42, + [1][1][2][1][RTW89_QATAR][0][1] = 6, + [1][1][2][1][RTW89_UK][1][1] = 42, + [1][1][2][1][RTW89_UK][0][1] = 6, + [1][1][2][1][RTW89_FCC][1][5] = 10, + [1][1][2][1][RTW89_FCC][2][5] = 58, + [1][1][2][1][RTW89_ETSI][1][5] = 42, + [1][1][2][1][RTW89_ETSI][0][5] = 6, + [1][1][2][1][RTW89_MKK][1][5] = 52, + [1][1][2][1][RTW89_MKK][0][5] = 12, + [1][1][2][1][RTW89_IC][1][5] = 10, + [1][1][2][1][RTW89_KCC][1][5] = 28, + [1][1][2][1][RTW89_KCC][0][5] = 12, + [1][1][2][1][RTW89_ACMA][1][5] = 42, + [1][1][2][1][RTW89_ACMA][0][5] = 6, + [1][1][2][1][RTW89_CHILE][1][5] = 10, + [1][1][2][1][RTW89_QATAR][1][5] = 42, + [1][1][2][1][RTW89_QATAR][0][5] = 6, + [1][1][2][1][RTW89_UK][1][5] = 42, + [1][1][2][1][RTW89_UK][0][5] = 6, + [1][1][2][1][RTW89_FCC][1][9] = 10, + [1][1][2][1][RTW89_FCC][2][9] = 58, + [1][1][2][1][RTW89_ETSI][1][9] = 42, + [1][1][2][1][RTW89_ETSI][0][9] = 6, + [1][1][2][1][RTW89_MKK][1][9] = 52, + [1][1][2][1][RTW89_MKK][0][9] = 12, + [1][1][2][1][RTW89_IC][1][9] = 10, + [1][1][2][1][RTW89_KCC][1][9] = 28, + [1][1][2][1][RTW89_KCC][0][9] = 12, + [1][1][2][1][RTW89_ACMA][1][9] = 42, + [1][1][2][1][RTW89_ACMA][0][9] = 6, + [1][1][2][1][RTW89_CHILE][1][9] = 10, + [1][1][2][1][RTW89_QATAR][1][9] = 42, + [1][1][2][1][RTW89_QATAR][0][9] = 6, + [1][1][2][1][RTW89_UK][1][9] = 42, + [1][1][2][1][RTW89_UK][0][9] = 6, + [1][1][2][1][RTW89_FCC][1][13] = 10, + [1][1][2][1][RTW89_FCC][2][13] = 58, + [1][1][2][1][RTW89_ETSI][1][13] = 42, + [1][1][2][1][RTW89_ETSI][0][13] = 6, + [1][1][2][1][RTW89_MKK][1][13] = 52, + [1][1][2][1][RTW89_MKK][0][13] = 12, + [1][1][2][1][RTW89_IC][1][13] = 10, + [1][1][2][1][RTW89_KCC][1][13] = 28, + [1][1][2][1][RTW89_KCC][0][13] = 12, + [1][1][2][1][RTW89_ACMA][1][13] = 42, + [1][1][2][1][RTW89_ACMA][0][13] = 6, + [1][1][2][1][RTW89_CHILE][1][13] = 10, + [1][1][2][1][RTW89_QATAR][1][13] = 42, + [1][1][2][1][RTW89_QATAR][0][13] = 6, + [1][1][2][1][RTW89_UK][1][13] = 42, + [1][1][2][1][RTW89_UK][0][13] = 6, + [1][1][2][1][RTW89_FCC][1][16] = 10, + [1][1][2][1][RTW89_FCC][2][16] = 58, + [1][1][2][1][RTW89_ETSI][1][16] = 42, + [1][1][2][1][RTW89_ETSI][0][16] = 6, + [1][1][2][1][RTW89_MKK][1][16] = 52, + [1][1][2][1][RTW89_MKK][0][16] = 12, + [1][1][2][1][RTW89_IC][1][16] = 10, + [1][1][2][1][RTW89_KCC][1][16] = 28, + [1][1][2][1][RTW89_KCC][0][16] = 12, + [1][1][2][1][RTW89_ACMA][1][16] = 42, + [1][1][2][1][RTW89_ACMA][0][16] = 6, + [1][1][2][1][RTW89_CHILE][1][16] = 10, + [1][1][2][1][RTW89_QATAR][1][16] = 42, + [1][1][2][1][RTW89_QATAR][0][16] = 6, + [1][1][2][1][RTW89_UK][1][16] = 42, + [1][1][2][1][RTW89_UK][0][16] = 6, + [1][1][2][1][RTW89_FCC][1][20] = 10, + [1][1][2][1][RTW89_FCC][2][20] = 58, + [1][1][2][1][RTW89_ETSI][1][20] = 42, + [1][1][2][1][RTW89_ETSI][0][20] = 6, + [1][1][2][1][RTW89_MKK][1][20] = 52, + [1][1][2][1][RTW89_MKK][0][20] = 12, + [1][1][2][1][RTW89_IC][1][20] = 10, + [1][1][2][1][RTW89_KCC][1][20] = 28, + [1][1][2][1][RTW89_KCC][0][20] = 12, + [1][1][2][1][RTW89_ACMA][1][20] = 42, + [1][1][2][1][RTW89_ACMA][0][20] = 6, + [1][1][2][1][RTW89_CHILE][1][20] = 10, + [1][1][2][1][RTW89_QATAR][1][20] = 42, + [1][1][2][1][RTW89_QATAR][0][20] = 6, + [1][1][2][1][RTW89_UK][1][20] = 42, + [1][1][2][1][RTW89_UK][0][20] = 6, + [1][1][2][1][RTW89_FCC][1][24] = 10, + [1][1][2][1][RTW89_FCC][2][24] = 70, + [1][1][2][1][RTW89_ETSI][1][24] = 42, + [1][1][2][1][RTW89_ETSI][0][24] = 6, + [1][1][2][1][RTW89_MKK][1][24] = 54, + [1][1][2][1][RTW89_MKK][0][24] = 14, + [1][1][2][1][RTW89_IC][1][24] = 10, + [1][1][2][1][RTW89_KCC][1][24] = 28, + [1][1][2][1][RTW89_KCC][0][24] = 12, + [1][1][2][1][RTW89_ACMA][1][24] = 42, + [1][1][2][1][RTW89_ACMA][0][24] = 6, + [1][1][2][1][RTW89_CHILE][1][24] = 10, + [1][1][2][1][RTW89_QATAR][1][24] = 42, + [1][1][2][1][RTW89_QATAR][0][24] = 6, + [1][1][2][1][RTW89_UK][1][24] = 42, + [1][1][2][1][RTW89_UK][0][24] = 6, + [1][1][2][1][RTW89_FCC][1][28] = 10, + [1][1][2][1][RTW89_FCC][2][28] = 70, + [1][1][2][1][RTW89_ETSI][1][28] = 42, + [1][1][2][1][RTW89_ETSI][0][28] = 6, + [1][1][2][1][RTW89_MKK][1][28] = 52, + [1][1][2][1][RTW89_MKK][0][28] = 14, + [1][1][2][1][RTW89_IC][1][28] = 10, + [1][1][2][1][RTW89_KCC][1][28] = 28, + [1][1][2][1][RTW89_KCC][0][28] = 14, + [1][1][2][1][RTW89_ACMA][1][28] = 42, + [1][1][2][1][RTW89_ACMA][0][28] = 6, + [1][1][2][1][RTW89_CHILE][1][28] = 10, + [1][1][2][1][RTW89_QATAR][1][28] = 42, + [1][1][2][1][RTW89_QATAR][0][28] = 6, + [1][1][2][1][RTW89_UK][1][28] = 42, + [1][1][2][1][RTW89_UK][0][28] = 6, + [1][1][2][1][RTW89_FCC][1][31] = 10, + [1][1][2][1][RTW89_FCC][2][31] = 70, + [1][1][2][1][RTW89_ETSI][1][31] = 42, + [1][1][2][1][RTW89_ETSI][0][31] = 6, + [1][1][2][1][RTW89_MKK][1][31] = 52, + [1][1][2][1][RTW89_MKK][0][31] = 14, + [1][1][2][1][RTW89_IC][1][31] = 10, + [1][1][2][1][RTW89_KCC][1][31] = 28, + [1][1][2][1][RTW89_KCC][0][31] = 14, + [1][1][2][1][RTW89_ACMA][1][31] = 42, + [1][1][2][1][RTW89_ACMA][0][31] = 6, + [1][1][2][1][RTW89_CHILE][1][31] = 10, + [1][1][2][1][RTW89_QATAR][1][31] = 42, + [1][1][2][1][RTW89_QATAR][0][31] = 6, + [1][1][2][1][RTW89_UK][1][31] = 42, + [1][1][2][1][RTW89_UK][0][31] = 6, + [1][1][2][1][RTW89_FCC][1][35] = 10, + [1][1][2][1][RTW89_FCC][2][35] = 70, + [1][1][2][1][RTW89_ETSI][1][35] = 42, + [1][1][2][1][RTW89_ETSI][0][35] = 6, + [1][1][2][1][RTW89_MKK][1][35] = 52, + [1][1][2][1][RTW89_MKK][0][35] = 14, + [1][1][2][1][RTW89_IC][1][35] = 10, + [1][1][2][1][RTW89_KCC][1][35] = 28, + [1][1][2][1][RTW89_KCC][0][35] = 14, + [1][1][2][1][RTW89_ACMA][1][35] = 42, + [1][1][2][1][RTW89_ACMA][0][35] = 6, + [1][1][2][1][RTW89_CHILE][1][35] = 10, + [1][1][2][1][RTW89_QATAR][1][35] = 42, + [1][1][2][1][RTW89_QATAR][0][35] = 6, + [1][1][2][1][RTW89_UK][1][35] = 42, + [1][1][2][1][RTW89_UK][0][35] = 6, + [1][1][2][1][RTW89_FCC][1][39] = 10, + [1][1][2][1][RTW89_FCC][2][39] = 70, + [1][1][2][1][RTW89_ETSI][1][39] = 42, + [1][1][2][1][RTW89_ETSI][0][39] = 6, + [1][1][2][1][RTW89_MKK][1][39] = 52, + [1][1][2][1][RTW89_MKK][0][39] = 14, + [1][1][2][1][RTW89_IC][1][39] = 10, + [1][1][2][1][RTW89_KCC][1][39] = 28, + [1][1][2][1][RTW89_KCC][0][39] = 14, + [1][1][2][1][RTW89_ACMA][1][39] = 42, + [1][1][2][1][RTW89_ACMA][0][39] = 6, + [1][1][2][1][RTW89_CHILE][1][39] = 10, + [1][1][2][1][RTW89_QATAR][1][39] = 42, + [1][1][2][1][RTW89_QATAR][0][39] = 6, + [1][1][2][1][RTW89_UK][1][39] = 42, + [1][1][2][1][RTW89_UK][0][39] = 6, + [1][1][2][1][RTW89_FCC][1][43] = 10, + [1][1][2][1][RTW89_FCC][2][43] = 70, + [1][1][2][1][RTW89_ETSI][1][43] = 42, + [1][1][2][1][RTW89_ETSI][0][43] = 6, + [1][1][2][1][RTW89_MKK][1][43] = 52, + [1][1][2][1][RTW89_MKK][0][43] = 14, + [1][1][2][1][RTW89_IC][1][43] = 10, + [1][1][2][1][RTW89_KCC][1][43] = 28, + [1][1][2][1][RTW89_KCC][0][43] = 14, + [1][1][2][1][RTW89_ACMA][1][43] = 42, + [1][1][2][1][RTW89_ACMA][0][43] = 6, + [1][1][2][1][RTW89_CHILE][1][43] = 10, + [1][1][2][1][RTW89_QATAR][1][43] = 42, + [1][1][2][1][RTW89_QATAR][0][43] = 6, + [1][1][2][1][RTW89_UK][1][43] = 42, + [1][1][2][1][RTW89_UK][0][43] = 6, + [1][1][2][1][RTW89_FCC][1][46] = 12, + [1][1][2][1][RTW89_FCC][2][46] = 127, + [1][1][2][1][RTW89_ETSI][1][46] = 127, + [1][1][2][1][RTW89_ETSI][0][46] = 127, + [1][1][2][1][RTW89_MKK][1][46] = 127, + [1][1][2][1][RTW89_MKK][0][46] = 127, + [1][1][2][1][RTW89_IC][1][46] = 12, + [1][1][2][1][RTW89_KCC][1][46] = 28, + [1][1][2][1][RTW89_KCC][0][46] = 127, + [1][1][2][1][RTW89_ACMA][1][46] = 127, + [1][1][2][1][RTW89_ACMA][0][46] = 127, + [1][1][2][1][RTW89_CHILE][1][46] = 12, + [1][1][2][1][RTW89_QATAR][1][46] = 127, + [1][1][2][1][RTW89_QATAR][0][46] = 127, + [1][1][2][1][RTW89_UK][1][46] = 127, + [1][1][2][1][RTW89_UK][0][46] = 127, + [1][1][2][1][RTW89_FCC][1][50] = 12, + [1][1][2][1][RTW89_FCC][2][50] = 127, + [1][1][2][1][RTW89_ETSI][1][50] = 127, + [1][1][2][1][RTW89_ETSI][0][50] = 127, + [1][1][2][1][RTW89_MKK][1][50] = 127, + [1][1][2][1][RTW89_MKK][0][50] = 127, + [1][1][2][1][RTW89_IC][1][50] = 12, + [1][1][2][1][RTW89_KCC][1][50] = 28, + [1][1][2][1][RTW89_KCC][0][50] = 127, + [1][1][2][1][RTW89_ACMA][1][50] = 127, + [1][1][2][1][RTW89_ACMA][0][50] = 127, + [1][1][2][1][RTW89_CHILE][1][50] = 12, + [1][1][2][1][RTW89_QATAR][1][50] = 127, + [1][1][2][1][RTW89_QATAR][0][50] = 127, + [1][1][2][1][RTW89_UK][1][50] = 127, + [1][1][2][1][RTW89_UK][0][50] = 127, + [1][1][2][1][RTW89_FCC][1][54] = 10, + [1][1][2][1][RTW89_FCC][2][54] = 127, + [1][1][2][1][RTW89_ETSI][1][54] = 127, + [1][1][2][1][RTW89_ETSI][0][54] = 127, + [1][1][2][1][RTW89_MKK][1][54] = 127, + [1][1][2][1][RTW89_MKK][0][54] = 127, + [1][1][2][1][RTW89_IC][1][54] = 10, + [1][1][2][1][RTW89_KCC][1][54] = 28, + [1][1][2][1][RTW89_KCC][0][54] = 127, + [1][1][2][1][RTW89_ACMA][1][54] = 127, + [1][1][2][1][RTW89_ACMA][0][54] = 127, + [1][1][2][1][RTW89_CHILE][1][54] = 10, + [1][1][2][1][RTW89_QATAR][1][54] = 127, + [1][1][2][1][RTW89_QATAR][0][54] = 127, + [1][1][2][1][RTW89_UK][1][54] = 127, + [1][1][2][1][RTW89_UK][0][54] = 127, + [1][1][2][1][RTW89_FCC][1][58] = 10, + [1][1][2][1][RTW89_FCC][2][58] = 66, + [1][1][2][1][RTW89_ETSI][1][58] = 127, + [1][1][2][1][RTW89_ETSI][0][58] = 127, + [1][1][2][1][RTW89_MKK][1][58] = 127, + [1][1][2][1][RTW89_MKK][0][58] = 127, + [1][1][2][1][RTW89_IC][1][58] = 10, + [1][1][2][1][RTW89_KCC][1][58] = 28, + [1][1][2][1][RTW89_KCC][0][58] = 127, + [1][1][2][1][RTW89_ACMA][1][58] = 127, + [1][1][2][1][RTW89_ACMA][0][58] = 127, + [1][1][2][1][RTW89_CHILE][1][58] = 10, + [1][1][2][1][RTW89_QATAR][1][58] = 127, + [1][1][2][1][RTW89_QATAR][0][58] = 127, + [1][1][2][1][RTW89_UK][1][58] = 127, + [1][1][2][1][RTW89_UK][0][58] = 127, + [1][1][2][1][RTW89_FCC][1][61] = 10, + [1][1][2][1][RTW89_FCC][2][61] = 66, + [1][1][2][1][RTW89_ETSI][1][61] = 127, + [1][1][2][1][RTW89_ETSI][0][61] = 127, + [1][1][2][1][RTW89_MKK][1][61] = 127, + [1][1][2][1][RTW89_MKK][0][61] = 127, + [1][1][2][1][RTW89_IC][1][61] = 10, + [1][1][2][1][RTW89_KCC][1][61] = 28, + [1][1][2][1][RTW89_KCC][0][61] = 127, + [1][1][2][1][RTW89_ACMA][1][61] = 127, + [1][1][2][1][RTW89_ACMA][0][61] = 127, + [1][1][2][1][RTW89_CHILE][1][61] = 10, + [1][1][2][1][RTW89_QATAR][1][61] = 127, + [1][1][2][1][RTW89_QATAR][0][61] = 127, + [1][1][2][1][RTW89_UK][1][61] = 127, + [1][1][2][1][RTW89_UK][0][61] = 127, + [1][1][2][1][RTW89_FCC][1][65] = 10, + [1][1][2][1][RTW89_FCC][2][65] = 66, + [1][1][2][1][RTW89_ETSI][1][65] = 127, + [1][1][2][1][RTW89_ETSI][0][65] = 127, + [1][1][2][1][RTW89_MKK][1][65] = 127, + [1][1][2][1][RTW89_MKK][0][65] = 127, + [1][1][2][1][RTW89_IC][1][65] = 10, + [1][1][2][1][RTW89_KCC][1][65] = 28, + [1][1][2][1][RTW89_KCC][0][65] = 127, + [1][1][2][1][RTW89_ACMA][1][65] = 127, + [1][1][2][1][RTW89_ACMA][0][65] = 127, + [1][1][2][1][RTW89_CHILE][1][65] = 10, + [1][1][2][1][RTW89_QATAR][1][65] = 127, + [1][1][2][1][RTW89_QATAR][0][65] = 127, + [1][1][2][1][RTW89_UK][1][65] = 127, + [1][1][2][1][RTW89_UK][0][65] = 127, + [1][1][2][1][RTW89_FCC][1][69] = 10, + [1][1][2][1][RTW89_FCC][2][69] = 66, + [1][1][2][1][RTW89_ETSI][1][69] = 127, + [1][1][2][1][RTW89_ETSI][0][69] = 127, + [1][1][2][1][RTW89_MKK][1][69] = 127, + [1][1][2][1][RTW89_MKK][0][69] = 127, + [1][1][2][1][RTW89_IC][1][69] = 10, + [1][1][2][1][RTW89_KCC][1][69] = 28, + [1][1][2][1][RTW89_KCC][0][69] = 127, + [1][1][2][1][RTW89_ACMA][1][69] = 127, + [1][1][2][1][RTW89_ACMA][0][69] = 127, + [1][1][2][1][RTW89_CHILE][1][69] = 10, + [1][1][2][1][RTW89_QATAR][1][69] = 127, + [1][1][2][1][RTW89_QATAR][0][69] = 127, + [1][1][2][1][RTW89_UK][1][69] = 127, + [1][1][2][1][RTW89_UK][0][69] = 127, + [1][1][2][1][RTW89_FCC][1][73] = 10, + [1][1][2][1][RTW89_FCC][2][73] = 66, + [1][1][2][1][RTW89_ETSI][1][73] = 127, + [1][1][2][1][RTW89_ETSI][0][73] = 127, + [1][1][2][1][RTW89_MKK][1][73] = 127, + [1][1][2][1][RTW89_MKK][0][73] = 127, + [1][1][2][1][RTW89_IC][1][73] = 10, + [1][1][2][1][RTW89_KCC][1][73] = 28, + [1][1][2][1][RTW89_KCC][0][73] = 127, + [1][1][2][1][RTW89_ACMA][1][73] = 127, + [1][1][2][1][RTW89_ACMA][0][73] = 127, + [1][1][2][1][RTW89_CHILE][1][73] = 10, + [1][1][2][1][RTW89_QATAR][1][73] = 127, + [1][1][2][1][RTW89_QATAR][0][73] = 127, + [1][1][2][1][RTW89_UK][1][73] = 127, + [1][1][2][1][RTW89_UK][0][73] = 127, + [1][1][2][1][RTW89_FCC][1][76] = 10, + [1][1][2][1][RTW89_FCC][2][76] = 66, + [1][1][2][1][RTW89_ETSI][1][76] = 127, + [1][1][2][1][RTW89_ETSI][0][76] = 127, + [1][1][2][1][RTW89_MKK][1][76] = 127, + [1][1][2][1][RTW89_MKK][0][76] = 127, + [1][1][2][1][RTW89_IC][1][76] = 10, + [1][1][2][1][RTW89_KCC][1][76] = 28, + [1][1][2][1][RTW89_KCC][0][76] = 127, + [1][1][2][1][RTW89_ACMA][1][76] = 127, + [1][1][2][1][RTW89_ACMA][0][76] = 127, + [1][1][2][1][RTW89_CHILE][1][76] = 10, + [1][1][2][1][RTW89_QATAR][1][76] = 127, + [1][1][2][1][RTW89_QATAR][0][76] = 127, + [1][1][2][1][RTW89_UK][1][76] = 127, + [1][1][2][1][RTW89_UK][0][76] = 127, + [1][1][2][1][RTW89_FCC][1][80] = 10, + [1][1][2][1][RTW89_FCC][2][80] = 66, + [1][1][2][1][RTW89_ETSI][1][80] = 127, + [1][1][2][1][RTW89_ETSI][0][80] = 127, + [1][1][2][1][RTW89_MKK][1][80] = 127, + [1][1][2][1][RTW89_MKK][0][80] = 127, + [1][1][2][1][RTW89_IC][1][80] = 10, + [1][1][2][1][RTW89_KCC][1][80] = 32, + [1][1][2][1][RTW89_KCC][0][80] = 127, + [1][1][2][1][RTW89_ACMA][1][80] = 127, + [1][1][2][1][RTW89_ACMA][0][80] = 127, + [1][1][2][1][RTW89_CHILE][1][80] = 10, + [1][1][2][1][RTW89_QATAR][1][80] = 127, + [1][1][2][1][RTW89_QATAR][0][80] = 127, + [1][1][2][1][RTW89_UK][1][80] = 127, + [1][1][2][1][RTW89_UK][0][80] = 127, + [1][1][2][1][RTW89_FCC][1][84] = 10, + [1][1][2][1][RTW89_FCC][2][84] = 66, + [1][1][2][1][RTW89_ETSI][1][84] = 127, + [1][1][2][1][RTW89_ETSI][0][84] = 127, + [1][1][2][1][RTW89_MKK][1][84] = 127, + [1][1][2][1][RTW89_MKK][0][84] = 127, + [1][1][2][1][RTW89_IC][1][84] = 10, + [1][1][2][1][RTW89_KCC][1][84] = 32, + [1][1][2][1][RTW89_KCC][0][84] = 127, + [1][1][2][1][RTW89_ACMA][1][84] = 127, + [1][1][2][1][RTW89_ACMA][0][84] = 127, + [1][1][2][1][RTW89_CHILE][1][84] = 10, + [1][1][2][1][RTW89_QATAR][1][84] = 127, + [1][1][2][1][RTW89_QATAR][0][84] = 127, + [1][1][2][1][RTW89_UK][1][84] = 127, + [1][1][2][1][RTW89_UK][0][84] = 127, + [1][1][2][1][RTW89_FCC][1][88] = 10, + [1][1][2][1][RTW89_FCC][2][88] = 127, + [1][1][2][1][RTW89_ETSI][1][88] = 127, + [1][1][2][1][RTW89_ETSI][0][88] = 127, + [1][1][2][1][RTW89_MKK][1][88] = 127, + [1][1][2][1][RTW89_MKK][0][88] = 127, + [1][1][2][1][RTW89_IC][1][88] = 10, + [1][1][2][1][RTW89_KCC][1][88] = 32, + [1][1][2][1][RTW89_KCC][0][88] = 127, + [1][1][2][1][RTW89_ACMA][1][88] = 127, + [1][1][2][1][RTW89_ACMA][0][88] = 127, + [1][1][2][1][RTW89_CHILE][1][88] = 10, + [1][1][2][1][RTW89_QATAR][1][88] = 127, + [1][1][2][1][RTW89_QATAR][0][88] = 127, + [1][1][2][1][RTW89_UK][1][88] = 127, + [1][1][2][1][RTW89_UK][0][88] = 127, + [1][1][2][1][RTW89_FCC][1][91] = 12, + [1][1][2][1][RTW89_FCC][2][91] = 127, + [1][1][2][1][RTW89_ETSI][1][91] = 127, + [1][1][2][1][RTW89_ETSI][0][91] = 127, + [1][1][2][1][RTW89_MKK][1][91] = 127, + [1][1][2][1][RTW89_MKK][0][91] = 127, + [1][1][2][1][RTW89_IC][1][91] = 12, + [1][1][2][1][RTW89_KCC][1][91] = 32, + [1][1][2][1][RTW89_KCC][0][91] = 127, + [1][1][2][1][RTW89_ACMA][1][91] = 127, + [1][1][2][1][RTW89_ACMA][0][91] = 127, + [1][1][2][1][RTW89_CHILE][1][91] = 12, + [1][1][2][1][RTW89_QATAR][1][91] = 127, + [1][1][2][1][RTW89_QATAR][0][91] = 127, + [1][1][2][1][RTW89_UK][1][91] = 127, + [1][1][2][1][RTW89_UK][0][91] = 127, + [1][1][2][1][RTW89_FCC][1][95] = 10, + [1][1][2][1][RTW89_FCC][2][95] = 127, + [1][1][2][1][RTW89_ETSI][1][95] = 127, + [1][1][2][1][RTW89_ETSI][0][95] = 127, + [1][1][2][1][RTW89_MKK][1][95] = 127, + [1][1][2][1][RTW89_MKK][0][95] = 127, + [1][1][2][1][RTW89_IC][1][95] = 10, + [1][1][2][1][RTW89_KCC][1][95] = 32, + [1][1][2][1][RTW89_KCC][0][95] = 127, + [1][1][2][1][RTW89_ACMA][1][95] = 127, + [1][1][2][1][RTW89_ACMA][0][95] = 127, + [1][1][2][1][RTW89_CHILE][1][95] = 10, + [1][1][2][1][RTW89_QATAR][1][95] = 127, + [1][1][2][1][RTW89_QATAR][0][95] = 127, + [1][1][2][1][RTW89_UK][1][95] = 127, + [1][1][2][1][RTW89_UK][0][95] = 127, + [1][1][2][1][RTW89_FCC][1][99] = 10, + [1][1][2][1][RTW89_FCC][2][99] = 127, + [1][1][2][1][RTW89_ETSI][1][99] = 127, + [1][1][2][1][RTW89_ETSI][0][99] = 127, + [1][1][2][1][RTW89_MKK][1][99] = 127, + [1][1][2][1][RTW89_MKK][0][99] = 127, + [1][1][2][1][RTW89_IC][1][99] = 10, + [1][1][2][1][RTW89_KCC][1][99] = 32, + [1][1][2][1][RTW89_KCC][0][99] = 127, + [1][1][2][1][RTW89_ACMA][1][99] = 127, + [1][1][2][1][RTW89_ACMA][0][99] = 127, + [1][1][2][1][RTW89_CHILE][1][99] = 10, + [1][1][2][1][RTW89_QATAR][1][99] = 127, + [1][1][2][1][RTW89_QATAR][0][99] = 127, + [1][1][2][1][RTW89_UK][1][99] = 127, + [1][1][2][1][RTW89_UK][0][99] = 127, + [1][1][2][1][RTW89_FCC][1][103] = 10, + [1][1][2][1][RTW89_FCC][2][103] = 127, + [1][1][2][1][RTW89_ETSI][1][103] = 127, + [1][1][2][1][RTW89_ETSI][0][103] = 127, + [1][1][2][1][RTW89_MKK][1][103] = 127, + [1][1][2][1][RTW89_MKK][0][103] = 127, + [1][1][2][1][RTW89_IC][1][103] = 10, + [1][1][2][1][RTW89_KCC][1][103] = 32, + [1][1][2][1][RTW89_KCC][0][103] = 127, + [1][1][2][1][RTW89_ACMA][1][103] = 127, + [1][1][2][1][RTW89_ACMA][0][103] = 127, + [1][1][2][1][RTW89_CHILE][1][103] = 10, + [1][1][2][1][RTW89_QATAR][1][103] = 127, + [1][1][2][1][RTW89_QATAR][0][103] = 127, + [1][1][2][1][RTW89_UK][1][103] = 127, + [1][1][2][1][RTW89_UK][0][103] = 127, + [1][1][2][1][RTW89_FCC][1][106] = 12, + [1][1][2][1][RTW89_FCC][2][106] = 127, + [1][1][2][1][RTW89_ETSI][1][106] = 127, + [1][1][2][1][RTW89_ETSI][0][106] = 127, + [1][1][2][1][RTW89_MKK][1][106] = 127, + [1][1][2][1][RTW89_MKK][0][106] = 127, + [1][1][2][1][RTW89_IC][1][106] = 12, + [1][1][2][1][RTW89_KCC][1][106] = 32, + [1][1][2][1][RTW89_KCC][0][106] = 127, + [1][1][2][1][RTW89_ACMA][1][106] = 127, + [1][1][2][1][RTW89_ACMA][0][106] = 127, + [1][1][2][1][RTW89_CHILE][1][106] = 12, + [1][1][2][1][RTW89_QATAR][1][106] = 127, + [1][1][2][1][RTW89_QATAR][0][106] = 127, + [1][1][2][1][RTW89_UK][1][106] = 127, + [1][1][2][1][RTW89_UK][0][106] = 127, + [1][1][2][1][RTW89_FCC][1][110] = 127, + [1][1][2][1][RTW89_FCC][2][110] = 127, + [1][1][2][1][RTW89_ETSI][1][110] = 127, + [1][1][2][1][RTW89_ETSI][0][110] = 127, + [1][1][2][1][RTW89_MKK][1][110] = 127, + [1][1][2][1][RTW89_MKK][0][110] = 127, + [1][1][2][1][RTW89_IC][1][110] = 127, + [1][1][2][1][RTW89_KCC][1][110] = 127, + [1][1][2][1][RTW89_KCC][0][110] = 127, + [1][1][2][1][RTW89_ACMA][1][110] = 127, + [1][1][2][1][RTW89_ACMA][0][110] = 127, + [1][1][2][1][RTW89_CHILE][1][110] = 127, + [1][1][2][1][RTW89_QATAR][1][110] = 127, + [1][1][2][1][RTW89_QATAR][0][110] = 127, + [1][1][2][1][RTW89_UK][1][110] = 127, + [1][1][2][1][RTW89_UK][0][110] = 127, + [1][1][2][1][RTW89_FCC][1][114] = 127, + [1][1][2][1][RTW89_FCC][2][114] = 127, + [1][1][2][1][RTW89_ETSI][1][114] = 127, + [1][1][2][1][RTW89_ETSI][0][114] = 127, + [1][1][2][1][RTW89_MKK][1][114] = 127, + [1][1][2][1][RTW89_MKK][0][114] = 127, + [1][1][2][1][RTW89_IC][1][114] = 127, + [1][1][2][1][RTW89_KCC][1][114] = 127, + [1][1][2][1][RTW89_KCC][0][114] = 127, + [1][1][2][1][RTW89_ACMA][1][114] = 127, + [1][1][2][1][RTW89_ACMA][0][114] = 127, + [1][1][2][1][RTW89_CHILE][1][114] = 127, + [1][1][2][1][RTW89_QATAR][1][114] = 127, + [1][1][2][1][RTW89_QATAR][0][114] = 127, + [1][1][2][1][RTW89_UK][1][114] = 127, + [1][1][2][1][RTW89_UK][0][114] = 127, + [1][1][2][1][RTW89_FCC][1][118] = 127, + [1][1][2][1][RTW89_FCC][2][118] = 127, + [1][1][2][1][RTW89_ETSI][1][118] = 127, + [1][1][2][1][RTW89_ETSI][0][118] = 127, + [1][1][2][1][RTW89_MKK][1][118] = 127, + [1][1][2][1][RTW89_MKK][0][118] = 127, + [1][1][2][1][RTW89_IC][1][118] = 127, + [1][1][2][1][RTW89_KCC][1][118] = 127, + [1][1][2][1][RTW89_KCC][0][118] = 127, + [1][1][2][1][RTW89_ACMA][1][118] = 127, + [1][1][2][1][RTW89_ACMA][0][118] = 127, + [1][1][2][1][RTW89_CHILE][1][118] = 127, + [1][1][2][1][RTW89_QATAR][1][118] = 127, + [1][1][2][1][RTW89_QATAR][0][118] = 127, + [1][1][2][1][RTW89_UK][1][118] = 127, + [1][1][2][1][RTW89_UK][0][118] = 127, + [2][0][2][0][RTW89_FCC][1][3] = 46, + [2][0][2][0][RTW89_FCC][2][3] = 60, + [2][0][2][0][RTW89_ETSI][1][3] = 58, + [2][0][2][0][RTW89_ETSI][0][3] = 30, + [2][0][2][0][RTW89_MKK][1][3] = 58, + [2][0][2][0][RTW89_MKK][0][3] = 26, + [2][0][2][0][RTW89_IC][1][3] = 46, + [2][0][2][0][RTW89_KCC][1][3] = 50, + [2][0][2][0][RTW89_KCC][0][3] = 24, + [2][0][2][0][RTW89_ACMA][1][3] = 58, + [2][0][2][0][RTW89_ACMA][0][3] = 30, + [2][0][2][0][RTW89_CHILE][1][3] = 46, + [2][0][2][0][RTW89_QATAR][1][3] = 58, + [2][0][2][0][RTW89_QATAR][0][3] = 30, + [2][0][2][0][RTW89_UK][1][3] = 58, + [2][0][2][0][RTW89_UK][0][3] = 30, + [2][0][2][0][RTW89_FCC][1][11] = 46, + [2][0][2][0][RTW89_FCC][2][11] = 60, + [2][0][2][0][RTW89_ETSI][1][11] = 58, + [2][0][2][0][RTW89_ETSI][0][11] = 30, + [2][0][2][0][RTW89_MKK][1][11] = 58, + [2][0][2][0][RTW89_MKK][0][11] = 24, + [2][0][2][0][RTW89_IC][1][11] = 46, + [2][0][2][0][RTW89_KCC][1][11] = 50, + [2][0][2][0][RTW89_KCC][0][11] = 24, + [2][0][2][0][RTW89_ACMA][1][11] = 58, + [2][0][2][0][RTW89_ACMA][0][11] = 30, + [2][0][2][0][RTW89_CHILE][1][11] = 46, + [2][0][2][0][RTW89_QATAR][1][11] = 58, + [2][0][2][0][RTW89_QATAR][0][11] = 30, + [2][0][2][0][RTW89_UK][1][11] = 58, + [2][0][2][0][RTW89_UK][0][11] = 30, + [2][0][2][0][RTW89_FCC][1][18] = 46, + [2][0][2][0][RTW89_FCC][2][18] = 60, + [2][0][2][0][RTW89_ETSI][1][18] = 58, + [2][0][2][0][RTW89_ETSI][0][18] = 30, + [2][0][2][0][RTW89_MKK][1][18] = 58, + [2][0][2][0][RTW89_MKK][0][18] = 24, + [2][0][2][0][RTW89_IC][1][18] = 46, + [2][0][2][0][RTW89_KCC][1][18] = 50, + [2][0][2][0][RTW89_KCC][0][18] = 24, + [2][0][2][0][RTW89_ACMA][1][18] = 58, + [2][0][2][0][RTW89_ACMA][0][18] = 30, + [2][0][2][0][RTW89_CHILE][1][18] = 46, + [2][0][2][0][RTW89_QATAR][1][18] = 58, + [2][0][2][0][RTW89_QATAR][0][18] = 30, + [2][0][2][0][RTW89_UK][1][18] = 58, + [2][0][2][0][RTW89_UK][0][18] = 30, + [2][0][2][0][RTW89_FCC][1][26] = 46, + [2][0][2][0][RTW89_FCC][2][26] = 60, + [2][0][2][0][RTW89_ETSI][1][26] = 58, + [2][0][2][0][RTW89_ETSI][0][26] = 30, + [2][0][2][0][RTW89_MKK][1][26] = 58, + [2][0][2][0][RTW89_MKK][0][26] = 24, + [2][0][2][0][RTW89_IC][1][26] = 46, + [2][0][2][0][RTW89_KCC][1][26] = 50, + [2][0][2][0][RTW89_KCC][0][26] = 26, + [2][0][2][0][RTW89_ACMA][1][26] = 58, + [2][0][2][0][RTW89_ACMA][0][26] = 30, + [2][0][2][0][RTW89_CHILE][1][26] = 46, + [2][0][2][0][RTW89_QATAR][1][26] = 58, + [2][0][2][0][RTW89_QATAR][0][26] = 30, + [2][0][2][0][RTW89_UK][1][26] = 58, + [2][0][2][0][RTW89_UK][0][26] = 30, + [2][0][2][0][RTW89_FCC][1][33] = 46, + [2][0][2][0][RTW89_FCC][2][33] = 60, + [2][0][2][0][RTW89_ETSI][1][33] = 58, + [2][0][2][0][RTW89_ETSI][0][33] = 30, + [2][0][2][0][RTW89_MKK][1][33] = 58, + [2][0][2][0][RTW89_MKK][0][33] = 24, + [2][0][2][0][RTW89_IC][1][33] = 46, + [2][0][2][0][RTW89_KCC][1][33] = 50, + [2][0][2][0][RTW89_KCC][0][33] = 24, + [2][0][2][0][RTW89_ACMA][1][33] = 58, + [2][0][2][0][RTW89_ACMA][0][33] = 30, + [2][0][2][0][RTW89_CHILE][1][33] = 46, + [2][0][2][0][RTW89_QATAR][1][33] = 58, + [2][0][2][0][RTW89_QATAR][0][33] = 30, + [2][0][2][0][RTW89_UK][1][33] = 58, + [2][0][2][0][RTW89_UK][0][33] = 30, + [2][0][2][0][RTW89_FCC][1][41] = 46, + [2][0][2][0][RTW89_FCC][2][41] = 60, + [2][0][2][0][RTW89_ETSI][1][41] = 58, + [2][0][2][0][RTW89_ETSI][0][41] = 30, + [2][0][2][0][RTW89_MKK][1][41] = 58, + [2][0][2][0][RTW89_MKK][0][41] = 24, + [2][0][2][0][RTW89_IC][1][41] = 46, + [2][0][2][0][RTW89_KCC][1][41] = 50, + [2][0][2][0][RTW89_KCC][0][41] = 24, + [2][0][2][0][RTW89_ACMA][1][41] = 58, + [2][0][2][0][RTW89_ACMA][0][41] = 30, + [2][0][2][0][RTW89_CHILE][1][41] = 46, + [2][0][2][0][RTW89_QATAR][1][41] = 58, + [2][0][2][0][RTW89_QATAR][0][41] = 30, + [2][0][2][0][RTW89_UK][1][41] = 58, + [2][0][2][0][RTW89_UK][0][41] = 30, + [2][0][2][0][RTW89_FCC][1][48] = 46, + [2][0][2][0][RTW89_FCC][2][48] = 127, + [2][0][2][0][RTW89_ETSI][1][48] = 127, + [2][0][2][0][RTW89_ETSI][0][48] = 127, + [2][0][2][0][RTW89_MKK][1][48] = 127, + [2][0][2][0][RTW89_MKK][0][48] = 127, + [2][0][2][0][RTW89_IC][1][48] = 46, + [2][0][2][0][RTW89_KCC][1][48] = 48, + [2][0][2][0][RTW89_KCC][0][48] = 127, + [2][0][2][0][RTW89_ACMA][1][48] = 127, + [2][0][2][0][RTW89_ACMA][0][48] = 127, + [2][0][2][0][RTW89_CHILE][1][48] = 46, + [2][0][2][0][RTW89_QATAR][1][48] = 127, + [2][0][2][0][RTW89_QATAR][0][48] = 127, + [2][0][2][0][RTW89_UK][1][48] = 127, + [2][0][2][0][RTW89_UK][0][48] = 127, + [2][0][2][0][RTW89_FCC][1][56] = 46, + [2][0][2][0][RTW89_FCC][2][56] = 127, + [2][0][2][0][RTW89_ETSI][1][56] = 127, + [2][0][2][0][RTW89_ETSI][0][56] = 127, + [2][0][2][0][RTW89_MKK][1][56] = 127, + [2][0][2][0][RTW89_MKK][0][56] = 127, + [2][0][2][0][RTW89_IC][1][56] = 46, + [2][0][2][0][RTW89_KCC][1][56] = 48, + [2][0][2][0][RTW89_KCC][0][56] = 127, + [2][0][2][0][RTW89_ACMA][1][56] = 127, + [2][0][2][0][RTW89_ACMA][0][56] = 127, + [2][0][2][0][RTW89_CHILE][1][56] = 46, + [2][0][2][0][RTW89_QATAR][1][56] = 127, + [2][0][2][0][RTW89_QATAR][0][56] = 127, + [2][0][2][0][RTW89_UK][1][56] = 127, + [2][0][2][0][RTW89_UK][0][56] = 127, + [2][0][2][0][RTW89_FCC][1][63] = 46, + [2][0][2][0][RTW89_FCC][2][63] = 58, + [2][0][2][0][RTW89_ETSI][1][63] = 127, + [2][0][2][0][RTW89_ETSI][0][63] = 127, + [2][0][2][0][RTW89_MKK][1][63] = 127, + [2][0][2][0][RTW89_MKK][0][63] = 127, + [2][0][2][0][RTW89_IC][1][63] = 46, + [2][0][2][0][RTW89_KCC][1][63] = 48, + [2][0][2][0][RTW89_KCC][0][63] = 127, + [2][0][2][0][RTW89_ACMA][1][63] = 127, + [2][0][2][0][RTW89_ACMA][0][63] = 127, + [2][0][2][0][RTW89_CHILE][1][63] = 46, + [2][0][2][0][RTW89_QATAR][1][63] = 127, + [2][0][2][0][RTW89_QATAR][0][63] = 127, + [2][0][2][0][RTW89_UK][1][63] = 127, + [2][0][2][0][RTW89_UK][0][63] = 127, + [2][0][2][0][RTW89_FCC][1][71] = 46, + [2][0][2][0][RTW89_FCC][2][71] = 58, + [2][0][2][0][RTW89_ETSI][1][71] = 127, + [2][0][2][0][RTW89_ETSI][0][71] = 127, + [2][0][2][0][RTW89_MKK][1][71] = 127, + [2][0][2][0][RTW89_MKK][0][71] = 127, + [2][0][2][0][RTW89_IC][1][71] = 46, + [2][0][2][0][RTW89_KCC][1][71] = 48, + [2][0][2][0][RTW89_KCC][0][71] = 127, + [2][0][2][0][RTW89_ACMA][1][71] = 127, + [2][0][2][0][RTW89_ACMA][0][71] = 127, + [2][0][2][0][RTW89_CHILE][1][71] = 46, + [2][0][2][0][RTW89_QATAR][1][71] = 127, + [2][0][2][0][RTW89_QATAR][0][71] = 127, + [2][0][2][0][RTW89_UK][1][71] = 127, + [2][0][2][0][RTW89_UK][0][71] = 127, + [2][0][2][0][RTW89_FCC][1][78] = 46, + [2][0][2][0][RTW89_FCC][2][78] = 58, + [2][0][2][0][RTW89_ETSI][1][78] = 127, + [2][0][2][0][RTW89_ETSI][0][78] = 127, + [2][0][2][0][RTW89_MKK][1][78] = 127, + [2][0][2][0][RTW89_MKK][0][78] = 127, + [2][0][2][0][RTW89_IC][1][78] = 46, + [2][0][2][0][RTW89_KCC][1][78] = 52, + [2][0][2][0][RTW89_KCC][0][78] = 127, + [2][0][2][0][RTW89_ACMA][1][78] = 127, + [2][0][2][0][RTW89_ACMA][0][78] = 127, + [2][0][2][0][RTW89_CHILE][1][78] = 46, + [2][0][2][0][RTW89_QATAR][1][78] = 127, + [2][0][2][0][RTW89_QATAR][0][78] = 127, + [2][0][2][0][RTW89_UK][1][78] = 127, + [2][0][2][0][RTW89_UK][0][78] = 127, + [2][0][2][0][RTW89_FCC][1][86] = 46, + [2][0][2][0][RTW89_FCC][2][86] = 127, + [2][0][2][0][RTW89_ETSI][1][86] = 127, + [2][0][2][0][RTW89_ETSI][0][86] = 127, + [2][0][2][0][RTW89_MKK][1][86] = 127, + [2][0][2][0][RTW89_MKK][0][86] = 127, + [2][0][2][0][RTW89_IC][1][86] = 46, + [2][0][2][0][RTW89_KCC][1][86] = 52, + [2][0][2][0][RTW89_KCC][0][86] = 127, + [2][0][2][0][RTW89_ACMA][1][86] = 127, + [2][0][2][0][RTW89_ACMA][0][86] = 127, + [2][0][2][0][RTW89_CHILE][1][86] = 46, + [2][0][2][0][RTW89_QATAR][1][86] = 127, + [2][0][2][0][RTW89_QATAR][0][86] = 127, + [2][0][2][0][RTW89_UK][1][86] = 127, + [2][0][2][0][RTW89_UK][0][86] = 127, + [2][0][2][0][RTW89_FCC][1][93] = 46, + [2][0][2][0][RTW89_FCC][2][93] = 127, + [2][0][2][0][RTW89_ETSI][1][93] = 127, + [2][0][2][0][RTW89_ETSI][0][93] = 127, + [2][0][2][0][RTW89_MKK][1][93] = 127, + [2][0][2][0][RTW89_MKK][0][93] = 127, + [2][0][2][0][RTW89_IC][1][93] = 46, + [2][0][2][0][RTW89_KCC][1][93] = 50, + [2][0][2][0][RTW89_KCC][0][93] = 127, + [2][0][2][0][RTW89_ACMA][1][93] = 127, + [2][0][2][0][RTW89_ACMA][0][93] = 127, + [2][0][2][0][RTW89_CHILE][1][93] = 46, + [2][0][2][0][RTW89_QATAR][1][93] = 127, + [2][0][2][0][RTW89_QATAR][0][93] = 127, + [2][0][2][0][RTW89_UK][1][93] = 127, + [2][0][2][0][RTW89_UK][0][93] = 127, + [2][0][2][0][RTW89_FCC][1][101] = 44, + [2][0][2][0][RTW89_FCC][2][101] = 127, + [2][0][2][0][RTW89_ETSI][1][101] = 127, + [2][0][2][0][RTW89_ETSI][0][101] = 127, + [2][0][2][0][RTW89_MKK][1][101] = 127, + [2][0][2][0][RTW89_MKK][0][101] = 127, + [2][0][2][0][RTW89_IC][1][101] = 44, + [2][0][2][0][RTW89_KCC][1][101] = 50, + [2][0][2][0][RTW89_KCC][0][101] = 127, + [2][0][2][0][RTW89_ACMA][1][101] = 127, + [2][0][2][0][RTW89_ACMA][0][101] = 127, + [2][0][2][0][RTW89_CHILE][1][101] = 44, + [2][0][2][0][RTW89_QATAR][1][101] = 127, + [2][0][2][0][RTW89_QATAR][0][101] = 127, + [2][0][2][0][RTW89_UK][1][101] = 127, + [2][0][2][0][RTW89_UK][0][101] = 127, + [2][0][2][0][RTW89_FCC][1][108] = 127, + [2][0][2][0][RTW89_FCC][2][108] = 127, + [2][0][2][0][RTW89_ETSI][1][108] = 127, + [2][0][2][0][RTW89_ETSI][0][108] = 127, + [2][0][2][0][RTW89_MKK][1][108] = 127, + [2][0][2][0][RTW89_MKK][0][108] = 127, + [2][0][2][0][RTW89_IC][1][108] = 127, + [2][0][2][0][RTW89_KCC][1][108] = 127, + [2][0][2][0][RTW89_KCC][0][108] = 127, + [2][0][2][0][RTW89_ACMA][1][108] = 127, + [2][0][2][0][RTW89_ACMA][0][108] = 127, + [2][0][2][0][RTW89_CHILE][1][108] = 127, + [2][0][2][0][RTW89_QATAR][1][108] = 127, + [2][0][2][0][RTW89_QATAR][0][108] = 127, + [2][0][2][0][RTW89_UK][1][108] = 127, + [2][0][2][0][RTW89_UK][0][108] = 127, + [2][0][2][0][RTW89_FCC][1][116] = 127, + [2][0][2][0][RTW89_FCC][2][116] = 127, + [2][0][2][0][RTW89_ETSI][1][116] = 127, + [2][0][2][0][RTW89_ETSI][0][116] = 127, + [2][0][2][0][RTW89_MKK][1][116] = 127, + [2][0][2][0][RTW89_MKK][0][116] = 127, + [2][0][2][0][RTW89_IC][1][116] = 127, + [2][0][2][0][RTW89_KCC][1][116] = 127, + [2][0][2][0][RTW89_KCC][0][116] = 127, + [2][0][2][0][RTW89_ACMA][1][116] = 127, + [2][0][2][0][RTW89_ACMA][0][116] = 127, + [2][0][2][0][RTW89_CHILE][1][116] = 127, + [2][0][2][0][RTW89_QATAR][1][116] = 127, + [2][0][2][0][RTW89_QATAR][0][116] = 127, + [2][0][2][0][RTW89_UK][1][116] = 127, + [2][0][2][0][RTW89_UK][0][116] = 127, + [2][1][2][0][RTW89_FCC][1][3] = 22, + [2][1][2][0][RTW89_FCC][2][3] = 50, + [2][1][2][0][RTW89_ETSI][1][3] = 54, + [2][1][2][0][RTW89_ETSI][0][3] = 16, + [2][1][2][0][RTW89_MKK][1][3] = 52, + [2][1][2][0][RTW89_MKK][0][3] = 14, + [2][1][2][0][RTW89_IC][1][3] = 22, + [2][1][2][0][RTW89_KCC][1][3] = 38, + [2][1][2][0][RTW89_KCC][0][3] = 12, + [2][1][2][0][RTW89_ACMA][1][3] = 54, + [2][1][2][0][RTW89_ACMA][0][3] = 16, + [2][1][2][0][RTW89_CHILE][1][3] = 22, + [2][1][2][0][RTW89_QATAR][1][3] = 54, + [2][1][2][0][RTW89_QATAR][0][3] = 16, + [2][1][2][0][RTW89_UK][1][3] = 54, + [2][1][2][0][RTW89_UK][0][3] = 16, + [2][1][2][0][RTW89_FCC][1][11] = 20, + [2][1][2][0][RTW89_FCC][2][11] = 50, + [2][1][2][0][RTW89_ETSI][1][11] = 54, + [2][1][2][0][RTW89_ETSI][0][11] = 16, + [2][1][2][0][RTW89_MKK][1][11] = 52, + [2][1][2][0][RTW89_MKK][0][11] = 12, + [2][1][2][0][RTW89_IC][1][11] = 20, + [2][1][2][0][RTW89_KCC][1][11] = 38, + [2][1][2][0][RTW89_KCC][0][11] = 12, + [2][1][2][0][RTW89_ACMA][1][11] = 54, + [2][1][2][0][RTW89_ACMA][0][11] = 16, + [2][1][2][0][RTW89_CHILE][1][11] = 20, + [2][1][2][0][RTW89_QATAR][1][11] = 54, + [2][1][2][0][RTW89_QATAR][0][11] = 16, + [2][1][2][0][RTW89_UK][1][11] = 54, + [2][1][2][0][RTW89_UK][0][11] = 16, + [2][1][2][0][RTW89_FCC][1][18] = 20, + [2][1][2][0][RTW89_FCC][2][18] = 50, + [2][1][2][0][RTW89_ETSI][1][18] = 54, + [2][1][2][0][RTW89_ETSI][0][18] = 16, + [2][1][2][0][RTW89_MKK][1][18] = 52, + [2][1][2][0][RTW89_MKK][0][18] = 12, + [2][1][2][0][RTW89_IC][1][18] = 20, + [2][1][2][0][RTW89_KCC][1][18] = 38, + [2][1][2][0][RTW89_KCC][0][18] = 12, + [2][1][2][0][RTW89_ACMA][1][18] = 54, + [2][1][2][0][RTW89_ACMA][0][18] = 16, + [2][1][2][0][RTW89_CHILE][1][18] = 20, + [2][1][2][0][RTW89_QATAR][1][18] = 54, + [2][1][2][0][RTW89_QATAR][0][18] = 16, + [2][1][2][0][RTW89_UK][1][18] = 54, + [2][1][2][0][RTW89_UK][0][18] = 16, + [2][1][2][0][RTW89_FCC][1][26] = 20, + [2][1][2][0][RTW89_FCC][2][26] = 60, + [2][1][2][0][RTW89_ETSI][1][26] = 54, + [2][1][2][0][RTW89_ETSI][0][26] = 16, + [2][1][2][0][RTW89_MKK][1][26] = 52, + [2][1][2][0][RTW89_MKK][0][26] = 12, + [2][1][2][0][RTW89_IC][1][26] = 20, + [2][1][2][0][RTW89_KCC][1][26] = 38, + [2][1][2][0][RTW89_KCC][0][26] = 12, + [2][1][2][0][RTW89_ACMA][1][26] = 54, + [2][1][2][0][RTW89_ACMA][0][26] = 16, + [2][1][2][0][RTW89_CHILE][1][26] = 20, + [2][1][2][0][RTW89_QATAR][1][26] = 54, + [2][1][2][0][RTW89_QATAR][0][26] = 16, + [2][1][2][0][RTW89_UK][1][26] = 54, + [2][1][2][0][RTW89_UK][0][26] = 16, + [2][1][2][0][RTW89_FCC][1][33] = 20, + [2][1][2][0][RTW89_FCC][2][33] = 60, + [2][1][2][0][RTW89_ETSI][1][33] = 54, + [2][1][2][0][RTW89_ETSI][0][33] = 16, + [2][1][2][0][RTW89_MKK][1][33] = 48, + [2][1][2][0][RTW89_MKK][0][33] = 12, + [2][1][2][0][RTW89_IC][1][33] = 20, + [2][1][2][0][RTW89_KCC][1][33] = 38, + [2][1][2][0][RTW89_KCC][0][33] = 12, + [2][1][2][0][RTW89_ACMA][1][33] = 54, + [2][1][2][0][RTW89_ACMA][0][33] = 16, + [2][1][2][0][RTW89_CHILE][1][33] = 20, + [2][1][2][0][RTW89_QATAR][1][33] = 54, + [2][1][2][0][RTW89_QATAR][0][33] = 16, + [2][1][2][0][RTW89_UK][1][33] = 54, + [2][1][2][0][RTW89_UK][0][33] = 16, + [2][1][2][0][RTW89_FCC][1][41] = 22, + [2][1][2][0][RTW89_FCC][2][41] = 60, + [2][1][2][0][RTW89_ETSI][1][41] = 54, + [2][1][2][0][RTW89_ETSI][0][41] = 18, + [2][1][2][0][RTW89_MKK][1][41] = 48, + [2][1][2][0][RTW89_MKK][0][41] = 12, + [2][1][2][0][RTW89_IC][1][41] = 22, + [2][1][2][0][RTW89_KCC][1][41] = 38, + [2][1][2][0][RTW89_KCC][0][41] = 12, + [2][1][2][0][RTW89_ACMA][1][41] = 54, + [2][1][2][0][RTW89_ACMA][0][41] = 18, + [2][1][2][0][RTW89_CHILE][1][41] = 22, + [2][1][2][0][RTW89_QATAR][1][41] = 54, + [2][1][2][0][RTW89_QATAR][0][41] = 18, + [2][1][2][0][RTW89_UK][1][41] = 54, + [2][1][2][0][RTW89_UK][0][41] = 18, + [2][1][2][0][RTW89_FCC][1][48] = 22, + [2][1][2][0][RTW89_FCC][2][48] = 127, + [2][1][2][0][RTW89_ETSI][1][48] = 127, + [2][1][2][0][RTW89_ETSI][0][48] = 127, + [2][1][2][0][RTW89_MKK][1][48] = 127, + [2][1][2][0][RTW89_MKK][0][48] = 127, + [2][1][2][0][RTW89_IC][1][48] = 22, + [2][1][2][0][RTW89_KCC][1][48] = 38, + [2][1][2][0][RTW89_KCC][0][48] = 127, + [2][1][2][0][RTW89_ACMA][1][48] = 127, + [2][1][2][0][RTW89_ACMA][0][48] = 127, + [2][1][2][0][RTW89_CHILE][1][48] = 22, + [2][1][2][0][RTW89_QATAR][1][48] = 127, + [2][1][2][0][RTW89_QATAR][0][48] = 127, + [2][1][2][0][RTW89_UK][1][48] = 127, + [2][1][2][0][RTW89_UK][0][48] = 127, + [2][1][2][0][RTW89_FCC][1][56] = 20, + [2][1][2][0][RTW89_FCC][2][56] = 127, + [2][1][2][0][RTW89_ETSI][1][56] = 127, + [2][1][2][0][RTW89_ETSI][0][56] = 127, + [2][1][2][0][RTW89_MKK][1][56] = 127, + [2][1][2][0][RTW89_MKK][0][56] = 127, + [2][1][2][0][RTW89_IC][1][56] = 20, + [2][1][2][0][RTW89_KCC][1][56] = 38, + [2][1][2][0][RTW89_KCC][0][56] = 127, + [2][1][2][0][RTW89_ACMA][1][56] = 127, + [2][1][2][0][RTW89_ACMA][0][56] = 127, + [2][1][2][0][RTW89_CHILE][1][56] = 20, + [2][1][2][0][RTW89_QATAR][1][56] = 127, + [2][1][2][0][RTW89_QATAR][0][56] = 127, + [2][1][2][0][RTW89_UK][1][56] = 127, + [2][1][2][0][RTW89_UK][0][56] = 127, + [2][1][2][0][RTW89_FCC][1][63] = 22, + [2][1][2][0][RTW89_FCC][2][63] = 58, + [2][1][2][0][RTW89_ETSI][1][63] = 127, + [2][1][2][0][RTW89_ETSI][0][63] = 127, + [2][1][2][0][RTW89_MKK][1][63] = 127, + [2][1][2][0][RTW89_MKK][0][63] = 127, + [2][1][2][0][RTW89_IC][1][63] = 22, + [2][1][2][0][RTW89_KCC][1][63] = 38, + [2][1][2][0][RTW89_KCC][0][63] = 127, + [2][1][2][0][RTW89_ACMA][1][63] = 127, + [2][1][2][0][RTW89_ACMA][0][63] = 127, + [2][1][2][0][RTW89_CHILE][1][63] = 22, + [2][1][2][0][RTW89_QATAR][1][63] = 127, + [2][1][2][0][RTW89_QATAR][0][63] = 127, + [2][1][2][0][RTW89_UK][1][63] = 127, + [2][1][2][0][RTW89_UK][0][63] = 127, + [2][1][2][0][RTW89_FCC][1][71] = 20, + [2][1][2][0][RTW89_FCC][2][71] = 58, + [2][1][2][0][RTW89_ETSI][1][71] = 127, + [2][1][2][0][RTW89_ETSI][0][71] = 127, + [2][1][2][0][RTW89_MKK][1][71] = 127, + [2][1][2][0][RTW89_MKK][0][71] = 127, + [2][1][2][0][RTW89_IC][1][71] = 20, + [2][1][2][0][RTW89_KCC][1][71] = 38, + [2][1][2][0][RTW89_KCC][0][71] = 127, + [2][1][2][0][RTW89_ACMA][1][71] = 127, + [2][1][2][0][RTW89_ACMA][0][71] = 127, + [2][1][2][0][RTW89_CHILE][1][71] = 20, + [2][1][2][0][RTW89_QATAR][1][71] = 127, + [2][1][2][0][RTW89_QATAR][0][71] = 127, + [2][1][2][0][RTW89_UK][1][71] = 127, + [2][1][2][0][RTW89_UK][0][71] = 127, + [2][1][2][0][RTW89_FCC][1][78] = 20, + [2][1][2][0][RTW89_FCC][2][78] = 58, + [2][1][2][0][RTW89_ETSI][1][78] = 127, + [2][1][2][0][RTW89_ETSI][0][78] = 127, + [2][1][2][0][RTW89_MKK][1][78] = 127, + [2][1][2][0][RTW89_MKK][0][78] = 127, + [2][1][2][0][RTW89_IC][1][78] = 20, + [2][1][2][0][RTW89_KCC][1][78] = 38, + [2][1][2][0][RTW89_KCC][0][78] = 127, + [2][1][2][0][RTW89_ACMA][1][78] = 127, + [2][1][2][0][RTW89_ACMA][0][78] = 127, + [2][1][2][0][RTW89_CHILE][1][78] = 20, + [2][1][2][0][RTW89_QATAR][1][78] = 127, + [2][1][2][0][RTW89_QATAR][0][78] = 127, + [2][1][2][0][RTW89_UK][1][78] = 127, + [2][1][2][0][RTW89_UK][0][78] = 127, + [2][1][2][0][RTW89_FCC][1][86] = 20, + [2][1][2][0][RTW89_FCC][2][86] = 127, + [2][1][2][0][RTW89_ETSI][1][86] = 127, + [2][1][2][0][RTW89_ETSI][0][86] = 127, + [2][1][2][0][RTW89_MKK][1][86] = 127, + [2][1][2][0][RTW89_MKK][0][86] = 127, + [2][1][2][0][RTW89_IC][1][86] = 20, + [2][1][2][0][RTW89_KCC][1][86] = 38, + [2][1][2][0][RTW89_KCC][0][86] = 127, + [2][1][2][0][RTW89_ACMA][1][86] = 127, + [2][1][2][0][RTW89_ACMA][0][86] = 127, + [2][1][2][0][RTW89_CHILE][1][86] = 20, + [2][1][2][0][RTW89_QATAR][1][86] = 127, + [2][1][2][0][RTW89_QATAR][0][86] = 127, + [2][1][2][0][RTW89_UK][1][86] = 127, + [2][1][2][0][RTW89_UK][0][86] = 127, + [2][1][2][0][RTW89_FCC][1][93] = 22, + [2][1][2][0][RTW89_FCC][2][93] = 127, + [2][1][2][0][RTW89_ETSI][1][93] = 127, + [2][1][2][0][RTW89_ETSI][0][93] = 127, + [2][1][2][0][RTW89_MKK][1][93] = 127, + [2][1][2][0][RTW89_MKK][0][93] = 127, + [2][1][2][0][RTW89_IC][1][93] = 22, + [2][1][2][0][RTW89_KCC][1][93] = 38, + [2][1][2][0][RTW89_KCC][0][93] = 127, + [2][1][2][0][RTW89_ACMA][1][93] = 127, + [2][1][2][0][RTW89_ACMA][0][93] = 127, + [2][1][2][0][RTW89_CHILE][1][93] = 22, + [2][1][2][0][RTW89_QATAR][1][93] = 127, + [2][1][2][0][RTW89_QATAR][0][93] = 127, + [2][1][2][0][RTW89_UK][1][93] = 127, + [2][1][2][0][RTW89_UK][0][93] = 127, + [2][1][2][0][RTW89_FCC][1][101] = 22, + [2][1][2][0][RTW89_FCC][2][101] = 127, + [2][1][2][0][RTW89_ETSI][1][101] = 127, + [2][1][2][0][RTW89_ETSI][0][101] = 127, + [2][1][2][0][RTW89_MKK][1][101] = 127, + [2][1][2][0][RTW89_MKK][0][101] = 127, + [2][1][2][0][RTW89_IC][1][101] = 22, + [2][1][2][0][RTW89_KCC][1][101] = 38, + [2][1][2][0][RTW89_KCC][0][101] = 127, + [2][1][2][0][RTW89_ACMA][1][101] = 127, + [2][1][2][0][RTW89_ACMA][0][101] = 127, + [2][1][2][0][RTW89_CHILE][1][101] = 22, + [2][1][2][0][RTW89_QATAR][1][101] = 127, + [2][1][2][0][RTW89_QATAR][0][101] = 127, + [2][1][2][0][RTW89_UK][1][101] = 127, + [2][1][2][0][RTW89_UK][0][101] = 127, + [2][1][2][0][RTW89_FCC][1][108] = 127, + [2][1][2][0][RTW89_FCC][2][108] = 127, + [2][1][2][0][RTW89_ETSI][1][108] = 127, + [2][1][2][0][RTW89_ETSI][0][108] = 127, + [2][1][2][0][RTW89_MKK][1][108] = 127, + [2][1][2][0][RTW89_MKK][0][108] = 127, + [2][1][2][0][RTW89_IC][1][108] = 127, + [2][1][2][0][RTW89_KCC][1][108] = 127, + [2][1][2][0][RTW89_KCC][0][108] = 127, + [2][1][2][0][RTW89_ACMA][1][108] = 127, + [2][1][2][0][RTW89_ACMA][0][108] = 127, + [2][1][2][0][RTW89_CHILE][1][108] = 127, + [2][1][2][0][RTW89_QATAR][1][108] = 127, + [2][1][2][0][RTW89_QATAR][0][108] = 127, + [2][1][2][0][RTW89_UK][1][108] = 127, + [2][1][2][0][RTW89_UK][0][108] = 127, + [2][1][2][0][RTW89_FCC][1][116] = 127, + [2][1][2][0][RTW89_FCC][2][116] = 127, + [2][1][2][0][RTW89_ETSI][1][116] = 127, + [2][1][2][0][RTW89_ETSI][0][116] = 127, + [2][1][2][0][RTW89_MKK][1][116] = 127, + [2][1][2][0][RTW89_MKK][0][116] = 127, + [2][1][2][0][RTW89_IC][1][116] = 127, + [2][1][2][0][RTW89_KCC][1][116] = 127, + [2][1][2][0][RTW89_KCC][0][116] = 127, + [2][1][2][0][RTW89_ACMA][1][116] = 127, + [2][1][2][0][RTW89_ACMA][0][116] = 127, + [2][1][2][0][RTW89_CHILE][1][116] = 127, + [2][1][2][0][RTW89_QATAR][1][116] = 127, + [2][1][2][0][RTW89_QATAR][0][116] = 127, + [2][1][2][0][RTW89_UK][1][116] = 127, + [2][1][2][0][RTW89_UK][0][116] = 127, + [2][1][2][1][RTW89_FCC][1][3] = 22, + [2][1][2][1][RTW89_FCC][2][3] = 50, + [2][1][2][1][RTW89_ETSI][1][3] = 42, + [2][1][2][1][RTW89_ETSI][0][3] = 6, + [2][1][2][1][RTW89_MKK][1][3] = 52, + [2][1][2][1][RTW89_MKK][0][3] = 14, + [2][1][2][1][RTW89_IC][1][3] = 22, + [2][1][2][1][RTW89_KCC][1][3] = 38, + [2][1][2][1][RTW89_KCC][0][3] = 12, + [2][1][2][1][RTW89_ACMA][1][3] = 42, + [2][1][2][1][RTW89_ACMA][0][3] = 6, + [2][1][2][1][RTW89_CHILE][1][3] = 22, + [2][1][2][1][RTW89_QATAR][1][3] = 42, + [2][1][2][1][RTW89_QATAR][0][3] = 6, + [2][1][2][1][RTW89_UK][1][3] = 42, + [2][1][2][1][RTW89_UK][0][3] = 6, + [2][1][2][1][RTW89_FCC][1][11] = 20, + [2][1][2][1][RTW89_FCC][2][11] = 50, + [2][1][2][1][RTW89_ETSI][1][11] = 42, + [2][1][2][1][RTW89_ETSI][0][11] = 6, + [2][1][2][1][RTW89_MKK][1][11] = 52, + [2][1][2][1][RTW89_MKK][0][11] = 12, + [2][1][2][1][RTW89_IC][1][11] = 20, + [2][1][2][1][RTW89_KCC][1][11] = 38, + [2][1][2][1][RTW89_KCC][0][11] = 12, + [2][1][2][1][RTW89_ACMA][1][11] = 42, + [2][1][2][1][RTW89_ACMA][0][11] = 6, + [2][1][2][1][RTW89_CHILE][1][11] = 20, + [2][1][2][1][RTW89_QATAR][1][11] = 42, + [2][1][2][1][RTW89_QATAR][0][11] = 6, + [2][1][2][1][RTW89_UK][1][11] = 42, + [2][1][2][1][RTW89_UK][0][11] = 6, + [2][1][2][1][RTW89_FCC][1][18] = 20, + [2][1][2][1][RTW89_FCC][2][18] = 50, + [2][1][2][1][RTW89_ETSI][1][18] = 42, + [2][1][2][1][RTW89_ETSI][0][18] = 6, + [2][1][2][1][RTW89_MKK][1][18] = 52, + [2][1][2][1][RTW89_MKK][0][18] = 12, + [2][1][2][1][RTW89_IC][1][18] = 20, + [2][1][2][1][RTW89_KCC][1][18] = 38, + [2][1][2][1][RTW89_KCC][0][18] = 12, + [2][1][2][1][RTW89_ACMA][1][18] = 42, + [2][1][2][1][RTW89_ACMA][0][18] = 6, + [2][1][2][1][RTW89_CHILE][1][18] = 20, + [2][1][2][1][RTW89_QATAR][1][18] = 42, + [2][1][2][1][RTW89_QATAR][0][18] = 6, + [2][1][2][1][RTW89_UK][1][18] = 42, + [2][1][2][1][RTW89_UK][0][18] = 6, + [2][1][2][1][RTW89_FCC][1][26] = 20, + [2][1][2][1][RTW89_FCC][2][26] = 60, + [2][1][2][1][RTW89_ETSI][1][26] = 42, + [2][1][2][1][RTW89_ETSI][0][26] = 6, + [2][1][2][1][RTW89_MKK][1][26] = 52, + [2][1][2][1][RTW89_MKK][0][26] = 12, + [2][1][2][1][RTW89_IC][1][26] = 20, + [2][1][2][1][RTW89_KCC][1][26] = 38, + [2][1][2][1][RTW89_KCC][0][26] = 12, + [2][1][2][1][RTW89_ACMA][1][26] = 42, + [2][1][2][1][RTW89_ACMA][0][26] = 6, + [2][1][2][1][RTW89_CHILE][1][26] = 20, + [2][1][2][1][RTW89_QATAR][1][26] = 42, + [2][1][2][1][RTW89_QATAR][0][26] = 6, + [2][1][2][1][RTW89_UK][1][26] = 42, + [2][1][2][1][RTW89_UK][0][26] = 6, + [2][1][2][1][RTW89_FCC][1][33] = 20, + [2][1][2][1][RTW89_FCC][2][33] = 60, + [2][1][2][1][RTW89_ETSI][1][33] = 42, + [2][1][2][1][RTW89_ETSI][0][33] = 6, + [2][1][2][1][RTW89_MKK][1][33] = 48, + [2][1][2][1][RTW89_MKK][0][33] = 12, + [2][1][2][1][RTW89_IC][1][33] = 20, + [2][1][2][1][RTW89_KCC][1][33] = 38, + [2][1][2][1][RTW89_KCC][0][33] = 12, + [2][1][2][1][RTW89_ACMA][1][33] = 42, + [2][1][2][1][RTW89_ACMA][0][33] = 6, + [2][1][2][1][RTW89_CHILE][1][33] = 20, + [2][1][2][1][RTW89_QATAR][1][33] = 42, + [2][1][2][1][RTW89_QATAR][0][33] = 6, + [2][1][2][1][RTW89_UK][1][33] = 42, + [2][1][2][1][RTW89_UK][0][33] = 6, + [2][1][2][1][RTW89_FCC][1][41] = 22, + [2][1][2][1][RTW89_FCC][2][41] = 60, + [2][1][2][1][RTW89_ETSI][1][41] = 42, + [2][1][2][1][RTW89_ETSI][0][41] = 6, + [2][1][2][1][RTW89_MKK][1][41] = 48, + [2][1][2][1][RTW89_MKK][0][41] = 12, + [2][1][2][1][RTW89_IC][1][41] = 22, + [2][1][2][1][RTW89_KCC][1][41] = 38, + [2][1][2][1][RTW89_KCC][0][41] = 12, + [2][1][2][1][RTW89_ACMA][1][41] = 42, + [2][1][2][1][RTW89_ACMA][0][41] = 6, + [2][1][2][1][RTW89_CHILE][1][41] = 22, + [2][1][2][1][RTW89_QATAR][1][41] = 42, + [2][1][2][1][RTW89_QATAR][0][41] = 6, + [2][1][2][1][RTW89_UK][1][41] = 42, + [2][1][2][1][RTW89_UK][0][41] = 6, + [2][1][2][1][RTW89_FCC][1][48] = 22, + [2][1][2][1][RTW89_FCC][2][48] = 127, + [2][1][2][1][RTW89_ETSI][1][48] = 127, + [2][1][2][1][RTW89_ETSI][0][48] = 127, + [2][1][2][1][RTW89_MKK][1][48] = 127, + [2][1][2][1][RTW89_MKK][0][48] = 127, + [2][1][2][1][RTW89_IC][1][48] = 22, + [2][1][2][1][RTW89_KCC][1][48] = 38, + [2][1][2][1][RTW89_KCC][0][48] = 127, + [2][1][2][1][RTW89_ACMA][1][48] = 127, + [2][1][2][1][RTW89_ACMA][0][48] = 127, + [2][1][2][1][RTW89_CHILE][1][48] = 22, + [2][1][2][1][RTW89_QATAR][1][48] = 127, + [2][1][2][1][RTW89_QATAR][0][48] = 127, + [2][1][2][1][RTW89_UK][1][48] = 127, + [2][1][2][1][RTW89_UK][0][48] = 127, + [2][1][2][1][RTW89_FCC][1][56] = 20, + [2][1][2][1][RTW89_FCC][2][56] = 127, + [2][1][2][1][RTW89_ETSI][1][56] = 127, + [2][1][2][1][RTW89_ETSI][0][56] = 127, + [2][1][2][1][RTW89_MKK][1][56] = 127, + [2][1][2][1][RTW89_MKK][0][56] = 127, + [2][1][2][1][RTW89_IC][1][56] = 20, + [2][1][2][1][RTW89_KCC][1][56] = 38, + [2][1][2][1][RTW89_KCC][0][56] = 127, + [2][1][2][1][RTW89_ACMA][1][56] = 127, + [2][1][2][1][RTW89_ACMA][0][56] = 127, + [2][1][2][1][RTW89_CHILE][1][56] = 20, + [2][1][2][1][RTW89_QATAR][1][56] = 127, + [2][1][2][1][RTW89_QATAR][0][56] = 127, + [2][1][2][1][RTW89_UK][1][56] = 127, + [2][1][2][1][RTW89_UK][0][56] = 127, + [2][1][2][1][RTW89_FCC][1][63] = 22, + [2][1][2][1][RTW89_FCC][2][63] = 58, + [2][1][2][1][RTW89_ETSI][1][63] = 127, + [2][1][2][1][RTW89_ETSI][0][63] = 127, + [2][1][2][1][RTW89_MKK][1][63] = 127, + [2][1][2][1][RTW89_MKK][0][63] = 127, + [2][1][2][1][RTW89_IC][1][63] = 22, + [2][1][2][1][RTW89_KCC][1][63] = 38, + [2][1][2][1][RTW89_KCC][0][63] = 127, + [2][1][2][1][RTW89_ACMA][1][63] = 127, + [2][1][2][1][RTW89_ACMA][0][63] = 127, + [2][1][2][1][RTW89_CHILE][1][63] = 22, + [2][1][2][1][RTW89_QATAR][1][63] = 127, + [2][1][2][1][RTW89_QATAR][0][63] = 127, + [2][1][2][1][RTW89_UK][1][63] = 127, + [2][1][2][1][RTW89_UK][0][63] = 127, + [2][1][2][1][RTW89_FCC][1][71] = 20, + [2][1][2][1][RTW89_FCC][2][71] = 58, + [2][1][2][1][RTW89_ETSI][1][71] = 127, + [2][1][2][1][RTW89_ETSI][0][71] = 127, + [2][1][2][1][RTW89_MKK][1][71] = 127, + [2][1][2][1][RTW89_MKK][0][71] = 127, + [2][1][2][1][RTW89_IC][1][71] = 20, + [2][1][2][1][RTW89_KCC][1][71] = 38, + [2][1][2][1][RTW89_KCC][0][71] = 127, + [2][1][2][1][RTW89_ACMA][1][71] = 127, + [2][1][2][1][RTW89_ACMA][0][71] = 127, + [2][1][2][1][RTW89_CHILE][1][71] = 20, + [2][1][2][1][RTW89_QATAR][1][71] = 127, + [2][1][2][1][RTW89_QATAR][0][71] = 127, + [2][1][2][1][RTW89_UK][1][71] = 127, + [2][1][2][1][RTW89_UK][0][71] = 127, + [2][1][2][1][RTW89_FCC][1][78] = 20, + [2][1][2][1][RTW89_FCC][2][78] = 58, + [2][1][2][1][RTW89_ETSI][1][78] = 127, + [2][1][2][1][RTW89_ETSI][0][78] = 127, + [2][1][2][1][RTW89_MKK][1][78] = 127, + [2][1][2][1][RTW89_MKK][0][78] = 127, + [2][1][2][1][RTW89_IC][1][78] = 20, + [2][1][2][1][RTW89_KCC][1][78] = 38, + [2][1][2][1][RTW89_KCC][0][78] = 127, + [2][1][2][1][RTW89_ACMA][1][78] = 127, + [2][1][2][1][RTW89_ACMA][0][78] = 127, + [2][1][2][1][RTW89_CHILE][1][78] = 20, + [2][1][2][1][RTW89_QATAR][1][78] = 127, + [2][1][2][1][RTW89_QATAR][0][78] = 127, + [2][1][2][1][RTW89_UK][1][78] = 127, + [2][1][2][1][RTW89_UK][0][78] = 127, + [2][1][2][1][RTW89_FCC][1][86] = 20, + [2][1][2][1][RTW89_FCC][2][86] = 127, + [2][1][2][1][RTW89_ETSI][1][86] = 127, + [2][1][2][1][RTW89_ETSI][0][86] = 127, + [2][1][2][1][RTW89_MKK][1][86] = 127, + [2][1][2][1][RTW89_MKK][0][86] = 127, + [2][1][2][1][RTW89_IC][1][86] = 20, + [2][1][2][1][RTW89_KCC][1][86] = 38, + [2][1][2][1][RTW89_KCC][0][86] = 127, + [2][1][2][1][RTW89_ACMA][1][86] = 127, + [2][1][2][1][RTW89_ACMA][0][86] = 127, + [2][1][2][1][RTW89_CHILE][1][86] = 20, + [2][1][2][1][RTW89_QATAR][1][86] = 127, + [2][1][2][1][RTW89_QATAR][0][86] = 127, + [2][1][2][1][RTW89_UK][1][86] = 127, + [2][1][2][1][RTW89_UK][0][86] = 127, + [2][1][2][1][RTW89_FCC][1][93] = 22, + [2][1][2][1][RTW89_FCC][2][93] = 127, + [2][1][2][1][RTW89_ETSI][1][93] = 127, + [2][1][2][1][RTW89_ETSI][0][93] = 127, + [2][1][2][1][RTW89_MKK][1][93] = 127, + [2][1][2][1][RTW89_MKK][0][93] = 127, + [2][1][2][1][RTW89_IC][1][93] = 22, + [2][1][2][1][RTW89_KCC][1][93] = 38, + [2][1][2][1][RTW89_KCC][0][93] = 127, + [2][1][2][1][RTW89_ACMA][1][93] = 127, + [2][1][2][1][RTW89_ACMA][0][93] = 127, + [2][1][2][1][RTW89_CHILE][1][93] = 22, + [2][1][2][1][RTW89_QATAR][1][93] = 127, + [2][1][2][1][RTW89_QATAR][0][93] = 127, + [2][1][2][1][RTW89_UK][1][93] = 127, + [2][1][2][1][RTW89_UK][0][93] = 127, + [2][1][2][1][RTW89_FCC][1][101] = 22, + [2][1][2][1][RTW89_FCC][2][101] = 127, + [2][1][2][1][RTW89_ETSI][1][101] = 127, + [2][1][2][1][RTW89_ETSI][0][101] = 127, + [2][1][2][1][RTW89_MKK][1][101] = 127, + [2][1][2][1][RTW89_MKK][0][101] = 127, + [2][1][2][1][RTW89_IC][1][101] = 22, + [2][1][2][1][RTW89_KCC][1][101] = 38, + [2][1][2][1][RTW89_KCC][0][101] = 127, + [2][1][2][1][RTW89_ACMA][1][101] = 127, + [2][1][2][1][RTW89_ACMA][0][101] = 127, + [2][1][2][1][RTW89_CHILE][1][101] = 22, + [2][1][2][1][RTW89_QATAR][1][101] = 127, + [2][1][2][1][RTW89_QATAR][0][101] = 127, + [2][1][2][1][RTW89_UK][1][101] = 127, + [2][1][2][1][RTW89_UK][0][101] = 127, + [2][1][2][1][RTW89_FCC][1][108] = 127, + [2][1][2][1][RTW89_FCC][2][108] = 127, + [2][1][2][1][RTW89_ETSI][1][108] = 127, + [2][1][2][1][RTW89_ETSI][0][108] = 127, + [2][1][2][1][RTW89_MKK][1][108] = 127, + [2][1][2][1][RTW89_MKK][0][108] = 127, + [2][1][2][1][RTW89_IC][1][108] = 127, + [2][1][2][1][RTW89_KCC][1][108] = 127, + [2][1][2][1][RTW89_KCC][0][108] = 127, + [2][1][2][1][RTW89_ACMA][1][108] = 127, + [2][1][2][1][RTW89_ACMA][0][108] = 127, + [2][1][2][1][RTW89_CHILE][1][108] = 127, + [2][1][2][1][RTW89_QATAR][1][108] = 127, + [2][1][2][1][RTW89_QATAR][0][108] = 127, + [2][1][2][1][RTW89_UK][1][108] = 127, + [2][1][2][1][RTW89_UK][0][108] = 127, + [2][1][2][1][RTW89_FCC][1][116] = 127, + [2][1][2][1][RTW89_FCC][2][116] = 127, + [2][1][2][1][RTW89_ETSI][1][116] = 127, + [2][1][2][1][RTW89_ETSI][0][116] = 127, + [2][1][2][1][RTW89_MKK][1][116] = 127, + [2][1][2][1][RTW89_MKK][0][116] = 127, + [2][1][2][1][RTW89_IC][1][116] = 127, + [2][1][2][1][RTW89_KCC][1][116] = 127, + [2][1][2][1][RTW89_KCC][0][116] = 127, + [2][1][2][1][RTW89_ACMA][1][116] = 127, + [2][1][2][1][RTW89_ACMA][0][116] = 127, + [2][1][2][1][RTW89_CHILE][1][116] = 127, + [2][1][2][1][RTW89_QATAR][1][116] = 127, + [2][1][2][1][RTW89_QATAR][0][116] = 127, + [2][1][2][1][RTW89_UK][1][116] = 127, + [2][1][2][1][RTW89_UK][0][116] = 127, + [3][0][2][0][RTW89_FCC][1][7] = 52, + [3][0][2][0][RTW89_FCC][2][7] = 52, + [3][0][2][0][RTW89_ETSI][1][7] = 50, + [3][0][2][0][RTW89_ETSI][0][7] = 30, + [3][0][2][0][RTW89_MKK][1][7] = 50, + [3][0][2][0][RTW89_MKK][0][7] = 22, + [3][0][2][0][RTW89_IC][1][7] = 52, + [3][0][2][0][RTW89_KCC][1][7] = 42, + [3][0][2][0][RTW89_KCC][0][7] = 24, + [3][0][2][0][RTW89_ACMA][1][7] = 50, + [3][0][2][0][RTW89_ACMA][0][7] = 30, + [3][0][2][0][RTW89_CHILE][1][7] = 52, + [3][0][2][0][RTW89_QATAR][1][7] = 50, + [3][0][2][0][RTW89_QATAR][0][7] = 30, + [3][0][2][0][RTW89_UK][1][7] = 50, + [3][0][2][0][RTW89_UK][0][7] = 30, + [3][0][2][0][RTW89_FCC][1][22] = 52, + [3][0][2][0][RTW89_FCC][2][22] = 52, + [3][0][2][0][RTW89_ETSI][1][22] = 50, + [3][0][2][0][RTW89_ETSI][0][22] = 30, + [3][0][2][0][RTW89_MKK][1][22] = 50, + [3][0][2][0][RTW89_MKK][0][22] = 20, + [3][0][2][0][RTW89_IC][1][22] = 52, + [3][0][2][0][RTW89_KCC][1][22] = 42, + [3][0][2][0][RTW89_KCC][0][22] = 24, + [3][0][2][0][RTW89_ACMA][1][22] = 50, + [3][0][2][0][RTW89_ACMA][0][22] = 30, + [3][0][2][0][RTW89_CHILE][1][22] = 52, + [3][0][2][0][RTW89_QATAR][1][22] = 50, + [3][0][2][0][RTW89_QATAR][0][22] = 30, + [3][0][2][0][RTW89_UK][1][22] = 50, + [3][0][2][0][RTW89_UK][0][22] = 30, + [3][0][2][0][RTW89_FCC][1][37] = 52, + [3][0][2][0][RTW89_FCC][2][37] = 52, + [3][0][2][0][RTW89_ETSI][1][37] = 50, + [3][0][2][0][RTW89_ETSI][0][37] = 30, + [3][0][2][0][RTW89_MKK][1][37] = 50, + [3][0][2][0][RTW89_MKK][0][37] = 20, + [3][0][2][0][RTW89_IC][1][37] = 52, + [3][0][2][0][RTW89_KCC][1][37] = 42, + [3][0][2][0][RTW89_KCC][0][37] = 24, + [3][0][2][0][RTW89_ACMA][1][37] = 50, + [3][0][2][0][RTW89_ACMA][0][37] = 30, + [3][0][2][0][RTW89_CHILE][1][37] = 52, + [3][0][2][0][RTW89_QATAR][1][37] = 50, + [3][0][2][0][RTW89_QATAR][0][37] = 30, + [3][0][2][0][RTW89_UK][1][37] = 50, + [3][0][2][0][RTW89_UK][0][37] = 30, + [3][0][2][0][RTW89_FCC][1][52] = 54, + [3][0][2][0][RTW89_FCC][2][52] = 127, + [3][0][2][0][RTW89_ETSI][1][52] = 127, + [3][0][2][0][RTW89_ETSI][0][52] = 127, + [3][0][2][0][RTW89_MKK][1][52] = 127, + [3][0][2][0][RTW89_MKK][0][52] = 127, + [3][0][2][0][RTW89_IC][1][52] = 54, + [3][0][2][0][RTW89_KCC][1][52] = 56, + [3][0][2][0][RTW89_KCC][0][52] = 127, + [3][0][2][0][RTW89_ACMA][1][52] = 127, + [3][0][2][0][RTW89_ACMA][0][52] = 127, + [3][0][2][0][RTW89_CHILE][1][52] = 54, + [3][0][2][0][RTW89_QATAR][1][52] = 127, + [3][0][2][0][RTW89_QATAR][0][52] = 127, + [3][0][2][0][RTW89_UK][1][52] = 127, + [3][0][2][0][RTW89_UK][0][52] = 127, + [3][0][2][0][RTW89_FCC][1][67] = 54, + [3][0][2][0][RTW89_FCC][2][67] = 54, + [3][0][2][0][RTW89_ETSI][1][67] = 127, + [3][0][2][0][RTW89_ETSI][0][67] = 127, + [3][0][2][0][RTW89_MKK][1][67] = 127, + [3][0][2][0][RTW89_MKK][0][67] = 127, + [3][0][2][0][RTW89_IC][1][67] = 54, + [3][0][2][0][RTW89_KCC][1][67] = 54, + [3][0][2][0][RTW89_KCC][0][67] = 127, + [3][0][2][0][RTW89_ACMA][1][67] = 127, + [3][0][2][0][RTW89_ACMA][0][67] = 127, + [3][0][2][0][RTW89_CHILE][1][67] = 54, + [3][0][2][0][RTW89_QATAR][1][67] = 127, + [3][0][2][0][RTW89_QATAR][0][67] = 127, + [3][0][2][0][RTW89_UK][1][67] = 127, + [3][0][2][0][RTW89_UK][0][67] = 127, + [3][0][2][0][RTW89_FCC][1][82] = 46, + [3][0][2][0][RTW89_FCC][2][82] = 127, + [3][0][2][0][RTW89_ETSI][1][82] = 127, + [3][0][2][0][RTW89_ETSI][0][82] = 127, + [3][0][2][0][RTW89_MKK][1][82] = 127, + [3][0][2][0][RTW89_MKK][0][82] = 127, + [3][0][2][0][RTW89_IC][1][82] = 46, + [3][0][2][0][RTW89_KCC][1][82] = 26, + [3][0][2][0][RTW89_KCC][0][82] = 127, + [3][0][2][0][RTW89_ACMA][1][82] = 127, + [3][0][2][0][RTW89_ACMA][0][82] = 127, + [3][0][2][0][RTW89_CHILE][1][82] = 46, + [3][0][2][0][RTW89_QATAR][1][82] = 127, + [3][0][2][0][RTW89_QATAR][0][82] = 127, + [3][0][2][0][RTW89_UK][1][82] = 127, + [3][0][2][0][RTW89_UK][0][82] = 127, + [3][0][2][0][RTW89_FCC][1][97] = 40, + [3][0][2][0][RTW89_FCC][2][97] = 127, + [3][0][2][0][RTW89_ETSI][1][97] = 127, + [3][0][2][0][RTW89_ETSI][0][97] = 127, + [3][0][2][0][RTW89_MKK][1][97] = 127, + [3][0][2][0][RTW89_MKK][0][97] = 127, + [3][0][2][0][RTW89_IC][1][97] = 40, + [3][0][2][0][RTW89_KCC][1][97] = 26, + [3][0][2][0][RTW89_KCC][0][97] = 127, + [3][0][2][0][RTW89_ACMA][1][97] = 127, + [3][0][2][0][RTW89_ACMA][0][97] = 127, + [3][0][2][0][RTW89_CHILE][1][97] = 40, + [3][0][2][0][RTW89_QATAR][1][97] = 127, + [3][0][2][0][RTW89_QATAR][0][97] = 127, + [3][0][2][0][RTW89_UK][1][97] = 127, + [3][0][2][0][RTW89_UK][0][97] = 127, + [3][0][2][0][RTW89_FCC][1][112] = 127, + [3][0][2][0][RTW89_FCC][2][112] = 127, + [3][0][2][0][RTW89_ETSI][1][112] = 127, + [3][0][2][0][RTW89_ETSI][0][112] = 127, + [3][0][2][0][RTW89_MKK][1][112] = 127, + [3][0][2][0][RTW89_MKK][0][112] = 127, + [3][0][2][0][RTW89_IC][1][112] = 127, + [3][0][2][0][RTW89_KCC][1][112] = 127, + [3][0][2][0][RTW89_KCC][0][112] = 127, + [3][0][2][0][RTW89_ACMA][1][112] = 127, + [3][0][2][0][RTW89_ACMA][0][112] = 127, + [3][0][2][0][RTW89_CHILE][1][112] = 127, + [3][0][2][0][RTW89_QATAR][1][112] = 127, + [3][0][2][0][RTW89_QATAR][0][112] = 127, + [3][0][2][0][RTW89_UK][1][112] = 127, + [3][0][2][0][RTW89_UK][0][112] = 127, + [3][1][2][0][RTW89_FCC][1][7] = 32, + [3][1][2][0][RTW89_FCC][2][7] = 46, + [3][1][2][0][RTW89_ETSI][1][7] = 50, + [3][1][2][0][RTW89_ETSI][0][7] = 18, + [3][1][2][0][RTW89_MKK][1][7] = 38, + [3][1][2][0][RTW89_MKK][0][7] = 10, + [3][1][2][0][RTW89_IC][1][7] = 32, + [3][1][2][0][RTW89_KCC][1][7] = 40, + [3][1][2][0][RTW89_KCC][0][7] = 12, + [3][1][2][0][RTW89_ACMA][1][7] = 50, + [3][1][2][0][RTW89_ACMA][0][7] = 18, + [3][1][2][0][RTW89_CHILE][1][7] = 32, + [3][1][2][0][RTW89_QATAR][1][7] = 50, + [3][1][2][0][RTW89_QATAR][0][7] = 18, + [3][1][2][0][RTW89_UK][1][7] = 50, + [3][1][2][0][RTW89_UK][0][7] = 18, + [3][1][2][0][RTW89_FCC][1][22] = 30, + [3][1][2][0][RTW89_FCC][2][22] = 52, + [3][1][2][0][RTW89_ETSI][1][22] = 46, + [3][1][2][0][RTW89_ETSI][0][22] = 16, + [3][1][2][0][RTW89_MKK][1][22] = 48, + [3][1][2][0][RTW89_MKK][0][22] = 8, + [3][1][2][0][RTW89_IC][1][22] = 30, + [3][1][2][0][RTW89_KCC][1][22] = 40, + [3][1][2][0][RTW89_KCC][0][22] = 12, + [3][1][2][0][RTW89_ACMA][1][22] = 46, + [3][1][2][0][RTW89_ACMA][0][22] = 16, + [3][1][2][0][RTW89_CHILE][1][22] = 30, + [3][1][2][0][RTW89_QATAR][1][22] = 46, + [3][1][2][0][RTW89_QATAR][0][22] = 16, + [3][1][2][0][RTW89_UK][1][22] = 46, + [3][1][2][0][RTW89_UK][0][22] = 16, + [3][1][2][0][RTW89_FCC][1][37] = 30, + [3][1][2][0][RTW89_FCC][2][37] = 52, + [3][1][2][0][RTW89_ETSI][1][37] = 46, + [3][1][2][0][RTW89_ETSI][0][37] = 16, + [3][1][2][0][RTW89_MKK][1][37] = 48, + [3][1][2][0][RTW89_MKK][0][37] = 8, + [3][1][2][0][RTW89_IC][1][37] = 30, + [3][1][2][0][RTW89_KCC][1][37] = 40, + [3][1][2][0][RTW89_KCC][0][37] = 12, + [3][1][2][0][RTW89_ACMA][1][37] = 46, + [3][1][2][0][RTW89_ACMA][0][37] = 16, + [3][1][2][0][RTW89_CHILE][1][37] = 30, + [3][1][2][0][RTW89_QATAR][1][37] = 46, + [3][1][2][0][RTW89_QATAR][0][37] = 16, + [3][1][2][0][RTW89_UK][1][37] = 46, + [3][1][2][0][RTW89_UK][0][37] = 16, + [3][1][2][0][RTW89_FCC][1][52] = 30, + [3][1][2][0][RTW89_FCC][2][52] = 127, + [3][1][2][0][RTW89_ETSI][1][52] = 127, + [3][1][2][0][RTW89_ETSI][0][52] = 127, + [3][1][2][0][RTW89_MKK][1][52] = 127, + [3][1][2][0][RTW89_MKK][0][52] = 127, + [3][1][2][0][RTW89_IC][1][52] = 30, + [3][1][2][0][RTW89_KCC][1][52] = 48, + [3][1][2][0][RTW89_KCC][0][52] = 127, + [3][1][2][0][RTW89_ACMA][1][52] = 127, + [3][1][2][0][RTW89_ACMA][0][52] = 127, + [3][1][2][0][RTW89_CHILE][1][52] = 30, + [3][1][2][0][RTW89_QATAR][1][52] = 127, + [3][1][2][0][RTW89_QATAR][0][52] = 127, + [3][1][2][0][RTW89_UK][1][52] = 127, + [3][1][2][0][RTW89_UK][0][52] = 127, + [3][1][2][0][RTW89_FCC][1][67] = 32, + [3][1][2][0][RTW89_FCC][2][67] = 54, + [3][1][2][0][RTW89_ETSI][1][67] = 127, + [3][1][2][0][RTW89_ETSI][0][67] = 127, + [3][1][2][0][RTW89_MKK][1][67] = 127, + [3][1][2][0][RTW89_MKK][0][67] = 127, + [3][1][2][0][RTW89_IC][1][67] = 32, + [3][1][2][0][RTW89_KCC][1][67] = 48, + [3][1][2][0][RTW89_KCC][0][67] = 127, + [3][1][2][0][RTW89_ACMA][1][67] = 127, + [3][1][2][0][RTW89_ACMA][0][67] = 127, + [3][1][2][0][RTW89_CHILE][1][67] = 32, + [3][1][2][0][RTW89_QATAR][1][67] = 127, + [3][1][2][0][RTW89_QATAR][0][67] = 127, + [3][1][2][0][RTW89_UK][1][67] = 127, + [3][1][2][0][RTW89_UK][0][67] = 127, + [3][1][2][0][RTW89_FCC][1][82] = 32, + [3][1][2][0][RTW89_FCC][2][82] = 127, + [3][1][2][0][RTW89_ETSI][1][82] = 127, + [3][1][2][0][RTW89_ETSI][0][82] = 127, + [3][1][2][0][RTW89_MKK][1][82] = 127, + [3][1][2][0][RTW89_MKK][0][82] = 127, + [3][1][2][0][RTW89_IC][1][82] = 32, + [3][1][2][0][RTW89_KCC][1][82] = 24, + [3][1][2][0][RTW89_KCC][0][82] = 127, + [3][1][2][0][RTW89_ACMA][1][82] = 127, + [3][1][2][0][RTW89_ACMA][0][82] = 127, + [3][1][2][0][RTW89_CHILE][1][82] = 32, + [3][1][2][0][RTW89_QATAR][1][82] = 127, + [3][1][2][0][RTW89_QATAR][0][82] = 127, + [3][1][2][0][RTW89_UK][1][82] = 127, + [3][1][2][0][RTW89_UK][0][82] = 127, + [3][1][2][0][RTW89_FCC][1][97] = 32, + [3][1][2][0][RTW89_FCC][2][97] = 127, + [3][1][2][0][RTW89_ETSI][1][97] = 127, + [3][1][2][0][RTW89_ETSI][0][97] = 127, + [3][1][2][0][RTW89_MKK][1][97] = 127, + [3][1][2][0][RTW89_MKK][0][97] = 127, + [3][1][2][0][RTW89_IC][1][97] = 32, + [3][1][2][0][RTW89_KCC][1][97] = 24, + [3][1][2][0][RTW89_KCC][0][97] = 127, + [3][1][2][0][RTW89_ACMA][1][97] = 127, + [3][1][2][0][RTW89_ACMA][0][97] = 127, + [3][1][2][0][RTW89_CHILE][1][97] = 32, + [3][1][2][0][RTW89_QATAR][1][97] = 127, + [3][1][2][0][RTW89_QATAR][0][97] = 127, + [3][1][2][0][RTW89_UK][1][97] = 127, + [3][1][2][0][RTW89_UK][0][97] = 127, + [3][1][2][0][RTW89_FCC][1][112] = 127, + [3][1][2][0][RTW89_FCC][2][112] = 127, + [3][1][2][0][RTW89_ETSI][1][112] = 127, + [3][1][2][0][RTW89_ETSI][0][112] = 127, + [3][1][2][0][RTW89_MKK][1][112] = 127, + [3][1][2][0][RTW89_MKK][0][112] = 127, + [3][1][2][0][RTW89_IC][1][112] = 127, + [3][1][2][0][RTW89_KCC][1][112] = 127, + [3][1][2][0][RTW89_KCC][0][112] = 127, + [3][1][2][0][RTW89_ACMA][1][112] = 127, + [3][1][2][0][RTW89_ACMA][0][112] = 127, + [3][1][2][0][RTW89_CHILE][1][112] = 127, + [3][1][2][0][RTW89_QATAR][1][112] = 127, + [3][1][2][0][RTW89_QATAR][0][112] = 127, + [3][1][2][0][RTW89_UK][1][112] = 127, + [3][1][2][0][RTW89_UK][0][112] = 127, + [3][1][2][1][RTW89_FCC][1][7] = 32, + [3][1][2][1][RTW89_FCC][2][7] = 46, + [3][1][2][1][RTW89_ETSI][1][7] = 42, + [3][1][2][1][RTW89_ETSI][0][7] = 6, + [3][1][2][1][RTW89_MKK][1][7] = 38, + [3][1][2][1][RTW89_MKK][0][7] = 10, + [3][1][2][1][RTW89_IC][1][7] = 32, + [3][1][2][1][RTW89_KCC][1][7] = 40, + [3][1][2][1][RTW89_KCC][0][7] = 12, + [3][1][2][1][RTW89_ACMA][1][7] = 42, + [3][1][2][1][RTW89_ACMA][0][7] = 6, + [3][1][2][1][RTW89_CHILE][1][7] = 32, + [3][1][2][1][RTW89_QATAR][1][7] = 42, + [3][1][2][1][RTW89_QATAR][0][7] = 6, + [3][1][2][1][RTW89_UK][1][7] = 42, + [3][1][2][1][RTW89_UK][0][7] = 6, + [3][1][2][1][RTW89_FCC][1][22] = 30, + [3][1][2][1][RTW89_FCC][2][22] = 52, + [3][1][2][1][RTW89_ETSI][1][22] = 42, + [3][1][2][1][RTW89_ETSI][0][22] = 6, + [3][1][2][1][RTW89_MKK][1][22] = 48, + [3][1][2][1][RTW89_MKK][0][22] = 8, + [3][1][2][1][RTW89_IC][1][22] = 30, + [3][1][2][1][RTW89_KCC][1][22] = 40, + [3][1][2][1][RTW89_KCC][0][22] = 12, + [3][1][2][1][RTW89_ACMA][1][22] = 42, + [3][1][2][1][RTW89_ACMA][0][22] = 6, + [3][1][2][1][RTW89_CHILE][1][22] = 30, + [3][1][2][1][RTW89_QATAR][1][22] = 42, + [3][1][2][1][RTW89_QATAR][0][22] = 6, + [3][1][2][1][RTW89_UK][1][22] = 42, + [3][1][2][1][RTW89_UK][0][22] = 6, + [3][1][2][1][RTW89_FCC][1][37] = 30, + [3][1][2][1][RTW89_FCC][2][37] = 52, + [3][1][2][1][RTW89_ETSI][1][37] = 42, + [3][1][2][1][RTW89_ETSI][0][37] = 6, + [3][1][2][1][RTW89_MKK][1][37] = 48, + [3][1][2][1][RTW89_MKK][0][37] = 8, + [3][1][2][1][RTW89_IC][1][37] = 30, + [3][1][2][1][RTW89_KCC][1][37] = 40, + [3][1][2][1][RTW89_KCC][0][37] = 12, + [3][1][2][1][RTW89_ACMA][1][37] = 42, + [3][1][2][1][RTW89_ACMA][0][37] = 6, + [3][1][2][1][RTW89_CHILE][1][37] = 30, + [3][1][2][1][RTW89_QATAR][1][37] = 42, + [3][1][2][1][RTW89_QATAR][0][37] = 6, + [3][1][2][1][RTW89_UK][1][37] = 42, + [3][1][2][1][RTW89_UK][0][37] = 6, + [3][1][2][1][RTW89_FCC][1][52] = 30, + [3][1][2][1][RTW89_FCC][2][52] = 127, + [3][1][2][1][RTW89_ETSI][1][52] = 127, + [3][1][2][1][RTW89_ETSI][0][52] = 127, + [3][1][2][1][RTW89_MKK][1][52] = 127, + [3][1][2][1][RTW89_MKK][0][52] = 127, + [3][1][2][1][RTW89_IC][1][52] = 30, + [3][1][2][1][RTW89_KCC][1][52] = 48, + [3][1][2][1][RTW89_KCC][0][52] = 127, + [3][1][2][1][RTW89_ACMA][1][52] = 127, + [3][1][2][1][RTW89_ACMA][0][52] = 127, + [3][1][2][1][RTW89_CHILE][1][52] = 30, + [3][1][2][1][RTW89_QATAR][1][52] = 127, + [3][1][2][1][RTW89_QATAR][0][52] = 127, + [3][1][2][1][RTW89_UK][1][52] = 127, + [3][1][2][1][RTW89_UK][0][52] = 127, + [3][1][2][1][RTW89_FCC][1][67] = 32, + [3][1][2][1][RTW89_FCC][2][67] = 54, + [3][1][2][1][RTW89_ETSI][1][67] = 127, + [3][1][2][1][RTW89_ETSI][0][67] = 127, + [3][1][2][1][RTW89_MKK][1][67] = 127, + [3][1][2][1][RTW89_MKK][0][67] = 127, + [3][1][2][1][RTW89_IC][1][67] = 32, + [3][1][2][1][RTW89_KCC][1][67] = 48, + [3][1][2][1][RTW89_KCC][0][67] = 127, + [3][1][2][1][RTW89_ACMA][1][67] = 127, + [3][1][2][1][RTW89_ACMA][0][67] = 127, + [3][1][2][1][RTW89_CHILE][1][67] = 32, + [3][1][2][1][RTW89_QATAR][1][67] = 127, + [3][1][2][1][RTW89_QATAR][0][67] = 127, + [3][1][2][1][RTW89_UK][1][67] = 127, + [3][1][2][1][RTW89_UK][0][67] = 127, + [3][1][2][1][RTW89_FCC][1][82] = 32, + [3][1][2][1][RTW89_FCC][2][82] = 127, + [3][1][2][1][RTW89_ETSI][1][82] = 127, + [3][1][2][1][RTW89_ETSI][0][82] = 127, + [3][1][2][1][RTW89_MKK][1][82] = 127, + [3][1][2][1][RTW89_MKK][0][82] = 127, + [3][1][2][1][RTW89_IC][1][82] = 32, + [3][1][2][1][RTW89_KCC][1][82] = 24, + [3][1][2][1][RTW89_KCC][0][82] = 127, + [3][1][2][1][RTW89_ACMA][1][82] = 127, + [3][1][2][1][RTW89_ACMA][0][82] = 127, + [3][1][2][1][RTW89_CHILE][1][82] = 32, + [3][1][2][1][RTW89_QATAR][1][82] = 127, + [3][1][2][1][RTW89_QATAR][0][82] = 127, + [3][1][2][1][RTW89_UK][1][82] = 127, + [3][1][2][1][RTW89_UK][0][82] = 127, + [3][1][2][1][RTW89_FCC][1][97] = 32, + [3][1][2][1][RTW89_FCC][2][97] = 127, + [3][1][2][1][RTW89_ETSI][1][97] = 127, + [3][1][2][1][RTW89_ETSI][0][97] = 127, + [3][1][2][1][RTW89_MKK][1][97] = 127, + [3][1][2][1][RTW89_MKK][0][97] = 127, + [3][1][2][1][RTW89_IC][1][97] = 32, + [3][1][2][1][RTW89_KCC][1][97] = 24, + [3][1][2][1][RTW89_KCC][0][97] = 127, + [3][1][2][1][RTW89_ACMA][1][97] = 127, + [3][1][2][1][RTW89_ACMA][0][97] = 127, + [3][1][2][1][RTW89_CHILE][1][97] = 32, + [3][1][2][1][RTW89_QATAR][1][97] = 127, + [3][1][2][1][RTW89_QATAR][0][97] = 127, + [3][1][2][1][RTW89_UK][1][97] = 127, + [3][1][2][1][RTW89_UK][0][97] = 127, + [3][1][2][1][RTW89_FCC][1][112] = 127, + [3][1][2][1][RTW89_FCC][2][112] = 127, + [3][1][2][1][RTW89_ETSI][1][112] = 127, + [3][1][2][1][RTW89_ETSI][0][112] = 127, + [3][1][2][1][RTW89_MKK][1][112] = 127, + [3][1][2][1][RTW89_MKK][0][112] = 127, + [3][1][2][1][RTW89_IC][1][112] = 127, + [3][1][2][1][RTW89_KCC][1][112] = 127, + [3][1][2][1][RTW89_KCC][0][112] = 127, + [3][1][2][1][RTW89_ACMA][1][112] = 127, + [3][1][2][1][RTW89_ACMA][0][112] = 127, + [3][1][2][1][RTW89_CHILE][1][112] = 127, + [3][1][2][1][RTW89_QATAR][1][112] = 127, + [3][1][2][1][RTW89_QATAR][0][112] = 127, + [3][1][2][1][RTW89_UK][1][112] = 127, + [3][1][2][1][RTW89_UK][0][112] = 127, }; static @@ -34017,10 +45842,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_WW][3] = 44, [1][0][RTW89_WW][4] = 44, [1][0][RTW89_WW][5] = 44, - [1][0][RTW89_WW][6] = 44, - [1][0][RTW89_WW][7] = 44, - [1][0][RTW89_WW][8] = 44, - [1][0][RTW89_WW][9] = 44, + [1][0][RTW89_WW][6] = 40, + [1][0][RTW89_WW][7] = 40, + [1][0][RTW89_WW][8] = 40, + [1][0][RTW89_WW][9] = 40, [1][0][RTW89_WW][10] = 44, [1][0][RTW89_WW][11] = 36, [1][0][RTW89_WW][12] = 4, @@ -34031,24 +45856,24 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_WW][3] = 32, [1][1][RTW89_WW][4] = 32, [1][1][RTW89_WW][5] = 32, - [1][1][RTW89_WW][6] = 32, - [1][1][RTW89_WW][7] = 32, - [1][1][RTW89_WW][8] = 32, - [1][1][RTW89_WW][9] = 32, + [1][1][RTW89_WW][6] = 30, + [1][1][RTW89_WW][7] = 30, + [1][1][RTW89_WW][8] = 30, + [1][1][RTW89_WW][9] = 30, [1][1][RTW89_WW][10] = 32, [1][1][RTW89_WW][11] = 30, [1][1][RTW89_WW][12] = -6, [1][1][RTW89_WW][13] = 0, [2][0][RTW89_WW][0] = 56, - [2][0][RTW89_WW][1] = 56, - [2][0][RTW89_WW][2] = 56, - [2][0][RTW89_WW][3] = 56, - [2][0][RTW89_WW][4] = 56, + [2][0][RTW89_WW][1] = 54, + [2][0][RTW89_WW][2] = 54, + [2][0][RTW89_WW][3] = 54, + [2][0][RTW89_WW][4] = 54, [2][0][RTW89_WW][5] = 56, - [2][0][RTW89_WW][6] = 56, - [2][0][RTW89_WW][7] = 56, - [2][0][RTW89_WW][8] = 56, - [2][0][RTW89_WW][9] = 56, + [2][0][RTW89_WW][6] = 48, + [2][0][RTW89_WW][7] = 48, + [2][0][RTW89_WW][8] = 48, + [2][0][RTW89_WW][9] = 48, [2][0][RTW89_WW][10] = 56, [2][0][RTW89_WW][11] = 48, [2][0][RTW89_WW][12] = 16, @@ -34059,10 +45884,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_WW][3] = 44, [2][1][RTW89_WW][4] = 44, [2][1][RTW89_WW][5] = 44, - [2][1][RTW89_WW][6] = 44, - [2][1][RTW89_WW][7] = 44, - [2][1][RTW89_WW][8] = 44, - [2][1][RTW89_WW][9] = 44, + [2][1][RTW89_WW][6] = 42, + [2][1][RTW89_WW][7] = 42, + [2][1][RTW89_WW][8] = 42, + [2][1][RTW89_WW][9] = 42, [2][1][RTW89_WW][10] = 44, [2][1][RTW89_WW][11] = 44, [2][1][RTW89_WW][12] = 6, @@ -34075,6 +45900,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][0] = 34, [0][0][RTW89_CN][0] = 32, [0][0][RTW89_UK][0] = 34, + [0][0][RTW89_MEXICO][0] = 60, + [0][0][RTW89_UKRAINE][0] = 34, + [0][0][RTW89_CHILE][0] = 60, + [0][0][RTW89_QATAR][0] = 34, [0][0][RTW89_FCC][1] = 60, [0][0][RTW89_ETSI][1] = 38, [0][0][RTW89_MKK][1] = 40, @@ -34083,6 +45912,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][1] = 38, [0][0][RTW89_CN][1] = 32, [0][0][RTW89_UK][1] = 38, + [0][0][RTW89_MEXICO][1] = 60, + [0][0][RTW89_UKRAINE][1] = 38, + [0][0][RTW89_CHILE][1] = 50, + [0][0][RTW89_QATAR][1] = 38, [0][0][RTW89_FCC][2] = 64, [0][0][RTW89_ETSI][2] = 38, [0][0][RTW89_MKK][2] = 40, @@ -34091,6 +45924,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][2] = 38, [0][0][RTW89_CN][2] = 32, [0][0][RTW89_UK][2] = 38, + [0][0][RTW89_MEXICO][2] = 64, + [0][0][RTW89_UKRAINE][2] = 38, + [0][0][RTW89_CHILE][2] = 50, + [0][0][RTW89_QATAR][2] = 38, [0][0][RTW89_FCC][3] = 68, [0][0][RTW89_ETSI][3] = 38, [0][0][RTW89_MKK][3] = 40, @@ -34099,78 +45936,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][3] = 38, [0][0][RTW89_CN][3] = 32, [0][0][RTW89_UK][3] = 38, + [0][0][RTW89_MEXICO][3] = 68, + [0][0][RTW89_UKRAINE][3] = 38, + [0][0][RTW89_CHILE][3] = 50, + [0][0][RTW89_QATAR][3] = 38, [0][0][RTW89_FCC][4] = 68, [0][0][RTW89_ETSI][4] = 38, [0][0][RTW89_MKK][4] = 40, [0][0][RTW89_IC][4] = 68, - [0][0][RTW89_KCC][4] = 42, + [0][0][RTW89_KCC][4] = 44, [0][0][RTW89_ACMA][4] = 38, [0][0][RTW89_CN][4] = 32, [0][0][RTW89_UK][4] = 38, + [0][0][RTW89_MEXICO][4] = 68, + [0][0][RTW89_UKRAINE][4] = 38, + [0][0][RTW89_CHILE][4] = 50, + [0][0][RTW89_QATAR][4] = 38, [0][0][RTW89_FCC][5] = 78, [0][0][RTW89_ETSI][5] = 38, [0][0][RTW89_MKK][5] = 40, [0][0][RTW89_IC][5] = 78, - [0][0][RTW89_KCC][5] = 42, + [0][0][RTW89_KCC][5] = 44, [0][0][RTW89_ACMA][5] = 38, [0][0][RTW89_CN][5] = 32, [0][0][RTW89_UK][5] = 38, + [0][0][RTW89_MEXICO][5] = 78, + [0][0][RTW89_UKRAINE][5] = 38, + [0][0][RTW89_CHILE][5] = 78, + [0][0][RTW89_QATAR][5] = 38, [0][0][RTW89_FCC][6] = 54, [0][0][RTW89_ETSI][6] = 38, [0][0][RTW89_MKK][6] = 40, [0][0][RTW89_IC][6] = 54, - [0][0][RTW89_KCC][6] = 42, + [0][0][RTW89_KCC][6] = 44, [0][0][RTW89_ACMA][6] = 38, [0][0][RTW89_CN][6] = 32, [0][0][RTW89_UK][6] = 38, + [0][0][RTW89_MEXICO][6] = 54, + [0][0][RTW89_UKRAINE][6] = 38, + [0][0][RTW89_CHILE][6] = 36, + [0][0][RTW89_QATAR][6] = 38, [0][0][RTW89_FCC][7] = 54, [0][0][RTW89_ETSI][7] = 38, [0][0][RTW89_MKK][7] = 40, [0][0][RTW89_IC][7] = 54, - [0][0][RTW89_KCC][7] = 42, + [0][0][RTW89_KCC][7] = 44, [0][0][RTW89_ACMA][7] = 38, [0][0][RTW89_CN][7] = 32, [0][0][RTW89_UK][7] = 38, + [0][0][RTW89_MEXICO][7] = 54, + [0][0][RTW89_UKRAINE][7] = 38, + [0][0][RTW89_CHILE][7] = 36, + [0][0][RTW89_QATAR][7] = 38, [0][0][RTW89_FCC][8] = 50, [0][0][RTW89_ETSI][8] = 38, [0][0][RTW89_MKK][8] = 40, [0][0][RTW89_IC][8] = 50, - [0][0][RTW89_KCC][8] = 42, + [0][0][RTW89_KCC][8] = 44, [0][0][RTW89_ACMA][8] = 38, [0][0][RTW89_CN][8] = 32, [0][0][RTW89_UK][8] = 38, + [0][0][RTW89_MEXICO][8] = 50, + [0][0][RTW89_UKRAINE][8] = 38, + [0][0][RTW89_CHILE][8] = 36, + [0][0][RTW89_QATAR][8] = 38, [0][0][RTW89_FCC][9] = 46, [0][0][RTW89_ETSI][9] = 38, [0][0][RTW89_MKK][9] = 40, [0][0][RTW89_IC][9] = 46, - [0][0][RTW89_KCC][9] = 40, + [0][0][RTW89_KCC][9] = 42, [0][0][RTW89_ACMA][9] = 38, [0][0][RTW89_CN][9] = 32, [0][0][RTW89_UK][9] = 38, + [0][0][RTW89_MEXICO][9] = 46, + [0][0][RTW89_UKRAINE][9] = 38, + [0][0][RTW89_CHILE][9] = 36, + [0][0][RTW89_QATAR][9] = 38, [0][0][RTW89_FCC][10] = 46, [0][0][RTW89_ETSI][10] = 38, [0][0][RTW89_MKK][10] = 40, [0][0][RTW89_IC][10] = 46, - [0][0][RTW89_KCC][10] = 40, + [0][0][RTW89_KCC][10] = 42, [0][0][RTW89_ACMA][10] = 38, [0][0][RTW89_CN][10] = 32, [0][0][RTW89_UK][10] = 38, + [0][0][RTW89_MEXICO][10] = 46, + [0][0][RTW89_UKRAINE][10] = 38, + [0][0][RTW89_CHILE][10] = 46, + [0][0][RTW89_QATAR][10] = 38, [0][0][RTW89_FCC][11] = 26, [0][0][RTW89_ETSI][11] = 38, [0][0][RTW89_MKK][11] = 40, [0][0][RTW89_IC][11] = 26, - [0][0][RTW89_KCC][11] = 40, + [0][0][RTW89_KCC][11] = 42, [0][0][RTW89_ACMA][11] = 38, [0][0][RTW89_CN][11] = 32, [0][0][RTW89_UK][11] = 38, + [0][0][RTW89_MEXICO][11] = 26, + [0][0][RTW89_UKRAINE][11] = 38, + [0][0][RTW89_CHILE][11] = 26, + [0][0][RTW89_QATAR][11] = 38, [0][0][RTW89_FCC][12] = -20, [0][0][RTW89_ETSI][12] = 34, [0][0][RTW89_MKK][12] = 36, [0][0][RTW89_IC][12] = -20, - [0][0][RTW89_KCC][12] = 40, + [0][0][RTW89_KCC][12] = 42, [0][0][RTW89_ACMA][12] = 34, [0][0][RTW89_CN][12] = 32, [0][0][RTW89_UK][12] = 34, + [0][0][RTW89_MEXICO][12] = -20, + [0][0][RTW89_UKRAINE][12] = 34, + [0][0][RTW89_CHILE][12] = -20, + [0][0][RTW89_QATAR][12] = 34, [0][0][RTW89_FCC][13] = 127, [0][0][RTW89_ETSI][13] = 127, [0][0][RTW89_MKK][13] = 127, @@ -34179,6 +46056,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][13] = 127, [0][0][RTW89_CN][13] = 127, [0][0][RTW89_UK][13] = 127, + [0][0][RTW89_MEXICO][13] = 127, + [0][0][RTW89_UKRAINE][13] = 127, + [0][0][RTW89_CHILE][13] = 127, + [0][0][RTW89_QATAR][13] = 127, [0][1][RTW89_FCC][0] = 56, [0][1][RTW89_ETSI][0] = 22, [0][1][RTW89_MKK][0] = 24, @@ -34187,6 +46068,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][0] = 22, [0][1][RTW89_CN][0] = 20, [0][1][RTW89_UK][0] = 22, + [0][1][RTW89_MEXICO][0] = 56, + [0][1][RTW89_UKRAINE][0] = 22, + [0][1][RTW89_CHILE][0] = 56, + [0][1][RTW89_QATAR][0] = 22, [0][1][RTW89_FCC][1] = 56, [0][1][RTW89_ETSI][1] = 24, [0][1][RTW89_MKK][1] = 30, @@ -34195,6 +46080,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][1] = 24, [0][1][RTW89_CN][1] = 22, [0][1][RTW89_UK][1] = 24, + [0][1][RTW89_MEXICO][1] = 56, + [0][1][RTW89_UKRAINE][1] = 24, + [0][1][RTW89_CHILE][1] = 40, + [0][1][RTW89_QATAR][1] = 24, [0][1][RTW89_FCC][2] = 60, [0][1][RTW89_ETSI][2] = 24, [0][1][RTW89_MKK][2] = 30, @@ -34203,6 +46092,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][2] = 24, [0][1][RTW89_CN][2] = 22, [0][1][RTW89_UK][2] = 24, + [0][1][RTW89_MEXICO][2] = 60, + [0][1][RTW89_UKRAINE][2] = 24, + [0][1][RTW89_CHILE][2] = 40, + [0][1][RTW89_QATAR][2] = 24, [0][1][RTW89_FCC][3] = 64, [0][1][RTW89_ETSI][3] = 24, [0][1][RTW89_MKK][3] = 30, @@ -34211,78 +46104,118 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][3] = 24, [0][1][RTW89_CN][3] = 22, [0][1][RTW89_UK][3] = 24, + [0][1][RTW89_MEXICO][3] = 64, + [0][1][RTW89_UKRAINE][3] = 24, + [0][1][RTW89_CHILE][3] = 40, + [0][1][RTW89_QATAR][3] = 24, [0][1][RTW89_FCC][4] = 68, [0][1][RTW89_ETSI][4] = 24, [0][1][RTW89_MKK][4] = 30, [0][1][RTW89_IC][4] = 68, - [0][1][RTW89_KCC][4] = 28, + [0][1][RTW89_KCC][4] = 34, [0][1][RTW89_ACMA][4] = 24, [0][1][RTW89_CN][4] = 22, [0][1][RTW89_UK][4] = 24, + [0][1][RTW89_MEXICO][4] = 68, + [0][1][RTW89_UKRAINE][4] = 24, + [0][1][RTW89_CHILE][4] = 40, + [0][1][RTW89_QATAR][4] = 24, [0][1][RTW89_FCC][5] = 76, [0][1][RTW89_ETSI][5] = 24, [0][1][RTW89_MKK][5] = 30, [0][1][RTW89_IC][5] = 76, - [0][1][RTW89_KCC][5] = 28, + [0][1][RTW89_KCC][5] = 34, [0][1][RTW89_ACMA][5] = 24, [0][1][RTW89_CN][5] = 22, [0][1][RTW89_UK][5] = 24, + [0][1][RTW89_MEXICO][5] = 76, + [0][1][RTW89_UKRAINE][5] = 24, + [0][1][RTW89_CHILE][5] = 76, + [0][1][RTW89_QATAR][5] = 24, [0][1][RTW89_FCC][6] = 54, [0][1][RTW89_ETSI][6] = 24, [0][1][RTW89_MKK][6] = 30, [0][1][RTW89_IC][6] = 54, - [0][1][RTW89_KCC][6] = 28, + [0][1][RTW89_KCC][6] = 34, [0][1][RTW89_ACMA][6] = 24, [0][1][RTW89_CN][6] = 22, [0][1][RTW89_UK][6] = 24, + [0][1][RTW89_MEXICO][6] = 54, + [0][1][RTW89_UKRAINE][6] = 24, + [0][1][RTW89_CHILE][6] = 26, + [0][1][RTW89_QATAR][6] = 24, [0][1][RTW89_FCC][7] = 50, [0][1][RTW89_ETSI][7] = 24, [0][1][RTW89_MKK][7] = 30, [0][1][RTW89_IC][7] = 50, - [0][1][RTW89_KCC][7] = 28, + [0][1][RTW89_KCC][7] = 34, [0][1][RTW89_ACMA][7] = 24, [0][1][RTW89_CN][7] = 22, [0][1][RTW89_UK][7] = 24, + [0][1][RTW89_MEXICO][7] = 50, + [0][1][RTW89_UKRAINE][7] = 24, + [0][1][RTW89_CHILE][7] = 26, + [0][1][RTW89_QATAR][7] = 24, [0][1][RTW89_FCC][8] = 46, [0][1][RTW89_ETSI][8] = 24, [0][1][RTW89_MKK][8] = 30, [0][1][RTW89_IC][8] = 46, - [0][1][RTW89_KCC][8] = 28, + [0][1][RTW89_KCC][8] = 34, [0][1][RTW89_ACMA][8] = 24, [0][1][RTW89_CN][8] = 22, [0][1][RTW89_UK][8] = 24, + [0][1][RTW89_MEXICO][8] = 46, + [0][1][RTW89_UKRAINE][8] = 24, + [0][1][RTW89_CHILE][8] = 26, + [0][1][RTW89_QATAR][8] = 24, [0][1][RTW89_FCC][9] = 42, [0][1][RTW89_ETSI][9] = 24, [0][1][RTW89_MKK][9] = 30, [0][1][RTW89_IC][9] = 42, - [0][1][RTW89_KCC][9] = 28, + [0][1][RTW89_KCC][9] = 32, [0][1][RTW89_ACMA][9] = 24, [0][1][RTW89_CN][9] = 22, [0][1][RTW89_UK][9] = 24, + [0][1][RTW89_MEXICO][9] = 42, + [0][1][RTW89_UKRAINE][9] = 24, + [0][1][RTW89_CHILE][9] = 26, + [0][1][RTW89_QATAR][9] = 24, [0][1][RTW89_FCC][10] = 42, [0][1][RTW89_ETSI][10] = 24, [0][1][RTW89_MKK][10] = 30, [0][1][RTW89_IC][10] = 42, - [0][1][RTW89_KCC][10] = 28, + [0][1][RTW89_KCC][10] = 32, [0][1][RTW89_ACMA][10] = 24, [0][1][RTW89_CN][10] = 22, [0][1][RTW89_UK][10] = 24, + [0][1][RTW89_MEXICO][10] = 42, + [0][1][RTW89_UKRAINE][10] = 24, + [0][1][RTW89_CHILE][10] = 42, + [0][1][RTW89_QATAR][10] = 24, [0][1][RTW89_FCC][11] = 22, [0][1][RTW89_ETSI][11] = 24, [0][1][RTW89_MKK][11] = 30, [0][1][RTW89_IC][11] = 22, - [0][1][RTW89_KCC][11] = 28, + [0][1][RTW89_KCC][11] = 32, [0][1][RTW89_ACMA][11] = 24, [0][1][RTW89_CN][11] = 22, [0][1][RTW89_UK][11] = 24, + [0][1][RTW89_MEXICO][11] = 22, + [0][1][RTW89_UKRAINE][11] = 24, + [0][1][RTW89_CHILE][11] = 22, + [0][1][RTW89_QATAR][11] = 24, [0][1][RTW89_FCC][12] = -30, [0][1][RTW89_ETSI][12] = 20, [0][1][RTW89_MKK][12] = 24, [0][1][RTW89_IC][12] = -30, - [0][1][RTW89_KCC][12] = 28, + [0][1][RTW89_KCC][12] = 32, [0][1][RTW89_ACMA][12] = 20, [0][1][RTW89_CN][12] = 20, [0][1][RTW89_UK][12] = 20, + [0][1][RTW89_MEXICO][12] = -30, + [0][1][RTW89_UKRAINE][12] = 20, + [0][1][RTW89_CHILE][12] = -30, + [0][1][RTW89_QATAR][12] = 20, [0][1][RTW89_FCC][13] = 127, [0][1][RTW89_ETSI][13] = 127, [0][1][RTW89_MKK][13] = 127, @@ -34291,110 +46224,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][13] = 127, [0][1][RTW89_CN][13] = 127, [0][1][RTW89_UK][13] = 127, + [0][1][RTW89_MEXICO][13] = 127, + [0][1][RTW89_UKRAINE][13] = 127, + [0][1][RTW89_CHILE][13] = 127, + [0][1][RTW89_QATAR][13] = 127, [1][0][RTW89_FCC][0] = 66, [1][0][RTW89_ETSI][0] = 46, [1][0][RTW89_MKK][0] = 48, [1][0][RTW89_IC][0] = 66, - [1][0][RTW89_KCC][0] = 50, + [1][0][RTW89_KCC][0] = 54, [1][0][RTW89_ACMA][0] = 46, [1][0][RTW89_CN][0] = 42, [1][0][RTW89_UK][0] = 46, + [1][0][RTW89_MEXICO][0] = 66, + [1][0][RTW89_UKRAINE][0] = 46, + [1][0][RTW89_CHILE][0] = 66, + [1][0][RTW89_QATAR][0] = 46, [1][0][RTW89_FCC][1] = 66, [1][0][RTW89_ETSI][1] = 46, [1][0][RTW89_MKK][1] = 48, [1][0][RTW89_IC][1] = 66, - [1][0][RTW89_KCC][1] = 50, + [1][0][RTW89_KCC][1] = 54, [1][0][RTW89_ACMA][1] = 46, [1][0][RTW89_CN][1] = 44, [1][0][RTW89_UK][1] = 46, + [1][0][RTW89_MEXICO][1] = 66, + [1][0][RTW89_UKRAINE][1] = 46, + [1][0][RTW89_CHILE][1] = 54, + [1][0][RTW89_QATAR][1] = 46, [1][0][RTW89_FCC][2] = 70, [1][0][RTW89_ETSI][2] = 46, [1][0][RTW89_MKK][2] = 48, [1][0][RTW89_IC][2] = 70, - [1][0][RTW89_KCC][2] = 50, + [1][0][RTW89_KCC][2] = 54, [1][0][RTW89_ACMA][2] = 46, [1][0][RTW89_CN][2] = 44, [1][0][RTW89_UK][2] = 46, + [1][0][RTW89_MEXICO][2] = 70, + [1][0][RTW89_UKRAINE][2] = 46, + [1][0][RTW89_CHILE][2] = 54, + [1][0][RTW89_QATAR][2] = 46, [1][0][RTW89_FCC][3] = 72, [1][0][RTW89_ETSI][3] = 46, [1][0][RTW89_MKK][3] = 48, [1][0][RTW89_IC][3] = 72, - [1][0][RTW89_KCC][3] = 50, + [1][0][RTW89_KCC][3] = 54, [1][0][RTW89_ACMA][3] = 46, [1][0][RTW89_CN][3] = 44, [1][0][RTW89_UK][3] = 46, + [1][0][RTW89_MEXICO][3] = 72, + [1][0][RTW89_UKRAINE][3] = 46, + [1][0][RTW89_CHILE][3] = 54, + [1][0][RTW89_QATAR][3] = 46, [1][0][RTW89_FCC][4] = 72, [1][0][RTW89_ETSI][4] = 46, [1][0][RTW89_MKK][4] = 48, [1][0][RTW89_IC][4] = 72, - [1][0][RTW89_KCC][4] = 50, + [1][0][RTW89_KCC][4] = 56, [1][0][RTW89_ACMA][4] = 46, [1][0][RTW89_CN][4] = 44, [1][0][RTW89_UK][4] = 46, + [1][0][RTW89_MEXICO][4] = 72, + [1][0][RTW89_UKRAINE][4] = 46, + [1][0][RTW89_CHILE][4] = 54, + [1][0][RTW89_QATAR][4] = 46, [1][0][RTW89_FCC][5] = 82, [1][0][RTW89_ETSI][5] = 46, [1][0][RTW89_MKK][5] = 48, [1][0][RTW89_IC][5] = 82, - [1][0][RTW89_KCC][5] = 50, + [1][0][RTW89_KCC][5] = 56, [1][0][RTW89_ACMA][5] = 46, [1][0][RTW89_CN][5] = 44, [1][0][RTW89_UK][5] = 46, + [1][0][RTW89_MEXICO][5] = 82, + [1][0][RTW89_UKRAINE][5] = 46, + [1][0][RTW89_CHILE][5] = 82, + [1][0][RTW89_QATAR][5] = 46, [1][0][RTW89_FCC][6] = 58, [1][0][RTW89_ETSI][6] = 44, [1][0][RTW89_MKK][6] = 48, [1][0][RTW89_IC][6] = 58, - [1][0][RTW89_KCC][6] = 50, + [1][0][RTW89_KCC][6] = 56, [1][0][RTW89_ACMA][6] = 44, [1][0][RTW89_CN][6] = 44, [1][0][RTW89_UK][6] = 44, + [1][0][RTW89_MEXICO][6] = 58, + [1][0][RTW89_UKRAINE][6] = 44, + [1][0][RTW89_CHILE][6] = 40, + [1][0][RTW89_QATAR][6] = 44, [1][0][RTW89_FCC][7] = 58, [1][0][RTW89_ETSI][7] = 46, [1][0][RTW89_MKK][7] = 48, [1][0][RTW89_IC][7] = 58, - [1][0][RTW89_KCC][7] = 50, + [1][0][RTW89_KCC][7] = 56, [1][0][RTW89_ACMA][7] = 46, [1][0][RTW89_CN][7] = 44, [1][0][RTW89_UK][7] = 46, + [1][0][RTW89_MEXICO][7] = 58, + [1][0][RTW89_UKRAINE][7] = 46, + [1][0][RTW89_CHILE][7] = 40, + [1][0][RTW89_QATAR][7] = 46, [1][0][RTW89_FCC][8] = 58, [1][0][RTW89_ETSI][8] = 46, [1][0][RTW89_MKK][8] = 48, [1][0][RTW89_IC][8] = 58, - [1][0][RTW89_KCC][8] = 50, + [1][0][RTW89_KCC][8] = 56, [1][0][RTW89_ACMA][8] = 46, [1][0][RTW89_CN][8] = 44, [1][0][RTW89_UK][8] = 46, + [1][0][RTW89_MEXICO][8] = 58, + [1][0][RTW89_UKRAINE][8] = 46, + [1][0][RTW89_CHILE][8] = 40, + [1][0][RTW89_QATAR][8] = 46, [1][0][RTW89_FCC][9] = 54, [1][0][RTW89_ETSI][9] = 46, [1][0][RTW89_MKK][9] = 48, [1][0][RTW89_IC][9] = 54, - [1][0][RTW89_KCC][9] = 50, + [1][0][RTW89_KCC][9] = 56, [1][0][RTW89_ACMA][9] = 46, [1][0][RTW89_CN][9] = 44, [1][0][RTW89_UK][9] = 46, + [1][0][RTW89_MEXICO][9] = 54, + [1][0][RTW89_UKRAINE][9] = 46, + [1][0][RTW89_CHILE][9] = 40, + [1][0][RTW89_QATAR][9] = 46, [1][0][RTW89_FCC][10] = 54, [1][0][RTW89_ETSI][10] = 46, [1][0][RTW89_MKK][10] = 48, [1][0][RTW89_IC][10] = 54, - [1][0][RTW89_KCC][10] = 50, + [1][0][RTW89_KCC][10] = 56, [1][0][RTW89_ACMA][10] = 46, [1][0][RTW89_CN][10] = 44, [1][0][RTW89_UK][10] = 46, + [1][0][RTW89_MEXICO][10] = 54, + [1][0][RTW89_UKRAINE][10] = 46, + [1][0][RTW89_CHILE][10] = 54, + [1][0][RTW89_QATAR][10] = 46, [1][0][RTW89_FCC][11] = 36, [1][0][RTW89_ETSI][11] = 46, [1][0][RTW89_MKK][11] = 48, [1][0][RTW89_IC][11] = 36, - [1][0][RTW89_KCC][11] = 50, + [1][0][RTW89_KCC][11] = 56, [1][0][RTW89_ACMA][11] = 46, [1][0][RTW89_CN][11] = 44, [1][0][RTW89_UK][11] = 46, + [1][0][RTW89_MEXICO][11] = 36, + [1][0][RTW89_UKRAINE][11] = 46, + [1][0][RTW89_CHILE][11] = 36, + [1][0][RTW89_QATAR][11] = 46, [1][0][RTW89_FCC][12] = 4, [1][0][RTW89_ETSI][12] = 46, [1][0][RTW89_MKK][12] = 46, [1][0][RTW89_IC][12] = 4, - [1][0][RTW89_KCC][12] = 50, + [1][0][RTW89_KCC][12] = 56, [1][0][RTW89_ACMA][12] = 46, [1][0][RTW89_CN][12] = 42, [1][0][RTW89_UK][12] = 46, + [1][0][RTW89_MEXICO][12] = 4, + [1][0][RTW89_UKRAINE][12] = 46, + [1][0][RTW89_CHILE][12] = 4, + [1][0][RTW89_QATAR][12] = 46, [1][0][RTW89_FCC][13] = 127, [1][0][RTW89_ETSI][13] = 127, [1][0][RTW89_MKK][13] = 127, @@ -34403,110 +46392,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][13] = 127, [1][0][RTW89_CN][13] = 127, [1][0][RTW89_UK][13] = 127, + [1][0][RTW89_MEXICO][13] = 127, + [1][0][RTW89_UKRAINE][13] = 127, + [1][0][RTW89_CHILE][13] = 127, + [1][0][RTW89_QATAR][13] = 127, [1][1][RTW89_FCC][0] = 58, [1][1][RTW89_ETSI][0] = 32, [1][1][RTW89_MKK][0] = 34, [1][1][RTW89_IC][0] = 58, - [1][1][RTW89_KCC][0] = 38, + [1][1][RTW89_KCC][0] = 42, [1][1][RTW89_ACMA][0] = 32, [1][1][RTW89_CN][0] = 32, [1][1][RTW89_UK][0] = 32, + [1][1][RTW89_MEXICO][0] = 58, + [1][1][RTW89_UKRAINE][0] = 32, + [1][1][RTW89_CHILE][0] = 58, + [1][1][RTW89_QATAR][0] = 32, [1][1][RTW89_FCC][1] = 58, [1][1][RTW89_ETSI][1] = 34, [1][1][RTW89_MKK][1] = 34, [1][1][RTW89_IC][1] = 58, - [1][1][RTW89_KCC][1] = 38, + [1][1][RTW89_KCC][1] = 42, [1][1][RTW89_ACMA][1] = 34, [1][1][RTW89_CN][1] = 32, [1][1][RTW89_UK][1] = 34, + [1][1][RTW89_MEXICO][1] = 58, + [1][1][RTW89_UKRAINE][1] = 34, + [1][1][RTW89_CHILE][1] = 40, + [1][1][RTW89_QATAR][1] = 34, [1][1][RTW89_FCC][2] = 62, [1][1][RTW89_ETSI][2] = 34, [1][1][RTW89_MKK][2] = 34, [1][1][RTW89_IC][2] = 62, - [1][1][RTW89_KCC][2] = 38, + [1][1][RTW89_KCC][2] = 42, [1][1][RTW89_ACMA][2] = 34, [1][1][RTW89_CN][2] = 32, [1][1][RTW89_UK][2] = 34, + [1][1][RTW89_MEXICO][2] = 62, + [1][1][RTW89_UKRAINE][2] = 34, + [1][1][RTW89_CHILE][2] = 40, + [1][1][RTW89_QATAR][2] = 34, [1][1][RTW89_FCC][3] = 66, [1][1][RTW89_ETSI][3] = 34, [1][1][RTW89_MKK][3] = 34, [1][1][RTW89_IC][3] = 66, - [1][1][RTW89_KCC][3] = 38, + [1][1][RTW89_KCC][3] = 42, [1][1][RTW89_ACMA][3] = 34, [1][1][RTW89_CN][3] = 32, [1][1][RTW89_UK][3] = 34, + [1][1][RTW89_MEXICO][3] = 66, + [1][1][RTW89_UKRAINE][3] = 34, + [1][1][RTW89_CHILE][3] = 40, + [1][1][RTW89_QATAR][3] = 34, [1][1][RTW89_FCC][4] = 70, [1][1][RTW89_ETSI][4] = 34, [1][1][RTW89_MKK][4] = 34, [1][1][RTW89_IC][4] = 70, - [1][1][RTW89_KCC][4] = 38, + [1][1][RTW89_KCC][4] = 44, [1][1][RTW89_ACMA][4] = 34, [1][1][RTW89_CN][4] = 32, [1][1][RTW89_UK][4] = 34, + [1][1][RTW89_MEXICO][4] = 70, + [1][1][RTW89_UKRAINE][4] = 34, + [1][1][RTW89_CHILE][4] = 40, + [1][1][RTW89_QATAR][4] = 34, [1][1][RTW89_FCC][5] = 82, [1][1][RTW89_ETSI][5] = 34, [1][1][RTW89_MKK][5] = 34, [1][1][RTW89_IC][5] = 82, - [1][1][RTW89_KCC][5] = 38, + [1][1][RTW89_KCC][5] = 44, [1][1][RTW89_ACMA][5] = 34, [1][1][RTW89_CN][5] = 32, [1][1][RTW89_UK][5] = 34, + [1][1][RTW89_MEXICO][5] = 82, + [1][1][RTW89_UKRAINE][5] = 34, + [1][1][RTW89_CHILE][5] = 78, + [1][1][RTW89_QATAR][5] = 34, [1][1][RTW89_FCC][6] = 60, [1][1][RTW89_ETSI][6] = 34, [1][1][RTW89_MKK][6] = 34, [1][1][RTW89_IC][6] = 60, - [1][1][RTW89_KCC][6] = 38, + [1][1][RTW89_KCC][6] = 44, [1][1][RTW89_ACMA][6] = 34, [1][1][RTW89_CN][6] = 32, [1][1][RTW89_UK][6] = 34, + [1][1][RTW89_MEXICO][6] = 60, + [1][1][RTW89_UKRAINE][6] = 34, + [1][1][RTW89_CHILE][6] = 30, + [1][1][RTW89_QATAR][6] = 34, [1][1][RTW89_FCC][7] = 56, [1][1][RTW89_ETSI][7] = 34, [1][1][RTW89_MKK][7] = 34, [1][1][RTW89_IC][7] = 56, - [1][1][RTW89_KCC][7] = 38, + [1][1][RTW89_KCC][7] = 44, [1][1][RTW89_ACMA][7] = 34, [1][1][RTW89_CN][7] = 32, [1][1][RTW89_UK][7] = 34, + [1][1][RTW89_MEXICO][7] = 56, + [1][1][RTW89_UKRAINE][7] = 34, + [1][1][RTW89_CHILE][7] = 30, + [1][1][RTW89_QATAR][7] = 34, [1][1][RTW89_FCC][8] = 52, [1][1][RTW89_ETSI][8] = 34, [1][1][RTW89_MKK][8] = 34, [1][1][RTW89_IC][8] = 52, - [1][1][RTW89_KCC][8] = 38, + [1][1][RTW89_KCC][8] = 44, [1][1][RTW89_ACMA][8] = 34, [1][1][RTW89_CN][8] = 32, [1][1][RTW89_UK][8] = 34, + [1][1][RTW89_MEXICO][8] = 52, + [1][1][RTW89_UKRAINE][8] = 34, + [1][1][RTW89_CHILE][8] = 30, + [1][1][RTW89_QATAR][8] = 34, [1][1][RTW89_FCC][9] = 48, [1][1][RTW89_ETSI][9] = 34, [1][1][RTW89_MKK][9] = 34, [1][1][RTW89_IC][9] = 48, - [1][1][RTW89_KCC][9] = 38, + [1][1][RTW89_KCC][9] = 44, [1][1][RTW89_ACMA][9] = 34, [1][1][RTW89_CN][9] = 32, [1][1][RTW89_UK][9] = 34, + [1][1][RTW89_MEXICO][9] = 48, + [1][1][RTW89_UKRAINE][9] = 34, + [1][1][RTW89_CHILE][9] = 30, + [1][1][RTW89_QATAR][9] = 34, [1][1][RTW89_FCC][10] = 48, [1][1][RTW89_ETSI][10] = 34, [1][1][RTW89_MKK][10] = 34, [1][1][RTW89_IC][10] = 48, - [1][1][RTW89_KCC][10] = 38, + [1][1][RTW89_KCC][10] = 44, [1][1][RTW89_ACMA][10] = 34, [1][1][RTW89_CN][10] = 32, [1][1][RTW89_UK][10] = 34, + [1][1][RTW89_MEXICO][10] = 48, + [1][1][RTW89_UKRAINE][10] = 34, + [1][1][RTW89_CHILE][10] = 48, + [1][1][RTW89_QATAR][10] = 34, [1][1][RTW89_FCC][11] = 30, [1][1][RTW89_ETSI][11] = 34, [1][1][RTW89_MKK][11] = 34, [1][1][RTW89_IC][11] = 30, - [1][1][RTW89_KCC][11] = 38, + [1][1][RTW89_KCC][11] = 44, [1][1][RTW89_ACMA][11] = 34, [1][1][RTW89_CN][11] = 32, [1][1][RTW89_UK][11] = 34, + [1][1][RTW89_MEXICO][11] = 30, + [1][1][RTW89_UKRAINE][11] = 34, + [1][1][RTW89_CHILE][11] = 30, + [1][1][RTW89_QATAR][11] = 34, [1][1][RTW89_FCC][12] = -6, [1][1][RTW89_ETSI][12] = 34, [1][1][RTW89_MKK][12] = 34, [1][1][RTW89_IC][12] = -6, - [1][1][RTW89_KCC][12] = 38, + [1][1][RTW89_KCC][12] = 44, [1][1][RTW89_ACMA][12] = 34, [1][1][RTW89_CN][12] = 32, [1][1][RTW89_UK][12] = 34, + [1][1][RTW89_MEXICO][12] = -6, + [1][1][RTW89_UKRAINE][12] = 34, + [1][1][RTW89_CHILE][12] = -6, + [1][1][RTW89_QATAR][12] = 34, [1][1][RTW89_FCC][13] = 127, [1][1][RTW89_ETSI][13] = 127, [1][1][RTW89_MKK][13] = 127, @@ -34515,110 +46560,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][13] = 127, [1][1][RTW89_CN][13] = 127, [1][1][RTW89_UK][13] = 127, + [1][1][RTW89_MEXICO][13] = 127, + [1][1][RTW89_UKRAINE][13] = 127, + [1][1][RTW89_CHILE][13] = 127, + [1][1][RTW89_QATAR][13] = 127, [2][0][RTW89_FCC][0] = 70, [2][0][RTW89_ETSI][0] = 58, [2][0][RTW89_MKK][0] = 58, [2][0][RTW89_IC][0] = 70, - [2][0][RTW89_KCC][0] = 64, + [2][0][RTW89_KCC][0] = 60, [2][0][RTW89_ACMA][0] = 58, [2][0][RTW89_CN][0] = 56, [2][0][RTW89_UK][0] = 58, + [2][0][RTW89_MEXICO][0] = 70, + [2][0][RTW89_UKRAINE][0] = 58, + [2][0][RTW89_CHILE][0] = 70, + [2][0][RTW89_QATAR][0] = 58, [2][0][RTW89_FCC][1] = 70, [2][0][RTW89_ETSI][1] = 58, [2][0][RTW89_MKK][1] = 58, [2][0][RTW89_IC][1] = 70, - [2][0][RTW89_KCC][1] = 64, + [2][0][RTW89_KCC][1] = 60, [2][0][RTW89_ACMA][1] = 58, [2][0][RTW89_CN][1] = 56, [2][0][RTW89_UK][1] = 58, + [2][0][RTW89_MEXICO][1] = 70, + [2][0][RTW89_UKRAINE][1] = 58, + [2][0][RTW89_CHILE][1] = 54, + [2][0][RTW89_QATAR][1] = 58, [2][0][RTW89_FCC][2] = 72, [2][0][RTW89_ETSI][2] = 58, [2][0][RTW89_MKK][2] = 58, [2][0][RTW89_IC][2] = 72, - [2][0][RTW89_KCC][2] = 64, + [2][0][RTW89_KCC][2] = 60, [2][0][RTW89_ACMA][2] = 58, [2][0][RTW89_CN][2] = 56, [2][0][RTW89_UK][2] = 58, + [2][0][RTW89_MEXICO][2] = 72, + [2][0][RTW89_UKRAINE][2] = 58, + [2][0][RTW89_CHILE][2] = 54, + [2][0][RTW89_QATAR][2] = 58, [2][0][RTW89_FCC][3] = 72, [2][0][RTW89_ETSI][3] = 58, [2][0][RTW89_MKK][3] = 58, [2][0][RTW89_IC][3] = 72, - [2][0][RTW89_KCC][3] = 64, + [2][0][RTW89_KCC][3] = 60, [2][0][RTW89_ACMA][3] = 58, [2][0][RTW89_CN][3] = 56, [2][0][RTW89_UK][3] = 58, + [2][0][RTW89_MEXICO][3] = 72, + [2][0][RTW89_UKRAINE][3] = 58, + [2][0][RTW89_CHILE][3] = 54, + [2][0][RTW89_QATAR][3] = 58, [2][0][RTW89_FCC][4] = 72, [2][0][RTW89_ETSI][4] = 58, [2][0][RTW89_MKK][4] = 58, [2][0][RTW89_IC][4] = 72, - [2][0][RTW89_KCC][4] = 64, + [2][0][RTW89_KCC][4] = 60, [2][0][RTW89_ACMA][4] = 58, [2][0][RTW89_CN][4] = 56, [2][0][RTW89_UK][4] = 58, + [2][0][RTW89_MEXICO][4] = 72, + [2][0][RTW89_UKRAINE][4] = 58, + [2][0][RTW89_CHILE][4] = 54, + [2][0][RTW89_QATAR][4] = 58, [2][0][RTW89_FCC][5] = 82, [2][0][RTW89_ETSI][5] = 58, [2][0][RTW89_MKK][5] = 58, [2][0][RTW89_IC][5] = 82, - [2][0][RTW89_KCC][5] = 64, + [2][0][RTW89_KCC][5] = 60, [2][0][RTW89_ACMA][5] = 58, [2][0][RTW89_CN][5] = 56, [2][0][RTW89_UK][5] = 58, + [2][0][RTW89_MEXICO][5] = 82, + [2][0][RTW89_UKRAINE][5] = 58, + [2][0][RTW89_CHILE][5] = 82, + [2][0][RTW89_QATAR][5] = 58, [2][0][RTW89_FCC][6] = 66, [2][0][RTW89_ETSI][6] = 56, [2][0][RTW89_MKK][6] = 58, [2][0][RTW89_IC][6] = 66, - [2][0][RTW89_KCC][6] = 64, + [2][0][RTW89_KCC][6] = 60, [2][0][RTW89_ACMA][6] = 56, [2][0][RTW89_CN][6] = 56, [2][0][RTW89_UK][6] = 56, + [2][0][RTW89_MEXICO][6] = 66, + [2][0][RTW89_UKRAINE][6] = 56, + [2][0][RTW89_CHILE][6] = 48, + [2][0][RTW89_QATAR][6] = 56, [2][0][RTW89_FCC][7] = 66, [2][0][RTW89_ETSI][7] = 58, [2][0][RTW89_MKK][7] = 58, [2][0][RTW89_IC][7] = 66, - [2][0][RTW89_KCC][7] = 64, + [2][0][RTW89_KCC][7] = 60, [2][0][RTW89_ACMA][7] = 58, [2][0][RTW89_CN][7] = 56, [2][0][RTW89_UK][7] = 58, + [2][0][RTW89_MEXICO][7] = 66, + [2][0][RTW89_UKRAINE][7] = 58, + [2][0][RTW89_CHILE][7] = 48, + [2][0][RTW89_QATAR][7] = 58, [2][0][RTW89_FCC][8] = 66, [2][0][RTW89_ETSI][8] = 58, [2][0][RTW89_MKK][8] = 58, [2][0][RTW89_IC][8] = 66, - [2][0][RTW89_KCC][8] = 64, + [2][0][RTW89_KCC][8] = 60, [2][0][RTW89_ACMA][8] = 58, [2][0][RTW89_CN][8] = 56, [2][0][RTW89_UK][8] = 58, + [2][0][RTW89_MEXICO][8] = 66, + [2][0][RTW89_UKRAINE][8] = 58, + [2][0][RTW89_CHILE][8] = 48, + [2][0][RTW89_QATAR][8] = 58, [2][0][RTW89_FCC][9] = 64, [2][0][RTW89_ETSI][9] = 58, [2][0][RTW89_MKK][9] = 58, [2][0][RTW89_IC][9] = 64, - [2][0][RTW89_KCC][9] = 64, + [2][0][RTW89_KCC][9] = 60, [2][0][RTW89_ACMA][9] = 58, [2][0][RTW89_CN][9] = 56, [2][0][RTW89_UK][9] = 58, + [2][0][RTW89_MEXICO][9] = 64, + [2][0][RTW89_UKRAINE][9] = 58, + [2][0][RTW89_CHILE][9] = 48, + [2][0][RTW89_QATAR][9] = 58, [2][0][RTW89_FCC][10] = 64, [2][0][RTW89_ETSI][10] = 58, [2][0][RTW89_MKK][10] = 58, [2][0][RTW89_IC][10] = 64, - [2][0][RTW89_KCC][10] = 64, + [2][0][RTW89_KCC][10] = 60, [2][0][RTW89_ACMA][10] = 58, [2][0][RTW89_CN][10] = 56, [2][0][RTW89_UK][10] = 58, + [2][0][RTW89_MEXICO][10] = 64, + [2][0][RTW89_UKRAINE][10] = 58, + [2][0][RTW89_CHILE][10] = 64, + [2][0][RTW89_QATAR][10] = 58, [2][0][RTW89_FCC][11] = 48, [2][0][RTW89_ETSI][11] = 58, [2][0][RTW89_MKK][11] = 58, [2][0][RTW89_IC][11] = 48, - [2][0][RTW89_KCC][11] = 64, + [2][0][RTW89_KCC][11] = 60, [2][0][RTW89_ACMA][11] = 58, [2][0][RTW89_CN][11] = 56, [2][0][RTW89_UK][11] = 58, + [2][0][RTW89_MEXICO][11] = 48, + [2][0][RTW89_UKRAINE][11] = 58, + [2][0][RTW89_CHILE][11] = 48, + [2][0][RTW89_QATAR][11] = 58, [2][0][RTW89_FCC][12] = 16, [2][0][RTW89_ETSI][12] = 58, [2][0][RTW89_MKK][12] = 58, [2][0][RTW89_IC][12] = 16, - [2][0][RTW89_KCC][12] = 64, + [2][0][RTW89_KCC][12] = 60, [2][0][RTW89_ACMA][12] = 58, [2][0][RTW89_CN][12] = 56, [2][0][RTW89_UK][12] = 58, + [2][0][RTW89_MEXICO][12] = 16, + [2][0][RTW89_UKRAINE][12] = 58, + [2][0][RTW89_CHILE][12] = 16, + [2][0][RTW89_QATAR][12] = 58, [2][0][RTW89_FCC][13] = 127, [2][0][RTW89_ETSI][13] = 127, [2][0][RTW89_MKK][13] = 127, @@ -34627,110 +46728,166 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][13] = 127, [2][0][RTW89_CN][13] = 127, [2][0][RTW89_UK][13] = 127, + [2][0][RTW89_MEXICO][13] = 127, + [2][0][RTW89_UKRAINE][13] = 127, + [2][0][RTW89_CHILE][13] = 127, + [2][0][RTW89_QATAR][13] = 127, [2][1][RTW89_FCC][0] = 64, [2][1][RTW89_ETSI][0] = 46, [2][1][RTW89_MKK][0] = 46, [2][1][RTW89_IC][0] = 64, - [2][1][RTW89_KCC][0] = 52, + [2][1][RTW89_KCC][0] = 48, [2][1][RTW89_ACMA][0] = 46, [2][1][RTW89_CN][0] = 44, [2][1][RTW89_UK][0] = 46, + [2][1][RTW89_MEXICO][0] = 64, + [2][1][RTW89_UKRAINE][0] = 46, + [2][1][RTW89_CHILE][0] = 64, + [2][1][RTW89_QATAR][0] = 46, [2][1][RTW89_FCC][1] = 64, [2][1][RTW89_ETSI][1] = 46, [2][1][RTW89_MKK][1] = 46, [2][1][RTW89_IC][1] = 64, - [2][1][RTW89_KCC][1] = 52, + [2][1][RTW89_KCC][1] = 48, [2][1][RTW89_ACMA][1] = 46, [2][1][RTW89_CN][1] = 44, [2][1][RTW89_UK][1] = 46, + [2][1][RTW89_MEXICO][1] = 64, + [2][1][RTW89_UKRAINE][1] = 46, + [2][1][RTW89_CHILE][1] = 44, + [2][1][RTW89_QATAR][1] = 46, [2][1][RTW89_FCC][2] = 68, [2][1][RTW89_ETSI][2] = 46, [2][1][RTW89_MKK][2] = 46, [2][1][RTW89_IC][2] = 68, - [2][1][RTW89_KCC][2] = 52, + [2][1][RTW89_KCC][2] = 48, [2][1][RTW89_ACMA][2] = 46, [2][1][RTW89_CN][2] = 44, [2][1][RTW89_UK][2] = 46, + [2][1][RTW89_MEXICO][2] = 68, + [2][1][RTW89_UKRAINE][2] = 46, + [2][1][RTW89_CHILE][2] = 44, + [2][1][RTW89_QATAR][2] = 46, [2][1][RTW89_FCC][3] = 72, [2][1][RTW89_ETSI][3] = 46, [2][1][RTW89_MKK][3] = 46, [2][1][RTW89_IC][3] = 72, - [2][1][RTW89_KCC][3] = 52, + [2][1][RTW89_KCC][3] = 48, [2][1][RTW89_ACMA][3] = 46, [2][1][RTW89_CN][3] = 44, [2][1][RTW89_UK][3] = 46, + [2][1][RTW89_MEXICO][3] = 72, + [2][1][RTW89_UKRAINE][3] = 46, + [2][1][RTW89_CHILE][3] = 44, + [2][1][RTW89_QATAR][3] = 46, [2][1][RTW89_FCC][4] = 74, [2][1][RTW89_ETSI][4] = 46, [2][1][RTW89_MKK][4] = 46, [2][1][RTW89_IC][4] = 74, - [2][1][RTW89_KCC][4] = 50, + [2][1][RTW89_KCC][4] = 48, [2][1][RTW89_ACMA][4] = 46, [2][1][RTW89_CN][4] = 44, [2][1][RTW89_UK][4] = 46, + [2][1][RTW89_MEXICO][4] = 74, + [2][1][RTW89_UKRAINE][4] = 46, + [2][1][RTW89_CHILE][4] = 44, + [2][1][RTW89_QATAR][4] = 46, [2][1][RTW89_FCC][5] = 82, [2][1][RTW89_ETSI][5] = 46, [2][1][RTW89_MKK][5] = 46, [2][1][RTW89_IC][5] = 82, - [2][1][RTW89_KCC][5] = 50, + [2][1][RTW89_KCC][5] = 48, [2][1][RTW89_ACMA][5] = 46, [2][1][RTW89_CN][5] = 44, [2][1][RTW89_UK][5] = 46, + [2][1][RTW89_MEXICO][5] = 82, + [2][1][RTW89_UKRAINE][5] = 46, + [2][1][RTW89_CHILE][5] = 78, + [2][1][RTW89_QATAR][5] = 46, [2][1][RTW89_FCC][6] = 72, [2][1][RTW89_ETSI][6] = 44, [2][1][RTW89_MKK][6] = 46, [2][1][RTW89_IC][6] = 72, - [2][1][RTW89_KCC][6] = 50, + [2][1][RTW89_KCC][6] = 48, [2][1][RTW89_ACMA][6] = 44, [2][1][RTW89_CN][6] = 44, [2][1][RTW89_UK][6] = 44, + [2][1][RTW89_MEXICO][6] = 72, + [2][1][RTW89_UKRAINE][6] = 44, + [2][1][RTW89_CHILE][6] = 42, + [2][1][RTW89_QATAR][6] = 44, [2][1][RTW89_FCC][7] = 72, [2][1][RTW89_ETSI][7] = 46, [2][1][RTW89_MKK][7] = 46, [2][1][RTW89_IC][7] = 72, - [2][1][RTW89_KCC][7] = 50, + [2][1][RTW89_KCC][7] = 48, [2][1][RTW89_ACMA][7] = 46, [2][1][RTW89_CN][7] = 44, [2][1][RTW89_UK][7] = 46, + [2][1][RTW89_MEXICO][7] = 72, + [2][1][RTW89_UKRAINE][7] = 46, + [2][1][RTW89_CHILE][7] = 42, + [2][1][RTW89_QATAR][7] = 46, [2][1][RTW89_FCC][8] = 68, [2][1][RTW89_ETSI][8] = 46, [2][1][RTW89_MKK][8] = 46, [2][1][RTW89_IC][8] = 68, - [2][1][RTW89_KCC][8] = 50, + [2][1][RTW89_KCC][8] = 48, [2][1][RTW89_ACMA][8] = 46, [2][1][RTW89_CN][8] = 44, [2][1][RTW89_UK][8] = 46, + [2][1][RTW89_MEXICO][8] = 68, + [2][1][RTW89_UKRAINE][8] = 46, + [2][1][RTW89_CHILE][8] = 42, + [2][1][RTW89_QATAR][8] = 46, [2][1][RTW89_FCC][9] = 64, [2][1][RTW89_ETSI][9] = 46, [2][1][RTW89_MKK][9] = 46, [2][1][RTW89_IC][9] = 64, - [2][1][RTW89_KCC][9] = 52, + [2][1][RTW89_KCC][9] = 48, [2][1][RTW89_ACMA][9] = 46, [2][1][RTW89_CN][9] = 44, [2][1][RTW89_UK][9] = 46, + [2][1][RTW89_MEXICO][9] = 64, + [2][1][RTW89_UKRAINE][9] = 46, + [2][1][RTW89_CHILE][9] = 42, + [2][1][RTW89_QATAR][9] = 46, [2][1][RTW89_FCC][10] = 64, [2][1][RTW89_ETSI][10] = 46, [2][1][RTW89_MKK][10] = 46, [2][1][RTW89_IC][10] = 64, - [2][1][RTW89_KCC][10] = 52, + [2][1][RTW89_KCC][10] = 48, [2][1][RTW89_ACMA][10] = 46, [2][1][RTW89_CN][10] = 44, [2][1][RTW89_UK][10] = 46, + [2][1][RTW89_MEXICO][10] = 64, + [2][1][RTW89_UKRAINE][10] = 46, + [2][1][RTW89_CHILE][10] = 64, + [2][1][RTW89_QATAR][10] = 46, [2][1][RTW89_FCC][11] = 46, [2][1][RTW89_ETSI][11] = 46, [2][1][RTW89_MKK][11] = 46, [2][1][RTW89_IC][11] = 46, - [2][1][RTW89_KCC][11] = 52, + [2][1][RTW89_KCC][11] = 48, [2][1][RTW89_ACMA][11] = 46, [2][1][RTW89_CN][11] = 44, [2][1][RTW89_UK][11] = 46, + [2][1][RTW89_MEXICO][11] = 46, + [2][1][RTW89_UKRAINE][11] = 46, + [2][1][RTW89_CHILE][11] = 46, + [2][1][RTW89_QATAR][11] = 46, [2][1][RTW89_FCC][12] = 6, [2][1][RTW89_ETSI][12] = 44, [2][1][RTW89_MKK][12] = 46, [2][1][RTW89_IC][12] = 6, - [2][1][RTW89_KCC][12] = 52, + [2][1][RTW89_KCC][12] = 48, [2][1][RTW89_ACMA][12] = 44, [2][1][RTW89_CN][12] = 42, [2][1][RTW89_UK][12] = 44, + [2][1][RTW89_MEXICO][12] = 6, + [2][1][RTW89_UKRAINE][12] = 44, + [2][1][RTW89_CHILE][12] = 6, + [2][1][RTW89_QATAR][12] = 44, [2][1][RTW89_FCC][13] = 127, [2][1][RTW89_ETSI][13] = 127, [2][1][RTW89_MKK][13] = 127, @@ -34739,6 +46896,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][13] = 127, [2][1][RTW89_CN][13] = 127, [2][1][RTW89_UK][13] = 127, + [2][1][RTW89_MEXICO][13] = 127, + [2][1][RTW89_UKRAINE][13] = 127, + [2][1][RTW89_CHILE][13] = 127, + [2][1][RTW89_QATAR][13] = 127, }; static @@ -34747,168 +46908,168 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_WW][0] = 16, [0][0][RTW89_WW][2] = 16, [0][0][RTW89_WW][4] = 16, - [0][0][RTW89_WW][6] = 10, + [0][0][RTW89_WW][6] = 16, [0][0][RTW89_WW][8] = 16, [0][0][RTW89_WW][10] = 16, [0][0][RTW89_WW][12] = 16, [0][0][RTW89_WW][14] = 16, - [0][0][RTW89_WW][15] = 30, - [0][0][RTW89_WW][17] = 30, - [0][0][RTW89_WW][19] = 30, - [0][0][RTW89_WW][21] = 30, - [0][0][RTW89_WW][23] = 30, - [0][0][RTW89_WW][25] = 30, - [0][0][RTW89_WW][27] = 30, - [0][0][RTW89_WW][29] = 30, - [0][0][RTW89_WW][31] = 30, - [0][0][RTW89_WW][33] = 30, - [0][0][RTW89_WW][35] = 30, + [0][0][RTW89_WW][15] = 22, + [0][0][RTW89_WW][17] = 22, + [0][0][RTW89_WW][19] = 22, + [0][0][RTW89_WW][21] = 22, + [0][0][RTW89_WW][23] = 22, + [0][0][RTW89_WW][25] = 22, + [0][0][RTW89_WW][27] = 22, + [0][0][RTW89_WW][29] = 22, + [0][0][RTW89_WW][31] = 22, + [0][0][RTW89_WW][33] = 22, + [0][0][RTW89_WW][35] = 22, [0][0][RTW89_WW][37] = 30, - [0][0][RTW89_WW][38] = 28, - [0][0][RTW89_WW][40] = 28, - [0][0][RTW89_WW][42] = 28, - [0][0][RTW89_WW][44] = 28, - [0][0][RTW89_WW][46] = 28, + [0][0][RTW89_WW][38] = 26, + [0][0][RTW89_WW][40] = 26, + [0][0][RTW89_WW][42] = 26, + [0][0][RTW89_WW][44] = 26, + [0][0][RTW89_WW][46] = 26, [0][0][RTW89_WW][48] = 46, [0][0][RTW89_WW][50] = 44, [0][0][RTW89_WW][52] = 34, [0][1][RTW89_WW][0] = 4, [0][1][RTW89_WW][2] = 4, [0][1][RTW89_WW][4] = 4, - [0][1][RTW89_WW][6] = 1, + [0][1][RTW89_WW][6] = 4, [0][1][RTW89_WW][8] = 4, [0][1][RTW89_WW][10] = 4, [0][1][RTW89_WW][12] = 4, [0][1][RTW89_WW][14] = 4, - [0][1][RTW89_WW][15] = 18, - [0][1][RTW89_WW][17] = 18, - [0][1][RTW89_WW][19] = 18, - [0][1][RTW89_WW][21] = 18, - [0][1][RTW89_WW][23] = 18, - [0][1][RTW89_WW][25] = 18, - [0][1][RTW89_WW][27] = 16, - [0][1][RTW89_WW][29] = 16, - [0][1][RTW89_WW][31] = 16, - [0][1][RTW89_WW][33] = 16, - [0][1][RTW89_WW][35] = 16, + [0][1][RTW89_WW][15] = 10, + [0][1][RTW89_WW][17] = 10, + [0][1][RTW89_WW][19] = 10, + [0][1][RTW89_WW][21] = 10, + [0][1][RTW89_WW][23] = 10, + [0][1][RTW89_WW][25] = 10, + [0][1][RTW89_WW][27] = 10, + [0][1][RTW89_WW][29] = 10, + [0][1][RTW89_WW][31] = 10, + [0][1][RTW89_WW][33] = 10, + [0][1][RTW89_WW][35] = 10, [0][1][RTW89_WW][37] = 18, - [0][1][RTW89_WW][38] = 16, - [0][1][RTW89_WW][40] = 16, - [0][1][RTW89_WW][42] = 16, - [0][1][RTW89_WW][44] = 16, - [0][1][RTW89_WW][46] = 16, + [0][1][RTW89_WW][38] = 14, + [0][1][RTW89_WW][40] = 14, + [0][1][RTW89_WW][42] = 14, + [0][1][RTW89_WW][44] = 14, + [0][1][RTW89_WW][46] = 14, [0][1][RTW89_WW][48] = 20, [0][1][RTW89_WW][50] = 20, [0][1][RTW89_WW][52] = 8, [1][0][RTW89_WW][0] = 26, [1][0][RTW89_WW][2] = 26, [1][0][RTW89_WW][4] = 26, - [1][0][RTW89_WW][6] = 24, + [1][0][RTW89_WW][6] = 26, [1][0][RTW89_WW][8] = 26, [1][0][RTW89_WW][10] = 26, [1][0][RTW89_WW][12] = 26, [1][0][RTW89_WW][14] = 26, - [1][0][RTW89_WW][15] = 40, - [1][0][RTW89_WW][17] = 40, - [1][0][RTW89_WW][19] = 40, - [1][0][RTW89_WW][21] = 40, - [1][0][RTW89_WW][23] = 40, - [1][0][RTW89_WW][25] = 40, - [1][0][RTW89_WW][27] = 42, - [1][0][RTW89_WW][29] = 42, - [1][0][RTW89_WW][31] = 42, - [1][0][RTW89_WW][33] = 42, - [1][0][RTW89_WW][35] = 42, + [1][0][RTW89_WW][15] = 32, + [1][0][RTW89_WW][17] = 32, + [1][0][RTW89_WW][19] = 32, + [1][0][RTW89_WW][21] = 32, + [1][0][RTW89_WW][23] = 32, + [1][0][RTW89_WW][25] = 32, + [1][0][RTW89_WW][27] = 32, + [1][0][RTW89_WW][29] = 32, + [1][0][RTW89_WW][31] = 32, + [1][0][RTW89_WW][33] = 32, + [1][0][RTW89_WW][35] = 32, [1][0][RTW89_WW][37] = 42, - [1][0][RTW89_WW][38] = 28, - [1][0][RTW89_WW][40] = 28, - [1][0][RTW89_WW][42] = 28, - [1][0][RTW89_WW][44] = 28, - [1][0][RTW89_WW][46] = 28, + [1][0][RTW89_WW][38] = 26, + [1][0][RTW89_WW][40] = 26, + [1][0][RTW89_WW][42] = 26, + [1][0][RTW89_WW][44] = 26, + [1][0][RTW89_WW][46] = 26, [1][0][RTW89_WW][48] = 56, [1][0][RTW89_WW][50] = 58, [1][0][RTW89_WW][52] = 56, [1][1][RTW89_WW][0] = 14, [1][1][RTW89_WW][2] = 14, [1][1][RTW89_WW][4] = 14, - [1][1][RTW89_WW][6] = 8, + [1][1][RTW89_WW][6] = 14, [1][1][RTW89_WW][8] = 14, [1][1][RTW89_WW][10] = 14, [1][1][RTW89_WW][12] = 14, [1][1][RTW89_WW][14] = 14, - [1][1][RTW89_WW][15] = 28, - [1][1][RTW89_WW][17] = 28, - [1][1][RTW89_WW][19] = 28, - [1][1][RTW89_WW][21] = 28, - [1][1][RTW89_WW][23] = 28, - [1][1][RTW89_WW][25] = 28, - [1][1][RTW89_WW][27] = 30, - [1][1][RTW89_WW][29] = 30, - [1][1][RTW89_WW][31] = 30, - [1][1][RTW89_WW][33] = 30, - [1][1][RTW89_WW][35] = 30, + [1][1][RTW89_WW][15] = 20, + [1][1][RTW89_WW][17] = 20, + [1][1][RTW89_WW][19] = 20, + [1][1][RTW89_WW][21] = 20, + [1][1][RTW89_WW][23] = 20, + [1][1][RTW89_WW][25] = 20, + [1][1][RTW89_WW][27] = 20, + [1][1][RTW89_WW][29] = 20, + [1][1][RTW89_WW][31] = 20, + [1][1][RTW89_WW][33] = 20, + [1][1][RTW89_WW][35] = 20, [1][1][RTW89_WW][37] = 32, - [1][1][RTW89_WW][38] = 16, - [1][1][RTW89_WW][40] = 16, - [1][1][RTW89_WW][42] = 16, - [1][1][RTW89_WW][44] = 16, - [1][1][RTW89_WW][46] = 16, + [1][1][RTW89_WW][38] = 14, + [1][1][RTW89_WW][40] = 14, + [1][1][RTW89_WW][42] = 14, + [1][1][RTW89_WW][44] = 14, + [1][1][RTW89_WW][46] = 14, [1][1][RTW89_WW][48] = 34, [1][1][RTW89_WW][50] = 34, [1][1][RTW89_WW][52] = 30, [2][0][RTW89_WW][0] = 40, [2][0][RTW89_WW][2] = 40, [2][0][RTW89_WW][4] = 40, - [2][0][RTW89_WW][6] = 36, + [2][0][RTW89_WW][6] = 38, [2][0][RTW89_WW][8] = 40, [2][0][RTW89_WW][10] = 40, [2][0][RTW89_WW][12] = 40, [2][0][RTW89_WW][14] = 40, - [2][0][RTW89_WW][15] = 52, - [2][0][RTW89_WW][17] = 52, - [2][0][RTW89_WW][19] = 52, - [2][0][RTW89_WW][21] = 52, - [2][0][RTW89_WW][23] = 52, - [2][0][RTW89_WW][25] = 52, - [2][0][RTW89_WW][27] = 52, - [2][0][RTW89_WW][29] = 52, - [2][0][RTW89_WW][31] = 52, - [2][0][RTW89_WW][33] = 52, - [2][0][RTW89_WW][35] = 52, + [2][0][RTW89_WW][15] = 46, + [2][0][RTW89_WW][17] = 46, + [2][0][RTW89_WW][19] = 46, + [2][0][RTW89_WW][21] = 46, + [2][0][RTW89_WW][23] = 46, + [2][0][RTW89_WW][25] = 46, + [2][0][RTW89_WW][27] = 46, + [2][0][RTW89_WW][29] = 46, + [2][0][RTW89_WW][31] = 46, + [2][0][RTW89_WW][33] = 46, + [2][0][RTW89_WW][35] = 46, [2][0][RTW89_WW][37] = 52, - [2][0][RTW89_WW][38] = 28, - [2][0][RTW89_WW][40] = 28, - [2][0][RTW89_WW][42] = 28, - [2][0][RTW89_WW][44] = 28, - [2][0][RTW89_WW][46] = 28, + [2][0][RTW89_WW][38] = 26, + [2][0][RTW89_WW][40] = 26, + [2][0][RTW89_WW][42] = 26, + [2][0][RTW89_WW][44] = 26, + [2][0][RTW89_WW][46] = 26, [2][0][RTW89_WW][48] = 64, [2][0][RTW89_WW][50] = 64, [2][0][RTW89_WW][52] = 64, [2][1][RTW89_WW][0] = 26, [2][1][RTW89_WW][2] = 26, [2][1][RTW89_WW][4] = 26, - [2][1][RTW89_WW][6] = 20, + [2][1][RTW89_WW][6] = 26, [2][1][RTW89_WW][8] = 28, [2][1][RTW89_WW][10] = 28, [2][1][RTW89_WW][12] = 28, [2][1][RTW89_WW][14] = 28, - [2][1][RTW89_WW][15] = 40, - [2][1][RTW89_WW][17] = 40, - [2][1][RTW89_WW][19] = 40, - [2][1][RTW89_WW][21] = 40, - [2][1][RTW89_WW][23] = 40, - [2][1][RTW89_WW][25] = 40, - [2][1][RTW89_WW][27] = 40, - [2][1][RTW89_WW][29] = 40, - [2][1][RTW89_WW][31] = 40, - [2][1][RTW89_WW][33] = 40, - [2][1][RTW89_WW][35] = 40, + [2][1][RTW89_WW][15] = 34, + [2][1][RTW89_WW][17] = 34, + [2][1][RTW89_WW][19] = 34, + [2][1][RTW89_WW][21] = 34, + [2][1][RTW89_WW][23] = 34, + [2][1][RTW89_WW][25] = 34, + [2][1][RTW89_WW][27] = 34, + [2][1][RTW89_WW][29] = 34, + [2][1][RTW89_WW][31] = 34, + [2][1][RTW89_WW][33] = 34, + [2][1][RTW89_WW][35] = 34, [2][1][RTW89_WW][37] = 42, - [2][1][RTW89_WW][38] = 16, - [2][1][RTW89_WW][40] = 16, - [2][1][RTW89_WW][42] = 16, - [2][1][RTW89_WW][44] = 16, - [2][1][RTW89_WW][46] = 16, + [2][1][RTW89_WW][38] = 14, + [2][1][RTW89_WW][40] = 14, + [2][1][RTW89_WW][42] = 14, + [2][1][RTW89_WW][44] = 14, + [2][1][RTW89_WW][46] = 14, [2][1][RTW89_WW][48] = 40, [2][1][RTW89_WW][50] = 40, [2][1][RTW89_WW][52] = 40, @@ -34920,6 +47081,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][0] = 30, [0][0][RTW89_CN][0] = 16, [0][0][RTW89_UK][0] = 30, + [0][0][RTW89_MEXICO][0] = 50, + [0][0][RTW89_UKRAINE][0] = 22, + [0][0][RTW89_CHILE][0] = 50, + [0][0][RTW89_QATAR][0] = 30, [0][0][RTW89_FCC][2] = 50, [0][0][RTW89_ETSI][2] = 30, [0][0][RTW89_MKK][2] = 36, @@ -34928,6 +47093,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][2] = 30, [0][0][RTW89_CN][2] = 16, [0][0][RTW89_UK][2] = 30, + [0][0][RTW89_MEXICO][2] = 50, + [0][0][RTW89_UKRAINE][2] = 22, + [0][0][RTW89_CHILE][2] = 50, + [0][0][RTW89_QATAR][2] = 30, [0][0][RTW89_FCC][4] = 50, [0][0][RTW89_ETSI][4] = 30, [0][0][RTW89_MKK][4] = 22, @@ -34936,30 +47105,46 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][4] = 30, [0][0][RTW89_CN][4] = 16, [0][0][RTW89_UK][4] = 30, + [0][0][RTW89_MEXICO][4] = 50, + [0][0][RTW89_UKRAINE][4] = 22, + [0][0][RTW89_CHILE][4] = 50, + [0][0][RTW89_QATAR][4] = 30, [0][0][RTW89_FCC][6] = 50, [0][0][RTW89_ETSI][6] = 30, [0][0][RTW89_MKK][6] = 22, [0][0][RTW89_IC][6] = 32, - [0][0][RTW89_KCC][6] = 10, + [0][0][RTW89_KCC][6] = 18, [0][0][RTW89_ACMA][6] = 30, [0][0][RTW89_CN][6] = 16, [0][0][RTW89_UK][6] = 30, + [0][0][RTW89_MEXICO][6] = 50, + [0][0][RTW89_UKRAINE][6] = 22, + [0][0][RTW89_CHILE][6] = 50, + [0][0][RTW89_QATAR][6] = 30, [0][0][RTW89_FCC][8] = 52, [0][0][RTW89_ETSI][8] = 28, [0][0][RTW89_MKK][8] = 18, [0][0][RTW89_IC][8] = 52, - [0][0][RTW89_KCC][8] = 44, + [0][0][RTW89_KCC][8] = 40, [0][0][RTW89_ACMA][8] = 28, [0][0][RTW89_CN][8] = 16, [0][0][RTW89_UK][8] = 28, + [0][0][RTW89_MEXICO][8] = 52, + [0][0][RTW89_UKRAINE][8] = 22, + [0][0][RTW89_CHILE][8] = 52, + [0][0][RTW89_QATAR][8] = 28, [0][0][RTW89_FCC][10] = 52, [0][0][RTW89_ETSI][10] = 28, [0][0][RTW89_MKK][10] = 18, [0][0][RTW89_IC][10] = 52, - [0][0][RTW89_KCC][10] = 44, + [0][0][RTW89_KCC][10] = 40, [0][0][RTW89_ACMA][10] = 28, [0][0][RTW89_CN][10] = 16, [0][0][RTW89_UK][10] = 28, + [0][0][RTW89_MEXICO][10] = 52, + [0][0][RTW89_UKRAINE][10] = 22, + [0][0][RTW89_CHILE][10] = 52, + [0][0][RTW89_QATAR][10] = 28, [0][0][RTW89_FCC][12] = 52, [0][0][RTW89_ETSI][12] = 28, [0][0][RTW89_MKK][12] = 34, @@ -34968,6 +47153,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][12] = 28, [0][0][RTW89_CN][12] = 16, [0][0][RTW89_UK][12] = 28, + [0][0][RTW89_MEXICO][12] = 52, + [0][0][RTW89_UKRAINE][12] = 22, + [0][0][RTW89_CHILE][12] = 52, + [0][0][RTW89_QATAR][12] = 28, [0][0][RTW89_FCC][14] = 52, [0][0][RTW89_ETSI][14] = 28, [0][0][RTW89_MKK][14] = 34, @@ -34976,70 +47165,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][14] = 28, [0][0][RTW89_CN][14] = 16, [0][0][RTW89_UK][14] = 28, + [0][0][RTW89_MEXICO][14] = 52, + [0][0][RTW89_UKRAINE][14] = 22, + [0][0][RTW89_CHILE][14] = 52, + [0][0][RTW89_QATAR][14] = 28, [0][0][RTW89_FCC][15] = 52, [0][0][RTW89_ETSI][15] = 30, [0][0][RTW89_MKK][15] = 56, [0][0][RTW89_IC][15] = 52, - [0][0][RTW89_KCC][15] = 42, + [0][0][RTW89_KCC][15] = 40, [0][0][RTW89_ACMA][15] = 30, [0][0][RTW89_CN][15] = 127, [0][0][RTW89_UK][15] = 30, + [0][0][RTW89_MEXICO][15] = 52, + [0][0][RTW89_UKRAINE][15] = 22, + [0][0][RTW89_CHILE][15] = 52, + [0][0][RTW89_QATAR][15] = 30, [0][0][RTW89_FCC][17] = 52, [0][0][RTW89_ETSI][17] = 30, [0][0][RTW89_MKK][17] = 58, [0][0][RTW89_IC][17] = 52, - [0][0][RTW89_KCC][17] = 42, + [0][0][RTW89_KCC][17] = 40, [0][0][RTW89_ACMA][17] = 30, [0][0][RTW89_CN][17] = 127, [0][0][RTW89_UK][17] = 30, + [0][0][RTW89_MEXICO][17] = 52, + [0][0][RTW89_UKRAINE][17] = 22, + [0][0][RTW89_CHILE][17] = 52, + [0][0][RTW89_QATAR][17] = 30, [0][0][RTW89_FCC][19] = 52, [0][0][RTW89_ETSI][19] = 30, [0][0][RTW89_MKK][19] = 58, [0][0][RTW89_IC][19] = 52, - [0][0][RTW89_KCC][19] = 42, + [0][0][RTW89_KCC][19] = 40, [0][0][RTW89_ACMA][19] = 30, [0][0][RTW89_CN][19] = 127, [0][0][RTW89_UK][19] = 30, + [0][0][RTW89_MEXICO][19] = 52, + [0][0][RTW89_UKRAINE][19] = 22, + [0][0][RTW89_CHILE][19] = 52, + [0][0][RTW89_QATAR][19] = 30, [0][0][RTW89_FCC][21] = 52, [0][0][RTW89_ETSI][21] = 30, [0][0][RTW89_MKK][21] = 58, [0][0][RTW89_IC][21] = 52, - [0][0][RTW89_KCC][21] = 42, + [0][0][RTW89_KCC][21] = 40, [0][0][RTW89_ACMA][21] = 30, [0][0][RTW89_CN][21] = 127, [0][0][RTW89_UK][21] = 30, + [0][0][RTW89_MEXICO][21] = 52, + [0][0][RTW89_UKRAINE][21] = 22, + [0][0][RTW89_CHILE][21] = 52, + [0][0][RTW89_QATAR][21] = 30, [0][0][RTW89_FCC][23] = 52, [0][0][RTW89_ETSI][23] = 30, [0][0][RTW89_MKK][23] = 58, [0][0][RTW89_IC][23] = 52, - [0][0][RTW89_KCC][23] = 42, + [0][0][RTW89_KCC][23] = 40, [0][0][RTW89_ACMA][23] = 30, [0][0][RTW89_CN][23] = 127, [0][0][RTW89_UK][23] = 30, + [0][0][RTW89_MEXICO][23] = 52, + [0][0][RTW89_UKRAINE][23] = 22, + [0][0][RTW89_CHILE][23] = 52, + [0][0][RTW89_QATAR][23] = 30, [0][0][RTW89_FCC][25] = 52, [0][0][RTW89_ETSI][25] = 30, [0][0][RTW89_MKK][25] = 58, [0][0][RTW89_IC][25] = 127, - [0][0][RTW89_KCC][25] = 42, + [0][0][RTW89_KCC][25] = 40, [0][0][RTW89_ACMA][25] = 127, [0][0][RTW89_CN][25] = 127, [0][0][RTW89_UK][25] = 30, + [0][0][RTW89_MEXICO][25] = 52, + [0][0][RTW89_UKRAINE][25] = 22, + [0][0][RTW89_CHILE][25] = 52, + [0][0][RTW89_QATAR][25] = 30, [0][0][RTW89_FCC][27] = 52, [0][0][RTW89_ETSI][27] = 30, [0][0][RTW89_MKK][27] = 58, [0][0][RTW89_IC][27] = 127, - [0][0][RTW89_KCC][27] = 42, + [0][0][RTW89_KCC][27] = 40, [0][0][RTW89_ACMA][27] = 127, [0][0][RTW89_CN][27] = 127, [0][0][RTW89_UK][27] = 30, + [0][0][RTW89_MEXICO][27] = 52, + [0][0][RTW89_UKRAINE][27] = 22, + [0][0][RTW89_CHILE][27] = 52, + [0][0][RTW89_QATAR][27] = 30, [0][0][RTW89_FCC][29] = 52, [0][0][RTW89_ETSI][29] = 30, [0][0][RTW89_MKK][29] = 58, [0][0][RTW89_IC][29] = 127, - [0][0][RTW89_KCC][29] = 42, + [0][0][RTW89_KCC][29] = 40, [0][0][RTW89_ACMA][29] = 127, [0][0][RTW89_CN][29] = 127, [0][0][RTW89_UK][29] = 30, + [0][0][RTW89_MEXICO][29] = 52, + [0][0][RTW89_UKRAINE][29] = 22, + [0][0][RTW89_CHILE][29] = 52, + [0][0][RTW89_QATAR][29] = 30, [0][0][RTW89_FCC][31] = 52, [0][0][RTW89_ETSI][31] = 30, [0][0][RTW89_MKK][31] = 58, @@ -35048,6 +47273,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][31] = 30, [0][0][RTW89_CN][31] = 127, [0][0][RTW89_UK][31] = 30, + [0][0][RTW89_MEXICO][31] = 52, + [0][0][RTW89_UKRAINE][31] = 22, + [0][0][RTW89_CHILE][31] = 52, + [0][0][RTW89_QATAR][31] = 30, [0][0][RTW89_FCC][33] = 44, [0][0][RTW89_ETSI][33] = 30, [0][0][RTW89_MKK][33] = 58, @@ -35056,6 +47285,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][33] = 30, [0][0][RTW89_CN][33] = 127, [0][0][RTW89_UK][33] = 30, + [0][0][RTW89_MEXICO][33] = 44, + [0][0][RTW89_UKRAINE][33] = 22, + [0][0][RTW89_CHILE][33] = 44, + [0][0][RTW89_QATAR][33] = 30, [0][0][RTW89_FCC][35] = 44, [0][0][RTW89_ETSI][35] = 30, [0][0][RTW89_MKK][35] = 58, @@ -35064,6 +47297,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][35] = 30, [0][0][RTW89_CN][35] = 127, [0][0][RTW89_UK][35] = 30, + [0][0][RTW89_MEXICO][35] = 44, + [0][0][RTW89_UKRAINE][35] = 22, + [0][0][RTW89_CHILE][35] = 44, + [0][0][RTW89_QATAR][35] = 30, [0][0][RTW89_FCC][37] = 52, [0][0][RTW89_ETSI][37] = 127, [0][0][RTW89_MKK][37] = 58, @@ -35072,6 +47309,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][37] = 52, [0][0][RTW89_CN][37] = 127, [0][0][RTW89_UK][37] = 30, + [0][0][RTW89_MEXICO][37] = 52, + [0][0][RTW89_UKRAINE][37] = 127, + [0][0][RTW89_CHILE][37] = 52, + [0][0][RTW89_QATAR][37] = 127, [0][0][RTW89_FCC][38] = 64, [0][0][RTW89_ETSI][38] = 28, [0][0][RTW89_MKK][38] = 127, @@ -35080,6 +47321,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][38] = 64, [0][0][RTW89_CN][38] = 54, [0][0][RTW89_UK][38] = 30, + [0][0][RTW89_MEXICO][38] = 64, + [0][0][RTW89_UKRAINE][38] = 26, + [0][0][RTW89_CHILE][38] = 64, + [0][0][RTW89_QATAR][38] = 26, [0][0][RTW89_FCC][40] = 64, [0][0][RTW89_ETSI][40] = 28, [0][0][RTW89_MKK][40] = 127, @@ -35088,6 +47333,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][40] = 64, [0][0][RTW89_CN][40] = 54, [0][0][RTW89_UK][40] = 30, + [0][0][RTW89_MEXICO][40] = 64, + [0][0][RTW89_UKRAINE][40] = 26, + [0][0][RTW89_CHILE][40] = 64, + [0][0][RTW89_QATAR][40] = 26, [0][0][RTW89_FCC][42] = 60, [0][0][RTW89_ETSI][42] = 28, [0][0][RTW89_MKK][42] = 127, @@ -35096,6 +47345,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][42] = 60, [0][0][RTW89_CN][42] = 54, [0][0][RTW89_UK][42] = 30, + [0][0][RTW89_MEXICO][42] = 60, + [0][0][RTW89_UKRAINE][42] = 26, + [0][0][RTW89_CHILE][42] = 60, + [0][0][RTW89_QATAR][42] = 26, [0][0][RTW89_FCC][44] = 60, [0][0][RTW89_ETSI][44] = 28, [0][0][RTW89_MKK][44] = 127, @@ -35104,6 +47357,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][44] = 60, [0][0][RTW89_CN][44] = 54, [0][0][RTW89_UK][44] = 30, + [0][0][RTW89_MEXICO][44] = 60, + [0][0][RTW89_UKRAINE][44] = 26, + [0][0][RTW89_CHILE][44] = 60, + [0][0][RTW89_QATAR][44] = 26, [0][0][RTW89_FCC][46] = 60, [0][0][RTW89_ETSI][46] = 28, [0][0][RTW89_MKK][46] = 127, @@ -35112,6 +47369,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][46] = 60, [0][0][RTW89_CN][46] = 54, [0][0][RTW89_UK][46] = 30, + [0][0][RTW89_MEXICO][46] = 60, + [0][0][RTW89_UKRAINE][46] = 26, + [0][0][RTW89_CHILE][46] = 60, + [0][0][RTW89_QATAR][46] = 26, [0][0][RTW89_FCC][48] = 46, [0][0][RTW89_ETSI][48] = 127, [0][0][RTW89_MKK][48] = 127, @@ -35120,6 +47381,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][48] = 127, [0][0][RTW89_CN][48] = 127, [0][0][RTW89_UK][48] = 127, + [0][0][RTW89_MEXICO][48] = 127, + [0][0][RTW89_UKRAINE][48] = 127, + [0][0][RTW89_CHILE][48] = 127, + [0][0][RTW89_QATAR][48] = 127, [0][0][RTW89_FCC][50] = 44, [0][0][RTW89_ETSI][50] = 127, [0][0][RTW89_MKK][50] = 127, @@ -35128,6 +47393,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][50] = 127, [0][0][RTW89_CN][50] = 127, [0][0][RTW89_UK][50] = 127, + [0][0][RTW89_MEXICO][50] = 127, + [0][0][RTW89_UKRAINE][50] = 127, + [0][0][RTW89_CHILE][50] = 127, + [0][0][RTW89_QATAR][50] = 127, [0][0][RTW89_FCC][52] = 34, [0][0][RTW89_ETSI][52] = 127, [0][0][RTW89_MKK][52] = 127, @@ -35136,38 +47405,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][0][RTW89_ACMA][52] = 127, [0][0][RTW89_CN][52] = 127, [0][0][RTW89_UK][52] = 127, + [0][0][RTW89_MEXICO][52] = 127, + [0][0][RTW89_UKRAINE][52] = 127, + [0][0][RTW89_CHILE][52] = 127, + [0][0][RTW89_QATAR][52] = 127, [0][1][RTW89_FCC][0] = 30, [0][1][RTW89_ETSI][0] = 18, [0][1][RTW89_MKK][0] = 20, [0][1][RTW89_IC][0] = 8, - [0][1][RTW89_KCC][0] = 26, + [0][1][RTW89_KCC][0] = 32, [0][1][RTW89_ACMA][0] = 18, [0][1][RTW89_CN][0] = 4, [0][1][RTW89_UK][0] = 18, + [0][1][RTW89_MEXICO][0] = 30, + [0][1][RTW89_UKRAINE][0] = 10, + [0][1][RTW89_CHILE][0] = 30, + [0][1][RTW89_QATAR][0] = 18, [0][1][RTW89_FCC][2] = 32, [0][1][RTW89_ETSI][2] = 18, [0][1][RTW89_MKK][2] = 20, [0][1][RTW89_IC][2] = 8, - [0][1][RTW89_KCC][2] = 26, + [0][1][RTW89_KCC][2] = 32, [0][1][RTW89_ACMA][2] = 18, [0][1][RTW89_CN][2] = 4, [0][1][RTW89_UK][2] = 18, + [0][1][RTW89_MEXICO][2] = 32, + [0][1][RTW89_UKRAINE][2] = 10, + [0][1][RTW89_CHILE][2] = 32, + [0][1][RTW89_QATAR][2] = 18, [0][1][RTW89_FCC][4] = 30, [0][1][RTW89_ETSI][4] = 18, [0][1][RTW89_MKK][4] = 8, [0][1][RTW89_IC][4] = 8, - [0][1][RTW89_KCC][4] = 26, + [0][1][RTW89_KCC][4] = 32, [0][1][RTW89_ACMA][4] = 18, [0][1][RTW89_CN][4] = 4, [0][1][RTW89_UK][4] = 18, + [0][1][RTW89_MEXICO][4] = 30, + [0][1][RTW89_UKRAINE][4] = 10, + [0][1][RTW89_CHILE][4] = 30, + [0][1][RTW89_QATAR][4] = 18, [0][1][RTW89_FCC][6] = 30, [0][1][RTW89_ETSI][6] = 18, [0][1][RTW89_MKK][6] = 8, [0][1][RTW89_IC][6] = 8, - [0][1][RTW89_KCC][6] = 0, + [0][1][RTW89_KCC][6] = 6, [0][1][RTW89_ACMA][6] = 18, [0][1][RTW89_CN][6] = 4, [0][1][RTW89_UK][6] = 18, + [0][1][RTW89_MEXICO][6] = 30, + [0][1][RTW89_UKRAINE][6] = 10, + [0][1][RTW89_CHILE][6] = 30, + [0][1][RTW89_QATAR][6] = 18, [0][1][RTW89_FCC][8] = 30, [0][1][RTW89_ETSI][8] = 16, [0][1][RTW89_MKK][8] = 20, @@ -35176,6 +47465,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][8] = 16, [0][1][RTW89_CN][8] = 4, [0][1][RTW89_UK][8] = 16, + [0][1][RTW89_MEXICO][8] = 30, + [0][1][RTW89_UKRAINE][8] = 10, + [0][1][RTW89_CHILE][8] = 30, + [0][1][RTW89_QATAR][8] = 16, [0][1][RTW89_FCC][10] = 30, [0][1][RTW89_ETSI][10] = 16, [0][1][RTW89_MKK][10] = 20, @@ -35184,22 +47477,34 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][10] = 16, [0][1][RTW89_CN][10] = 4, [0][1][RTW89_UK][10] = 16, + [0][1][RTW89_MEXICO][10] = 30, + [0][1][RTW89_UKRAINE][10] = 10, + [0][1][RTW89_CHILE][10] = 30, + [0][1][RTW89_QATAR][10] = 16, [0][1][RTW89_FCC][12] = 30, [0][1][RTW89_ETSI][12] = 16, [0][1][RTW89_MKK][12] = 34, [0][1][RTW89_IC][12] = 30, - [0][1][RTW89_KCC][12] = 28, + [0][1][RTW89_KCC][12] = 26, [0][1][RTW89_ACMA][12] = 16, [0][1][RTW89_CN][12] = 4, [0][1][RTW89_UK][12] = 16, + [0][1][RTW89_MEXICO][12] = 30, + [0][1][RTW89_UKRAINE][12] = 10, + [0][1][RTW89_CHILE][12] = 30, + [0][1][RTW89_QATAR][12] = 16, [0][1][RTW89_FCC][14] = 30, [0][1][RTW89_ETSI][14] = 16, [0][1][RTW89_MKK][14] = 34, [0][1][RTW89_IC][14] = 30, - [0][1][RTW89_KCC][14] = 28, + [0][1][RTW89_KCC][14] = 26, [0][1][RTW89_ACMA][14] = 16, [0][1][RTW89_CN][14] = 4, [0][1][RTW89_UK][14] = 16, + [0][1][RTW89_MEXICO][14] = 30, + [0][1][RTW89_UKRAINE][14] = 10, + [0][1][RTW89_CHILE][14] = 30, + [0][1][RTW89_QATAR][14] = 16, [0][1][RTW89_FCC][15] = 32, [0][1][RTW89_ETSI][15] = 18, [0][1][RTW89_MKK][15] = 44, @@ -35208,6 +47513,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][15] = 18, [0][1][RTW89_CN][15] = 127, [0][1][RTW89_UK][15] = 18, + [0][1][RTW89_MEXICO][15] = 32, + [0][1][RTW89_UKRAINE][15] = 10, + [0][1][RTW89_CHILE][15] = 32, + [0][1][RTW89_QATAR][15] = 18, [0][1][RTW89_FCC][17] = 32, [0][1][RTW89_ETSI][17] = 18, [0][1][RTW89_MKK][17] = 44, @@ -35216,6 +47525,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][17] = 18, [0][1][RTW89_CN][17] = 127, [0][1][RTW89_UK][17] = 18, + [0][1][RTW89_MEXICO][17] = 32, + [0][1][RTW89_UKRAINE][17] = 10, + [0][1][RTW89_CHILE][17] = 32, + [0][1][RTW89_QATAR][17] = 18, [0][1][RTW89_FCC][19] = 32, [0][1][RTW89_ETSI][19] = 18, [0][1][RTW89_MKK][19] = 44, @@ -35224,6 +47537,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][19] = 18, [0][1][RTW89_CN][19] = 127, [0][1][RTW89_UK][19] = 18, + [0][1][RTW89_MEXICO][19] = 32, + [0][1][RTW89_UKRAINE][19] = 10, + [0][1][RTW89_CHILE][19] = 32, + [0][1][RTW89_QATAR][19] = 18, [0][1][RTW89_FCC][21] = 32, [0][1][RTW89_ETSI][21] = 18, [0][1][RTW89_MKK][21] = 44, @@ -35232,6 +47549,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][21] = 18, [0][1][RTW89_CN][21] = 127, [0][1][RTW89_UK][21] = 18, + [0][1][RTW89_MEXICO][21] = 32, + [0][1][RTW89_UKRAINE][21] = 10, + [0][1][RTW89_CHILE][21] = 32, + [0][1][RTW89_QATAR][21] = 18, [0][1][RTW89_FCC][23] = 32, [0][1][RTW89_ETSI][23] = 18, [0][1][RTW89_MKK][23] = 44, @@ -35240,6 +47561,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][23] = 18, [0][1][RTW89_CN][23] = 127, [0][1][RTW89_UK][23] = 18, + [0][1][RTW89_MEXICO][23] = 32, + [0][1][RTW89_UKRAINE][23] = 10, + [0][1][RTW89_CHILE][23] = 32, + [0][1][RTW89_QATAR][23] = 18, [0][1][RTW89_FCC][25] = 32, [0][1][RTW89_ETSI][25] = 18, [0][1][RTW89_MKK][25] = 44, @@ -35248,6 +47573,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][25] = 127, [0][1][RTW89_CN][25] = 127, [0][1][RTW89_UK][25] = 18, + [0][1][RTW89_MEXICO][25] = 32, + [0][1][RTW89_UKRAINE][25] = 10, + [0][1][RTW89_CHILE][25] = 32, + [0][1][RTW89_QATAR][25] = 18, [0][1][RTW89_FCC][27] = 32, [0][1][RTW89_ETSI][27] = 16, [0][1][RTW89_MKK][27] = 44, @@ -35256,6 +47585,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][27] = 127, [0][1][RTW89_CN][27] = 127, [0][1][RTW89_UK][27] = 16, + [0][1][RTW89_MEXICO][27] = 32, + [0][1][RTW89_UKRAINE][27] = 10, + [0][1][RTW89_CHILE][27] = 32, + [0][1][RTW89_QATAR][27] = 16, [0][1][RTW89_FCC][29] = 32, [0][1][RTW89_ETSI][29] = 16, [0][1][RTW89_MKK][29] = 44, @@ -35264,6 +47597,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][29] = 127, [0][1][RTW89_CN][29] = 127, [0][1][RTW89_UK][29] = 16, + [0][1][RTW89_MEXICO][29] = 32, + [0][1][RTW89_UKRAINE][29] = 10, + [0][1][RTW89_CHILE][29] = 32, + [0][1][RTW89_QATAR][29] = 16, [0][1][RTW89_FCC][31] = 32, [0][1][RTW89_ETSI][31] = 16, [0][1][RTW89_MKK][31] = 44, @@ -35272,6 +47609,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][31] = 16, [0][1][RTW89_CN][31] = 127, [0][1][RTW89_UK][31] = 16, + [0][1][RTW89_MEXICO][31] = 32, + [0][1][RTW89_UKRAINE][31] = 10, + [0][1][RTW89_CHILE][31] = 32, + [0][1][RTW89_QATAR][31] = 16, [0][1][RTW89_FCC][33] = 30, [0][1][RTW89_ETSI][33] = 16, [0][1][RTW89_MKK][33] = 44, @@ -35280,6 +47621,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][33] = 16, [0][1][RTW89_CN][33] = 127, [0][1][RTW89_UK][33] = 16, + [0][1][RTW89_MEXICO][33] = 30, + [0][1][RTW89_UKRAINE][33] = 10, + [0][1][RTW89_CHILE][33] = 30, + [0][1][RTW89_QATAR][33] = 16, [0][1][RTW89_FCC][35] = 30, [0][1][RTW89_ETSI][35] = 16, [0][1][RTW89_MKK][35] = 44, @@ -35288,6 +47633,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][35] = 16, [0][1][RTW89_CN][35] = 127, [0][1][RTW89_UK][35] = 16, + [0][1][RTW89_MEXICO][35] = 30, + [0][1][RTW89_UKRAINE][35] = 10, + [0][1][RTW89_CHILE][35] = 30, + [0][1][RTW89_QATAR][35] = 16, [0][1][RTW89_FCC][37] = 34, [0][1][RTW89_ETSI][37] = 127, [0][1][RTW89_MKK][37] = 44, @@ -35296,46 +47645,70 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][37] = 34, [0][1][RTW89_CN][37] = 127, [0][1][RTW89_UK][37] = 18, + [0][1][RTW89_MEXICO][37] = 34, + [0][1][RTW89_UKRAINE][37] = 127, + [0][1][RTW89_CHILE][37] = 34, + [0][1][RTW89_QATAR][37] = 127, [0][1][RTW89_FCC][38] = 62, [0][1][RTW89_ETSI][38] = 16, [0][1][RTW89_MKK][38] = 127, [0][1][RTW89_IC][38] = 62, - [0][1][RTW89_KCC][38] = 28, + [0][1][RTW89_KCC][38] = 30, [0][1][RTW89_ACMA][38] = 62, [0][1][RTW89_CN][38] = 42, [0][1][RTW89_UK][38] = 18, + [0][1][RTW89_MEXICO][38] = 62, + [0][1][RTW89_UKRAINE][38] = 14, + [0][1][RTW89_CHILE][38] = 62, + [0][1][RTW89_QATAR][38] = 14, [0][1][RTW89_FCC][40] = 62, [0][1][RTW89_ETSI][40] = 16, [0][1][RTW89_MKK][40] = 127, [0][1][RTW89_IC][40] = 62, - [0][1][RTW89_KCC][40] = 28, + [0][1][RTW89_KCC][40] = 30, [0][1][RTW89_ACMA][40] = 62, [0][1][RTW89_CN][40] = 42, [0][1][RTW89_UK][40] = 18, + [0][1][RTW89_MEXICO][40] = 62, + [0][1][RTW89_UKRAINE][40] = 14, + [0][1][RTW89_CHILE][40] = 62, + [0][1][RTW89_QATAR][40] = 14, [0][1][RTW89_FCC][42] = 58, [0][1][RTW89_ETSI][42] = 16, [0][1][RTW89_MKK][42] = 127, [0][1][RTW89_IC][42] = 58, - [0][1][RTW89_KCC][42] = 28, + [0][1][RTW89_KCC][42] = 30, [0][1][RTW89_ACMA][42] = 58, [0][1][RTW89_CN][42] = 42, [0][1][RTW89_UK][42] = 18, + [0][1][RTW89_MEXICO][42] = 58, + [0][1][RTW89_UKRAINE][42] = 14, + [0][1][RTW89_CHILE][42] = 58, + [0][1][RTW89_QATAR][42] = 14, [0][1][RTW89_FCC][44] = 56, [0][1][RTW89_ETSI][44] = 16, [0][1][RTW89_MKK][44] = 127, [0][1][RTW89_IC][44] = 56, - [0][1][RTW89_KCC][44] = 28, + [0][1][RTW89_KCC][44] = 30, [0][1][RTW89_ACMA][44] = 56, [0][1][RTW89_CN][44] = 42, [0][1][RTW89_UK][44] = 18, + [0][1][RTW89_MEXICO][44] = 56, + [0][1][RTW89_UKRAINE][44] = 14, + [0][1][RTW89_CHILE][44] = 56, + [0][1][RTW89_QATAR][44] = 14, [0][1][RTW89_FCC][46] = 56, [0][1][RTW89_ETSI][46] = 16, [0][1][RTW89_MKK][46] = 127, [0][1][RTW89_IC][46] = 56, - [0][1][RTW89_KCC][46] = 28, + [0][1][RTW89_KCC][46] = 30, [0][1][RTW89_ACMA][46] = 56, [0][1][RTW89_CN][46] = 42, [0][1][RTW89_UK][46] = 18, + [0][1][RTW89_MEXICO][46] = 56, + [0][1][RTW89_UKRAINE][46] = 14, + [0][1][RTW89_CHILE][46] = 56, + [0][1][RTW89_QATAR][46] = 14, [0][1][RTW89_FCC][48] = 20, [0][1][RTW89_ETSI][48] = 127, [0][1][RTW89_MKK][48] = 127, @@ -35344,6 +47717,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][48] = 127, [0][1][RTW89_CN][48] = 127, [0][1][RTW89_UK][48] = 127, + [0][1][RTW89_MEXICO][48] = 127, + [0][1][RTW89_UKRAINE][48] = 127, + [0][1][RTW89_CHILE][48] = 127, + [0][1][RTW89_QATAR][48] = 127, [0][1][RTW89_FCC][50] = 20, [0][1][RTW89_ETSI][50] = 127, [0][1][RTW89_MKK][50] = 127, @@ -35352,6 +47729,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][50] = 127, [0][1][RTW89_CN][50] = 127, [0][1][RTW89_UK][50] = 127, + [0][1][RTW89_MEXICO][50] = 127, + [0][1][RTW89_UKRAINE][50] = 127, + [0][1][RTW89_CHILE][50] = 127, + [0][1][RTW89_QATAR][50] = 127, [0][1][RTW89_FCC][52] = 8, [0][1][RTW89_ETSI][52] = 127, [0][1][RTW89_MKK][52] = 127, @@ -35360,70 +47741,106 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [0][1][RTW89_ACMA][52] = 127, [0][1][RTW89_CN][52] = 127, [0][1][RTW89_UK][52] = 127, + [0][1][RTW89_MEXICO][52] = 127, + [0][1][RTW89_UKRAINE][52] = 127, + [0][1][RTW89_CHILE][52] = 127, + [0][1][RTW89_QATAR][52] = 127, [1][0][RTW89_FCC][0] = 62, [1][0][RTW89_ETSI][0] = 40, [1][0][RTW89_MKK][0] = 48, [1][0][RTW89_IC][0] = 42, - [1][0][RTW89_KCC][0] = 50, + [1][0][RTW89_KCC][0] = 54, [1][0][RTW89_ACMA][0] = 40, [1][0][RTW89_CN][0] = 26, [1][0][RTW89_UK][0] = 40, + [1][0][RTW89_MEXICO][0] = 62, + [1][0][RTW89_UKRAINE][0] = 32, + [1][0][RTW89_CHILE][0] = 62, + [1][0][RTW89_QATAR][0] = 40, [1][0][RTW89_FCC][2] = 62, [1][0][RTW89_ETSI][2] = 40, [1][0][RTW89_MKK][2] = 48, [1][0][RTW89_IC][2] = 42, - [1][0][RTW89_KCC][2] = 50, + [1][0][RTW89_KCC][2] = 54, [1][0][RTW89_ACMA][2] = 40, [1][0][RTW89_CN][2] = 26, [1][0][RTW89_UK][2] = 40, + [1][0][RTW89_MEXICO][2] = 62, + [1][0][RTW89_UKRAINE][2] = 32, + [1][0][RTW89_CHILE][2] = 62, + [1][0][RTW89_QATAR][2] = 40, [1][0][RTW89_FCC][4] = 64, [1][0][RTW89_ETSI][4] = 40, [1][0][RTW89_MKK][4] = 40, [1][0][RTW89_IC][4] = 42, - [1][0][RTW89_KCC][4] = 50, + [1][0][RTW89_KCC][4] = 54, [1][0][RTW89_ACMA][4] = 40, [1][0][RTW89_CN][4] = 26, [1][0][RTW89_UK][4] = 40, + [1][0][RTW89_MEXICO][4] = 64, + [1][0][RTW89_UKRAINE][4] = 32, + [1][0][RTW89_CHILE][4] = 64, + [1][0][RTW89_QATAR][4] = 40, [1][0][RTW89_FCC][6] = 64, [1][0][RTW89_ETSI][6] = 40, [1][0][RTW89_MKK][6] = 40, [1][0][RTW89_IC][6] = 42, - [1][0][RTW89_KCC][6] = 24, + [1][0][RTW89_KCC][6] = 32, [1][0][RTW89_ACMA][6] = 40, [1][0][RTW89_CN][6] = 26, [1][0][RTW89_UK][6] = 40, + [1][0][RTW89_MEXICO][6] = 64, + [1][0][RTW89_UKRAINE][6] = 32, + [1][0][RTW89_CHILE][6] = 64, + [1][0][RTW89_QATAR][6] = 40, [1][0][RTW89_FCC][8] = 62, [1][0][RTW89_ETSI][8] = 40, [1][0][RTW89_MKK][8] = 34, [1][0][RTW89_IC][8] = 62, - [1][0][RTW89_KCC][8] = 52, + [1][0][RTW89_KCC][8] = 50, [1][0][RTW89_ACMA][8] = 40, [1][0][RTW89_CN][8] = 26, [1][0][RTW89_UK][8] = 40, + [1][0][RTW89_MEXICO][8] = 62, + [1][0][RTW89_UKRAINE][8] = 32, + [1][0][RTW89_CHILE][8] = 62, + [1][0][RTW89_QATAR][8] = 40, [1][0][RTW89_FCC][10] = 62, [1][0][RTW89_ETSI][10] = 40, [1][0][RTW89_MKK][10] = 34, [1][0][RTW89_IC][10] = 62, - [1][0][RTW89_KCC][10] = 52, + [1][0][RTW89_KCC][10] = 50, [1][0][RTW89_ACMA][10] = 40, [1][0][RTW89_CN][10] = 26, [1][0][RTW89_UK][10] = 40, + [1][0][RTW89_MEXICO][10] = 62, + [1][0][RTW89_UKRAINE][10] = 32, + [1][0][RTW89_CHILE][10] = 62, + [1][0][RTW89_QATAR][10] = 40, [1][0][RTW89_FCC][12] = 62, [1][0][RTW89_ETSI][12] = 40, [1][0][RTW89_MKK][12] = 46, [1][0][RTW89_IC][12] = 62, - [1][0][RTW89_KCC][12] = 52, + [1][0][RTW89_KCC][12] = 50, [1][0][RTW89_ACMA][12] = 40, [1][0][RTW89_CN][12] = 26, [1][0][RTW89_UK][12] = 40, + [1][0][RTW89_MEXICO][12] = 62, + [1][0][RTW89_UKRAINE][12] = 32, + [1][0][RTW89_CHILE][12] = 62, + [1][0][RTW89_QATAR][12] = 40, [1][0][RTW89_FCC][14] = 62, [1][0][RTW89_ETSI][14] = 40, [1][0][RTW89_MKK][14] = 46, [1][0][RTW89_IC][14] = 62, - [1][0][RTW89_KCC][14] = 52, + [1][0][RTW89_KCC][14] = 50, [1][0][RTW89_ACMA][14] = 40, [1][0][RTW89_CN][14] = 26, [1][0][RTW89_UK][14] = 40, + [1][0][RTW89_MEXICO][14] = 62, + [1][0][RTW89_UKRAINE][14] = 32, + [1][0][RTW89_CHILE][14] = 62, + [1][0][RTW89_QATAR][14] = 40, [1][0][RTW89_FCC][15] = 62, [1][0][RTW89_ETSI][15] = 40, [1][0][RTW89_MKK][15] = 62, @@ -35432,6 +47849,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][15] = 40, [1][0][RTW89_CN][15] = 127, [1][0][RTW89_UK][15] = 40, + [1][0][RTW89_MEXICO][15] = 62, + [1][0][RTW89_UKRAINE][15] = 32, + [1][0][RTW89_CHILE][15] = 62, + [1][0][RTW89_QATAR][15] = 40, [1][0][RTW89_FCC][17] = 62, [1][0][RTW89_ETSI][17] = 40, [1][0][RTW89_MKK][17] = 68, @@ -35440,6 +47861,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][17] = 40, [1][0][RTW89_CN][17] = 127, [1][0][RTW89_UK][17] = 40, + [1][0][RTW89_MEXICO][17] = 62, + [1][0][RTW89_UKRAINE][17] = 32, + [1][0][RTW89_CHILE][17] = 62, + [1][0][RTW89_QATAR][17] = 40, [1][0][RTW89_FCC][19] = 64, [1][0][RTW89_ETSI][19] = 40, [1][0][RTW89_MKK][19] = 68, @@ -35448,6 +47873,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][19] = 40, [1][0][RTW89_CN][19] = 127, [1][0][RTW89_UK][19] = 40, + [1][0][RTW89_MEXICO][19] = 64, + [1][0][RTW89_UKRAINE][19] = 32, + [1][0][RTW89_CHILE][19] = 64, + [1][0][RTW89_QATAR][19] = 40, [1][0][RTW89_FCC][21] = 64, [1][0][RTW89_ETSI][21] = 40, [1][0][RTW89_MKK][21] = 68, @@ -35456,6 +47885,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][21] = 40, [1][0][RTW89_CN][21] = 127, [1][0][RTW89_UK][21] = 40, + [1][0][RTW89_MEXICO][21] = 64, + [1][0][RTW89_UKRAINE][21] = 32, + [1][0][RTW89_CHILE][21] = 64, + [1][0][RTW89_QATAR][21] = 40, [1][0][RTW89_FCC][23] = 64, [1][0][RTW89_ETSI][23] = 40, [1][0][RTW89_MKK][23] = 68, @@ -35464,6 +47897,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][23] = 40, [1][0][RTW89_CN][23] = 127, [1][0][RTW89_UK][23] = 40, + [1][0][RTW89_MEXICO][23] = 64, + [1][0][RTW89_UKRAINE][23] = 32, + [1][0][RTW89_CHILE][23] = 64, + [1][0][RTW89_QATAR][23] = 40, [1][0][RTW89_FCC][25] = 64, [1][0][RTW89_ETSI][25] = 40, [1][0][RTW89_MKK][25] = 68, @@ -35472,6 +47909,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][25] = 127, [1][0][RTW89_CN][25] = 127, [1][0][RTW89_UK][25] = 40, + [1][0][RTW89_MEXICO][25] = 64, + [1][0][RTW89_UKRAINE][25] = 32, + [1][0][RTW89_CHILE][25] = 64, + [1][0][RTW89_QATAR][25] = 40, [1][0][RTW89_FCC][27] = 64, [1][0][RTW89_ETSI][27] = 42, [1][0][RTW89_MKK][27] = 68, @@ -35480,6 +47921,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][27] = 127, [1][0][RTW89_CN][27] = 127, [1][0][RTW89_UK][27] = 42, + [1][0][RTW89_MEXICO][27] = 64, + [1][0][RTW89_UKRAINE][27] = 32, + [1][0][RTW89_CHILE][27] = 64, + [1][0][RTW89_QATAR][27] = 42, [1][0][RTW89_FCC][29] = 64, [1][0][RTW89_ETSI][29] = 42, [1][0][RTW89_MKK][29] = 68, @@ -35488,38 +47933,58 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][29] = 127, [1][0][RTW89_CN][29] = 127, [1][0][RTW89_UK][29] = 42, + [1][0][RTW89_MEXICO][29] = 64, + [1][0][RTW89_UKRAINE][29] = 32, + [1][0][RTW89_CHILE][29] = 64, + [1][0][RTW89_QATAR][29] = 42, [1][0][RTW89_FCC][31] = 64, [1][0][RTW89_ETSI][31] = 42, [1][0][RTW89_MKK][31] = 68, [1][0][RTW89_IC][31] = 56, - [1][0][RTW89_KCC][31] = 52, + [1][0][RTW89_KCC][31] = 50, [1][0][RTW89_ACMA][31] = 42, [1][0][RTW89_CN][31] = 127, [1][0][RTW89_UK][31] = 42, + [1][0][RTW89_MEXICO][31] = 64, + [1][0][RTW89_UKRAINE][31] = 32, + [1][0][RTW89_CHILE][31] = 64, + [1][0][RTW89_QATAR][31] = 42, [1][0][RTW89_FCC][33] = 56, [1][0][RTW89_ETSI][33] = 42, [1][0][RTW89_MKK][33] = 68, [1][0][RTW89_IC][33] = 56, - [1][0][RTW89_KCC][33] = 52, + [1][0][RTW89_KCC][33] = 50, [1][0][RTW89_ACMA][33] = 42, [1][0][RTW89_CN][33] = 127, [1][0][RTW89_UK][33] = 42, + [1][0][RTW89_MEXICO][33] = 56, + [1][0][RTW89_UKRAINE][33] = 32, + [1][0][RTW89_CHILE][33] = 56, + [1][0][RTW89_QATAR][33] = 42, [1][0][RTW89_FCC][35] = 56, [1][0][RTW89_ETSI][35] = 42, [1][0][RTW89_MKK][35] = 68, [1][0][RTW89_IC][35] = 56, - [1][0][RTW89_KCC][35] = 52, + [1][0][RTW89_KCC][35] = 50, [1][0][RTW89_ACMA][35] = 42, [1][0][RTW89_CN][35] = 127, [1][0][RTW89_UK][35] = 42, + [1][0][RTW89_MEXICO][35] = 56, + [1][0][RTW89_UKRAINE][35] = 32, + [1][0][RTW89_CHILE][35] = 56, + [1][0][RTW89_QATAR][35] = 42, [1][0][RTW89_FCC][37] = 66, [1][0][RTW89_ETSI][37] = 127, [1][0][RTW89_MKK][37] = 68, [1][0][RTW89_IC][37] = 66, - [1][0][RTW89_KCC][37] = 52, + [1][0][RTW89_KCC][37] = 50, [1][0][RTW89_ACMA][37] = 66, [1][0][RTW89_CN][37] = 127, [1][0][RTW89_UK][37] = 42, + [1][0][RTW89_MEXICO][37] = 66, + [1][0][RTW89_UKRAINE][37] = 127, + [1][0][RTW89_CHILE][37] = 66, + [1][0][RTW89_QATAR][37] = 127, [1][0][RTW89_FCC][38] = 76, [1][0][RTW89_ETSI][38] = 28, [1][0][RTW89_MKK][38] = 127, @@ -35528,6 +47993,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][38] = 76, [1][0][RTW89_CN][38] = 66, [1][0][RTW89_UK][38] = 44, + [1][0][RTW89_MEXICO][38] = 76, + [1][0][RTW89_UKRAINE][38] = 26, + [1][0][RTW89_CHILE][38] = 76, + [1][0][RTW89_QATAR][38] = 26, [1][0][RTW89_FCC][40] = 76, [1][0][RTW89_ETSI][40] = 28, [1][0][RTW89_MKK][40] = 127, @@ -35536,6 +48005,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][40] = 76, [1][0][RTW89_CN][40] = 66, [1][0][RTW89_UK][40] = 44, + [1][0][RTW89_MEXICO][40] = 76, + [1][0][RTW89_UKRAINE][40] = 26, + [1][0][RTW89_CHILE][40] = 76, + [1][0][RTW89_QATAR][40] = 26, [1][0][RTW89_FCC][42] = 68, [1][0][RTW89_ETSI][42] = 28, [1][0][RTW89_MKK][42] = 127, @@ -35544,6 +48017,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][42] = 68, [1][0][RTW89_CN][42] = 66, [1][0][RTW89_UK][42] = 44, + [1][0][RTW89_MEXICO][42] = 68, + [1][0][RTW89_UKRAINE][42] = 26, + [1][0][RTW89_CHILE][42] = 68, + [1][0][RTW89_QATAR][42] = 26, [1][0][RTW89_FCC][44] = 70, [1][0][RTW89_ETSI][44] = 28, [1][0][RTW89_MKK][44] = 127, @@ -35552,6 +48029,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][44] = 70, [1][0][RTW89_CN][44] = 66, [1][0][RTW89_UK][44] = 42, + [1][0][RTW89_MEXICO][44] = 70, + [1][0][RTW89_UKRAINE][44] = 26, + [1][0][RTW89_CHILE][44] = 70, + [1][0][RTW89_QATAR][44] = 26, [1][0][RTW89_FCC][46] = 70, [1][0][RTW89_ETSI][46] = 28, [1][0][RTW89_MKK][46] = 127, @@ -35560,6 +48041,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][46] = 70, [1][0][RTW89_CN][46] = 66, [1][0][RTW89_UK][46] = 42, + [1][0][RTW89_MEXICO][46] = 70, + [1][0][RTW89_UKRAINE][46] = 26, + [1][0][RTW89_CHILE][46] = 70, + [1][0][RTW89_QATAR][46] = 26, [1][0][RTW89_FCC][48] = 56, [1][0][RTW89_ETSI][48] = 127, [1][0][RTW89_MKK][48] = 127, @@ -35568,6 +48053,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][48] = 127, [1][0][RTW89_CN][48] = 127, [1][0][RTW89_UK][48] = 127, + [1][0][RTW89_MEXICO][48] = 127, + [1][0][RTW89_UKRAINE][48] = 127, + [1][0][RTW89_CHILE][48] = 127, + [1][0][RTW89_QATAR][48] = 127, [1][0][RTW89_FCC][50] = 58, [1][0][RTW89_ETSI][50] = 127, [1][0][RTW89_MKK][50] = 127, @@ -35576,6 +48065,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][50] = 127, [1][0][RTW89_CN][50] = 127, [1][0][RTW89_UK][50] = 127, + [1][0][RTW89_MEXICO][50] = 127, + [1][0][RTW89_UKRAINE][50] = 127, + [1][0][RTW89_CHILE][50] = 127, + [1][0][RTW89_QATAR][50] = 127, [1][0][RTW89_FCC][52] = 56, [1][0][RTW89_ETSI][52] = 127, [1][0][RTW89_MKK][52] = 127, @@ -35584,54 +48077,82 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][0][RTW89_ACMA][52] = 127, [1][0][RTW89_CN][52] = 127, [1][0][RTW89_UK][52] = 127, + [1][0][RTW89_MEXICO][52] = 127, + [1][0][RTW89_UKRAINE][52] = 127, + [1][0][RTW89_CHILE][52] = 127, + [1][0][RTW89_QATAR][52] = 127, [1][1][RTW89_FCC][0] = 44, [1][1][RTW89_ETSI][0] = 30, [1][1][RTW89_MKK][0] = 34, [1][1][RTW89_IC][0] = 20, - [1][1][RTW89_KCC][0] = 34, + [1][1][RTW89_KCC][0] = 40, [1][1][RTW89_ACMA][0] = 30, [1][1][RTW89_CN][0] = 14, [1][1][RTW89_UK][0] = 30, + [1][1][RTW89_MEXICO][0] = 44, + [1][1][RTW89_UKRAINE][0] = 20, + [1][1][RTW89_CHILE][0] = 44, + [1][1][RTW89_QATAR][0] = 30, [1][1][RTW89_FCC][2] = 44, [1][1][RTW89_ETSI][2] = 30, [1][1][RTW89_MKK][2] = 34, [1][1][RTW89_IC][2] = 18, - [1][1][RTW89_KCC][2] = 34, + [1][1][RTW89_KCC][2] = 40, [1][1][RTW89_ACMA][2] = 30, [1][1][RTW89_CN][2] = 14, [1][1][RTW89_UK][2] = 30, + [1][1][RTW89_MEXICO][2] = 44, + [1][1][RTW89_UKRAINE][2] = 20, + [1][1][RTW89_CHILE][2] = 44, + [1][1][RTW89_QATAR][2] = 30, [1][1][RTW89_FCC][4] = 46, [1][1][RTW89_ETSI][4] = 30, [1][1][RTW89_MKK][4] = 26, [1][1][RTW89_IC][4] = 20, - [1][1][RTW89_KCC][4] = 34, + [1][1][RTW89_KCC][4] = 40, [1][1][RTW89_ACMA][4] = 30, [1][1][RTW89_CN][4] = 14, [1][1][RTW89_UK][4] = 30, + [1][1][RTW89_MEXICO][4] = 46, + [1][1][RTW89_UKRAINE][4] = 20, + [1][1][RTW89_CHILE][4] = 46, + [1][1][RTW89_QATAR][4] = 30, [1][1][RTW89_FCC][6] = 46, [1][1][RTW89_ETSI][6] = 30, [1][1][RTW89_MKK][6] = 26, [1][1][RTW89_IC][6] = 20, - [1][1][RTW89_KCC][6] = 8, + [1][1][RTW89_KCC][6] = 18, [1][1][RTW89_ACMA][6] = 30, [1][1][RTW89_CN][6] = 14, [1][1][RTW89_UK][6] = 30, + [1][1][RTW89_MEXICO][6] = 46, + [1][1][RTW89_UKRAINE][6] = 20, + [1][1][RTW89_CHILE][6] = 46, + [1][1][RTW89_QATAR][6] = 30, [1][1][RTW89_FCC][8] = 44, [1][1][RTW89_ETSI][8] = 30, [1][1][RTW89_MKK][8] = 20, [1][1][RTW89_IC][8] = 44, - [1][1][RTW89_KCC][8] = 34, + [1][1][RTW89_KCC][8] = 38, [1][1][RTW89_ACMA][8] = 30, [1][1][RTW89_CN][8] = 14, [1][1][RTW89_UK][8] = 30, + [1][1][RTW89_MEXICO][8] = 44, + [1][1][RTW89_UKRAINE][8] = 20, + [1][1][RTW89_CHILE][8] = 44, + [1][1][RTW89_QATAR][8] = 30, [1][1][RTW89_FCC][10] = 44, [1][1][RTW89_ETSI][10] = 30, [1][1][RTW89_MKK][10] = 20, [1][1][RTW89_IC][10] = 44, - [1][1][RTW89_KCC][10] = 34, + [1][1][RTW89_KCC][10] = 38, [1][1][RTW89_ACMA][10] = 30, [1][1][RTW89_CN][10] = 14, [1][1][RTW89_UK][10] = 30, + [1][1][RTW89_MEXICO][10] = 44, + [1][1][RTW89_UKRAINE][10] = 20, + [1][1][RTW89_CHILE][10] = 44, + [1][1][RTW89_QATAR][10] = 30, [1][1][RTW89_FCC][12] = 44, [1][1][RTW89_ETSI][12] = 30, [1][1][RTW89_MKK][12] = 34, @@ -35640,6 +48161,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][12] = 30, [1][1][RTW89_CN][12] = 14, [1][1][RTW89_UK][12] = 30, + [1][1][RTW89_MEXICO][12] = 44, + [1][1][RTW89_UKRAINE][12] = 20, + [1][1][RTW89_CHILE][12] = 44, + [1][1][RTW89_QATAR][12] = 30, [1][1][RTW89_FCC][14] = 44, [1][1][RTW89_ETSI][14] = 30, [1][1][RTW89_MKK][14] = 34, @@ -35648,142 +48173,214 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][14] = 30, [1][1][RTW89_CN][14] = 14, [1][1][RTW89_UK][14] = 30, + [1][1][RTW89_MEXICO][14] = 44, + [1][1][RTW89_UKRAINE][14] = 20, + [1][1][RTW89_CHILE][14] = 44, + [1][1][RTW89_QATAR][14] = 30, [1][1][RTW89_FCC][15] = 44, [1][1][RTW89_ETSI][15] = 28, [1][1][RTW89_MKK][15] = 56, [1][1][RTW89_IC][15] = 44, - [1][1][RTW89_KCC][15] = 36, + [1][1][RTW89_KCC][15] = 38, [1][1][RTW89_ACMA][15] = 28, [1][1][RTW89_CN][15] = 127, [1][1][RTW89_UK][15] = 28, + [1][1][RTW89_MEXICO][15] = 44, + [1][1][RTW89_UKRAINE][15] = 20, + [1][1][RTW89_CHILE][15] = 44, + [1][1][RTW89_QATAR][15] = 28, [1][1][RTW89_FCC][17] = 44, [1][1][RTW89_ETSI][17] = 28, [1][1][RTW89_MKK][17] = 58, [1][1][RTW89_IC][17] = 44, - [1][1][RTW89_KCC][17] = 36, + [1][1][RTW89_KCC][17] = 38, [1][1][RTW89_ACMA][17] = 28, [1][1][RTW89_CN][17] = 127, [1][1][RTW89_UK][17] = 28, + [1][1][RTW89_MEXICO][17] = 44, + [1][1][RTW89_UKRAINE][17] = 20, + [1][1][RTW89_CHILE][17] = 44, + [1][1][RTW89_QATAR][17] = 28, [1][1][RTW89_FCC][19] = 44, [1][1][RTW89_ETSI][19] = 28, [1][1][RTW89_MKK][19] = 58, [1][1][RTW89_IC][19] = 44, - [1][1][RTW89_KCC][19] = 36, + [1][1][RTW89_KCC][19] = 38, [1][1][RTW89_ACMA][19] = 28, [1][1][RTW89_CN][19] = 127, [1][1][RTW89_UK][19] = 28, + [1][1][RTW89_MEXICO][19] = 44, + [1][1][RTW89_UKRAINE][19] = 20, + [1][1][RTW89_CHILE][19] = 44, + [1][1][RTW89_QATAR][19] = 28, [1][1][RTW89_FCC][21] = 44, [1][1][RTW89_ETSI][21] = 28, [1][1][RTW89_MKK][21] = 58, [1][1][RTW89_IC][21] = 44, - [1][1][RTW89_KCC][21] = 36, + [1][1][RTW89_KCC][21] = 38, [1][1][RTW89_ACMA][21] = 28, [1][1][RTW89_CN][21] = 127, [1][1][RTW89_UK][21] = 28, + [1][1][RTW89_MEXICO][21] = 44, + [1][1][RTW89_UKRAINE][21] = 20, + [1][1][RTW89_CHILE][21] = 44, + [1][1][RTW89_QATAR][21] = 28, [1][1][RTW89_FCC][23] = 44, [1][1][RTW89_ETSI][23] = 28, [1][1][RTW89_MKK][23] = 58, [1][1][RTW89_IC][23] = 44, - [1][1][RTW89_KCC][23] = 36, + [1][1][RTW89_KCC][23] = 38, [1][1][RTW89_ACMA][23] = 28, [1][1][RTW89_CN][23] = 127, [1][1][RTW89_UK][23] = 28, + [1][1][RTW89_MEXICO][23] = 44, + [1][1][RTW89_UKRAINE][23] = 20, + [1][1][RTW89_CHILE][23] = 44, + [1][1][RTW89_QATAR][23] = 28, [1][1][RTW89_FCC][25] = 44, [1][1][RTW89_ETSI][25] = 28, [1][1][RTW89_MKK][25] = 58, [1][1][RTW89_IC][25] = 127, - [1][1][RTW89_KCC][25] = 36, + [1][1][RTW89_KCC][25] = 38, [1][1][RTW89_ACMA][25] = 127, [1][1][RTW89_CN][25] = 127, [1][1][RTW89_UK][25] = 28, + [1][1][RTW89_MEXICO][25] = 44, + [1][1][RTW89_UKRAINE][25] = 20, + [1][1][RTW89_CHILE][25] = 44, + [1][1][RTW89_QATAR][25] = 28, [1][1][RTW89_FCC][27] = 44, [1][1][RTW89_ETSI][27] = 30, [1][1][RTW89_MKK][27] = 58, [1][1][RTW89_IC][27] = 127, - [1][1][RTW89_KCC][27] = 36, + [1][1][RTW89_KCC][27] = 38, [1][1][RTW89_ACMA][27] = 127, [1][1][RTW89_CN][27] = 127, [1][1][RTW89_UK][27] = 30, + [1][1][RTW89_MEXICO][27] = 44, + [1][1][RTW89_UKRAINE][27] = 20, + [1][1][RTW89_CHILE][27] = 44, + [1][1][RTW89_QATAR][27] = 30, [1][1][RTW89_FCC][29] = 44, [1][1][RTW89_ETSI][29] = 30, [1][1][RTW89_MKK][29] = 58, [1][1][RTW89_IC][29] = 127, - [1][1][RTW89_KCC][29] = 36, + [1][1][RTW89_KCC][29] = 38, [1][1][RTW89_ACMA][29] = 127, [1][1][RTW89_CN][29] = 127, [1][1][RTW89_UK][29] = 30, + [1][1][RTW89_MEXICO][29] = 44, + [1][1][RTW89_UKRAINE][29] = 20, + [1][1][RTW89_CHILE][29] = 44, + [1][1][RTW89_QATAR][29] = 30, [1][1][RTW89_FCC][31] = 44, [1][1][RTW89_ETSI][31] = 30, [1][1][RTW89_MKK][31] = 58, [1][1][RTW89_IC][31] = 38, - [1][1][RTW89_KCC][31] = 36, + [1][1][RTW89_KCC][31] = 40, [1][1][RTW89_ACMA][31] = 30, [1][1][RTW89_CN][31] = 127, [1][1][RTW89_UK][31] = 30, + [1][1][RTW89_MEXICO][31] = 44, + [1][1][RTW89_UKRAINE][31] = 20, + [1][1][RTW89_CHILE][31] = 44, + [1][1][RTW89_QATAR][31] = 30, [1][1][RTW89_FCC][33] = 38, [1][1][RTW89_ETSI][33] = 30, [1][1][RTW89_MKK][33] = 58, [1][1][RTW89_IC][33] = 38, - [1][1][RTW89_KCC][33] = 36, + [1][1][RTW89_KCC][33] = 40, [1][1][RTW89_ACMA][33] = 30, [1][1][RTW89_CN][33] = 127, [1][1][RTW89_UK][33] = 30, + [1][1][RTW89_MEXICO][33] = 38, + [1][1][RTW89_UKRAINE][33] = 20, + [1][1][RTW89_CHILE][33] = 38, + [1][1][RTW89_QATAR][33] = 30, [1][1][RTW89_FCC][35] = 38, [1][1][RTW89_ETSI][35] = 30, [1][1][RTW89_MKK][35] = 58, [1][1][RTW89_IC][35] = 38, - [1][1][RTW89_KCC][35] = 36, + [1][1][RTW89_KCC][35] = 40, [1][1][RTW89_ACMA][35] = 30, [1][1][RTW89_CN][35] = 127, [1][1][RTW89_UK][35] = 30, + [1][1][RTW89_MEXICO][35] = 38, + [1][1][RTW89_UKRAINE][35] = 20, + [1][1][RTW89_CHILE][35] = 38, + [1][1][RTW89_QATAR][35] = 30, [1][1][RTW89_FCC][37] = 46, [1][1][RTW89_ETSI][37] = 127, [1][1][RTW89_MKK][37] = 58, [1][1][RTW89_IC][37] = 46, - [1][1][RTW89_KCC][37] = 36, + [1][1][RTW89_KCC][37] = 40, [1][1][RTW89_ACMA][37] = 46, [1][1][RTW89_CN][37] = 127, [1][1][RTW89_UK][37] = 32, + [1][1][RTW89_MEXICO][37] = 46, + [1][1][RTW89_UKRAINE][37] = 127, + [1][1][RTW89_CHILE][37] = 46, + [1][1][RTW89_QATAR][37] = 127, [1][1][RTW89_FCC][38] = 74, [1][1][RTW89_ETSI][38] = 16, [1][1][RTW89_MKK][38] = 127, [1][1][RTW89_IC][38] = 74, - [1][1][RTW89_KCC][38] = 36, + [1][1][RTW89_KCC][38] = 38, [1][1][RTW89_ACMA][38] = 74, [1][1][RTW89_CN][38] = 54, [1][1][RTW89_UK][38] = 30, + [1][1][RTW89_MEXICO][38] = 74, + [1][1][RTW89_UKRAINE][38] = 14, + [1][1][RTW89_CHILE][38] = 72, + [1][1][RTW89_QATAR][38] = 14, [1][1][RTW89_FCC][40] = 74, [1][1][RTW89_ETSI][40] = 16, [1][1][RTW89_MKK][40] = 127, [1][1][RTW89_IC][40] = 74, - [1][1][RTW89_KCC][40] = 36, + [1][1][RTW89_KCC][40] = 38, [1][1][RTW89_ACMA][40] = 74, [1][1][RTW89_CN][40] = 54, [1][1][RTW89_UK][40] = 30, + [1][1][RTW89_MEXICO][40] = 74, + [1][1][RTW89_UKRAINE][40] = 14, + [1][1][RTW89_CHILE][40] = 72, + [1][1][RTW89_QATAR][40] = 14, [1][1][RTW89_FCC][42] = 74, [1][1][RTW89_ETSI][42] = 16, [1][1][RTW89_MKK][42] = 127, [1][1][RTW89_IC][42] = 74, - [1][1][RTW89_KCC][42] = 36, + [1][1][RTW89_KCC][42] = 38, [1][1][RTW89_ACMA][42] = 74, [1][1][RTW89_CN][42] = 54, [1][1][RTW89_UK][42] = 30, + [1][1][RTW89_MEXICO][42] = 74, + [1][1][RTW89_UKRAINE][42] = 14, + [1][1][RTW89_CHILE][42] = 72, + [1][1][RTW89_QATAR][42] = 14, [1][1][RTW89_FCC][44] = 74, [1][1][RTW89_ETSI][44] = 16, [1][1][RTW89_MKK][44] = 127, [1][1][RTW89_IC][44] = 74, - [1][1][RTW89_KCC][44] = 36, + [1][1][RTW89_KCC][44] = 38, [1][1][RTW89_ACMA][44] = 74, [1][1][RTW89_CN][44] = 54, [1][1][RTW89_UK][44] = 30, + [1][1][RTW89_MEXICO][44] = 74, + [1][1][RTW89_UKRAINE][44] = 14, + [1][1][RTW89_CHILE][44] = 72, + [1][1][RTW89_QATAR][44] = 14, [1][1][RTW89_FCC][46] = 74, [1][1][RTW89_ETSI][46] = 16, [1][1][RTW89_MKK][46] = 127, [1][1][RTW89_IC][46] = 74, - [1][1][RTW89_KCC][46] = 36, + [1][1][RTW89_KCC][46] = 38, [1][1][RTW89_ACMA][46] = 74, [1][1][RTW89_CN][46] = 54, [1][1][RTW89_UK][46] = 30, + [1][1][RTW89_MEXICO][46] = 74, + [1][1][RTW89_UKRAINE][46] = 14, + [1][1][RTW89_CHILE][46] = 72, + [1][1][RTW89_QATAR][46] = 14, [1][1][RTW89_FCC][48] = 34, [1][1][RTW89_ETSI][48] = 127, [1][1][RTW89_MKK][48] = 127, @@ -35792,6 +48389,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][48] = 127, [1][1][RTW89_CN][48] = 127, [1][1][RTW89_UK][48] = 127, + [1][1][RTW89_MEXICO][48] = 127, + [1][1][RTW89_UKRAINE][48] = 127, + [1][1][RTW89_CHILE][48] = 127, + [1][1][RTW89_QATAR][48] = 127, [1][1][RTW89_FCC][50] = 34, [1][1][RTW89_ETSI][50] = 127, [1][1][RTW89_MKK][50] = 127, @@ -35800,6 +48401,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][50] = 127, [1][1][RTW89_CN][50] = 127, [1][1][RTW89_UK][50] = 127, + [1][1][RTW89_MEXICO][50] = 127, + [1][1][RTW89_UKRAINE][50] = 127, + [1][1][RTW89_CHILE][50] = 127, + [1][1][RTW89_QATAR][50] = 127, [1][1][RTW89_FCC][52] = 30, [1][1][RTW89_ETSI][52] = 127, [1][1][RTW89_MKK][52] = 127, @@ -35808,206 +48413,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [1][1][RTW89_ACMA][52] = 127, [1][1][RTW89_CN][52] = 127, [1][1][RTW89_UK][52] = 127, + [1][1][RTW89_MEXICO][52] = 127, + [1][1][RTW89_UKRAINE][52] = 127, + [1][1][RTW89_CHILE][52] = 127, + [1][1][RTW89_QATAR][52] = 127, [2][0][RTW89_FCC][0] = 68, [2][0][RTW89_ETSI][0] = 52, [2][0][RTW89_MKK][0] = 60, [2][0][RTW89_IC][0] = 52, - [2][0][RTW89_KCC][0] = 64, + [2][0][RTW89_KCC][0] = 60, [2][0][RTW89_ACMA][0] = 52, [2][0][RTW89_CN][0] = 40, [2][0][RTW89_UK][0] = 52, + [2][0][RTW89_MEXICO][0] = 62, + [2][0][RTW89_UKRAINE][0] = 46, + [2][0][RTW89_CHILE][0] = 68, + [2][0][RTW89_QATAR][0] = 52, [2][0][RTW89_FCC][2] = 64, [2][0][RTW89_ETSI][2] = 52, [2][0][RTW89_MKK][2] = 60, [2][0][RTW89_IC][2] = 50, - [2][0][RTW89_KCC][2] = 64, + [2][0][RTW89_KCC][2] = 60, [2][0][RTW89_ACMA][2] = 52, [2][0][RTW89_CN][2] = 40, [2][0][RTW89_UK][2] = 52, + [2][0][RTW89_MEXICO][2] = 62, + [2][0][RTW89_UKRAINE][2] = 46, + [2][0][RTW89_CHILE][2] = 64, + [2][0][RTW89_QATAR][2] = 52, [2][0][RTW89_FCC][4] = 68, [2][0][RTW89_ETSI][4] = 52, [2][0][RTW89_MKK][4] = 50, [2][0][RTW89_IC][4] = 50, - [2][0][RTW89_KCC][4] = 64, + [2][0][RTW89_KCC][4] = 60, [2][0][RTW89_ACMA][4] = 52, [2][0][RTW89_CN][4] = 40, [2][0][RTW89_UK][4] = 52, + [2][0][RTW89_MEXICO][4] = 62, + [2][0][RTW89_UKRAINE][4] = 46, + [2][0][RTW89_CHILE][4] = 68, + [2][0][RTW89_QATAR][4] = 52, [2][0][RTW89_FCC][6] = 68, [2][0][RTW89_ETSI][6] = 52, [2][0][RTW89_MKK][6] = 50, [2][0][RTW89_IC][6] = 50, - [2][0][RTW89_KCC][6] = 36, + [2][0][RTW89_KCC][6] = 38, [2][0][RTW89_ACMA][6] = 52, [2][0][RTW89_CN][6] = 40, [2][0][RTW89_UK][6] = 52, + [2][0][RTW89_MEXICO][6] = 62, + [2][0][RTW89_UKRAINE][6] = 46, + [2][0][RTW89_CHILE][6] = 68, + [2][0][RTW89_QATAR][6] = 52, [2][0][RTW89_FCC][8] = 68, [2][0][RTW89_ETSI][8] = 52, [2][0][RTW89_MKK][8] = 44, [2][0][RTW89_IC][8] = 64, - [2][0][RTW89_KCC][8] = 62, + [2][0][RTW89_KCC][8] = 56, [2][0][RTW89_ACMA][8] = 52, [2][0][RTW89_CN][8] = 40, [2][0][RTW89_UK][8] = 52, + [2][0][RTW89_MEXICO][8] = 68, + [2][0][RTW89_UKRAINE][8] = 46, + [2][0][RTW89_CHILE][8] = 68, + [2][0][RTW89_QATAR][8] = 52, [2][0][RTW89_FCC][10] = 68, [2][0][RTW89_ETSI][10] = 52, [2][0][RTW89_MKK][10] = 44, [2][0][RTW89_IC][10] = 64, - [2][0][RTW89_KCC][10] = 62, + [2][0][RTW89_KCC][10] = 56, [2][0][RTW89_ACMA][10] = 52, [2][0][RTW89_CN][10] = 40, [2][0][RTW89_UK][10] = 52, + [2][0][RTW89_MEXICO][10] = 68, + [2][0][RTW89_UKRAINE][10] = 46, + [2][0][RTW89_CHILE][10] = 68, + [2][0][RTW89_QATAR][10] = 52, [2][0][RTW89_FCC][12] = 68, [2][0][RTW89_ETSI][12] = 52, [2][0][RTW89_MKK][12] = 58, [2][0][RTW89_IC][12] = 64, - [2][0][RTW89_KCC][12] = 62, + [2][0][RTW89_KCC][12] = 58, [2][0][RTW89_ACMA][12] = 52, [2][0][RTW89_CN][12] = 40, [2][0][RTW89_UK][12] = 52, + [2][0][RTW89_MEXICO][12] = 68, + [2][0][RTW89_UKRAINE][12] = 46, + [2][0][RTW89_CHILE][12] = 68, + [2][0][RTW89_QATAR][12] = 52, [2][0][RTW89_FCC][14] = 68, [2][0][RTW89_ETSI][14] = 52, [2][0][RTW89_MKK][14] = 58, [2][0][RTW89_IC][14] = 64, - [2][0][RTW89_KCC][14] = 62, + [2][0][RTW89_KCC][14] = 58, [2][0][RTW89_ACMA][14] = 52, [2][0][RTW89_CN][14] = 40, [2][0][RTW89_UK][14] = 52, + [2][0][RTW89_MEXICO][14] = 68, + [2][0][RTW89_UKRAINE][14] = 46, + [2][0][RTW89_CHILE][14] = 68, + [2][0][RTW89_QATAR][14] = 52, [2][0][RTW89_FCC][15] = 68, [2][0][RTW89_ETSI][15] = 52, [2][0][RTW89_MKK][15] = 68, [2][0][RTW89_IC][15] = 68, - [2][0][RTW89_KCC][15] = 62, + [2][0][RTW89_KCC][15] = 58, [2][0][RTW89_ACMA][15] = 52, [2][0][RTW89_CN][15] = 127, [2][0][RTW89_UK][15] = 52, + [2][0][RTW89_MEXICO][15] = 68, + [2][0][RTW89_UKRAINE][15] = 46, + [2][0][RTW89_CHILE][15] = 68, + [2][0][RTW89_QATAR][15] = 52, [2][0][RTW89_FCC][17] = 68, [2][0][RTW89_ETSI][17] = 52, [2][0][RTW89_MKK][17] = 74, [2][0][RTW89_IC][17] = 68, - [2][0][RTW89_KCC][17] = 62, + [2][0][RTW89_KCC][17] = 58, [2][0][RTW89_ACMA][17] = 52, [2][0][RTW89_CN][17] = 127, [2][0][RTW89_UK][17] = 52, + [2][0][RTW89_MEXICO][17] = 68, + [2][0][RTW89_UKRAINE][17] = 46, + [2][0][RTW89_CHILE][17] = 68, + [2][0][RTW89_QATAR][17] = 52, [2][0][RTW89_FCC][19] = 70, [2][0][RTW89_ETSI][19] = 52, [2][0][RTW89_MKK][19] = 74, [2][0][RTW89_IC][19] = 70, - [2][0][RTW89_KCC][19] = 62, + [2][0][RTW89_KCC][19] = 58, [2][0][RTW89_ACMA][19] = 52, [2][0][RTW89_CN][19] = 127, [2][0][RTW89_UK][19] = 52, + [2][0][RTW89_MEXICO][19] = 70, + [2][0][RTW89_UKRAINE][19] = 46, + [2][0][RTW89_CHILE][19] = 70, + [2][0][RTW89_QATAR][19] = 52, [2][0][RTW89_FCC][21] = 70, [2][0][RTW89_ETSI][21] = 52, [2][0][RTW89_MKK][21] = 74, [2][0][RTW89_IC][21] = 70, - [2][0][RTW89_KCC][21] = 62, + [2][0][RTW89_KCC][21] = 58, [2][0][RTW89_ACMA][21] = 52, [2][0][RTW89_CN][21] = 127, [2][0][RTW89_UK][21] = 52, + [2][0][RTW89_MEXICO][21] = 70, + [2][0][RTW89_UKRAINE][21] = 46, + [2][0][RTW89_CHILE][21] = 70, + [2][0][RTW89_QATAR][21] = 52, [2][0][RTW89_FCC][23] = 70, [2][0][RTW89_ETSI][23] = 52, [2][0][RTW89_MKK][23] = 74, [2][0][RTW89_IC][23] = 70, - [2][0][RTW89_KCC][23] = 62, + [2][0][RTW89_KCC][23] = 58, [2][0][RTW89_ACMA][23] = 52, [2][0][RTW89_CN][23] = 127, [2][0][RTW89_UK][23] = 52, + [2][0][RTW89_MEXICO][23] = 70, + [2][0][RTW89_UKRAINE][23] = 46, + [2][0][RTW89_CHILE][23] = 70, + [2][0][RTW89_QATAR][23] = 52, [2][0][RTW89_FCC][25] = 70, [2][0][RTW89_ETSI][25] = 52, [2][0][RTW89_MKK][25] = 74, [2][0][RTW89_IC][25] = 127, - [2][0][RTW89_KCC][25] = 62, + [2][0][RTW89_KCC][25] = 58, [2][0][RTW89_ACMA][25] = 127, [2][0][RTW89_CN][25] = 127, [2][0][RTW89_UK][25] = 52, + [2][0][RTW89_MEXICO][25] = 70, + [2][0][RTW89_UKRAINE][25] = 46, + [2][0][RTW89_CHILE][25] = 70, + [2][0][RTW89_QATAR][25] = 52, [2][0][RTW89_FCC][27] = 70, [2][0][RTW89_ETSI][27] = 52, [2][0][RTW89_MKK][27] = 74, [2][0][RTW89_IC][27] = 127, - [2][0][RTW89_KCC][27] = 62, + [2][0][RTW89_KCC][27] = 58, [2][0][RTW89_ACMA][27] = 127, [2][0][RTW89_CN][27] = 127, [2][0][RTW89_UK][27] = 52, + [2][0][RTW89_MEXICO][27] = 70, + [2][0][RTW89_UKRAINE][27] = 46, + [2][0][RTW89_CHILE][27] = 70, + [2][0][RTW89_QATAR][27] = 52, [2][0][RTW89_FCC][29] = 70, [2][0][RTW89_ETSI][29] = 52, [2][0][RTW89_MKK][29] = 74, [2][0][RTW89_IC][29] = 127, - [2][0][RTW89_KCC][29] = 62, + [2][0][RTW89_KCC][29] = 58, [2][0][RTW89_ACMA][29] = 127, [2][0][RTW89_CN][29] = 127, [2][0][RTW89_UK][29] = 52, + [2][0][RTW89_MEXICO][29] = 70, + [2][0][RTW89_UKRAINE][29] = 46, + [2][0][RTW89_CHILE][29] = 70, + [2][0][RTW89_QATAR][29] = 52, [2][0][RTW89_FCC][31] = 70, [2][0][RTW89_ETSI][31] = 52, [2][0][RTW89_MKK][31] = 74, [2][0][RTW89_IC][31] = 62, - [2][0][RTW89_KCC][31] = 62, + [2][0][RTW89_KCC][31] = 56, [2][0][RTW89_ACMA][31] = 52, [2][0][RTW89_CN][31] = 127, [2][0][RTW89_UK][31] = 52, + [2][0][RTW89_MEXICO][31] = 70, + [2][0][RTW89_UKRAINE][31] = 46, + [2][0][RTW89_CHILE][31] = 70, + [2][0][RTW89_QATAR][31] = 52, [2][0][RTW89_FCC][33] = 62, [2][0][RTW89_ETSI][33] = 52, [2][0][RTW89_MKK][33] = 74, [2][0][RTW89_IC][33] = 62, - [2][0][RTW89_KCC][33] = 62, + [2][0][RTW89_KCC][33] = 56, [2][0][RTW89_ACMA][33] = 52, [2][0][RTW89_CN][33] = 127, [2][0][RTW89_UK][33] = 52, + [2][0][RTW89_MEXICO][33] = 62, + [2][0][RTW89_UKRAINE][33] = 46, + [2][0][RTW89_CHILE][33] = 62, + [2][0][RTW89_QATAR][33] = 52, [2][0][RTW89_FCC][35] = 62, [2][0][RTW89_ETSI][35] = 52, [2][0][RTW89_MKK][35] = 74, [2][0][RTW89_IC][35] = 62, - [2][0][RTW89_KCC][35] = 62, + [2][0][RTW89_KCC][35] = 56, [2][0][RTW89_ACMA][35] = 52, [2][0][RTW89_CN][35] = 127, [2][0][RTW89_UK][35] = 52, + [2][0][RTW89_MEXICO][35] = 62, + [2][0][RTW89_UKRAINE][35] = 46, + [2][0][RTW89_CHILE][35] = 62, + [2][0][RTW89_QATAR][35] = 52, [2][0][RTW89_FCC][37] = 70, [2][0][RTW89_ETSI][37] = 127, [2][0][RTW89_MKK][37] = 74, [2][0][RTW89_IC][37] = 70, - [2][0][RTW89_KCC][37] = 62, + [2][0][RTW89_KCC][37] = 56, [2][0][RTW89_ACMA][37] = 70, [2][0][RTW89_CN][37] = 127, [2][0][RTW89_UK][37] = 52, + [2][0][RTW89_MEXICO][37] = 70, + [2][0][RTW89_UKRAINE][37] = 127, + [2][0][RTW89_CHILE][37] = 70, + [2][0][RTW89_QATAR][37] = 127, [2][0][RTW89_FCC][38] = 82, [2][0][RTW89_ETSI][38] = 28, [2][0][RTW89_MKK][38] = 127, [2][0][RTW89_IC][38] = 82, - [2][0][RTW89_KCC][38] = 64, + [2][0][RTW89_KCC][38] = 60, [2][0][RTW89_ACMA][38] = 82, [2][0][RTW89_CN][38] = 68, [2][0][RTW89_UK][38] = 54, + [2][0][RTW89_MEXICO][38] = 82, + [2][0][RTW89_UKRAINE][38] = 26, + [2][0][RTW89_CHILE][38] = 82, + [2][0][RTW89_QATAR][38] = 26, [2][0][RTW89_FCC][40] = 82, [2][0][RTW89_ETSI][40] = 28, [2][0][RTW89_MKK][40] = 127, [2][0][RTW89_IC][40] = 82, - [2][0][RTW89_KCC][40] = 64, + [2][0][RTW89_KCC][40] = 60, [2][0][RTW89_ACMA][40] = 82, [2][0][RTW89_CN][40] = 68, [2][0][RTW89_UK][40] = 54, + [2][0][RTW89_MEXICO][40] = 82, + [2][0][RTW89_UKRAINE][40] = 26, + [2][0][RTW89_CHILE][40] = 82, + [2][0][RTW89_QATAR][40] = 26, [2][0][RTW89_FCC][42] = 76, [2][0][RTW89_ETSI][42] = 28, [2][0][RTW89_MKK][42] = 127, [2][0][RTW89_IC][42] = 76, - [2][0][RTW89_KCC][42] = 64, + [2][0][RTW89_KCC][42] = 60, [2][0][RTW89_ACMA][42] = 76, [2][0][RTW89_CN][42] = 68, [2][0][RTW89_UK][42] = 54, + [2][0][RTW89_MEXICO][42] = 76, + [2][0][RTW89_UKRAINE][42] = 26, + [2][0][RTW89_CHILE][42] = 76, + [2][0][RTW89_QATAR][42] = 26, [2][0][RTW89_FCC][44] = 80, [2][0][RTW89_ETSI][44] = 28, [2][0][RTW89_MKK][44] = 127, [2][0][RTW89_IC][44] = 80, - [2][0][RTW89_KCC][44] = 64, + [2][0][RTW89_KCC][44] = 60, [2][0][RTW89_ACMA][44] = 80, [2][0][RTW89_CN][44] = 68, [2][0][RTW89_UK][44] = 54, + [2][0][RTW89_MEXICO][44] = 80, + [2][0][RTW89_UKRAINE][44] = 26, + [2][0][RTW89_CHILE][44] = 80, + [2][0][RTW89_QATAR][44] = 26, [2][0][RTW89_FCC][46] = 80, [2][0][RTW89_ETSI][46] = 28, [2][0][RTW89_MKK][46] = 127, [2][0][RTW89_IC][46] = 80, - [2][0][RTW89_KCC][46] = 64, + [2][0][RTW89_KCC][46] = 60, [2][0][RTW89_ACMA][46] = 80, [2][0][RTW89_CN][46] = 68, [2][0][RTW89_UK][46] = 54, + [2][0][RTW89_MEXICO][46] = 80, + [2][0][RTW89_UKRAINE][46] = 26, + [2][0][RTW89_CHILE][46] = 80, + [2][0][RTW89_QATAR][46] = 26, [2][0][RTW89_FCC][48] = 64, [2][0][RTW89_ETSI][48] = 127, [2][0][RTW89_MKK][48] = 127, @@ -36016,6 +48725,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][48] = 127, [2][0][RTW89_CN][48] = 127, [2][0][RTW89_UK][48] = 127, + [2][0][RTW89_MEXICO][48] = 127, + [2][0][RTW89_UKRAINE][48] = 127, + [2][0][RTW89_CHILE][48] = 127, + [2][0][RTW89_QATAR][48] = 127, [2][0][RTW89_FCC][50] = 64, [2][0][RTW89_ETSI][50] = 127, [2][0][RTW89_MKK][50] = 127, @@ -36024,6 +48737,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][50] = 127, [2][0][RTW89_CN][50] = 127, [2][0][RTW89_UK][50] = 127, + [2][0][RTW89_MEXICO][50] = 127, + [2][0][RTW89_UKRAINE][50] = 127, + [2][0][RTW89_CHILE][50] = 127, + [2][0][RTW89_QATAR][50] = 127, [2][0][RTW89_FCC][52] = 64, [2][0][RTW89_ETSI][52] = 127, [2][0][RTW89_MKK][52] = 127, @@ -36032,206 +48749,310 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][0][RTW89_ACMA][52] = 127, [2][0][RTW89_CN][52] = 127, [2][0][RTW89_UK][52] = 127, + [2][0][RTW89_MEXICO][52] = 127, + [2][0][RTW89_UKRAINE][52] = 127, + [2][0][RTW89_CHILE][52] = 127, + [2][0][RTW89_QATAR][52] = 127, [2][1][RTW89_FCC][0] = 50, [2][1][RTW89_ETSI][0] = 40, [2][1][RTW89_MKK][0] = 44, [2][1][RTW89_IC][0] = 26, - [2][1][RTW89_KCC][0] = 44, + [2][1][RTW89_KCC][0] = 52, [2][1][RTW89_ACMA][0] = 40, [2][1][RTW89_CN][0] = 28, [2][1][RTW89_UK][0] = 40, + [2][1][RTW89_MEXICO][0] = 50, + [2][1][RTW89_UKRAINE][0] = 34, + [2][1][RTW89_CHILE][0] = 50, + [2][1][RTW89_QATAR][0] = 40, [2][1][RTW89_FCC][2] = 50, [2][1][RTW89_ETSI][2] = 40, [2][1][RTW89_MKK][2] = 44, [2][1][RTW89_IC][2] = 26, - [2][1][RTW89_KCC][2] = 44, + [2][1][RTW89_KCC][2] = 52, [2][1][RTW89_ACMA][2] = 40, [2][1][RTW89_CN][2] = 28, [2][1][RTW89_UK][2] = 40, + [2][1][RTW89_MEXICO][2] = 50, + [2][1][RTW89_UKRAINE][2] = 34, + [2][1][RTW89_CHILE][2] = 50, + [2][1][RTW89_QATAR][2] = 40, [2][1][RTW89_FCC][4] = 50, [2][1][RTW89_ETSI][4] = 40, [2][1][RTW89_MKK][4] = 36, [2][1][RTW89_IC][4] = 26, - [2][1][RTW89_KCC][4] = 44, + [2][1][RTW89_KCC][4] = 52, [2][1][RTW89_ACMA][4] = 40, [2][1][RTW89_CN][4] = 28, [2][1][RTW89_UK][4] = 40, + [2][1][RTW89_MEXICO][4] = 50, + [2][1][RTW89_UKRAINE][4] = 34, + [2][1][RTW89_CHILE][4] = 50, + [2][1][RTW89_QATAR][4] = 40, [2][1][RTW89_FCC][6] = 50, [2][1][RTW89_ETSI][6] = 40, [2][1][RTW89_MKK][6] = 36, [2][1][RTW89_IC][6] = 26, - [2][1][RTW89_KCC][6] = 20, + [2][1][RTW89_KCC][6] = 30, [2][1][RTW89_ACMA][6] = 40, [2][1][RTW89_CN][6] = 28, [2][1][RTW89_UK][6] = 40, + [2][1][RTW89_MEXICO][6] = 50, + [2][1][RTW89_UKRAINE][6] = 34, + [2][1][RTW89_CHILE][6] = 50, + [2][1][RTW89_QATAR][6] = 40, [2][1][RTW89_FCC][8] = 50, [2][1][RTW89_ETSI][8] = 40, [2][1][RTW89_MKK][8] = 32, [2][1][RTW89_IC][8] = 50, - [2][1][RTW89_KCC][8] = 46, + [2][1][RTW89_KCC][8] = 50, [2][1][RTW89_ACMA][8] = 40, [2][1][RTW89_CN][8] = 28, [2][1][RTW89_UK][8] = 40, + [2][1][RTW89_MEXICO][8] = 50, + [2][1][RTW89_UKRAINE][8] = 34, + [2][1][RTW89_CHILE][8] = 50, + [2][1][RTW89_QATAR][8] = 40, [2][1][RTW89_FCC][10] = 50, [2][1][RTW89_ETSI][10] = 40, [2][1][RTW89_MKK][10] = 32, [2][1][RTW89_IC][10] = 50, - [2][1][RTW89_KCC][10] = 46, + [2][1][RTW89_KCC][10] = 50, [2][1][RTW89_ACMA][10] = 40, [2][1][RTW89_CN][10] = 28, [2][1][RTW89_UK][10] = 40, + [2][1][RTW89_MEXICO][10] = 50, + [2][1][RTW89_UKRAINE][10] = 34, + [2][1][RTW89_CHILE][10] = 50, + [2][1][RTW89_QATAR][10] = 40, [2][1][RTW89_FCC][12] = 48, [2][1][RTW89_ETSI][12] = 40, [2][1][RTW89_MKK][12] = 44, [2][1][RTW89_IC][12] = 48, - [2][1][RTW89_KCC][12] = 46, + [2][1][RTW89_KCC][12] = 48, [2][1][RTW89_ACMA][12] = 40, [2][1][RTW89_CN][12] = 28, [2][1][RTW89_UK][12] = 40, + [2][1][RTW89_MEXICO][12] = 48, + [2][1][RTW89_UKRAINE][12] = 34, + [2][1][RTW89_CHILE][12] = 48, + [2][1][RTW89_QATAR][12] = 40, [2][1][RTW89_FCC][14] = 48, [2][1][RTW89_ETSI][14] = 40, [2][1][RTW89_MKK][14] = 44, [2][1][RTW89_IC][14] = 48, - [2][1][RTW89_KCC][14] = 46, + [2][1][RTW89_KCC][14] = 48, [2][1][RTW89_ACMA][14] = 40, [2][1][RTW89_CN][14] = 28, [2][1][RTW89_UK][14] = 40, + [2][1][RTW89_MEXICO][14] = 48, + [2][1][RTW89_UKRAINE][14] = 34, + [2][1][RTW89_CHILE][14] = 48, + [2][1][RTW89_QATAR][14] = 40, [2][1][RTW89_FCC][15] = 50, [2][1][RTW89_ETSI][15] = 40, [2][1][RTW89_MKK][15] = 66, [2][1][RTW89_IC][15] = 50, - [2][1][RTW89_KCC][15] = 46, + [2][1][RTW89_KCC][15] = 48, [2][1][RTW89_ACMA][15] = 40, [2][1][RTW89_CN][15] = 127, [2][1][RTW89_UK][15] = 40, + [2][1][RTW89_MEXICO][15] = 50, + [2][1][RTW89_UKRAINE][15] = 34, + [2][1][RTW89_CHILE][15] = 50, + [2][1][RTW89_QATAR][15] = 40, [2][1][RTW89_FCC][17] = 50, [2][1][RTW89_ETSI][17] = 40, [2][1][RTW89_MKK][17] = 66, [2][1][RTW89_IC][17] = 50, - [2][1][RTW89_KCC][17] = 46, + [2][1][RTW89_KCC][17] = 48, [2][1][RTW89_ACMA][17] = 40, [2][1][RTW89_CN][17] = 127, [2][1][RTW89_UK][17] = 40, + [2][1][RTW89_MEXICO][17] = 50, + [2][1][RTW89_UKRAINE][17] = 34, + [2][1][RTW89_CHILE][17] = 50, + [2][1][RTW89_QATAR][17] = 40, [2][1][RTW89_FCC][19] = 50, [2][1][RTW89_ETSI][19] = 40, [2][1][RTW89_MKK][19] = 66, [2][1][RTW89_IC][19] = 50, - [2][1][RTW89_KCC][19] = 46, + [2][1][RTW89_KCC][19] = 48, [2][1][RTW89_ACMA][19] = 40, [2][1][RTW89_CN][19] = 127, [2][1][RTW89_UK][19] = 40, + [2][1][RTW89_MEXICO][19] = 50, + [2][1][RTW89_UKRAINE][19] = 34, + [2][1][RTW89_CHILE][19] = 50, + [2][1][RTW89_QATAR][19] = 40, [2][1][RTW89_FCC][21] = 50, [2][1][RTW89_ETSI][21] = 40, [2][1][RTW89_MKK][21] = 66, [2][1][RTW89_IC][21] = 50, - [2][1][RTW89_KCC][21] = 46, + [2][1][RTW89_KCC][21] = 48, [2][1][RTW89_ACMA][21] = 40, [2][1][RTW89_CN][21] = 127, [2][1][RTW89_UK][21] = 40, + [2][1][RTW89_MEXICO][21] = 50, + [2][1][RTW89_UKRAINE][21] = 34, + [2][1][RTW89_CHILE][21] = 50, + [2][1][RTW89_QATAR][21] = 40, [2][1][RTW89_FCC][23] = 50, [2][1][RTW89_ETSI][23] = 40, [2][1][RTW89_MKK][23] = 66, [2][1][RTW89_IC][23] = 50, - [2][1][RTW89_KCC][23] = 46, + [2][1][RTW89_KCC][23] = 48, [2][1][RTW89_ACMA][23] = 40, [2][1][RTW89_CN][23] = 127, [2][1][RTW89_UK][23] = 40, + [2][1][RTW89_MEXICO][23] = 50, + [2][1][RTW89_UKRAINE][23] = 34, + [2][1][RTW89_CHILE][23] = 50, + [2][1][RTW89_QATAR][23] = 40, [2][1][RTW89_FCC][25] = 50, [2][1][RTW89_ETSI][25] = 40, [2][1][RTW89_MKK][25] = 66, [2][1][RTW89_IC][25] = 127, - [2][1][RTW89_KCC][25] = 46, + [2][1][RTW89_KCC][25] = 48, [2][1][RTW89_ACMA][25] = 127, [2][1][RTW89_CN][25] = 127, [2][1][RTW89_UK][25] = 40, + [2][1][RTW89_MEXICO][25] = 50, + [2][1][RTW89_UKRAINE][25] = 34, + [2][1][RTW89_CHILE][25] = 50, + [2][1][RTW89_QATAR][25] = 40, [2][1][RTW89_FCC][27] = 50, [2][1][RTW89_ETSI][27] = 40, [2][1][RTW89_MKK][27] = 66, [2][1][RTW89_IC][27] = 127, - [2][1][RTW89_KCC][27] = 46, + [2][1][RTW89_KCC][27] = 48, [2][1][RTW89_ACMA][27] = 127, [2][1][RTW89_CN][27] = 127, [2][1][RTW89_UK][27] = 40, + [2][1][RTW89_MEXICO][27] = 50, + [2][1][RTW89_UKRAINE][27] = 34, + [2][1][RTW89_CHILE][27] = 50, + [2][1][RTW89_QATAR][27] = 40, [2][1][RTW89_FCC][29] = 50, [2][1][RTW89_ETSI][29] = 40, [2][1][RTW89_MKK][29] = 66, [2][1][RTW89_IC][29] = 127, - [2][1][RTW89_KCC][29] = 46, + [2][1][RTW89_KCC][29] = 48, [2][1][RTW89_ACMA][29] = 127, [2][1][RTW89_CN][29] = 127, [2][1][RTW89_UK][29] = 40, + [2][1][RTW89_MEXICO][29] = 50, + [2][1][RTW89_UKRAINE][29] = 34, + [2][1][RTW89_CHILE][29] = 50, + [2][1][RTW89_QATAR][29] = 40, [2][1][RTW89_FCC][31] = 50, [2][1][RTW89_ETSI][31] = 40, [2][1][RTW89_MKK][31] = 66, [2][1][RTW89_IC][31] = 48, - [2][1][RTW89_KCC][31] = 46, + [2][1][RTW89_KCC][31] = 48, [2][1][RTW89_ACMA][31] = 40, [2][1][RTW89_CN][31] = 127, [2][1][RTW89_UK][31] = 40, + [2][1][RTW89_MEXICO][31] = 50, + [2][1][RTW89_UKRAINE][31] = 34, + [2][1][RTW89_CHILE][31] = 50, + [2][1][RTW89_QATAR][31] = 40, [2][1][RTW89_FCC][33] = 48, [2][1][RTW89_ETSI][33] = 40, [2][1][RTW89_MKK][33] = 66, [2][1][RTW89_IC][33] = 48, - [2][1][RTW89_KCC][33] = 46, + [2][1][RTW89_KCC][33] = 48, [2][1][RTW89_ACMA][33] = 40, [2][1][RTW89_CN][33] = 127, [2][1][RTW89_UK][33] = 40, + [2][1][RTW89_MEXICO][33] = 48, + [2][1][RTW89_UKRAINE][33] = 34, + [2][1][RTW89_CHILE][33] = 48, + [2][1][RTW89_QATAR][33] = 40, [2][1][RTW89_FCC][35] = 48, [2][1][RTW89_ETSI][35] = 40, [2][1][RTW89_MKK][35] = 66, [2][1][RTW89_IC][35] = 48, - [2][1][RTW89_KCC][35] = 46, + [2][1][RTW89_KCC][35] = 48, [2][1][RTW89_ACMA][35] = 40, [2][1][RTW89_CN][35] = 127, [2][1][RTW89_UK][35] = 40, + [2][1][RTW89_MEXICO][35] = 48, + [2][1][RTW89_UKRAINE][35] = 34, + [2][1][RTW89_CHILE][35] = 48, + [2][1][RTW89_QATAR][35] = 40, [2][1][RTW89_FCC][37] = 52, [2][1][RTW89_ETSI][37] = 127, [2][1][RTW89_MKK][37] = 66, [2][1][RTW89_IC][37] = 52, - [2][1][RTW89_KCC][37] = 46, + [2][1][RTW89_KCC][37] = 48, [2][1][RTW89_ACMA][37] = 52, [2][1][RTW89_CN][37] = 127, [2][1][RTW89_UK][37] = 42, + [2][1][RTW89_MEXICO][37] = 52, + [2][1][RTW89_UKRAINE][37] = 127, + [2][1][RTW89_CHILE][37] = 52, + [2][1][RTW89_QATAR][37] = 127, [2][1][RTW89_FCC][38] = 78, [2][1][RTW89_ETSI][38] = 16, [2][1][RTW89_MKK][38] = 127, [2][1][RTW89_IC][38] = 78, - [2][1][RTW89_KCC][38] = 46, + [2][1][RTW89_KCC][38] = 50, [2][1][RTW89_ACMA][38] = 78, [2][1][RTW89_CN][38] = 56, [2][1][RTW89_UK][38] = 42, + [2][1][RTW89_MEXICO][38] = 78, + [2][1][RTW89_UKRAINE][38] = 14, + [2][1][RTW89_CHILE][38] = 72, + [2][1][RTW89_QATAR][38] = 14, [2][1][RTW89_FCC][40] = 78, [2][1][RTW89_ETSI][40] = 16, [2][1][RTW89_MKK][40] = 127, [2][1][RTW89_IC][40] = 78, - [2][1][RTW89_KCC][40] = 46, + [2][1][RTW89_KCC][40] = 50, [2][1][RTW89_ACMA][40] = 78, [2][1][RTW89_CN][40] = 56, [2][1][RTW89_UK][40] = 42, + [2][1][RTW89_MEXICO][40] = 78, + [2][1][RTW89_UKRAINE][40] = 14, + [2][1][RTW89_CHILE][40] = 72, + [2][1][RTW89_QATAR][40] = 14, [2][1][RTW89_FCC][42] = 78, [2][1][RTW89_ETSI][42] = 16, [2][1][RTW89_MKK][42] = 127, [2][1][RTW89_IC][42] = 78, - [2][1][RTW89_KCC][42] = 46, + [2][1][RTW89_KCC][42] = 50, [2][1][RTW89_ACMA][42] = 78, [2][1][RTW89_CN][42] = 56, [2][1][RTW89_UK][42] = 42, + [2][1][RTW89_MEXICO][42] = 78, + [2][1][RTW89_UKRAINE][42] = 14, + [2][1][RTW89_CHILE][42] = 72, + [2][1][RTW89_QATAR][42] = 14, [2][1][RTW89_FCC][44] = 74, [2][1][RTW89_ETSI][44] = 16, [2][1][RTW89_MKK][44] = 127, [2][1][RTW89_IC][44] = 74, - [2][1][RTW89_KCC][44] = 46, + [2][1][RTW89_KCC][44] = 50, [2][1][RTW89_ACMA][44] = 74, [2][1][RTW89_CN][44] = 56, [2][1][RTW89_UK][44] = 42, + [2][1][RTW89_MEXICO][44] = 74, + [2][1][RTW89_UKRAINE][44] = 14, + [2][1][RTW89_CHILE][44] = 72, + [2][1][RTW89_QATAR][44] = 14, [2][1][RTW89_FCC][46] = 74, [2][1][RTW89_ETSI][46] = 16, [2][1][RTW89_MKK][46] = 127, [2][1][RTW89_IC][46] = 74, - [2][1][RTW89_KCC][46] = 46, + [2][1][RTW89_KCC][46] = 50, [2][1][RTW89_ACMA][46] = 74, [2][1][RTW89_CN][46] = 56, [2][1][RTW89_UK][46] = 42, + [2][1][RTW89_MEXICO][46] = 74, + [2][1][RTW89_UKRAINE][46] = 14, + [2][1][RTW89_CHILE][46] = 72, + [2][1][RTW89_QATAR][46] = 14, [2][1][RTW89_FCC][48] = 40, [2][1][RTW89_ETSI][48] = 127, [2][1][RTW89_MKK][48] = 127, @@ -36240,6 +49061,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][48] = 127, [2][1][RTW89_CN][48] = 127, [2][1][RTW89_UK][48] = 127, + [2][1][RTW89_MEXICO][48] = 127, + [2][1][RTW89_UKRAINE][48] = 127, + [2][1][RTW89_CHILE][48] = 127, + [2][1][RTW89_QATAR][48] = 127, [2][1][RTW89_FCC][50] = 40, [2][1][RTW89_ETSI][50] = 127, [2][1][RTW89_MKK][50] = 127, @@ -36248,6 +49073,10 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][50] = 127, [2][1][RTW89_CN][50] = 127, [2][1][RTW89_UK][50] = 127, + [2][1][RTW89_MEXICO][50] = 127, + [2][1][RTW89_UKRAINE][50] = 127, + [2][1][RTW89_CHILE][50] = 127, + [2][1][RTW89_QATAR][50] = 127, [2][1][RTW89_FCC][52] = 40, [2][1][RTW89_ETSI][52] = 127, [2][1][RTW89_MKK][52] = 127, @@ -36256,1163 +49085,7312 @@ const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM] [2][1][RTW89_ACMA][52] = 127, [2][1][RTW89_CN][52] = 127, [2][1][RTW89_UK][52] = 127, + [2][1][RTW89_MEXICO][52] = 127, + [2][1][RTW89_UKRAINE][52] = 127, + [2][1][RTW89_CHILE][52] = 127, + [2][1][RTW89_QATAR][52] = 127, }; static const s8 rtw89_8852c_txpwr_lmt_ru_6g[RTW89_RU_NUM][RTW89_NTX_NUM] - [RTW89_REGD_NUM][RTW89_6G_CH_NUM] = { - [0][0][RTW89_WW][0] = -16, - [0][0][RTW89_WW][2] = -18, - [0][0][RTW89_WW][4] = -18, - [0][0][RTW89_WW][6] = -18, - [0][0][RTW89_WW][8] = -18, - [0][0][RTW89_WW][10] = -18, - [0][0][RTW89_WW][12] = -18, - [0][0][RTW89_WW][14] = -18, - [0][0][RTW89_WW][15] = -18, - [0][0][RTW89_WW][17] = -18, - [0][0][RTW89_WW][19] = -18, - [0][0][RTW89_WW][21] = -18, - [0][0][RTW89_WW][23] = -18, - [0][0][RTW89_WW][25] = -18, - [0][0][RTW89_WW][27] = -18, - [0][0][RTW89_WW][29] = -18, - [0][0][RTW89_WW][30] = -18, - [0][0][RTW89_WW][32] = -18, - [0][0][RTW89_WW][34] = -18, - [0][0][RTW89_WW][36] = -18, - [0][0][RTW89_WW][38] = -18, - [0][0][RTW89_WW][40] = -18, - [0][0][RTW89_WW][42] = -18, - [0][0][RTW89_WW][44] = -16, - [0][0][RTW89_WW][45] = -16, - [0][0][RTW89_WW][47] = -18, - [0][0][RTW89_WW][49] = -18, - [0][0][RTW89_WW][51] = -18, - [0][0][RTW89_WW][53] = -16, - [0][0][RTW89_WW][55] = -18, - [0][0][RTW89_WW][57] = -18, - [0][0][RTW89_WW][59] = -18, - [0][0][RTW89_WW][60] = -18, - [0][0][RTW89_WW][62] = -18, - [0][0][RTW89_WW][64] = -18, - [0][0][RTW89_WW][66] = -18, - [0][0][RTW89_WW][68] = -18, - [0][0][RTW89_WW][70] = -16, - [0][0][RTW89_WW][72] = -18, - [0][0][RTW89_WW][74] = -18, - [0][0][RTW89_WW][75] = -18, - [0][0][RTW89_WW][77] = -18, - [0][0][RTW89_WW][79] = -18, - [0][0][RTW89_WW][81] = -18, - [0][0][RTW89_WW][83] = -18, - [0][0][RTW89_WW][85] = -18, - [0][0][RTW89_WW][87] = -16, - [0][0][RTW89_WW][89] = -16, - [0][0][RTW89_WW][90] = -16, - [0][0][RTW89_WW][92] = -16, - [0][0][RTW89_WW][94] = -16, - [0][0][RTW89_WW][96] = -16, - [0][0][RTW89_WW][98] = -16, - [0][0][RTW89_WW][100] = -16, - [0][0][RTW89_WW][102] = -16, - [0][0][RTW89_WW][104] = -16, - [0][0][RTW89_WW][105] = -16, - [0][0][RTW89_WW][107] = -12, - [0][0][RTW89_WW][109] = -12, - [0][0][RTW89_WW][111] = 0, - [0][0][RTW89_WW][113] = 0, - [0][0][RTW89_WW][115] = 0, - [0][0][RTW89_WW][117] = 0, - [0][0][RTW89_WW][119] = 0, - [0][1][RTW89_WW][0] = -40, - [0][1][RTW89_WW][2] = -40, - [0][1][RTW89_WW][4] = -40, - [0][1][RTW89_WW][6] = -40, - [0][1][RTW89_WW][8] = -40, - [0][1][RTW89_WW][10] = -40, - [0][1][RTW89_WW][12] = -40, - [0][1][RTW89_WW][14] = -40, - [0][1][RTW89_WW][15] = -40, - [0][1][RTW89_WW][17] = -40, - [0][1][RTW89_WW][19] = -40, - [0][1][RTW89_WW][21] = -40, - [0][1][RTW89_WW][23] = -40, - [0][1][RTW89_WW][25] = -40, - [0][1][RTW89_WW][27] = -40, - [0][1][RTW89_WW][29] = -40, - [0][1][RTW89_WW][30] = -40, - [0][1][RTW89_WW][32] = -40, - [0][1][RTW89_WW][34] = -40, - [0][1][RTW89_WW][36] = -40, - [0][1][RTW89_WW][38] = -40, - [0][1][RTW89_WW][40] = -40, - [0][1][RTW89_WW][42] = -40, - [0][1][RTW89_WW][44] = -40, - [0][1][RTW89_WW][45] = -40, - [0][1][RTW89_WW][47] = -40, - [0][1][RTW89_WW][49] = -40, - [0][1][RTW89_WW][51] = -40, - [0][1][RTW89_WW][53] = -40, - [0][1][RTW89_WW][55] = -40, - [0][1][RTW89_WW][57] = -40, - [0][1][RTW89_WW][59] = -40, - [0][1][RTW89_WW][60] = -40, - [0][1][RTW89_WW][62] = -40, - [0][1][RTW89_WW][64] = -40, - [0][1][RTW89_WW][66] = -40, - [0][1][RTW89_WW][68] = -40, - [0][1][RTW89_WW][70] = -38, - [0][1][RTW89_WW][72] = -38, - [0][1][RTW89_WW][74] = -38, - [0][1][RTW89_WW][75] = -38, - [0][1][RTW89_WW][77] = -38, - [0][1][RTW89_WW][79] = -38, - [0][1][RTW89_WW][81] = -38, - [0][1][RTW89_WW][83] = -38, - [0][1][RTW89_WW][85] = -38, - [0][1][RTW89_WW][87] = -40, - [0][1][RTW89_WW][89] = -38, - [0][1][RTW89_WW][90] = -38, - [0][1][RTW89_WW][92] = -38, - [0][1][RTW89_WW][94] = -38, - [0][1][RTW89_WW][96] = -38, - [0][1][RTW89_WW][98] = -38, - [0][1][RTW89_WW][100] = -38, - [0][1][RTW89_WW][102] = -38, - [0][1][RTW89_WW][104] = -38, - [0][1][RTW89_WW][105] = -38, - [0][1][RTW89_WW][107] = -34, - [0][1][RTW89_WW][109] = -34, - [0][1][RTW89_WW][111] = 0, - [0][1][RTW89_WW][113] = 0, - [0][1][RTW89_WW][115] = 0, - [0][1][RTW89_WW][117] = 0, - [0][1][RTW89_WW][119] = 0, - [1][0][RTW89_WW][0] = -4, - [1][0][RTW89_WW][2] = -4, - [1][0][RTW89_WW][4] = -4, - [1][0][RTW89_WW][6] = -4, - [1][0][RTW89_WW][8] = -4, - [1][0][RTW89_WW][10] = -4, - [1][0][RTW89_WW][12] = -4, - [1][0][RTW89_WW][14] = -4, - [1][0][RTW89_WW][15] = -4, - [1][0][RTW89_WW][17] = -4, - [1][0][RTW89_WW][19] = -4, - [1][0][RTW89_WW][21] = -4, - [1][0][RTW89_WW][23] = -4, - [1][0][RTW89_WW][25] = -4, - [1][0][RTW89_WW][27] = -4, - [1][0][RTW89_WW][29] = -4, - [1][0][RTW89_WW][30] = -4, - [1][0][RTW89_WW][32] = -4, - [1][0][RTW89_WW][34] = -4, - [1][0][RTW89_WW][36] = -4, - [1][0][RTW89_WW][38] = -4, - [1][0][RTW89_WW][40] = -4, - [1][0][RTW89_WW][42] = -4, - [1][0][RTW89_WW][44] = -4, - [1][0][RTW89_WW][45] = -4, - [1][0][RTW89_WW][47] = -4, - [1][0][RTW89_WW][49] = -4, - [1][0][RTW89_WW][51] = -4, - [1][0][RTW89_WW][53] = -4, - [1][0][RTW89_WW][55] = -4, - [1][0][RTW89_WW][57] = -4, - [1][0][RTW89_WW][59] = -4, - [1][0][RTW89_WW][60] = -4, - [1][0][RTW89_WW][62] = -4, - [1][0][RTW89_WW][64] = -4, - [1][0][RTW89_WW][66] = -4, - [1][0][RTW89_WW][68] = -4, - [1][0][RTW89_WW][70] = -4, - [1][0][RTW89_WW][72] = -4, - [1][0][RTW89_WW][74] = -4, - [1][0][RTW89_WW][75] = -4, - [1][0][RTW89_WW][77] = -4, - [1][0][RTW89_WW][79] = -4, - [1][0][RTW89_WW][81] = -4, - [1][0][RTW89_WW][83] = -4, - [1][0][RTW89_WW][85] = -4, - [1][0][RTW89_WW][87] = -4, - [1][0][RTW89_WW][89] = -4, - [1][0][RTW89_WW][90] = -4, - [1][0][RTW89_WW][92] = -4, - [1][0][RTW89_WW][94] = -4, - [1][0][RTW89_WW][96] = -4, - [1][0][RTW89_WW][98] = -4, - [1][0][RTW89_WW][100] = -4, - [1][0][RTW89_WW][102] = -4, - [1][0][RTW89_WW][104] = -4, - [1][0][RTW89_WW][105] = -4, - [1][0][RTW89_WW][107] = 1, - [1][0][RTW89_WW][109] = 2, - [1][0][RTW89_WW][111] = 0, - [1][0][RTW89_WW][113] = 0, - [1][0][RTW89_WW][115] = 0, - [1][0][RTW89_WW][117] = 0, - [1][0][RTW89_WW][119] = 0, - [1][1][RTW89_WW][0] = -26, - [1][1][RTW89_WW][2] = -28, - [1][1][RTW89_WW][4] = -28, - [1][1][RTW89_WW][6] = -28, - [1][1][RTW89_WW][8] = -28, - [1][1][RTW89_WW][10] = -28, - [1][1][RTW89_WW][12] = -28, - [1][1][RTW89_WW][14] = -28, - [1][1][RTW89_WW][15] = -28, - [1][1][RTW89_WW][17] = -28, - [1][1][RTW89_WW][19] = -28, - [1][1][RTW89_WW][21] = -28, - [1][1][RTW89_WW][23] = -28, - [1][1][RTW89_WW][25] = -28, - [1][1][RTW89_WW][27] = -28, - [1][1][RTW89_WW][29] = -28, - [1][1][RTW89_WW][30] = -28, - [1][1][RTW89_WW][32] = -28, - [1][1][RTW89_WW][34] = -28, - [1][1][RTW89_WW][36] = -28, - [1][1][RTW89_WW][38] = -28, - [1][1][RTW89_WW][40] = -28, - [1][1][RTW89_WW][42] = -28, - [1][1][RTW89_WW][44] = -28, - [1][1][RTW89_WW][45] = -26, - [1][1][RTW89_WW][47] = -28, - [1][1][RTW89_WW][49] = -28, - [1][1][RTW89_WW][51] = -28, - [1][1][RTW89_WW][53] = -26, - [1][1][RTW89_WW][55] = -28, - [1][1][RTW89_WW][57] = -28, - [1][1][RTW89_WW][59] = -28, - [1][1][RTW89_WW][60] = -28, - [1][1][RTW89_WW][62] = -28, - [1][1][RTW89_WW][64] = -28, - [1][1][RTW89_WW][66] = -28, - [1][1][RTW89_WW][68] = -28, - [1][1][RTW89_WW][70] = -26, - [1][1][RTW89_WW][72] = -28, - [1][1][RTW89_WW][74] = -28, - [1][1][RTW89_WW][75] = -28, - [1][1][RTW89_WW][77] = -28, - [1][1][RTW89_WW][79] = -28, - [1][1][RTW89_WW][81] = -28, - [1][1][RTW89_WW][83] = -28, - [1][1][RTW89_WW][85] = -28, - [1][1][RTW89_WW][87] = -28, - [1][1][RTW89_WW][89] = -26, - [1][1][RTW89_WW][90] = -26, - [1][1][RTW89_WW][92] = -26, - [1][1][RTW89_WW][94] = -26, - [1][1][RTW89_WW][96] = -26, - [1][1][RTW89_WW][98] = -26, - [1][1][RTW89_WW][100] = -26, - [1][1][RTW89_WW][102] = -26, - [1][1][RTW89_WW][104] = -26, - [1][1][RTW89_WW][105] = -26, - [1][1][RTW89_WW][107] = -22, - [1][1][RTW89_WW][109] = -22, - [1][1][RTW89_WW][111] = 0, - [1][1][RTW89_WW][113] = 0, - [1][1][RTW89_WW][115] = 0, - [1][1][RTW89_WW][117] = 0, - [1][1][RTW89_WW][119] = 0, - [2][0][RTW89_WW][0] = 8, - [2][0][RTW89_WW][2] = 8, - [2][0][RTW89_WW][4] = 8, - [2][0][RTW89_WW][6] = 8, - [2][0][RTW89_WW][8] = 8, - [2][0][RTW89_WW][10] = 8, - [2][0][RTW89_WW][12] = 8, - [2][0][RTW89_WW][14] = 8, - [2][0][RTW89_WW][15] = 8, - [2][0][RTW89_WW][17] = 8, - [2][0][RTW89_WW][19] = 8, - [2][0][RTW89_WW][21] = 8, - [2][0][RTW89_WW][23] = 8, - [2][0][RTW89_WW][25] = 8, - [2][0][RTW89_WW][27] = 8, - [2][0][RTW89_WW][29] = 8, - [2][0][RTW89_WW][30] = 8, - [2][0][RTW89_WW][32] = 8, - [2][0][RTW89_WW][34] = 8, - [2][0][RTW89_WW][36] = 8, - [2][0][RTW89_WW][38] = 8, - [2][0][RTW89_WW][40] = 8, - [2][0][RTW89_WW][42] = 8, - [2][0][RTW89_WW][44] = 8, - [2][0][RTW89_WW][45] = 8, - [2][0][RTW89_WW][47] = 8, - [2][0][RTW89_WW][49] = 8, - [2][0][RTW89_WW][51] = 8, - [2][0][RTW89_WW][53] = 8, - [2][0][RTW89_WW][55] = 8, - [2][0][RTW89_WW][57] = 8, - [2][0][RTW89_WW][59] = 8, - [2][0][RTW89_WW][60] = 8, - [2][0][RTW89_WW][62] = 8, - [2][0][RTW89_WW][64] = 8, - [2][0][RTW89_WW][66] = 8, - [2][0][RTW89_WW][68] = 8, - [2][0][RTW89_WW][70] = 8, - [2][0][RTW89_WW][72] = 8, - [2][0][RTW89_WW][74] = 8, - [2][0][RTW89_WW][75] = 8, - [2][0][RTW89_WW][77] = 8, - [2][0][RTW89_WW][79] = 8, - [2][0][RTW89_WW][81] = 8, - [2][0][RTW89_WW][83] = 8, - [2][0][RTW89_WW][85] = 8, - [2][0][RTW89_WW][87] = 8, - [2][0][RTW89_WW][89] = 8, - [2][0][RTW89_WW][90] = 8, - [2][0][RTW89_WW][92] = 8, - [2][0][RTW89_WW][94] = 8, - [2][0][RTW89_WW][96] = 8, - [2][0][RTW89_WW][98] = 8, - [2][0][RTW89_WW][100] = 8, - [2][0][RTW89_WW][102] = 8, - [2][0][RTW89_WW][104] = 8, - [2][0][RTW89_WW][105] = 8, - [2][0][RTW89_WW][107] = 10, - [2][0][RTW89_WW][109] = 12, - [2][0][RTW89_WW][111] = 0, - [2][0][RTW89_WW][113] = 0, - [2][0][RTW89_WW][115] = 0, - [2][0][RTW89_WW][117] = 0, - [2][0][RTW89_WW][119] = 0, - [2][1][RTW89_WW][0] = -16, - [2][1][RTW89_WW][2] = -16, - [2][1][RTW89_WW][4] = -16, - [2][1][RTW89_WW][6] = -16, - [2][1][RTW89_WW][8] = -16, - [2][1][RTW89_WW][10] = -16, - [2][1][RTW89_WW][12] = -16, - [2][1][RTW89_WW][14] = -16, - [2][1][RTW89_WW][15] = -16, - [2][1][RTW89_WW][17] = -16, - [2][1][RTW89_WW][19] = -16, - [2][1][RTW89_WW][21] = -16, - [2][1][RTW89_WW][23] = -16, - [2][1][RTW89_WW][25] = -16, - [2][1][RTW89_WW][27] = -16, - [2][1][RTW89_WW][29] = -16, - [2][1][RTW89_WW][30] = -16, - [2][1][RTW89_WW][32] = -16, - [2][1][RTW89_WW][34] = -16, - [2][1][RTW89_WW][36] = -16, - [2][1][RTW89_WW][38] = -16, - [2][1][RTW89_WW][40] = -16, - [2][1][RTW89_WW][42] = -16, - [2][1][RTW89_WW][44] = -16, - [2][1][RTW89_WW][45] = -16, - [2][1][RTW89_WW][47] = -16, - [2][1][RTW89_WW][49] = -16, - [2][1][RTW89_WW][51] = -16, - [2][1][RTW89_WW][53] = -16, - [2][1][RTW89_WW][55] = -16, - [2][1][RTW89_WW][57] = -16, - [2][1][RTW89_WW][59] = -16, - [2][1][RTW89_WW][60] = -16, - [2][1][RTW89_WW][62] = -16, - [2][1][RTW89_WW][64] = -16, - [2][1][RTW89_WW][66] = -16, - [2][1][RTW89_WW][68] = -16, - [2][1][RTW89_WW][70] = -16, - [2][1][RTW89_WW][72] = -16, - [2][1][RTW89_WW][74] = -16, - [2][1][RTW89_WW][75] = -16, - [2][1][RTW89_WW][77] = -16, - [2][1][RTW89_WW][79] = -16, - [2][1][RTW89_WW][81] = -16, - [2][1][RTW89_WW][83] = -16, - [2][1][RTW89_WW][85] = -18, - [2][1][RTW89_WW][87] = -16, - [2][1][RTW89_WW][89] = -16, - [2][1][RTW89_WW][90] = -16, - [2][1][RTW89_WW][92] = -16, - [2][1][RTW89_WW][94] = -16, - [2][1][RTW89_WW][96] = -16, - [2][1][RTW89_WW][98] = -16, - [2][1][RTW89_WW][100] = -16, - [2][1][RTW89_WW][102] = -16, - [2][1][RTW89_WW][104] = -16, - [2][1][RTW89_WW][105] = -16, - [2][1][RTW89_WW][107] = -12, - [2][1][RTW89_WW][109] = -10, - [2][1][RTW89_WW][111] = 0, - [2][1][RTW89_WW][113] = 0, - [2][1][RTW89_WW][115] = 0, - [2][1][RTW89_WW][117] = 0, - [2][1][RTW89_WW][119] = 0, - [0][0][RTW89_FCC][0] = -16, - [0][0][RTW89_ETSI][0] = 32, - [0][0][RTW89_FCC][2] = -18, - [0][0][RTW89_ETSI][2] = 32, - [0][0][RTW89_FCC][4] = -18, - [0][0][RTW89_ETSI][4] = 32, - [0][0][RTW89_FCC][6] = -18, - [0][0][RTW89_ETSI][6] = 32, - [0][0][RTW89_FCC][8] = -18, - [0][0][RTW89_ETSI][8] = 32, - [0][0][RTW89_FCC][10] = -18, - [0][0][RTW89_ETSI][10] = 32, - [0][0][RTW89_FCC][12] = -18, - [0][0][RTW89_ETSI][12] = 32, - [0][0][RTW89_FCC][14] = -18, - [0][0][RTW89_ETSI][14] = 32, - [0][0][RTW89_FCC][15] = -18, - [0][0][RTW89_ETSI][15] = 32, - [0][0][RTW89_FCC][17] = -18, - [0][0][RTW89_ETSI][17] = 32, - [0][0][RTW89_FCC][19] = -18, - [0][0][RTW89_ETSI][19] = 32, - [0][0][RTW89_FCC][21] = -18, - [0][0][RTW89_ETSI][21] = 32, - [0][0][RTW89_FCC][23] = -18, - [0][0][RTW89_ETSI][23] = 32, - [0][0][RTW89_FCC][25] = -18, - [0][0][RTW89_ETSI][25] = 32, - [0][0][RTW89_FCC][27] = -18, - [0][0][RTW89_ETSI][27] = 32, - [0][0][RTW89_FCC][29] = -18, - [0][0][RTW89_ETSI][29] = 32, - [0][0][RTW89_FCC][30] = -18, - [0][0][RTW89_ETSI][30] = 32, - [0][0][RTW89_FCC][32] = -18, - [0][0][RTW89_ETSI][32] = 32, - [0][0][RTW89_FCC][34] = -18, - [0][0][RTW89_ETSI][34] = 32, - [0][0][RTW89_FCC][36] = -18, - [0][0][RTW89_ETSI][36] = 32, - [0][0][RTW89_FCC][38] = -18, - [0][0][RTW89_ETSI][38] = 32, - [0][0][RTW89_FCC][40] = -18, - [0][0][RTW89_ETSI][40] = 32, - [0][0][RTW89_FCC][42] = -18, - [0][0][RTW89_ETSI][42] = 32, - [0][0][RTW89_FCC][44] = -16, - [0][0][RTW89_ETSI][44] = 32, - [0][0][RTW89_FCC][45] = -16, - [0][0][RTW89_ETSI][45] = 127, - [0][0][RTW89_FCC][47] = -18, - [0][0][RTW89_ETSI][47] = 127, - [0][0][RTW89_FCC][49] = -18, - [0][0][RTW89_ETSI][49] = 127, - [0][0][RTW89_FCC][51] = -18, - [0][0][RTW89_ETSI][51] = 127, - [0][0][RTW89_FCC][53] = -16, - [0][0][RTW89_ETSI][53] = 127, - [0][0][RTW89_FCC][55] = -18, - [0][0][RTW89_ETSI][55] = 127, - [0][0][RTW89_FCC][57] = -18, - [0][0][RTW89_ETSI][57] = 127, - [0][0][RTW89_FCC][59] = -18, - [0][0][RTW89_ETSI][59] = 127, - [0][0][RTW89_FCC][60] = -18, - [0][0][RTW89_ETSI][60] = 127, - [0][0][RTW89_FCC][62] = -18, - [0][0][RTW89_ETSI][62] = 127, - [0][0][RTW89_FCC][64] = -18, - [0][0][RTW89_ETSI][64] = 127, - [0][0][RTW89_FCC][66] = -18, - [0][0][RTW89_ETSI][66] = 127, - [0][0][RTW89_FCC][68] = -18, - [0][0][RTW89_ETSI][68] = 127, - [0][0][RTW89_FCC][70] = -16, - [0][0][RTW89_ETSI][70] = 127, - [0][0][RTW89_FCC][72] = -18, - [0][0][RTW89_ETSI][72] = 127, - [0][0][RTW89_FCC][74] = -18, - [0][0][RTW89_ETSI][74] = 127, - [0][0][RTW89_FCC][75] = -18, - [0][0][RTW89_ETSI][75] = 127, - [0][0][RTW89_FCC][77] = -18, - [0][0][RTW89_ETSI][77] = 127, - [0][0][RTW89_FCC][79] = -18, - [0][0][RTW89_ETSI][79] = 127, - [0][0][RTW89_FCC][81] = -18, - [0][0][RTW89_ETSI][81] = 127, - [0][0][RTW89_FCC][83] = -18, - [0][0][RTW89_ETSI][83] = 127, - [0][0][RTW89_FCC][85] = -18, - [0][0][RTW89_ETSI][85] = 127, - [0][0][RTW89_FCC][87] = -16, - [0][0][RTW89_ETSI][87] = 127, - [0][0][RTW89_FCC][89] = -16, - [0][0][RTW89_ETSI][89] = 127, - [0][0][RTW89_FCC][90] = -16, - [0][0][RTW89_ETSI][90] = 127, - [0][0][RTW89_FCC][92] = -16, - [0][0][RTW89_ETSI][92] = 127, - [0][0][RTW89_FCC][94] = -16, - [0][0][RTW89_ETSI][94] = 127, - [0][0][RTW89_FCC][96] = -16, - [0][0][RTW89_ETSI][96] = 127, - [0][0][RTW89_FCC][98] = -16, - [0][0][RTW89_ETSI][98] = 127, - [0][0][RTW89_FCC][100] = -16, - [0][0][RTW89_ETSI][100] = 127, - [0][0][RTW89_FCC][102] = -16, - [0][0][RTW89_ETSI][102] = 127, - [0][0][RTW89_FCC][104] = -16, - [0][0][RTW89_ETSI][104] = 127, - [0][0][RTW89_FCC][105] = -16, - [0][0][RTW89_ETSI][105] = 127, - [0][0][RTW89_FCC][107] = -12, - [0][0][RTW89_ETSI][107] = 127, - [0][0][RTW89_FCC][109] = -12, - [0][0][RTW89_ETSI][109] = 127, - [0][0][RTW89_FCC][111] = 127, - [0][0][RTW89_ETSI][111] = 127, - [0][0][RTW89_FCC][113] = 127, - [0][0][RTW89_ETSI][113] = 127, - [0][0][RTW89_FCC][115] = 127, - [0][0][RTW89_ETSI][115] = 127, - [0][0][RTW89_FCC][117] = 127, - [0][0][RTW89_ETSI][117] = 127, - [0][0][RTW89_FCC][119] = 127, - [0][0][RTW89_ETSI][119] = 127, - [0][1][RTW89_FCC][0] = -40, - [0][1][RTW89_ETSI][0] = 20, - [0][1][RTW89_FCC][2] = -40, - [0][1][RTW89_ETSI][2] = 20, - [0][1][RTW89_FCC][4] = -40, - [0][1][RTW89_ETSI][4] = 20, - [0][1][RTW89_FCC][6] = -40, - [0][1][RTW89_ETSI][6] = 20, - [0][1][RTW89_FCC][8] = -40, - [0][1][RTW89_ETSI][8] = 20, - [0][1][RTW89_FCC][10] = -40, - [0][1][RTW89_ETSI][10] = 20, - [0][1][RTW89_FCC][12] = -40, - [0][1][RTW89_ETSI][12] = 20, - [0][1][RTW89_FCC][14] = -40, - [0][1][RTW89_ETSI][14] = 20, - [0][1][RTW89_FCC][15] = -40, - [0][1][RTW89_ETSI][15] = 20, - [0][1][RTW89_FCC][17] = -40, - [0][1][RTW89_ETSI][17] = 20, - [0][1][RTW89_FCC][19] = -40, - [0][1][RTW89_ETSI][19] = 20, - [0][1][RTW89_FCC][21] = -40, - [0][1][RTW89_ETSI][21] = 20, - [0][1][RTW89_FCC][23] = -40, - [0][1][RTW89_ETSI][23] = 20, - [0][1][RTW89_FCC][25] = -40, - [0][1][RTW89_ETSI][25] = 20, - [0][1][RTW89_FCC][27] = -40, - [0][1][RTW89_ETSI][27] = 20, - [0][1][RTW89_FCC][29] = -40, - [0][1][RTW89_ETSI][29] = 20, - [0][1][RTW89_FCC][30] = -40, - [0][1][RTW89_ETSI][30] = 20, - [0][1][RTW89_FCC][32] = -40, - [0][1][RTW89_ETSI][32] = 20, - [0][1][RTW89_FCC][34] = -40, - [0][1][RTW89_ETSI][34] = 20, - [0][1][RTW89_FCC][36] = -40, - [0][1][RTW89_ETSI][36] = 20, - [0][1][RTW89_FCC][38] = -40, - [0][1][RTW89_ETSI][38] = 20, - [0][1][RTW89_FCC][40] = -40, - [0][1][RTW89_ETSI][40] = 20, - [0][1][RTW89_FCC][42] = -40, - [0][1][RTW89_ETSI][42] = 20, - [0][1][RTW89_FCC][44] = -40, - [0][1][RTW89_ETSI][44] = 20, - [0][1][RTW89_FCC][45] = -40, - [0][1][RTW89_ETSI][45] = 127, - [0][1][RTW89_FCC][47] = -40, - [0][1][RTW89_ETSI][47] = 127, - [0][1][RTW89_FCC][49] = -40, - [0][1][RTW89_ETSI][49] = 127, - [0][1][RTW89_FCC][51] = -40, - [0][1][RTW89_ETSI][51] = 127, - [0][1][RTW89_FCC][53] = -40, - [0][1][RTW89_ETSI][53] = 127, - [0][1][RTW89_FCC][55] = -40, - [0][1][RTW89_ETSI][55] = 127, - [0][1][RTW89_FCC][57] = -40, - [0][1][RTW89_ETSI][57] = 127, - [0][1][RTW89_FCC][59] = -40, - [0][1][RTW89_ETSI][59] = 127, - [0][1][RTW89_FCC][60] = -40, - [0][1][RTW89_ETSI][60] = 127, - [0][1][RTW89_FCC][62] = -40, - [0][1][RTW89_ETSI][62] = 127, - [0][1][RTW89_FCC][64] = -40, - [0][1][RTW89_ETSI][64] = 127, - [0][1][RTW89_FCC][66] = -40, - [0][1][RTW89_ETSI][66] = 127, - [0][1][RTW89_FCC][68] = -40, - [0][1][RTW89_ETSI][68] = 127, - [0][1][RTW89_FCC][70] = -38, - [0][1][RTW89_ETSI][70] = 127, - [0][1][RTW89_FCC][72] = -38, - [0][1][RTW89_ETSI][72] = 127, - [0][1][RTW89_FCC][74] = -38, - [0][1][RTW89_ETSI][74] = 127, - [0][1][RTW89_FCC][75] = -38, - [0][1][RTW89_ETSI][75] = 127, - [0][1][RTW89_FCC][77] = -38, - [0][1][RTW89_ETSI][77] = 127, - [0][1][RTW89_FCC][79] = -38, - [0][1][RTW89_ETSI][79] = 127, - [0][1][RTW89_FCC][81] = -38, - [0][1][RTW89_ETSI][81] = 127, - [0][1][RTW89_FCC][83] = -38, - [0][1][RTW89_ETSI][83] = 127, - [0][1][RTW89_FCC][85] = -38, - [0][1][RTW89_ETSI][85] = 127, - [0][1][RTW89_FCC][87] = -40, - [0][1][RTW89_ETSI][87] = 127, - [0][1][RTW89_FCC][89] = -38, - [0][1][RTW89_ETSI][89] = 127, - [0][1][RTW89_FCC][90] = -38, - [0][1][RTW89_ETSI][90] = 127, - [0][1][RTW89_FCC][92] = -38, - [0][1][RTW89_ETSI][92] = 127, - [0][1][RTW89_FCC][94] = -38, - [0][1][RTW89_ETSI][94] = 127, - [0][1][RTW89_FCC][96] = -38, - [0][1][RTW89_ETSI][96] = 127, - [0][1][RTW89_FCC][98] = -38, - [0][1][RTW89_ETSI][98] = 127, - [0][1][RTW89_FCC][100] = -38, - [0][1][RTW89_ETSI][100] = 127, - [0][1][RTW89_FCC][102] = -38, - [0][1][RTW89_ETSI][102] = 127, - [0][1][RTW89_FCC][104] = -38, - [0][1][RTW89_ETSI][104] = 127, - [0][1][RTW89_FCC][105] = -38, - [0][1][RTW89_ETSI][105] = 127, - [0][1][RTW89_FCC][107] = -34, - [0][1][RTW89_ETSI][107] = 127, - [0][1][RTW89_FCC][109] = -34, - [0][1][RTW89_ETSI][109] = 127, - [0][1][RTW89_FCC][111] = 127, - [0][1][RTW89_ETSI][111] = 127, - [0][1][RTW89_FCC][113] = 127, - [0][1][RTW89_ETSI][113] = 127, - [0][1][RTW89_FCC][115] = 127, - [0][1][RTW89_ETSI][115] = 127, - [0][1][RTW89_FCC][117] = 127, - [0][1][RTW89_ETSI][117] = 127, - [0][1][RTW89_FCC][119] = 127, - [0][1][RTW89_ETSI][119] = 127, - [1][0][RTW89_FCC][0] = -4, - [1][0][RTW89_ETSI][0] = 46, - [1][0][RTW89_FCC][2] = -4, - [1][0][RTW89_ETSI][2] = 46, - [1][0][RTW89_FCC][4] = -4, - [1][0][RTW89_ETSI][4] = 46, - [1][0][RTW89_FCC][6] = -4, - [1][0][RTW89_ETSI][6] = 46, - [1][0][RTW89_FCC][8] = -4, - [1][0][RTW89_ETSI][8] = 46, - [1][0][RTW89_FCC][10] = -4, - [1][0][RTW89_ETSI][10] = 46, - [1][0][RTW89_FCC][12] = -4, - [1][0][RTW89_ETSI][12] = 46, - [1][0][RTW89_FCC][14] = -4, - [1][0][RTW89_ETSI][14] = 46, - [1][0][RTW89_FCC][15] = -4, - [1][0][RTW89_ETSI][15] = 46, - [1][0][RTW89_FCC][17] = -4, - [1][0][RTW89_ETSI][17] = 46, - [1][0][RTW89_FCC][19] = -4, - [1][0][RTW89_ETSI][19] = 46, - [1][0][RTW89_FCC][21] = -4, - [1][0][RTW89_ETSI][21] = 46, - [1][0][RTW89_FCC][23] = -4, - [1][0][RTW89_ETSI][23] = 46, - [1][0][RTW89_FCC][25] = -4, - [1][0][RTW89_ETSI][25] = 46, - [1][0][RTW89_FCC][27] = -4, - [1][0][RTW89_ETSI][27] = 46, - [1][0][RTW89_FCC][29] = -4, - [1][0][RTW89_ETSI][29] = 46, - [1][0][RTW89_FCC][30] = -4, - [1][0][RTW89_ETSI][30] = 46, - [1][0][RTW89_FCC][32] = -4, - [1][0][RTW89_ETSI][32] = 46, - [1][0][RTW89_FCC][34] = -4, - [1][0][RTW89_ETSI][34] = 46, - [1][0][RTW89_FCC][36] = -4, - [1][0][RTW89_ETSI][36] = 46, - [1][0][RTW89_FCC][38] = -4, - [1][0][RTW89_ETSI][38] = 46, - [1][0][RTW89_FCC][40] = -4, - [1][0][RTW89_ETSI][40] = 46, - [1][0][RTW89_FCC][42] = -4, - [1][0][RTW89_ETSI][42] = 46, - [1][0][RTW89_FCC][44] = -4, - [1][0][RTW89_ETSI][44] = 46, - [1][0][RTW89_FCC][45] = -4, - [1][0][RTW89_ETSI][45] = 127, - [1][0][RTW89_FCC][47] = -4, - [1][0][RTW89_ETSI][47] = 127, - [1][0][RTW89_FCC][49] = -4, - [1][0][RTW89_ETSI][49] = 127, - [1][0][RTW89_FCC][51] = -4, - [1][0][RTW89_ETSI][51] = 127, - [1][0][RTW89_FCC][53] = -4, - [1][0][RTW89_ETSI][53] = 127, - [1][0][RTW89_FCC][55] = -4, - [1][0][RTW89_ETSI][55] = 127, - [1][0][RTW89_FCC][57] = -4, - [1][0][RTW89_ETSI][57] = 127, - [1][0][RTW89_FCC][59] = -4, - [1][0][RTW89_ETSI][59] = 127, - [1][0][RTW89_FCC][60] = -4, - [1][0][RTW89_ETSI][60] = 127, - [1][0][RTW89_FCC][62] = -4, - [1][0][RTW89_ETSI][62] = 127, - [1][0][RTW89_FCC][64] = -4, - [1][0][RTW89_ETSI][64] = 127, - [1][0][RTW89_FCC][66] = -4, - [1][0][RTW89_ETSI][66] = 127, - [1][0][RTW89_FCC][68] = -4, - [1][0][RTW89_ETSI][68] = 127, - [1][0][RTW89_FCC][70] = -4, - [1][0][RTW89_ETSI][70] = 127, - [1][0][RTW89_FCC][72] = -4, - [1][0][RTW89_ETSI][72] = 127, - [1][0][RTW89_FCC][74] = -4, - [1][0][RTW89_ETSI][74] = 127, - [1][0][RTW89_FCC][75] = -4, - [1][0][RTW89_ETSI][75] = 127, - [1][0][RTW89_FCC][77] = -4, - [1][0][RTW89_ETSI][77] = 127, - [1][0][RTW89_FCC][79] = -4, - [1][0][RTW89_ETSI][79] = 127, - [1][0][RTW89_FCC][81] = -4, - [1][0][RTW89_ETSI][81] = 127, - [1][0][RTW89_FCC][83] = -4, - [1][0][RTW89_ETSI][83] = 127, - [1][0][RTW89_FCC][85] = -4, - [1][0][RTW89_ETSI][85] = 127, - [1][0][RTW89_FCC][87] = -4, - [1][0][RTW89_ETSI][87] = 127, - [1][0][RTW89_FCC][89] = -4, - [1][0][RTW89_ETSI][89] = 127, - [1][0][RTW89_FCC][90] = -4, - [1][0][RTW89_ETSI][90] = 127, - [1][0][RTW89_FCC][92] = -4, - [1][0][RTW89_ETSI][92] = 127, - [1][0][RTW89_FCC][94] = -4, - [1][0][RTW89_ETSI][94] = 127, - [1][0][RTW89_FCC][96] = -4, - [1][0][RTW89_ETSI][96] = 127, - [1][0][RTW89_FCC][98] = -4, - [1][0][RTW89_ETSI][98] = 127, - [1][0][RTW89_FCC][100] = -4, - [1][0][RTW89_ETSI][100] = 127, - [1][0][RTW89_FCC][102] = -4, - [1][0][RTW89_ETSI][102] = 127, - [1][0][RTW89_FCC][104] = -4, - [1][0][RTW89_ETSI][104] = 127, - [1][0][RTW89_FCC][105] = -4, - [1][0][RTW89_ETSI][105] = 127, - [1][0][RTW89_FCC][107] = 0, - [1][0][RTW89_ETSI][107] = 127, - [1][0][RTW89_FCC][109] = 2, - [1][0][RTW89_ETSI][109] = 127, - [1][0][RTW89_FCC][111] = 127, - [1][0][RTW89_ETSI][111] = 127, - [1][0][RTW89_FCC][113] = 127, - [1][0][RTW89_ETSI][113] = 127, - [1][0][RTW89_FCC][115] = 127, - [1][0][RTW89_ETSI][115] = 127, - [1][0][RTW89_FCC][117] = 127, - [1][0][RTW89_ETSI][117] = 127, - [1][0][RTW89_FCC][119] = 127, - [1][0][RTW89_ETSI][119] = 127, - [1][1][RTW89_FCC][0] = -26, - [1][1][RTW89_ETSI][0] = 32, - [1][1][RTW89_FCC][2] = -28, - [1][1][RTW89_ETSI][2] = 32, - [1][1][RTW89_FCC][4] = -28, - [1][1][RTW89_ETSI][4] = 32, - [1][1][RTW89_FCC][6] = -28, - [1][1][RTW89_ETSI][6] = 32, - [1][1][RTW89_FCC][8] = -28, - [1][1][RTW89_ETSI][8] = 32, - [1][1][RTW89_FCC][10] = -28, - [1][1][RTW89_ETSI][10] = 32, - [1][1][RTW89_FCC][12] = -28, - [1][1][RTW89_ETSI][12] = 32, - [1][1][RTW89_FCC][14] = -28, - [1][1][RTW89_ETSI][14] = 32, - [1][1][RTW89_FCC][15] = -28, - [1][1][RTW89_ETSI][15] = 32, - [1][1][RTW89_FCC][17] = -28, - [1][1][RTW89_ETSI][17] = 32, - [1][1][RTW89_FCC][19] = -28, - [1][1][RTW89_ETSI][19] = 32, - [1][1][RTW89_FCC][21] = -28, - [1][1][RTW89_ETSI][21] = 32, - [1][1][RTW89_FCC][23] = -28, - [1][1][RTW89_ETSI][23] = 32, - [1][1][RTW89_FCC][25] = -28, - [1][1][RTW89_ETSI][25] = 32, - [1][1][RTW89_FCC][27] = -28, - [1][1][RTW89_ETSI][27] = 32, - [1][1][RTW89_FCC][29] = -28, - [1][1][RTW89_ETSI][29] = 32, - [1][1][RTW89_FCC][30] = -28, - [1][1][RTW89_ETSI][30] = 32, - [1][1][RTW89_FCC][32] = -28, - [1][1][RTW89_ETSI][32] = 32, - [1][1][RTW89_FCC][34] = -28, - [1][1][RTW89_ETSI][34] = 32, - [1][1][RTW89_FCC][36] = -28, - [1][1][RTW89_ETSI][36] = 32, - [1][1][RTW89_FCC][38] = -28, - [1][1][RTW89_ETSI][38] = 32, - [1][1][RTW89_FCC][40] = -28, - [1][1][RTW89_ETSI][40] = 32, - [1][1][RTW89_FCC][42] = -28, - [1][1][RTW89_ETSI][42] = 32, - [1][1][RTW89_FCC][44] = -28, - [1][1][RTW89_ETSI][44] = 34, - [1][1][RTW89_FCC][45] = -26, - [1][1][RTW89_ETSI][45] = 127, - [1][1][RTW89_FCC][47] = -28, - [1][1][RTW89_ETSI][47] = 127, - [1][1][RTW89_FCC][49] = -28, - [1][1][RTW89_ETSI][49] = 127, - [1][1][RTW89_FCC][51] = -28, - [1][1][RTW89_ETSI][51] = 127, - [1][1][RTW89_FCC][53] = -26, - [1][1][RTW89_ETSI][53] = 127, - [1][1][RTW89_FCC][55] = -28, - [1][1][RTW89_ETSI][55] = 127, - [1][1][RTW89_FCC][57] = -28, - [1][1][RTW89_ETSI][57] = 127, - [1][1][RTW89_FCC][59] = -28, - [1][1][RTW89_ETSI][59] = 127, - [1][1][RTW89_FCC][60] = -28, - [1][1][RTW89_ETSI][60] = 127, - [1][1][RTW89_FCC][62] = -28, - [1][1][RTW89_ETSI][62] = 127, - [1][1][RTW89_FCC][64] = -28, - [1][1][RTW89_ETSI][64] = 127, - [1][1][RTW89_FCC][66] = -28, - [1][1][RTW89_ETSI][66] = 127, - [1][1][RTW89_FCC][68] = -28, - [1][1][RTW89_ETSI][68] = 127, - [1][1][RTW89_FCC][70] = -26, - [1][1][RTW89_ETSI][70] = 127, - [1][1][RTW89_FCC][72] = -28, - [1][1][RTW89_ETSI][72] = 127, - [1][1][RTW89_FCC][74] = -28, - [1][1][RTW89_ETSI][74] = 127, - [1][1][RTW89_FCC][75] = -28, - [1][1][RTW89_ETSI][75] = 127, - [1][1][RTW89_FCC][77] = -28, - [1][1][RTW89_ETSI][77] = 127, - [1][1][RTW89_FCC][79] = -28, - [1][1][RTW89_ETSI][79] = 127, - [1][1][RTW89_FCC][81] = -28, - [1][1][RTW89_ETSI][81] = 127, - [1][1][RTW89_FCC][83] = -28, - [1][1][RTW89_ETSI][83] = 127, - [1][1][RTW89_FCC][85] = -28, - [1][1][RTW89_ETSI][85] = 127, - [1][1][RTW89_FCC][87] = -28, - [1][1][RTW89_ETSI][87] = 127, - [1][1][RTW89_FCC][89] = -26, - [1][1][RTW89_ETSI][89] = 127, - [1][1][RTW89_FCC][90] = -26, - [1][1][RTW89_ETSI][90] = 127, - [1][1][RTW89_FCC][92] = -26, - [1][1][RTW89_ETSI][92] = 127, - [1][1][RTW89_FCC][94] = -26, - [1][1][RTW89_ETSI][94] = 127, - [1][1][RTW89_FCC][96] = -26, - [1][1][RTW89_ETSI][96] = 127, - [1][1][RTW89_FCC][98] = -26, - [1][1][RTW89_ETSI][98] = 127, - [1][1][RTW89_FCC][100] = -26, - [1][1][RTW89_ETSI][100] = 127, - [1][1][RTW89_FCC][102] = -26, - [1][1][RTW89_ETSI][102] = 127, - [1][1][RTW89_FCC][104] = -26, - [1][1][RTW89_ETSI][104] = 127, - [1][1][RTW89_FCC][105] = -26, - [1][1][RTW89_ETSI][105] = 127, - [1][1][RTW89_FCC][107] = -22, - [1][1][RTW89_ETSI][107] = 127, - [1][1][RTW89_FCC][109] = -22, - [1][1][RTW89_ETSI][109] = 127, - [1][1][RTW89_FCC][111] = 127, - [1][1][RTW89_ETSI][111] = 127, - [1][1][RTW89_FCC][113] = 127, - [1][1][RTW89_ETSI][113] = 127, - [1][1][RTW89_FCC][115] = 127, - [1][1][RTW89_ETSI][115] = 127, - [1][1][RTW89_FCC][117] = 127, - [1][1][RTW89_ETSI][117] = 127, - [1][1][RTW89_FCC][119] = 127, - [1][1][RTW89_ETSI][119] = 127, - [2][0][RTW89_FCC][0] = 8, - [2][0][RTW89_ETSI][0] = 56, - [2][0][RTW89_FCC][2] = 8, - [2][0][RTW89_ETSI][2] = 56, - [2][0][RTW89_FCC][4] = 8, - [2][0][RTW89_ETSI][4] = 56, - [2][0][RTW89_FCC][6] = 8, - [2][0][RTW89_ETSI][6] = 56, - [2][0][RTW89_FCC][8] = 8, - [2][0][RTW89_ETSI][8] = 56, - [2][0][RTW89_FCC][10] = 8, - [2][0][RTW89_ETSI][10] = 56, - [2][0][RTW89_FCC][12] = 8, - [2][0][RTW89_ETSI][12] = 56, - [2][0][RTW89_FCC][14] = 8, - [2][0][RTW89_ETSI][14] = 56, - [2][0][RTW89_FCC][15] = 8, - [2][0][RTW89_ETSI][15] = 56, - [2][0][RTW89_FCC][17] = 8, - [2][0][RTW89_ETSI][17] = 56, - [2][0][RTW89_FCC][19] = 8, - [2][0][RTW89_ETSI][19] = 56, - [2][0][RTW89_FCC][21] = 8, - [2][0][RTW89_ETSI][21] = 56, - [2][0][RTW89_FCC][23] = 8, - [2][0][RTW89_ETSI][23] = 56, - [2][0][RTW89_FCC][25] = 8, - [2][0][RTW89_ETSI][25] = 56, - [2][0][RTW89_FCC][27] = 8, - [2][0][RTW89_ETSI][27] = 56, - [2][0][RTW89_FCC][29] = 8, - [2][0][RTW89_ETSI][29] = 56, - [2][0][RTW89_FCC][30] = 8, - [2][0][RTW89_ETSI][30] = 56, - [2][0][RTW89_FCC][32] = 8, - [2][0][RTW89_ETSI][32] = 56, - [2][0][RTW89_FCC][34] = 8, - [2][0][RTW89_ETSI][34] = 56, - [2][0][RTW89_FCC][36] = 8, - [2][0][RTW89_ETSI][36] = 56, - [2][0][RTW89_FCC][38] = 8, - [2][0][RTW89_ETSI][38] = 56, - [2][0][RTW89_FCC][40] = 8, - [2][0][RTW89_ETSI][40] = 56, - [2][0][RTW89_FCC][42] = 8, - [2][0][RTW89_ETSI][42] = 56, - [2][0][RTW89_FCC][44] = 8, - [2][0][RTW89_ETSI][44] = 56, - [2][0][RTW89_FCC][45] = 8, - [2][0][RTW89_ETSI][45] = 127, - [2][0][RTW89_FCC][47] = 8, - [2][0][RTW89_ETSI][47] = 127, - [2][0][RTW89_FCC][49] = 8, - [2][0][RTW89_ETSI][49] = 127, - [2][0][RTW89_FCC][51] = 8, - [2][0][RTW89_ETSI][51] = 127, - [2][0][RTW89_FCC][53] = 8, - [2][0][RTW89_ETSI][53] = 127, - [2][0][RTW89_FCC][55] = 8, - [2][0][RTW89_ETSI][55] = 127, - [2][0][RTW89_FCC][57] = 8, - [2][0][RTW89_ETSI][57] = 127, - [2][0][RTW89_FCC][59] = 8, - [2][0][RTW89_ETSI][59] = 127, - [2][0][RTW89_FCC][60] = 8, - [2][0][RTW89_ETSI][60] = 127, - [2][0][RTW89_FCC][62] = 8, - [2][0][RTW89_ETSI][62] = 127, - [2][0][RTW89_FCC][64] = 8, - [2][0][RTW89_ETSI][64] = 127, - [2][0][RTW89_FCC][66] = 8, - [2][0][RTW89_ETSI][66] = 127, - [2][0][RTW89_FCC][68] = 8, - [2][0][RTW89_ETSI][68] = 127, - [2][0][RTW89_FCC][70] = 8, - [2][0][RTW89_ETSI][70] = 127, - [2][0][RTW89_FCC][72] = 8, - [2][0][RTW89_ETSI][72] = 127, - [2][0][RTW89_FCC][74] = 8, - [2][0][RTW89_ETSI][74] = 127, - [2][0][RTW89_FCC][75] = 8, - [2][0][RTW89_ETSI][75] = 127, - [2][0][RTW89_FCC][77] = 8, - [2][0][RTW89_ETSI][77] = 127, - [2][0][RTW89_FCC][79] = 8, - [2][0][RTW89_ETSI][79] = 127, - [2][0][RTW89_FCC][81] = 8, - [2][0][RTW89_ETSI][81] = 127, - [2][0][RTW89_FCC][83] = 8, - [2][0][RTW89_ETSI][83] = 127, - [2][0][RTW89_FCC][85] = 8, - [2][0][RTW89_ETSI][85] = 127, - [2][0][RTW89_FCC][87] = 8, - [2][0][RTW89_ETSI][87] = 127, - [2][0][RTW89_FCC][89] = 8, - [2][0][RTW89_ETSI][89] = 127, - [2][0][RTW89_FCC][90] = 8, - [2][0][RTW89_ETSI][90] = 127, - [2][0][RTW89_FCC][92] = 8, - [2][0][RTW89_ETSI][92] = 127, - [2][0][RTW89_FCC][94] = 8, - [2][0][RTW89_ETSI][94] = 127, - [2][0][RTW89_FCC][96] = 8, - [2][0][RTW89_ETSI][96] = 127, - [2][0][RTW89_FCC][98] = 8, - [2][0][RTW89_ETSI][98] = 127, - [2][0][RTW89_FCC][100] = 8, - [2][0][RTW89_ETSI][100] = 127, - [2][0][RTW89_FCC][102] = 8, - [2][0][RTW89_ETSI][102] = 127, - [2][0][RTW89_FCC][104] = 8, - [2][0][RTW89_ETSI][104] = 127, - [2][0][RTW89_FCC][105] = 8, - [2][0][RTW89_ETSI][105] = 127, - [2][0][RTW89_FCC][107] = 10, - [2][0][RTW89_ETSI][107] = 127, - [2][0][RTW89_FCC][109] = 12, - [2][0][RTW89_ETSI][109] = 127, - [2][0][RTW89_FCC][111] = 127, - [2][0][RTW89_ETSI][111] = 127, - [2][0][RTW89_FCC][113] = 127, - [2][0][RTW89_ETSI][113] = 127, - [2][0][RTW89_FCC][115] = 127, - [2][0][RTW89_ETSI][115] = 127, - [2][0][RTW89_FCC][117] = 127, - [2][0][RTW89_ETSI][117] = 127, - [2][0][RTW89_FCC][119] = 127, - [2][0][RTW89_ETSI][119] = 127, - [2][1][RTW89_FCC][0] = -16, - [2][1][RTW89_ETSI][0] = 44, - [2][1][RTW89_FCC][2] = -16, - [2][1][RTW89_ETSI][2] = 44, - [2][1][RTW89_FCC][4] = -16, - [2][1][RTW89_ETSI][4] = 44, - [2][1][RTW89_FCC][6] = -16, - [2][1][RTW89_ETSI][6] = 44, - [2][1][RTW89_FCC][8] = -16, - [2][1][RTW89_ETSI][8] = 44, - [2][1][RTW89_FCC][10] = -16, - [2][1][RTW89_ETSI][10] = 44, - [2][1][RTW89_FCC][12] = -16, - [2][1][RTW89_ETSI][12] = 44, - [2][1][RTW89_FCC][14] = -16, - [2][1][RTW89_ETSI][14] = 44, - [2][1][RTW89_FCC][15] = -16, - [2][1][RTW89_ETSI][15] = 44, - [2][1][RTW89_FCC][17] = -16, - [2][1][RTW89_ETSI][17] = 44, - [2][1][RTW89_FCC][19] = -16, - [2][1][RTW89_ETSI][19] = 44, - [2][1][RTW89_FCC][21] = -16, - [2][1][RTW89_ETSI][21] = 44, - [2][1][RTW89_FCC][23] = -16, - [2][1][RTW89_ETSI][23] = 44, - [2][1][RTW89_FCC][25] = -16, - [2][1][RTW89_ETSI][25] = 44, - [2][1][RTW89_FCC][27] = -16, - [2][1][RTW89_ETSI][27] = 44, - [2][1][RTW89_FCC][29] = -16, - [2][1][RTW89_ETSI][29] = 44, - [2][1][RTW89_FCC][30] = -16, - [2][1][RTW89_ETSI][30] = 44, - [2][1][RTW89_FCC][32] = -16, - [2][1][RTW89_ETSI][32] = 44, - [2][1][RTW89_FCC][34] = -16, - [2][1][RTW89_ETSI][34] = 44, - [2][1][RTW89_FCC][36] = -16, - [2][1][RTW89_ETSI][36] = 44, - [2][1][RTW89_FCC][38] = -16, - [2][1][RTW89_ETSI][38] = 44, - [2][1][RTW89_FCC][40] = -16, - [2][1][RTW89_ETSI][40] = 44, - [2][1][RTW89_FCC][42] = -16, - [2][1][RTW89_ETSI][42] = 44, - [2][1][RTW89_FCC][44] = -16, - [2][1][RTW89_ETSI][44] = 44, - [2][1][RTW89_FCC][45] = -16, - [2][1][RTW89_ETSI][45] = 127, - [2][1][RTW89_FCC][47] = -16, - [2][1][RTW89_ETSI][47] = 127, - [2][1][RTW89_FCC][49] = -16, - [2][1][RTW89_ETSI][49] = 127, - [2][1][RTW89_FCC][51] = -16, - [2][1][RTW89_ETSI][51] = 127, - [2][1][RTW89_FCC][53] = -16, - [2][1][RTW89_ETSI][53] = 127, - [2][1][RTW89_FCC][55] = -16, - [2][1][RTW89_ETSI][55] = 127, - [2][1][RTW89_FCC][57] = -16, - [2][1][RTW89_ETSI][57] = 127, - [2][1][RTW89_FCC][59] = -16, - [2][1][RTW89_ETSI][59] = 127, - [2][1][RTW89_FCC][60] = -16, - [2][1][RTW89_ETSI][60] = 127, - [2][1][RTW89_FCC][62] = -16, - [2][1][RTW89_ETSI][62] = 127, - [2][1][RTW89_FCC][64] = -16, - [2][1][RTW89_ETSI][64] = 127, - [2][1][RTW89_FCC][66] = -16, - [2][1][RTW89_ETSI][66] = 127, - [2][1][RTW89_FCC][68] = -16, - [2][1][RTW89_ETSI][68] = 127, - [2][1][RTW89_FCC][70] = -16, - [2][1][RTW89_ETSI][70] = 127, - [2][1][RTW89_FCC][72] = -16, - [2][1][RTW89_ETSI][72] = 127, - [2][1][RTW89_FCC][74] = -16, - [2][1][RTW89_ETSI][74] = 127, - [2][1][RTW89_FCC][75] = -16, - [2][1][RTW89_ETSI][75] = 127, - [2][1][RTW89_FCC][77] = -16, - [2][1][RTW89_ETSI][77] = 127, - [2][1][RTW89_FCC][79] = -16, - [2][1][RTW89_ETSI][79] = 127, - [2][1][RTW89_FCC][81] = -16, - [2][1][RTW89_ETSI][81] = 127, - [2][1][RTW89_FCC][83] = -16, - [2][1][RTW89_ETSI][83] = 127, - [2][1][RTW89_FCC][85] = -18, - [2][1][RTW89_ETSI][85] = 127, - [2][1][RTW89_FCC][87] = -16, - [2][1][RTW89_ETSI][87] = 127, - [2][1][RTW89_FCC][89] = -16, - [2][1][RTW89_ETSI][89] = 127, - [2][1][RTW89_FCC][90] = -16, - [2][1][RTW89_ETSI][90] = 127, - [2][1][RTW89_FCC][92] = -16, - [2][1][RTW89_ETSI][92] = 127, - [2][1][RTW89_FCC][94] = -16, - [2][1][RTW89_ETSI][94] = 127, - [2][1][RTW89_FCC][96] = -16, - [2][1][RTW89_ETSI][96] = 127, - [2][1][RTW89_FCC][98] = -16, - [2][1][RTW89_ETSI][98] = 127, - [2][1][RTW89_FCC][100] = -16, - [2][1][RTW89_ETSI][100] = 127, - [2][1][RTW89_FCC][102] = -16, - [2][1][RTW89_ETSI][102] = 127, - [2][1][RTW89_FCC][104] = -16, - [2][1][RTW89_ETSI][104] = 127, - [2][1][RTW89_FCC][105] = -16, - [2][1][RTW89_ETSI][105] = 127, - [2][1][RTW89_FCC][107] = -12, - [2][1][RTW89_ETSI][107] = 127, - [2][1][RTW89_FCC][109] = -10, - [2][1][RTW89_ETSI][109] = 127, - [2][1][RTW89_FCC][111] = 127, - [2][1][RTW89_ETSI][111] = 127, - [2][1][RTW89_FCC][113] = 127, - [2][1][RTW89_ETSI][113] = 127, - [2][1][RTW89_FCC][115] = 127, - [2][1][RTW89_ETSI][115] = 127, - [2][1][RTW89_FCC][117] = 127, - [2][1][RTW89_ETSI][117] = 127, - [2][1][RTW89_FCC][119] = 127, - [2][1][RTW89_ETSI][119] = 127, + [RTW89_REGD_NUM][NUM_OF_RTW89_REG_6GHZ_POWER] + [RTW89_6G_CH_NUM] = { + [0][0][RTW89_WW][0][0] = -16, + [0][0][RTW89_WW][1][0] = -16, + [0][0][RTW89_WW][2][0] = 44, + [0][0][RTW89_WW][0][2] = -18, + [0][0][RTW89_WW][1][2] = -18, + [0][0][RTW89_WW][2][2] = 44, + [0][0][RTW89_WW][0][4] = -18, + [0][0][RTW89_WW][1][4] = -18, + [0][0][RTW89_WW][2][4] = 44, + [0][0][RTW89_WW][0][6] = -18, + [0][0][RTW89_WW][1][6] = -18, + [0][0][RTW89_WW][2][6] = 44, + [0][0][RTW89_WW][0][8] = -18, + [0][0][RTW89_WW][1][8] = -18, + [0][0][RTW89_WW][2][8] = 44, + [0][0][RTW89_WW][0][10] = -18, + [0][0][RTW89_WW][1][10] = -18, + [0][0][RTW89_WW][2][10] = 44, + [0][0][RTW89_WW][0][12] = -18, + [0][0][RTW89_WW][1][12] = -18, + [0][0][RTW89_WW][2][12] = 44, + [0][0][RTW89_WW][0][14] = -18, + [0][0][RTW89_WW][1][14] = -18, + [0][0][RTW89_WW][2][14] = 44, + [0][0][RTW89_WW][0][15] = -18, + [0][0][RTW89_WW][1][15] = -18, + [0][0][RTW89_WW][2][15] = 44, + [0][0][RTW89_WW][0][17] = -18, + [0][0][RTW89_WW][1][17] = -18, + [0][0][RTW89_WW][2][17] = 44, + [0][0][RTW89_WW][0][19] = -18, + [0][0][RTW89_WW][1][19] = -18, + [0][0][RTW89_WW][2][19] = 44, + [0][0][RTW89_WW][0][21] = -18, + [0][0][RTW89_WW][1][21] = -18, + [0][0][RTW89_WW][2][21] = 44, + [0][0][RTW89_WW][0][23] = -18, + [0][0][RTW89_WW][1][23] = -18, + [0][0][RTW89_WW][2][23] = 54, + [0][0][RTW89_WW][0][25] = -18, + [0][0][RTW89_WW][1][25] = -18, + [0][0][RTW89_WW][2][25] = 54, + [0][0][RTW89_WW][0][27] = -18, + [0][0][RTW89_WW][1][27] = -18, + [0][0][RTW89_WW][2][27] = 54, + [0][0][RTW89_WW][0][29] = -18, + [0][0][RTW89_WW][1][29] = -18, + [0][0][RTW89_WW][2][29] = 54, + [0][0][RTW89_WW][0][30] = -18, + [0][0][RTW89_WW][1][30] = -18, + [0][0][RTW89_WW][2][30] = 54, + [0][0][RTW89_WW][0][32] = -18, + [0][0][RTW89_WW][1][32] = -18, + [0][0][RTW89_WW][2][32] = 54, + [0][0][RTW89_WW][0][34] = -18, + [0][0][RTW89_WW][1][34] = -18, + [0][0][RTW89_WW][2][34] = 54, + [0][0][RTW89_WW][0][36] = -18, + [0][0][RTW89_WW][1][36] = -18, + [0][0][RTW89_WW][2][36] = 54, + [0][0][RTW89_WW][0][38] = -18, + [0][0][RTW89_WW][1][38] = -18, + [0][0][RTW89_WW][2][38] = 54, + [0][0][RTW89_WW][0][40] = -18, + [0][0][RTW89_WW][1][40] = -18, + [0][0][RTW89_WW][2][40] = 54, + [0][0][RTW89_WW][0][42] = -18, + [0][0][RTW89_WW][1][42] = -18, + [0][0][RTW89_WW][2][42] = 54, + [0][0][RTW89_WW][0][44] = -16, + [0][0][RTW89_WW][1][44] = -16, + [0][0][RTW89_WW][2][44] = 56, + [0][0][RTW89_WW][0][45] = -16, + [0][0][RTW89_WW][1][45] = -16, + [0][0][RTW89_WW][2][45] = 0, + [0][0][RTW89_WW][0][47] = -18, + [0][0][RTW89_WW][1][47] = -18, + [0][0][RTW89_WW][2][47] = 0, + [0][0][RTW89_WW][0][49] = -18, + [0][0][RTW89_WW][1][49] = -18, + [0][0][RTW89_WW][2][49] = 0, + [0][0][RTW89_WW][0][51] = -18, + [0][0][RTW89_WW][1][51] = -18, + [0][0][RTW89_WW][2][51] = 0, + [0][0][RTW89_WW][0][53] = -16, + [0][0][RTW89_WW][1][53] = -16, + [0][0][RTW89_WW][2][53] = 0, + [0][0][RTW89_WW][0][55] = -18, + [0][0][RTW89_WW][1][55] = -18, + [0][0][RTW89_WW][2][55] = 56, + [0][0][RTW89_WW][0][57] = -18, + [0][0][RTW89_WW][1][57] = -18, + [0][0][RTW89_WW][2][57] = 56, + [0][0][RTW89_WW][0][59] = -18, + [0][0][RTW89_WW][1][59] = -18, + [0][0][RTW89_WW][2][59] = 56, + [0][0][RTW89_WW][0][60] = -18, + [0][0][RTW89_WW][1][60] = -18, + [0][0][RTW89_WW][2][60] = 56, + [0][0][RTW89_WW][0][62] = -18, + [0][0][RTW89_WW][1][62] = -18, + [0][0][RTW89_WW][2][62] = 56, + [0][0][RTW89_WW][0][64] = -18, + [0][0][RTW89_WW][1][64] = -18, + [0][0][RTW89_WW][2][64] = 56, + [0][0][RTW89_WW][0][66] = -18, + [0][0][RTW89_WW][1][66] = -18, + [0][0][RTW89_WW][2][66] = 56, + [0][0][RTW89_WW][0][68] = -18, + [0][0][RTW89_WW][1][68] = -18, + [0][0][RTW89_WW][2][68] = 56, + [0][0][RTW89_WW][0][70] = -16, + [0][0][RTW89_WW][1][70] = -16, + [0][0][RTW89_WW][2][70] = 56, + [0][0][RTW89_WW][0][72] = -18, + [0][0][RTW89_WW][1][72] = -18, + [0][0][RTW89_WW][2][72] = 56, + [0][0][RTW89_WW][0][74] = -18, + [0][0][RTW89_WW][1][74] = -18, + [0][0][RTW89_WW][2][74] = 56, + [0][0][RTW89_WW][0][75] = -18, + [0][0][RTW89_WW][1][75] = -18, + [0][0][RTW89_WW][2][75] = 56, + [0][0][RTW89_WW][0][77] = -18, + [0][0][RTW89_WW][1][77] = -18, + [0][0][RTW89_WW][2][77] = 56, + [0][0][RTW89_WW][0][79] = -18, + [0][0][RTW89_WW][1][79] = -18, + [0][0][RTW89_WW][2][79] = 56, + [0][0][RTW89_WW][0][81] = -18, + [0][0][RTW89_WW][1][81] = -18, + [0][0][RTW89_WW][2][81] = 56, + [0][0][RTW89_WW][0][83] = -18, + [0][0][RTW89_WW][1][83] = -18, + [0][0][RTW89_WW][2][83] = 56, + [0][0][RTW89_WW][0][85] = -18, + [0][0][RTW89_WW][1][85] = -18, + [0][0][RTW89_WW][2][85] = 56, + [0][0][RTW89_WW][0][87] = -16, + [0][0][RTW89_WW][1][87] = -16, + [0][0][RTW89_WW][2][87] = 0, + [0][0][RTW89_WW][0][89] = -16, + [0][0][RTW89_WW][1][89] = -16, + [0][0][RTW89_WW][2][89] = 0, + [0][0][RTW89_WW][0][90] = -16, + [0][0][RTW89_WW][1][90] = -16, + [0][0][RTW89_WW][2][90] = 0, + [0][0][RTW89_WW][0][92] = -16, + [0][0][RTW89_WW][1][92] = -16, + [0][0][RTW89_WW][2][92] = 0, + [0][0][RTW89_WW][0][94] = -16, + [0][0][RTW89_WW][1][94] = -16, + [0][0][RTW89_WW][2][94] = 0, + [0][0][RTW89_WW][0][96] = -16, + [0][0][RTW89_WW][1][96] = -16, + [0][0][RTW89_WW][2][96] = 0, + [0][0][RTW89_WW][0][98] = -16, + [0][0][RTW89_WW][1][98] = -16, + [0][0][RTW89_WW][2][98] = 0, + [0][0][RTW89_WW][0][100] = -16, + [0][0][RTW89_WW][1][100] = -16, + [0][0][RTW89_WW][2][100] = 0, + [0][0][RTW89_WW][0][102] = -16, + [0][0][RTW89_WW][1][102] = -16, + [0][0][RTW89_WW][2][102] = 0, + [0][0][RTW89_WW][0][104] = -16, + [0][0][RTW89_WW][1][104] = -16, + [0][0][RTW89_WW][2][104] = 0, + [0][0][RTW89_WW][0][105] = -16, + [0][0][RTW89_WW][1][105] = -16, + [0][0][RTW89_WW][2][105] = 0, + [0][0][RTW89_WW][0][107] = -12, + [0][0][RTW89_WW][1][107] = -12, + [0][0][RTW89_WW][2][107] = 0, + [0][0][RTW89_WW][0][109] = -12, + [0][0][RTW89_WW][1][109] = -12, + [0][0][RTW89_WW][2][109] = 0, + [0][0][RTW89_WW][0][111] = 0, + [0][0][RTW89_WW][1][111] = 0, + [0][0][RTW89_WW][2][111] = 0, + [0][0][RTW89_WW][0][113] = 0, + [0][0][RTW89_WW][1][113] = 0, + [0][0][RTW89_WW][2][113] = 0, + [0][0][RTW89_WW][0][115] = 0, + [0][0][RTW89_WW][1][115] = 0, + [0][0][RTW89_WW][2][115] = 0, + [0][0][RTW89_WW][0][117] = 0, + [0][0][RTW89_WW][1][117] = 0, + [0][0][RTW89_WW][2][117] = 0, + [0][0][RTW89_WW][0][119] = 0, + [0][0][RTW89_WW][1][119] = 0, + [0][0][RTW89_WW][2][119] = 0, + [0][1][RTW89_WW][0][0] = -40, + [0][1][RTW89_WW][1][0] = -40, + [0][1][RTW89_WW][2][0] = 32, + [0][1][RTW89_WW][0][2] = -40, + [0][1][RTW89_WW][1][2] = -40, + [0][1][RTW89_WW][2][2] = 32, + [0][1][RTW89_WW][0][4] = -40, + [0][1][RTW89_WW][1][4] = -40, + [0][1][RTW89_WW][2][4] = 32, + [0][1][RTW89_WW][0][6] = -40, + [0][1][RTW89_WW][1][6] = -40, + [0][1][RTW89_WW][2][6] = 32, + [0][1][RTW89_WW][0][8] = -40, + [0][1][RTW89_WW][1][8] = -40, + [0][1][RTW89_WW][2][8] = 32, + [0][1][RTW89_WW][0][10] = -40, + [0][1][RTW89_WW][1][10] = -40, + [0][1][RTW89_WW][2][10] = 32, + [0][1][RTW89_WW][0][12] = -40, + [0][1][RTW89_WW][1][12] = -40, + [0][1][RTW89_WW][2][12] = 32, + [0][1][RTW89_WW][0][14] = -40, + [0][1][RTW89_WW][1][14] = -40, + [0][1][RTW89_WW][2][14] = 32, + [0][1][RTW89_WW][0][15] = -40, + [0][1][RTW89_WW][1][15] = -40, + [0][1][RTW89_WW][2][15] = 32, + [0][1][RTW89_WW][0][17] = -40, + [0][1][RTW89_WW][1][17] = -40, + [0][1][RTW89_WW][2][17] = 32, + [0][1][RTW89_WW][0][19] = -40, + [0][1][RTW89_WW][1][19] = -40, + [0][1][RTW89_WW][2][19] = 32, + [0][1][RTW89_WW][0][21] = -40, + [0][1][RTW89_WW][1][21] = -40, + [0][1][RTW89_WW][2][21] = 32, + [0][1][RTW89_WW][0][23] = -40, + [0][1][RTW89_WW][1][23] = -40, + [0][1][RTW89_WW][2][23] = 32, + [0][1][RTW89_WW][0][25] = -40, + [0][1][RTW89_WW][1][25] = -40, + [0][1][RTW89_WW][2][25] = 32, + [0][1][RTW89_WW][0][27] = -40, + [0][1][RTW89_WW][1][27] = -40, + [0][1][RTW89_WW][2][27] = 32, + [0][1][RTW89_WW][0][29] = -40, + [0][1][RTW89_WW][1][29] = -40, + [0][1][RTW89_WW][2][29] = 32, + [0][1][RTW89_WW][0][30] = -40, + [0][1][RTW89_WW][1][30] = -40, + [0][1][RTW89_WW][2][30] = 32, + [0][1][RTW89_WW][0][32] = -40, + [0][1][RTW89_WW][1][32] = -40, + [0][1][RTW89_WW][2][32] = 32, + [0][1][RTW89_WW][0][34] = -40, + [0][1][RTW89_WW][1][34] = -40, + [0][1][RTW89_WW][2][34] = 32, + [0][1][RTW89_WW][0][36] = -40, + [0][1][RTW89_WW][1][36] = -40, + [0][1][RTW89_WW][2][36] = 32, + [0][1][RTW89_WW][0][38] = -40, + [0][1][RTW89_WW][1][38] = -40, + [0][1][RTW89_WW][2][38] = 32, + [0][1][RTW89_WW][0][40] = -40, + [0][1][RTW89_WW][1][40] = -40, + [0][1][RTW89_WW][2][40] = 32, + [0][1][RTW89_WW][0][42] = -40, + [0][1][RTW89_WW][1][42] = -40, + [0][1][RTW89_WW][2][42] = 32, + [0][1][RTW89_WW][0][44] = -40, + [0][1][RTW89_WW][1][44] = -40, + [0][1][RTW89_WW][2][44] = 32, + [0][1][RTW89_WW][0][45] = -40, + [0][1][RTW89_WW][1][45] = -40, + [0][1][RTW89_WW][2][45] = 0, + [0][1][RTW89_WW][0][47] = -40, + [0][1][RTW89_WW][1][47] = -40, + [0][1][RTW89_WW][2][47] = 0, + [0][1][RTW89_WW][0][49] = -40, + [0][1][RTW89_WW][1][49] = -40, + [0][1][RTW89_WW][2][49] = 0, + [0][1][RTW89_WW][0][51] = -40, + [0][1][RTW89_WW][1][51] = -40, + [0][1][RTW89_WW][2][51] = 0, + [0][1][RTW89_WW][0][53] = -40, + [0][1][RTW89_WW][1][53] = -40, + [0][1][RTW89_WW][2][53] = 0, + [0][1][RTW89_WW][0][55] = -40, + [0][1][RTW89_WW][1][55] = -40, + [0][1][RTW89_WW][2][55] = 30, + [0][1][RTW89_WW][0][57] = -40, + [0][1][RTW89_WW][1][57] = -40, + [0][1][RTW89_WW][2][57] = 30, + [0][1][RTW89_WW][0][59] = -40, + [0][1][RTW89_WW][1][59] = -40, + [0][1][RTW89_WW][2][59] = 30, + [0][1][RTW89_WW][0][60] = -40, + [0][1][RTW89_WW][1][60] = -40, + [0][1][RTW89_WW][2][60] = 30, + [0][1][RTW89_WW][0][62] = -40, + [0][1][RTW89_WW][1][62] = -40, + [0][1][RTW89_WW][2][62] = 30, + [0][1][RTW89_WW][0][64] = -40, + [0][1][RTW89_WW][1][64] = -40, + [0][1][RTW89_WW][2][64] = 30, + [0][1][RTW89_WW][0][66] = -40, + [0][1][RTW89_WW][1][66] = -40, + [0][1][RTW89_WW][2][66] = 30, + [0][1][RTW89_WW][0][68] = -40, + [0][1][RTW89_WW][1][68] = -40, + [0][1][RTW89_WW][2][68] = 30, + [0][1][RTW89_WW][0][70] = -38, + [0][1][RTW89_WW][1][70] = -38, + [0][1][RTW89_WW][2][70] = 30, + [0][1][RTW89_WW][0][72] = -38, + [0][1][RTW89_WW][1][72] = -38, + [0][1][RTW89_WW][2][72] = 30, + [0][1][RTW89_WW][0][74] = -38, + [0][1][RTW89_WW][1][74] = -38, + [0][1][RTW89_WW][2][74] = 30, + [0][1][RTW89_WW][0][75] = -38, + [0][1][RTW89_WW][1][75] = -38, + [0][1][RTW89_WW][2][75] = 30, + [0][1][RTW89_WW][0][77] = -38, + [0][1][RTW89_WW][1][77] = -38, + [0][1][RTW89_WW][2][77] = 30, + [0][1][RTW89_WW][0][79] = -38, + [0][1][RTW89_WW][1][79] = -38, + [0][1][RTW89_WW][2][79] = 30, + [0][1][RTW89_WW][0][81] = -38, + [0][1][RTW89_WW][1][81] = -38, + [0][1][RTW89_WW][2][81] = 30, + [0][1][RTW89_WW][0][83] = -38, + [0][1][RTW89_WW][1][83] = -38, + [0][1][RTW89_WW][2][83] = 30, + [0][1][RTW89_WW][0][85] = -38, + [0][1][RTW89_WW][1][85] = -38, + [0][1][RTW89_WW][2][85] = 30, + [0][1][RTW89_WW][0][87] = -40, + [0][1][RTW89_WW][1][87] = -40, + [0][1][RTW89_WW][2][87] = 0, + [0][1][RTW89_WW][0][89] = -38, + [0][1][RTW89_WW][1][89] = -38, + [0][1][RTW89_WW][2][89] = 0, + [0][1][RTW89_WW][0][90] = -38, + [0][1][RTW89_WW][1][90] = -38, + [0][1][RTW89_WW][2][90] = 0, + [0][1][RTW89_WW][0][92] = -38, + [0][1][RTW89_WW][1][92] = -38, + [0][1][RTW89_WW][2][92] = 0, + [0][1][RTW89_WW][0][94] = -38, + [0][1][RTW89_WW][1][94] = -38, + [0][1][RTW89_WW][2][94] = 0, + [0][1][RTW89_WW][0][96] = -38, + [0][1][RTW89_WW][1][96] = -38, + [0][1][RTW89_WW][2][96] = 0, + [0][1][RTW89_WW][0][98] = -38, + [0][1][RTW89_WW][1][98] = -38, + [0][1][RTW89_WW][2][98] = 0, + [0][1][RTW89_WW][0][100] = -38, + [0][1][RTW89_WW][1][100] = -38, + [0][1][RTW89_WW][2][100] = 0, + [0][1][RTW89_WW][0][102] = -38, + [0][1][RTW89_WW][1][102] = -38, + [0][1][RTW89_WW][2][102] = 0, + [0][1][RTW89_WW][0][104] = -38, + [0][1][RTW89_WW][1][104] = -38, + [0][1][RTW89_WW][2][104] = 0, + [0][1][RTW89_WW][0][105] = -38, + [0][1][RTW89_WW][1][105] = -38, + [0][1][RTW89_WW][2][105] = 0, + [0][1][RTW89_WW][0][107] = -34, + [0][1][RTW89_WW][1][107] = -34, + [0][1][RTW89_WW][2][107] = 0, + [0][1][RTW89_WW][0][109] = -34, + [0][1][RTW89_WW][1][109] = -34, + [0][1][RTW89_WW][2][109] = 0, + [0][1][RTW89_WW][0][111] = 0, + [0][1][RTW89_WW][1][111] = 0, + [0][1][RTW89_WW][2][111] = 0, + [0][1][RTW89_WW][0][113] = 0, + [0][1][RTW89_WW][1][113] = 0, + [0][1][RTW89_WW][2][113] = 0, + [0][1][RTW89_WW][0][115] = 0, + [0][1][RTW89_WW][1][115] = 0, + [0][1][RTW89_WW][2][115] = 0, + [0][1][RTW89_WW][0][117] = 0, + [0][1][RTW89_WW][1][117] = 0, + [0][1][RTW89_WW][2][117] = 0, + [0][1][RTW89_WW][0][119] = 0, + [0][1][RTW89_WW][1][119] = 0, + [0][1][RTW89_WW][2][119] = 0, + [1][0][RTW89_WW][0][0] = -4, + [1][0][RTW89_WW][1][0] = -4, + [1][0][RTW89_WW][2][0] = 52, + [1][0][RTW89_WW][0][2] = -4, + [1][0][RTW89_WW][1][2] = -4, + [1][0][RTW89_WW][2][2] = 52, + [1][0][RTW89_WW][0][4] = -4, + [1][0][RTW89_WW][1][4] = -4, + [1][0][RTW89_WW][2][4] = 52, + [1][0][RTW89_WW][0][6] = -4, + [1][0][RTW89_WW][1][6] = -4, + [1][0][RTW89_WW][2][6] = 52, + [1][0][RTW89_WW][0][8] = -4, + [1][0][RTW89_WW][1][8] = -4, + [1][0][RTW89_WW][2][8] = 52, + [1][0][RTW89_WW][0][10] = -4, + [1][0][RTW89_WW][1][10] = -4, + [1][0][RTW89_WW][2][10] = 52, + [1][0][RTW89_WW][0][12] = -4, + [1][0][RTW89_WW][1][12] = -4, + [1][0][RTW89_WW][2][12] = 52, + [1][0][RTW89_WW][0][14] = -4, + [1][0][RTW89_WW][1][14] = -4, + [1][0][RTW89_WW][2][14] = 52, + [1][0][RTW89_WW][0][15] = -4, + [1][0][RTW89_WW][1][15] = -4, + [1][0][RTW89_WW][2][15] = 52, + [1][0][RTW89_WW][0][17] = -4, + [1][0][RTW89_WW][1][17] = -4, + [1][0][RTW89_WW][2][17] = 52, + [1][0][RTW89_WW][0][19] = -4, + [1][0][RTW89_WW][1][19] = -4, + [1][0][RTW89_WW][2][19] = 52, + [1][0][RTW89_WW][0][21] = -4, + [1][0][RTW89_WW][1][21] = -4, + [1][0][RTW89_WW][2][21] = 52, + [1][0][RTW89_WW][0][23] = -4, + [1][0][RTW89_WW][1][23] = -4, + [1][0][RTW89_WW][2][23] = 66, + [1][0][RTW89_WW][0][25] = -4, + [1][0][RTW89_WW][1][25] = -4, + [1][0][RTW89_WW][2][25] = 66, + [1][0][RTW89_WW][0][27] = -4, + [1][0][RTW89_WW][1][27] = -4, + [1][0][RTW89_WW][2][27] = 66, + [1][0][RTW89_WW][0][29] = -4, + [1][0][RTW89_WW][1][29] = -4, + [1][0][RTW89_WW][2][29] = 66, + [1][0][RTW89_WW][0][30] = -4, + [1][0][RTW89_WW][1][30] = -4, + [1][0][RTW89_WW][2][30] = 66, + [1][0][RTW89_WW][0][32] = -4, + [1][0][RTW89_WW][1][32] = -4, + [1][0][RTW89_WW][2][32] = 66, + [1][0][RTW89_WW][0][34] = -4, + [1][0][RTW89_WW][1][34] = -4, + [1][0][RTW89_WW][2][34] = 66, + [1][0][RTW89_WW][0][36] = -4, + [1][0][RTW89_WW][1][36] = -4, + [1][0][RTW89_WW][2][36] = 66, + [1][0][RTW89_WW][0][38] = -4, + [1][0][RTW89_WW][1][38] = -4, + [1][0][RTW89_WW][2][38] = 66, + [1][0][RTW89_WW][0][40] = -4, + [1][0][RTW89_WW][1][40] = -4, + [1][0][RTW89_WW][2][40] = 66, + [1][0][RTW89_WW][0][42] = -4, + [1][0][RTW89_WW][1][42] = -4, + [1][0][RTW89_WW][2][42] = 66, + [1][0][RTW89_WW][0][44] = -4, + [1][0][RTW89_WW][1][44] = -4, + [1][0][RTW89_WW][2][44] = 66, + [1][0][RTW89_WW][0][45] = -4, + [1][0][RTW89_WW][1][45] = -4, + [1][0][RTW89_WW][2][45] = 0, + [1][0][RTW89_WW][0][47] = -4, + [1][0][RTW89_WW][1][47] = -4, + [1][0][RTW89_WW][2][47] = 0, + [1][0][RTW89_WW][0][49] = -4, + [1][0][RTW89_WW][1][49] = -4, + [1][0][RTW89_WW][2][49] = 0, + [1][0][RTW89_WW][0][51] = -4, + [1][0][RTW89_WW][1][51] = -4, + [1][0][RTW89_WW][2][51] = 0, + [1][0][RTW89_WW][0][53] = -4, + [1][0][RTW89_WW][1][53] = -4, + [1][0][RTW89_WW][2][53] = 0, + [1][0][RTW89_WW][0][55] = -4, + [1][0][RTW89_WW][1][55] = -4, + [1][0][RTW89_WW][2][55] = 68, + [1][0][RTW89_WW][0][57] = -4, + [1][0][RTW89_WW][1][57] = -4, + [1][0][RTW89_WW][2][57] = 68, + [1][0][RTW89_WW][0][59] = -4, + [1][0][RTW89_WW][1][59] = -4, + [1][0][RTW89_WW][2][59] = 68, + [1][0][RTW89_WW][0][60] = -4, + [1][0][RTW89_WW][1][60] = -4, + [1][0][RTW89_WW][2][60] = 68, + [1][0][RTW89_WW][0][62] = -4, + [1][0][RTW89_WW][1][62] = -4, + [1][0][RTW89_WW][2][62] = 68, + [1][0][RTW89_WW][0][64] = -4, + [1][0][RTW89_WW][1][64] = -4, + [1][0][RTW89_WW][2][64] = 68, + [1][0][RTW89_WW][0][66] = -4, + [1][0][RTW89_WW][1][66] = -4, + [1][0][RTW89_WW][2][66] = 68, + [1][0][RTW89_WW][0][68] = -4, + [1][0][RTW89_WW][1][68] = -4, + [1][0][RTW89_WW][2][68] = 68, + [1][0][RTW89_WW][0][70] = -4, + [1][0][RTW89_WW][1][70] = -4, + [1][0][RTW89_WW][2][70] = 68, + [1][0][RTW89_WW][0][72] = -4, + [1][0][RTW89_WW][1][72] = -4, + [1][0][RTW89_WW][2][72] = 68, + [1][0][RTW89_WW][0][74] = -4, + [1][0][RTW89_WW][1][74] = -4, + [1][0][RTW89_WW][2][74] = 68, + [1][0][RTW89_WW][0][75] = -4, + [1][0][RTW89_WW][1][75] = -4, + [1][0][RTW89_WW][2][75] = 68, + [1][0][RTW89_WW][0][77] = -4, + [1][0][RTW89_WW][1][77] = -4, + [1][0][RTW89_WW][2][77] = 68, + [1][0][RTW89_WW][0][79] = -4, + [1][0][RTW89_WW][1][79] = -4, + [1][0][RTW89_WW][2][79] = 68, + [1][0][RTW89_WW][0][81] = -4, + [1][0][RTW89_WW][1][81] = -4, + [1][0][RTW89_WW][2][81] = 68, + [1][0][RTW89_WW][0][83] = -4, + [1][0][RTW89_WW][1][83] = -4, + [1][0][RTW89_WW][2][83] = 68, + [1][0][RTW89_WW][0][85] = -4, + [1][0][RTW89_WW][1][85] = -4, + [1][0][RTW89_WW][2][85] = 68, + [1][0][RTW89_WW][0][87] = -4, + [1][0][RTW89_WW][1][87] = -4, + [1][0][RTW89_WW][2][87] = 0, + [1][0][RTW89_WW][0][89] = -4, + [1][0][RTW89_WW][1][89] = -4, + [1][0][RTW89_WW][2][89] = 0, + [1][0][RTW89_WW][0][90] = -4, + [1][0][RTW89_WW][1][90] = -4, + [1][0][RTW89_WW][2][90] = 0, + [1][0][RTW89_WW][0][92] = -4, + [1][0][RTW89_WW][1][92] = -4, + [1][0][RTW89_WW][2][92] = 0, + [1][0][RTW89_WW][0][94] = -4, + [1][0][RTW89_WW][1][94] = -4, + [1][0][RTW89_WW][2][94] = 0, + [1][0][RTW89_WW][0][96] = -4, + [1][0][RTW89_WW][1][96] = -4, + [1][0][RTW89_WW][2][96] = 0, + [1][0][RTW89_WW][0][98] = -4, + [1][0][RTW89_WW][1][98] = -4, + [1][0][RTW89_WW][2][98] = 0, + [1][0][RTW89_WW][0][100] = -4, + [1][0][RTW89_WW][1][100] = -4, + [1][0][RTW89_WW][2][100] = 0, + [1][0][RTW89_WW][0][102] = -4, + [1][0][RTW89_WW][1][102] = -4, + [1][0][RTW89_WW][2][102] = 0, + [1][0][RTW89_WW][0][104] = -4, + [1][0][RTW89_WW][1][104] = -4, + [1][0][RTW89_WW][2][104] = 0, + [1][0][RTW89_WW][0][105] = -4, + [1][0][RTW89_WW][1][105] = -4, + [1][0][RTW89_WW][2][105] = 0, + [1][0][RTW89_WW][0][107] = -2, + [1][0][RTW89_WW][1][107] = -2, + [1][0][RTW89_WW][2][107] = 0, + [1][0][RTW89_WW][0][109] = 2, + [1][0][RTW89_WW][1][109] = 2, + [1][0][RTW89_WW][2][109] = 0, + [1][0][RTW89_WW][0][111] = 0, + [1][0][RTW89_WW][1][111] = 0, + [1][0][RTW89_WW][2][111] = 0, + [1][0][RTW89_WW][0][113] = 0, + [1][0][RTW89_WW][1][113] = 0, + [1][0][RTW89_WW][2][113] = 0, + [1][0][RTW89_WW][0][115] = 0, + [1][0][RTW89_WW][1][115] = 0, + [1][0][RTW89_WW][2][115] = 0, + [1][0][RTW89_WW][0][117] = 0, + [1][0][RTW89_WW][1][117] = 0, + [1][0][RTW89_WW][2][117] = 0, + [1][0][RTW89_WW][0][119] = 0, + [1][0][RTW89_WW][1][119] = 0, + [1][0][RTW89_WW][2][119] = 0, + [1][1][RTW89_WW][0][0] = -26, + [1][1][RTW89_WW][1][0] = -26, + [1][1][RTW89_WW][2][0] = 44, + [1][1][RTW89_WW][0][2] = -28, + [1][1][RTW89_WW][1][2] = -28, + [1][1][RTW89_WW][2][2] = 44, + [1][1][RTW89_WW][0][4] = -28, + [1][1][RTW89_WW][1][4] = -28, + [1][1][RTW89_WW][2][4] = 44, + [1][1][RTW89_WW][0][6] = -28, + [1][1][RTW89_WW][1][6] = -28, + [1][1][RTW89_WW][2][6] = 44, + [1][1][RTW89_WW][0][8] = -28, + [1][1][RTW89_WW][1][8] = -28, + [1][1][RTW89_WW][2][8] = 44, + [1][1][RTW89_WW][0][10] = -28, + [1][1][RTW89_WW][1][10] = -28, + [1][1][RTW89_WW][2][10] = 44, + [1][1][RTW89_WW][0][12] = -28, + [1][1][RTW89_WW][1][12] = -28, + [1][1][RTW89_WW][2][12] = 44, + [1][1][RTW89_WW][0][14] = -28, + [1][1][RTW89_WW][1][14] = -28, + [1][1][RTW89_WW][2][14] = 44, + [1][1][RTW89_WW][0][15] = -28, + [1][1][RTW89_WW][1][15] = -28, + [1][1][RTW89_WW][2][15] = 44, + [1][1][RTW89_WW][0][17] = -28, + [1][1][RTW89_WW][1][17] = -28, + [1][1][RTW89_WW][2][17] = 44, + [1][1][RTW89_WW][0][19] = -28, + [1][1][RTW89_WW][1][19] = -28, + [1][1][RTW89_WW][2][19] = 44, + [1][1][RTW89_WW][0][21] = -28, + [1][1][RTW89_WW][1][21] = -28, + [1][1][RTW89_WW][2][21] = 44, + [1][1][RTW89_WW][0][23] = -28, + [1][1][RTW89_WW][1][23] = -28, + [1][1][RTW89_WW][2][23] = 44, + [1][1][RTW89_WW][0][25] = -28, + [1][1][RTW89_WW][1][25] = -28, + [1][1][RTW89_WW][2][25] = 44, + [1][1][RTW89_WW][0][27] = -28, + [1][1][RTW89_WW][1][27] = -28, + [1][1][RTW89_WW][2][27] = 44, + [1][1][RTW89_WW][0][29] = -28, + [1][1][RTW89_WW][1][29] = -28, + [1][1][RTW89_WW][2][29] = 44, + [1][1][RTW89_WW][0][30] = -28, + [1][1][RTW89_WW][1][30] = -28, + [1][1][RTW89_WW][2][30] = 44, + [1][1][RTW89_WW][0][32] = -28, + [1][1][RTW89_WW][1][32] = -28, + [1][1][RTW89_WW][2][32] = 44, + [1][1][RTW89_WW][0][34] = -28, + [1][1][RTW89_WW][1][34] = -28, + [1][1][RTW89_WW][2][34] = 44, + [1][1][RTW89_WW][0][36] = -28, + [1][1][RTW89_WW][1][36] = -28, + [1][1][RTW89_WW][2][36] = 44, + [1][1][RTW89_WW][0][38] = -28, + [1][1][RTW89_WW][1][38] = -28, + [1][1][RTW89_WW][2][38] = 44, + [1][1][RTW89_WW][0][40] = -28, + [1][1][RTW89_WW][1][40] = -28, + [1][1][RTW89_WW][2][40] = 44, + [1][1][RTW89_WW][0][42] = -28, + [1][1][RTW89_WW][1][42] = -28, + [1][1][RTW89_WW][2][42] = 44, + [1][1][RTW89_WW][0][44] = -28, + [1][1][RTW89_WW][1][44] = -28, + [1][1][RTW89_WW][2][44] = 44, + [1][1][RTW89_WW][0][45] = -26, + [1][1][RTW89_WW][1][45] = -26, + [1][1][RTW89_WW][2][45] = 0, + [1][1][RTW89_WW][0][47] = -28, + [1][1][RTW89_WW][1][47] = -28, + [1][1][RTW89_WW][2][47] = 0, + [1][1][RTW89_WW][0][49] = -28, + [1][1][RTW89_WW][1][49] = -28, + [1][1][RTW89_WW][2][49] = 0, + [1][1][RTW89_WW][0][51] = -28, + [1][1][RTW89_WW][1][51] = -28, + [1][1][RTW89_WW][2][51] = 0, + [1][1][RTW89_WW][0][53] = -26, + [1][1][RTW89_WW][1][53] = -26, + [1][1][RTW89_WW][2][53] = 0, + [1][1][RTW89_WW][0][55] = -28, + [1][1][RTW89_WW][1][55] = -28, + [1][1][RTW89_WW][2][55] = 44, + [1][1][RTW89_WW][0][57] = -28, + [1][1][RTW89_WW][1][57] = -28, + [1][1][RTW89_WW][2][57] = 44, + [1][1][RTW89_WW][0][59] = -28, + [1][1][RTW89_WW][1][59] = -28, + [1][1][RTW89_WW][2][59] = 44, + [1][1][RTW89_WW][0][60] = -28, + [1][1][RTW89_WW][1][60] = -28, + [1][1][RTW89_WW][2][60] = 44, + [1][1][RTW89_WW][0][62] = -28, + [1][1][RTW89_WW][1][62] = -28, + [1][1][RTW89_WW][2][62] = 44, + [1][1][RTW89_WW][0][64] = -28, + [1][1][RTW89_WW][1][64] = -28, + [1][1][RTW89_WW][2][64] = 44, + [1][1][RTW89_WW][0][66] = -28, + [1][1][RTW89_WW][1][66] = -28, + [1][1][RTW89_WW][2][66] = 44, + [1][1][RTW89_WW][0][68] = -28, + [1][1][RTW89_WW][1][68] = -28, + [1][1][RTW89_WW][2][68] = 44, + [1][1][RTW89_WW][0][70] = -26, + [1][1][RTW89_WW][1][70] = -26, + [1][1][RTW89_WW][2][70] = 44, + [1][1][RTW89_WW][0][72] = -28, + [1][1][RTW89_WW][1][72] = -28, + [1][1][RTW89_WW][2][72] = 44, + [1][1][RTW89_WW][0][74] = -28, + [1][1][RTW89_WW][1][74] = -28, + [1][1][RTW89_WW][2][74] = 44, + [1][1][RTW89_WW][0][75] = -28, + [1][1][RTW89_WW][1][75] = -28, + [1][1][RTW89_WW][2][75] = 44, + [1][1][RTW89_WW][0][77] = -28, + [1][1][RTW89_WW][1][77] = -28, + [1][1][RTW89_WW][2][77] = 44, + [1][1][RTW89_WW][0][79] = -28, + [1][1][RTW89_WW][1][79] = -28, + [1][1][RTW89_WW][2][79] = 44, + [1][1][RTW89_WW][0][81] = -28, + [1][1][RTW89_WW][1][81] = -28, + [1][1][RTW89_WW][2][81] = 44, + [1][1][RTW89_WW][0][83] = -28, + [1][1][RTW89_WW][1][83] = -28, + [1][1][RTW89_WW][2][83] = 44, + [1][1][RTW89_WW][0][85] = -28, + [1][1][RTW89_WW][1][85] = -28, + [1][1][RTW89_WW][2][85] = 44, + [1][1][RTW89_WW][0][87] = -28, + [1][1][RTW89_WW][1][87] = -28, + [1][1][RTW89_WW][2][87] = 0, + [1][1][RTW89_WW][0][89] = -26, + [1][1][RTW89_WW][1][89] = -26, + [1][1][RTW89_WW][2][89] = 0, + [1][1][RTW89_WW][0][90] = -26, + [1][1][RTW89_WW][1][90] = -26, + [1][1][RTW89_WW][2][90] = 0, + [1][1][RTW89_WW][0][92] = -26, + [1][1][RTW89_WW][1][92] = -26, + [1][1][RTW89_WW][2][92] = 0, + [1][1][RTW89_WW][0][94] = -26, + [1][1][RTW89_WW][1][94] = -26, + [1][1][RTW89_WW][2][94] = 0, + [1][1][RTW89_WW][0][96] = -26, + [1][1][RTW89_WW][1][96] = -26, + [1][1][RTW89_WW][2][96] = 0, + [1][1][RTW89_WW][0][98] = -26, + [1][1][RTW89_WW][1][98] = -26, + [1][1][RTW89_WW][2][98] = 0, + [1][1][RTW89_WW][0][100] = -26, + [1][1][RTW89_WW][1][100] = -26, + [1][1][RTW89_WW][2][100] = 0, + [1][1][RTW89_WW][0][102] = -26, + [1][1][RTW89_WW][1][102] = -26, + [1][1][RTW89_WW][2][102] = 0, + [1][1][RTW89_WW][0][104] = -26, + [1][1][RTW89_WW][1][104] = -26, + [1][1][RTW89_WW][2][104] = 0, + [1][1][RTW89_WW][0][105] = -26, + [1][1][RTW89_WW][1][105] = -26, + [1][1][RTW89_WW][2][105] = 0, + [1][1][RTW89_WW][0][107] = -22, + [1][1][RTW89_WW][1][107] = -22, + [1][1][RTW89_WW][2][107] = 0, + [1][1][RTW89_WW][0][109] = -22, + [1][1][RTW89_WW][1][109] = -22, + [1][1][RTW89_WW][2][109] = 0, + [1][1][RTW89_WW][0][111] = 0, + [1][1][RTW89_WW][1][111] = 0, + [1][1][RTW89_WW][2][111] = 0, + [1][1][RTW89_WW][0][113] = 0, + [1][1][RTW89_WW][1][113] = 0, + [1][1][RTW89_WW][2][113] = 0, + [1][1][RTW89_WW][0][115] = 0, + [1][1][RTW89_WW][1][115] = 0, + [1][1][RTW89_WW][2][115] = 0, + [1][1][RTW89_WW][0][117] = 0, + [1][1][RTW89_WW][1][117] = 0, + [1][1][RTW89_WW][2][117] = 0, + [1][1][RTW89_WW][0][119] = 0, + [1][1][RTW89_WW][1][119] = 0, + [1][1][RTW89_WW][2][119] = 0, + [2][0][RTW89_WW][0][0] = -2, + [2][0][RTW89_WW][1][0] = -2, + [2][0][RTW89_WW][2][0] = 60, + [2][0][RTW89_WW][0][2] = -2, + [2][0][RTW89_WW][1][2] = -2, + [2][0][RTW89_WW][2][2] = 60, + [2][0][RTW89_WW][0][4] = -2, + [2][0][RTW89_WW][1][4] = -2, + [2][0][RTW89_WW][2][4] = 60, + [2][0][RTW89_WW][0][6] = -2, + [2][0][RTW89_WW][1][6] = -2, + [2][0][RTW89_WW][2][6] = 60, + [2][0][RTW89_WW][0][8] = -2, + [2][0][RTW89_WW][1][8] = -2, + [2][0][RTW89_WW][2][8] = 60, + [2][0][RTW89_WW][0][10] = -2, + [2][0][RTW89_WW][1][10] = -2, + [2][0][RTW89_WW][2][10] = 60, + [2][0][RTW89_WW][0][12] = -2, + [2][0][RTW89_WW][1][12] = -2, + [2][0][RTW89_WW][2][12] = 60, + [2][0][RTW89_WW][0][14] = -2, + [2][0][RTW89_WW][1][14] = -2, + [2][0][RTW89_WW][2][14] = 60, + [2][0][RTW89_WW][0][15] = -2, + [2][0][RTW89_WW][1][15] = -2, + [2][0][RTW89_WW][2][15] = 60, + [2][0][RTW89_WW][0][17] = -2, + [2][0][RTW89_WW][1][17] = -2, + [2][0][RTW89_WW][2][17] = 60, + [2][0][RTW89_WW][0][19] = -2, + [2][0][RTW89_WW][1][19] = -2, + [2][0][RTW89_WW][2][19] = 60, + [2][0][RTW89_WW][0][21] = -2, + [2][0][RTW89_WW][1][21] = -2, + [2][0][RTW89_WW][2][21] = 60, + [2][0][RTW89_WW][0][23] = -2, + [2][0][RTW89_WW][1][23] = -2, + [2][0][RTW89_WW][2][23] = 78, + [2][0][RTW89_WW][0][25] = -2, + [2][0][RTW89_WW][1][25] = -2, + [2][0][RTW89_WW][2][25] = 78, + [2][0][RTW89_WW][0][27] = -2, + [2][0][RTW89_WW][1][27] = -2, + [2][0][RTW89_WW][2][27] = 78, + [2][0][RTW89_WW][0][29] = -2, + [2][0][RTW89_WW][1][29] = -2, + [2][0][RTW89_WW][2][29] = 78, + [2][0][RTW89_WW][0][30] = -2, + [2][0][RTW89_WW][1][30] = -2, + [2][0][RTW89_WW][2][30] = 78, + [2][0][RTW89_WW][0][32] = -2, + [2][0][RTW89_WW][1][32] = -2, + [2][0][RTW89_WW][2][32] = 78, + [2][0][RTW89_WW][0][34] = -2, + [2][0][RTW89_WW][1][34] = -2, + [2][0][RTW89_WW][2][34] = 78, + [2][0][RTW89_WW][0][36] = -2, + [2][0][RTW89_WW][1][36] = -2, + [2][0][RTW89_WW][2][36] = 78, + [2][0][RTW89_WW][0][38] = -2, + [2][0][RTW89_WW][1][38] = -2, + [2][0][RTW89_WW][2][38] = 78, + [2][0][RTW89_WW][0][40] = -2, + [2][0][RTW89_WW][1][40] = -2, + [2][0][RTW89_WW][2][40] = 78, + [2][0][RTW89_WW][0][42] = -2, + [2][0][RTW89_WW][1][42] = -2, + [2][0][RTW89_WW][2][42] = 78, + [2][0][RTW89_WW][0][44] = -2, + [2][0][RTW89_WW][1][44] = -2, + [2][0][RTW89_WW][2][44] = 78, + [2][0][RTW89_WW][0][45] = -2, + [2][0][RTW89_WW][1][45] = -2, + [2][0][RTW89_WW][2][45] = 0, + [2][0][RTW89_WW][0][47] = -2, + [2][0][RTW89_WW][1][47] = -2, + [2][0][RTW89_WW][2][47] = 0, + [2][0][RTW89_WW][0][49] = -2, + [2][0][RTW89_WW][1][49] = -2, + [2][0][RTW89_WW][2][49] = 0, + [2][0][RTW89_WW][0][51] = -2, + [2][0][RTW89_WW][1][51] = -2, + [2][0][RTW89_WW][2][51] = 0, + [2][0][RTW89_WW][0][53] = -2, + [2][0][RTW89_WW][1][53] = -2, + [2][0][RTW89_WW][2][53] = 0, + [2][0][RTW89_WW][0][55] = -2, + [2][0][RTW89_WW][1][55] = -2, + [2][0][RTW89_WW][2][55] = 78, + [2][0][RTW89_WW][0][57] = -2, + [2][0][RTW89_WW][1][57] = -2, + [2][0][RTW89_WW][2][57] = 78, + [2][0][RTW89_WW][0][59] = -2, + [2][0][RTW89_WW][1][59] = -2, + [2][0][RTW89_WW][2][59] = 78, + [2][0][RTW89_WW][0][60] = -2, + [2][0][RTW89_WW][1][60] = -2, + [2][0][RTW89_WW][2][60] = 78, + [2][0][RTW89_WW][0][62] = -2, + [2][0][RTW89_WW][1][62] = -2, + [2][0][RTW89_WW][2][62] = 78, + [2][0][RTW89_WW][0][64] = -2, + [2][0][RTW89_WW][1][64] = -2, + [2][0][RTW89_WW][2][64] = 78, + [2][0][RTW89_WW][0][66] = -2, + [2][0][RTW89_WW][1][66] = -2, + [2][0][RTW89_WW][2][66] = 78, + [2][0][RTW89_WW][0][68] = -2, + [2][0][RTW89_WW][1][68] = -2, + [2][0][RTW89_WW][2][68] = 78, + [2][0][RTW89_WW][0][70] = -2, + [2][0][RTW89_WW][1][70] = -2, + [2][0][RTW89_WW][2][70] = 78, + [2][0][RTW89_WW][0][72] = -2, + [2][0][RTW89_WW][1][72] = -2, + [2][0][RTW89_WW][2][72] = 78, + [2][0][RTW89_WW][0][74] = -2, + [2][0][RTW89_WW][1][74] = -2, + [2][0][RTW89_WW][2][74] = 78, + [2][0][RTW89_WW][0][75] = -2, + [2][0][RTW89_WW][1][75] = -2, + [2][0][RTW89_WW][2][75] = 78, + [2][0][RTW89_WW][0][77] = -2, + [2][0][RTW89_WW][1][77] = -2, + [2][0][RTW89_WW][2][77] = 78, + [2][0][RTW89_WW][0][79] = -2, + [2][0][RTW89_WW][1][79] = -2, + [2][0][RTW89_WW][2][79] = 78, + [2][0][RTW89_WW][0][81] = -2, + [2][0][RTW89_WW][1][81] = -2, + [2][0][RTW89_WW][2][81] = 78, + [2][0][RTW89_WW][0][83] = -2, + [2][0][RTW89_WW][1][83] = -2, + [2][0][RTW89_WW][2][83] = 78, + [2][0][RTW89_WW][0][85] = -2, + [2][0][RTW89_WW][1][85] = -2, + [2][0][RTW89_WW][2][85] = 78, + [2][0][RTW89_WW][0][87] = -2, + [2][0][RTW89_WW][1][87] = -2, + [2][0][RTW89_WW][2][87] = 0, + [2][0][RTW89_WW][0][89] = -2, + [2][0][RTW89_WW][1][89] = -2, + [2][0][RTW89_WW][2][89] = 0, + [2][0][RTW89_WW][0][90] = -2, + [2][0][RTW89_WW][1][90] = -2, + [2][0][RTW89_WW][2][90] = 0, + [2][0][RTW89_WW][0][92] = -2, + [2][0][RTW89_WW][1][92] = -2, + [2][0][RTW89_WW][2][92] = 0, + [2][0][RTW89_WW][0][94] = -2, + [2][0][RTW89_WW][1][94] = -2, + [2][0][RTW89_WW][2][94] = 0, + [2][0][RTW89_WW][0][96] = -2, + [2][0][RTW89_WW][1][96] = -2, + [2][0][RTW89_WW][2][96] = 0, + [2][0][RTW89_WW][0][98] = -2, + [2][0][RTW89_WW][1][98] = -2, + [2][0][RTW89_WW][2][98] = 0, + [2][0][RTW89_WW][0][100] = -2, + [2][0][RTW89_WW][1][100] = -2, + [2][0][RTW89_WW][2][100] = 0, + [2][0][RTW89_WW][0][102] = -2, + [2][0][RTW89_WW][1][102] = -2, + [2][0][RTW89_WW][2][102] = 0, + [2][0][RTW89_WW][0][104] = -2, + [2][0][RTW89_WW][1][104] = -2, + [2][0][RTW89_WW][2][104] = 0, + [2][0][RTW89_WW][0][105] = -2, + [2][0][RTW89_WW][1][105] = -2, + [2][0][RTW89_WW][2][105] = 0, + [2][0][RTW89_WW][0][107] = -2, + [2][0][RTW89_WW][1][107] = -2, + [2][0][RTW89_WW][2][107] = 0, + [2][0][RTW89_WW][0][109] = 12, + [2][0][RTW89_WW][1][109] = 12, + [2][0][RTW89_WW][2][109] = 0, + [2][0][RTW89_WW][0][111] = 0, + [2][0][RTW89_WW][1][111] = 0, + [2][0][RTW89_WW][2][111] = 0, + [2][0][RTW89_WW][0][113] = 0, + [2][0][RTW89_WW][1][113] = 0, + [2][0][RTW89_WW][2][113] = 0, + [2][0][RTW89_WW][0][115] = 0, + [2][0][RTW89_WW][1][115] = 0, + [2][0][RTW89_WW][2][115] = 0, + [2][0][RTW89_WW][0][117] = 0, + [2][0][RTW89_WW][1][117] = 0, + [2][0][RTW89_WW][2][117] = 0, + [2][0][RTW89_WW][0][119] = 0, + [2][0][RTW89_WW][1][119] = 0, + [2][0][RTW89_WW][2][119] = 0, + [2][1][RTW89_WW][0][0] = -16, + [2][1][RTW89_WW][1][0] = -16, + [2][1][RTW89_WW][2][0] = 54, + [2][1][RTW89_WW][0][2] = -16, + [2][1][RTW89_WW][1][2] = -16, + [2][1][RTW89_WW][2][2] = 54, + [2][1][RTW89_WW][0][4] = -16, + [2][1][RTW89_WW][1][4] = -16, + [2][1][RTW89_WW][2][4] = 54, + [2][1][RTW89_WW][0][6] = -16, + [2][1][RTW89_WW][1][6] = -16, + [2][1][RTW89_WW][2][6] = 54, + [2][1][RTW89_WW][0][8] = -16, + [2][1][RTW89_WW][1][8] = -16, + [2][1][RTW89_WW][2][8] = 54, + [2][1][RTW89_WW][0][10] = -16, + [2][1][RTW89_WW][1][10] = -16, + [2][1][RTW89_WW][2][10] = 54, + [2][1][RTW89_WW][0][12] = -16, + [2][1][RTW89_WW][1][12] = -16, + [2][1][RTW89_WW][2][12] = 54, + [2][1][RTW89_WW][0][14] = -16, + [2][1][RTW89_WW][1][14] = -16, + [2][1][RTW89_WW][2][14] = 54, + [2][1][RTW89_WW][0][15] = -16, + [2][1][RTW89_WW][1][15] = -16, + [2][1][RTW89_WW][2][15] = 54, + [2][1][RTW89_WW][0][17] = -16, + [2][1][RTW89_WW][1][17] = -16, + [2][1][RTW89_WW][2][17] = 54, + [2][1][RTW89_WW][0][19] = -16, + [2][1][RTW89_WW][1][19] = -16, + [2][1][RTW89_WW][2][19] = 54, + [2][1][RTW89_WW][0][21] = -16, + [2][1][RTW89_WW][1][21] = -16, + [2][1][RTW89_WW][2][21] = 54, + [2][1][RTW89_WW][0][23] = -16, + [2][1][RTW89_WW][1][23] = -16, + [2][1][RTW89_WW][2][23] = 54, + [2][1][RTW89_WW][0][25] = -16, + [2][1][RTW89_WW][1][25] = -16, + [2][1][RTW89_WW][2][25] = 54, + [2][1][RTW89_WW][0][27] = -16, + [2][1][RTW89_WW][1][27] = -16, + [2][1][RTW89_WW][2][27] = 54, + [2][1][RTW89_WW][0][29] = -16, + [2][1][RTW89_WW][1][29] = -16, + [2][1][RTW89_WW][2][29] = 54, + [2][1][RTW89_WW][0][30] = -16, + [2][1][RTW89_WW][1][30] = -16, + [2][1][RTW89_WW][2][30] = 54, + [2][1][RTW89_WW][0][32] = -16, + [2][1][RTW89_WW][1][32] = -16, + [2][1][RTW89_WW][2][32] = 54, + [2][1][RTW89_WW][0][34] = -16, + [2][1][RTW89_WW][1][34] = -16, + [2][1][RTW89_WW][2][34] = 54, + [2][1][RTW89_WW][0][36] = -16, + [2][1][RTW89_WW][1][36] = -16, + [2][1][RTW89_WW][2][36] = 54, + [2][1][RTW89_WW][0][38] = -16, + [2][1][RTW89_WW][1][38] = -16, + [2][1][RTW89_WW][2][38] = 54, + [2][1][RTW89_WW][0][40] = -16, + [2][1][RTW89_WW][1][40] = -16, + [2][1][RTW89_WW][2][40] = 54, + [2][1][RTW89_WW][0][42] = -16, + [2][1][RTW89_WW][1][42] = -16, + [2][1][RTW89_WW][2][42] = 54, + [2][1][RTW89_WW][0][44] = -16, + [2][1][RTW89_WW][1][44] = -16, + [2][1][RTW89_WW][2][44] = 54, + [2][1][RTW89_WW][0][45] = -16, + [2][1][RTW89_WW][1][45] = -16, + [2][1][RTW89_WW][2][45] = 0, + [2][1][RTW89_WW][0][47] = -16, + [2][1][RTW89_WW][1][47] = -16, + [2][1][RTW89_WW][2][47] = 0, + [2][1][RTW89_WW][0][49] = -16, + [2][1][RTW89_WW][1][49] = -16, + [2][1][RTW89_WW][2][49] = 0, + [2][1][RTW89_WW][0][51] = -16, + [2][1][RTW89_WW][1][51] = -16, + [2][1][RTW89_WW][2][51] = 0, + [2][1][RTW89_WW][0][53] = -16, + [2][1][RTW89_WW][1][53] = -16, + [2][1][RTW89_WW][2][53] = 0, + [2][1][RTW89_WW][0][55] = -16, + [2][1][RTW89_WW][1][55] = -16, + [2][1][RTW89_WW][2][55] = 54, + [2][1][RTW89_WW][0][57] = -16, + [2][1][RTW89_WW][1][57] = -16, + [2][1][RTW89_WW][2][57] = 54, + [2][1][RTW89_WW][0][59] = -16, + [2][1][RTW89_WW][1][59] = -16, + [2][1][RTW89_WW][2][59] = 54, + [2][1][RTW89_WW][0][60] = -16, + [2][1][RTW89_WW][1][60] = -16, + [2][1][RTW89_WW][2][60] = 54, + [2][1][RTW89_WW][0][62] = -16, + [2][1][RTW89_WW][1][62] = -16, + [2][1][RTW89_WW][2][62] = 54, + [2][1][RTW89_WW][0][64] = -16, + [2][1][RTW89_WW][1][64] = -16, + [2][1][RTW89_WW][2][64] = 54, + [2][1][RTW89_WW][0][66] = -16, + [2][1][RTW89_WW][1][66] = -16, + [2][1][RTW89_WW][2][66] = 54, + [2][1][RTW89_WW][0][68] = -16, + [2][1][RTW89_WW][1][68] = -16, + [2][1][RTW89_WW][2][68] = 54, + [2][1][RTW89_WW][0][70] = -16, + [2][1][RTW89_WW][1][70] = -16, + [2][1][RTW89_WW][2][70] = 56, + [2][1][RTW89_WW][0][72] = -16, + [2][1][RTW89_WW][1][72] = -16, + [2][1][RTW89_WW][2][72] = 56, + [2][1][RTW89_WW][0][74] = -16, + [2][1][RTW89_WW][1][74] = -16, + [2][1][RTW89_WW][2][74] = 56, + [2][1][RTW89_WW][0][75] = -16, + [2][1][RTW89_WW][1][75] = -16, + [2][1][RTW89_WW][2][75] = 56, + [2][1][RTW89_WW][0][77] = -16, + [2][1][RTW89_WW][1][77] = -16, + [2][1][RTW89_WW][2][77] = 56, + [2][1][RTW89_WW][0][79] = -16, + [2][1][RTW89_WW][1][79] = -16, + [2][1][RTW89_WW][2][79] = 56, + [2][1][RTW89_WW][0][81] = -16, + [2][1][RTW89_WW][1][81] = -16, + [2][1][RTW89_WW][2][81] = 56, + [2][1][RTW89_WW][0][83] = -16, + [2][1][RTW89_WW][1][83] = -16, + [2][1][RTW89_WW][2][83] = 56, + [2][1][RTW89_WW][0][85] = -18, + [2][1][RTW89_WW][1][85] = -18, + [2][1][RTW89_WW][2][85] = 56, + [2][1][RTW89_WW][0][87] = -16, + [2][1][RTW89_WW][1][87] = -16, + [2][1][RTW89_WW][2][87] = 0, + [2][1][RTW89_WW][0][89] = -16, + [2][1][RTW89_WW][1][89] = -16, + [2][1][RTW89_WW][2][89] = 0, + [2][1][RTW89_WW][0][90] = -16, + [2][1][RTW89_WW][1][90] = -16, + [2][1][RTW89_WW][2][90] = 0, + [2][1][RTW89_WW][0][92] = -16, + [2][1][RTW89_WW][1][92] = -16, + [2][1][RTW89_WW][2][92] = 0, + [2][1][RTW89_WW][0][94] = -16, + [2][1][RTW89_WW][1][94] = -16, + [2][1][RTW89_WW][2][94] = 0, + [2][1][RTW89_WW][0][96] = -16, + [2][1][RTW89_WW][1][96] = -16, + [2][1][RTW89_WW][2][96] = 0, + [2][1][RTW89_WW][0][98] = -16, + [2][1][RTW89_WW][1][98] = -16, + [2][1][RTW89_WW][2][98] = 0, + [2][1][RTW89_WW][0][100] = -16, + [2][1][RTW89_WW][1][100] = -16, + [2][1][RTW89_WW][2][100] = 0, + [2][1][RTW89_WW][0][102] = -16, + [2][1][RTW89_WW][1][102] = -16, + [2][1][RTW89_WW][2][102] = 0, + [2][1][RTW89_WW][0][104] = -16, + [2][1][RTW89_WW][1][104] = -16, + [2][1][RTW89_WW][2][104] = 0, + [2][1][RTW89_WW][0][105] = -16, + [2][1][RTW89_WW][1][105] = -16, + [2][1][RTW89_WW][2][105] = 0, + [2][1][RTW89_WW][0][107] = -14, + [2][1][RTW89_WW][1][107] = -14, + [2][1][RTW89_WW][2][107] = 0, + [2][1][RTW89_WW][0][109] = -10, + [2][1][RTW89_WW][1][109] = -10, + [2][1][RTW89_WW][2][109] = 0, + [2][1][RTW89_WW][0][111] = 0, + [2][1][RTW89_WW][1][111] = 0, + [2][1][RTW89_WW][2][111] = 0, + [2][1][RTW89_WW][0][113] = 0, + [2][1][RTW89_WW][1][113] = 0, + [2][1][RTW89_WW][2][113] = 0, + [2][1][RTW89_WW][0][115] = 0, + [2][1][RTW89_WW][1][115] = 0, + [2][1][RTW89_WW][2][115] = 0, + [2][1][RTW89_WW][0][117] = 0, + [2][1][RTW89_WW][1][117] = 0, + [2][1][RTW89_WW][2][117] = 0, + [2][1][RTW89_WW][0][119] = 0, + [2][1][RTW89_WW][1][119] = 0, + [2][1][RTW89_WW][2][119] = 0, + [0][0][RTW89_FCC][1][0] = -16, + [0][0][RTW89_FCC][2][0] = 44, + [0][0][RTW89_ETSI][1][0] = 32, + [0][0][RTW89_ETSI][0][0] = -8, + [0][0][RTW89_MKK][1][0] = 30, + [0][0][RTW89_MKK][0][0] = -8, + [0][0][RTW89_IC][1][0] = -16, + [0][0][RTW89_KCC][1][0] = -2, + [0][0][RTW89_KCC][0][0] = -2, + [0][0][RTW89_ACMA][1][0] = 32, + [0][0][RTW89_ACMA][0][0] = -8, + [0][0][RTW89_CHILE][1][0] = -16, + [0][0][RTW89_QATAR][1][0] = 32, + [0][0][RTW89_QATAR][0][0] = -8, + [0][0][RTW89_UK][1][0] = 32, + [0][0][RTW89_UK][0][0] = -8, + [0][0][RTW89_FCC][1][2] = -18, + [0][0][RTW89_FCC][2][2] = 44, + [0][0][RTW89_ETSI][1][2] = 32, + [0][0][RTW89_ETSI][0][2] = -8, + [0][0][RTW89_MKK][1][2] = 30, + [0][0][RTW89_MKK][0][2] = -8, + [0][0][RTW89_IC][1][2] = -18, + [0][0][RTW89_KCC][1][2] = -2, + [0][0][RTW89_KCC][0][2] = -2, + [0][0][RTW89_ACMA][1][2] = 32, + [0][0][RTW89_ACMA][0][2] = -8, + [0][0][RTW89_CHILE][1][2] = -18, + [0][0][RTW89_QATAR][1][2] = 32, + [0][0][RTW89_QATAR][0][2] = -8, + [0][0][RTW89_UK][1][2] = 32, + [0][0][RTW89_UK][0][2] = -8, + [0][0][RTW89_FCC][1][4] = -18, + [0][0][RTW89_FCC][2][4] = 44, + [0][0][RTW89_ETSI][1][4] = 32, + [0][0][RTW89_ETSI][0][4] = -8, + [0][0][RTW89_MKK][1][4] = 30, + [0][0][RTW89_MKK][0][4] = -8, + [0][0][RTW89_IC][1][4] = -18, + [0][0][RTW89_KCC][1][4] = -2, + [0][0][RTW89_KCC][0][4] = -2, + [0][0][RTW89_ACMA][1][4] = 32, + [0][0][RTW89_ACMA][0][4] = -8, + [0][0][RTW89_CHILE][1][4] = -18, + [0][0][RTW89_QATAR][1][4] = 32, + [0][0][RTW89_QATAR][0][4] = -8, + [0][0][RTW89_UK][1][4] = 32, + [0][0][RTW89_UK][0][4] = -8, + [0][0][RTW89_FCC][1][6] = -18, + [0][0][RTW89_FCC][2][6] = 44, + [0][0][RTW89_ETSI][1][6] = 32, + [0][0][RTW89_ETSI][0][6] = -8, + [0][0][RTW89_MKK][1][6] = 30, + [0][0][RTW89_MKK][0][6] = -8, + [0][0][RTW89_IC][1][6] = -18, + [0][0][RTW89_KCC][1][6] = -2, + [0][0][RTW89_KCC][0][6] = -2, + [0][0][RTW89_ACMA][1][6] = 32, + [0][0][RTW89_ACMA][0][6] = -8, + [0][0][RTW89_CHILE][1][6] = -18, + [0][0][RTW89_QATAR][1][6] = 32, + [0][0][RTW89_QATAR][0][6] = -8, + [0][0][RTW89_UK][1][6] = 32, + [0][0][RTW89_UK][0][6] = -8, + [0][0][RTW89_FCC][1][8] = -18, + [0][0][RTW89_FCC][2][8] = 44, + [0][0][RTW89_ETSI][1][8] = 32, + [0][0][RTW89_ETSI][0][8] = -8, + [0][0][RTW89_MKK][1][8] = 30, + [0][0][RTW89_MKK][0][8] = -8, + [0][0][RTW89_IC][1][8] = -18, + [0][0][RTW89_KCC][1][8] = -2, + [0][0][RTW89_KCC][0][8] = -2, + [0][0][RTW89_ACMA][1][8] = 32, + [0][0][RTW89_ACMA][0][8] = -8, + [0][0][RTW89_CHILE][1][8] = -18, + [0][0][RTW89_QATAR][1][8] = 32, + [0][0][RTW89_QATAR][0][8] = -8, + [0][0][RTW89_UK][1][8] = 32, + [0][0][RTW89_UK][0][8] = -8, + [0][0][RTW89_FCC][1][10] = -18, + [0][0][RTW89_FCC][2][10] = 44, + [0][0][RTW89_ETSI][1][10] = 32, + [0][0][RTW89_ETSI][0][10] = -8, + [0][0][RTW89_MKK][1][10] = 30, + [0][0][RTW89_MKK][0][10] = -8, + [0][0][RTW89_IC][1][10] = -18, + [0][0][RTW89_KCC][1][10] = -2, + [0][0][RTW89_KCC][0][10] = -2, + [0][0][RTW89_ACMA][1][10] = 32, + [0][0][RTW89_ACMA][0][10] = -8, + [0][0][RTW89_CHILE][1][10] = -18, + [0][0][RTW89_QATAR][1][10] = 32, + [0][0][RTW89_QATAR][0][10] = -8, + [0][0][RTW89_UK][1][10] = 32, + [0][0][RTW89_UK][0][10] = -8, + [0][0][RTW89_FCC][1][12] = -18, + [0][0][RTW89_FCC][2][12] = 44, + [0][0][RTW89_ETSI][1][12] = 32, + [0][0][RTW89_ETSI][0][12] = -8, + [0][0][RTW89_MKK][1][12] = 30, + [0][0][RTW89_MKK][0][12] = -8, + [0][0][RTW89_IC][1][12] = -18, + [0][0][RTW89_KCC][1][12] = -2, + [0][0][RTW89_KCC][0][12] = -2, + [0][0][RTW89_ACMA][1][12] = 32, + [0][0][RTW89_ACMA][0][12] = -8, + [0][0][RTW89_CHILE][1][12] = -18, + [0][0][RTW89_QATAR][1][12] = 32, + [0][0][RTW89_QATAR][0][12] = -8, + [0][0][RTW89_UK][1][12] = 32, + [0][0][RTW89_UK][0][12] = -8, + [0][0][RTW89_FCC][1][14] = -18, + [0][0][RTW89_FCC][2][14] = 44, + [0][0][RTW89_ETSI][1][14] = 32, + [0][0][RTW89_ETSI][0][14] = -8, + [0][0][RTW89_MKK][1][14] = 30, + [0][0][RTW89_MKK][0][14] = -8, + [0][0][RTW89_IC][1][14] = -18, + [0][0][RTW89_KCC][1][14] = -2, + [0][0][RTW89_KCC][0][14] = -2, + [0][0][RTW89_ACMA][1][14] = 32, + [0][0][RTW89_ACMA][0][14] = -8, + [0][0][RTW89_CHILE][1][14] = -18, + [0][0][RTW89_QATAR][1][14] = 32, + [0][0][RTW89_QATAR][0][14] = -8, + [0][0][RTW89_UK][1][14] = 32, + [0][0][RTW89_UK][0][14] = -8, + [0][0][RTW89_FCC][1][15] = -18, + [0][0][RTW89_FCC][2][15] = 44, + [0][0][RTW89_ETSI][1][15] = 32, + [0][0][RTW89_ETSI][0][15] = -8, + [0][0][RTW89_MKK][1][15] = 30, + [0][0][RTW89_MKK][0][15] = -8, + [0][0][RTW89_IC][1][15] = -18, + [0][0][RTW89_KCC][1][15] = -2, + [0][0][RTW89_KCC][0][15] = -2, + [0][0][RTW89_ACMA][1][15] = 32, + [0][0][RTW89_ACMA][0][15] = -8, + [0][0][RTW89_CHILE][1][15] = -18, + [0][0][RTW89_QATAR][1][15] = 32, + [0][0][RTW89_QATAR][0][15] = -8, + [0][0][RTW89_UK][1][15] = 32, + [0][0][RTW89_UK][0][15] = -8, + [0][0][RTW89_FCC][1][17] = -18, + [0][0][RTW89_FCC][2][17] = 44, + [0][0][RTW89_ETSI][1][17] = 32, + [0][0][RTW89_ETSI][0][17] = -8, + [0][0][RTW89_MKK][1][17] = 30, + [0][0][RTW89_MKK][0][17] = -8, + [0][0][RTW89_IC][1][17] = -18, + [0][0][RTW89_KCC][1][17] = -2, + [0][0][RTW89_KCC][0][17] = -2, + [0][0][RTW89_ACMA][1][17] = 32, + [0][0][RTW89_ACMA][0][17] = -8, + [0][0][RTW89_CHILE][1][17] = -18, + [0][0][RTW89_QATAR][1][17] = 32, + [0][0][RTW89_QATAR][0][17] = -8, + [0][0][RTW89_UK][1][17] = 32, + [0][0][RTW89_UK][0][17] = -8, + [0][0][RTW89_FCC][1][19] = -18, + [0][0][RTW89_FCC][2][19] = 44, + [0][0][RTW89_ETSI][1][19] = 32, + [0][0][RTW89_ETSI][0][19] = -8, + [0][0][RTW89_MKK][1][19] = 30, + [0][0][RTW89_MKK][0][19] = -8, + [0][0][RTW89_IC][1][19] = -18, + [0][0][RTW89_KCC][1][19] = -2, + [0][0][RTW89_KCC][0][19] = -2, + [0][0][RTW89_ACMA][1][19] = 32, + [0][0][RTW89_ACMA][0][19] = -8, + [0][0][RTW89_CHILE][1][19] = -18, + [0][0][RTW89_QATAR][1][19] = 32, + [0][0][RTW89_QATAR][0][19] = -8, + [0][0][RTW89_UK][1][19] = 32, + [0][0][RTW89_UK][0][19] = -8, + [0][0][RTW89_FCC][1][21] = -18, + [0][0][RTW89_FCC][2][21] = 44, + [0][0][RTW89_ETSI][1][21] = 32, + [0][0][RTW89_ETSI][0][21] = -8, + [0][0][RTW89_MKK][1][21] = 30, + [0][0][RTW89_MKK][0][21] = -8, + [0][0][RTW89_IC][1][21] = -18, + [0][0][RTW89_KCC][1][21] = -2, + [0][0][RTW89_KCC][0][21] = -2, + [0][0][RTW89_ACMA][1][21] = 32, + [0][0][RTW89_ACMA][0][21] = -8, + [0][0][RTW89_CHILE][1][21] = -18, + [0][0][RTW89_QATAR][1][21] = 32, + [0][0][RTW89_QATAR][0][21] = -8, + [0][0][RTW89_UK][1][21] = 32, + [0][0][RTW89_UK][0][21] = -8, + [0][0][RTW89_FCC][1][23] = -18, + [0][0][RTW89_FCC][2][23] = 54, + [0][0][RTW89_ETSI][1][23] = 32, + [0][0][RTW89_ETSI][0][23] = -8, + [0][0][RTW89_MKK][1][23] = 30, + [0][0][RTW89_MKK][0][23] = -8, + [0][0][RTW89_IC][1][23] = -18, + [0][0][RTW89_KCC][1][23] = -2, + [0][0][RTW89_KCC][0][23] = -2, + [0][0][RTW89_ACMA][1][23] = 32, + [0][0][RTW89_ACMA][0][23] = -8, + [0][0][RTW89_CHILE][1][23] = -18, + [0][0][RTW89_QATAR][1][23] = 32, + [0][0][RTW89_QATAR][0][23] = -8, + [0][0][RTW89_UK][1][23] = 32, + [0][0][RTW89_UK][0][23] = -8, + [0][0][RTW89_FCC][1][25] = -18, + [0][0][RTW89_FCC][2][25] = 54, + [0][0][RTW89_ETSI][1][25] = 32, + [0][0][RTW89_ETSI][0][25] = -8, + [0][0][RTW89_MKK][1][25] = 30, + [0][0][RTW89_MKK][0][25] = -8, + [0][0][RTW89_IC][1][25] = -18, + [0][0][RTW89_KCC][1][25] = -2, + [0][0][RTW89_KCC][0][25] = -2, + [0][0][RTW89_ACMA][1][25] = 32, + [0][0][RTW89_ACMA][0][25] = -8, + [0][0][RTW89_CHILE][1][25] = -18, + [0][0][RTW89_QATAR][1][25] = 32, + [0][0][RTW89_QATAR][0][25] = -8, + [0][0][RTW89_UK][1][25] = 32, + [0][0][RTW89_UK][0][25] = -8, + [0][0][RTW89_FCC][1][27] = -18, + [0][0][RTW89_FCC][2][27] = 54, + [0][0][RTW89_ETSI][1][27] = 32, + [0][0][RTW89_ETSI][0][27] = -8, + [0][0][RTW89_MKK][1][27] = 30, + [0][0][RTW89_MKK][0][27] = -8, + [0][0][RTW89_IC][1][27] = -18, + [0][0][RTW89_KCC][1][27] = -2, + [0][0][RTW89_KCC][0][27] = -2, + [0][0][RTW89_ACMA][1][27] = 32, + [0][0][RTW89_ACMA][0][27] = -8, + [0][0][RTW89_CHILE][1][27] = -18, + [0][0][RTW89_QATAR][1][27] = 32, + [0][0][RTW89_QATAR][0][27] = -8, + [0][0][RTW89_UK][1][27] = 32, + [0][0][RTW89_UK][0][27] = -8, + [0][0][RTW89_FCC][1][29] = -18, + [0][0][RTW89_FCC][2][29] = 54, + [0][0][RTW89_ETSI][1][29] = 32, + [0][0][RTW89_ETSI][0][29] = -8, + [0][0][RTW89_MKK][1][29] = 30, + [0][0][RTW89_MKK][0][29] = -8, + [0][0][RTW89_IC][1][29] = -18, + [0][0][RTW89_KCC][1][29] = -2, + [0][0][RTW89_KCC][0][29] = -2, + [0][0][RTW89_ACMA][1][29] = 32, + [0][0][RTW89_ACMA][0][29] = -8, + [0][0][RTW89_CHILE][1][29] = -18, + [0][0][RTW89_QATAR][1][29] = 32, + [0][0][RTW89_QATAR][0][29] = -8, + [0][0][RTW89_UK][1][29] = 32, + [0][0][RTW89_UK][0][29] = -8, + [0][0][RTW89_FCC][1][30] = -18, + [0][0][RTW89_FCC][2][30] = 54, + [0][0][RTW89_ETSI][1][30] = 32, + [0][0][RTW89_ETSI][0][30] = -8, + [0][0][RTW89_MKK][1][30] = 30, + [0][0][RTW89_MKK][0][30] = -8, + [0][0][RTW89_IC][1][30] = -18, + [0][0][RTW89_KCC][1][30] = -2, + [0][0][RTW89_KCC][0][30] = -2, + [0][0][RTW89_ACMA][1][30] = 32, + [0][0][RTW89_ACMA][0][30] = -8, + [0][0][RTW89_CHILE][1][30] = -18, + [0][0][RTW89_QATAR][1][30] = 32, + [0][0][RTW89_QATAR][0][30] = -8, + [0][0][RTW89_UK][1][30] = 32, + [0][0][RTW89_UK][0][30] = -8, + [0][0][RTW89_FCC][1][32] = -18, + [0][0][RTW89_FCC][2][32] = 54, + [0][0][RTW89_ETSI][1][32] = 32, + [0][0][RTW89_ETSI][0][32] = -8, + [0][0][RTW89_MKK][1][32] = 30, + [0][0][RTW89_MKK][0][32] = -8, + [0][0][RTW89_IC][1][32] = -18, + [0][0][RTW89_KCC][1][32] = -2, + [0][0][RTW89_KCC][0][32] = -2, + [0][0][RTW89_ACMA][1][32] = 32, + [0][0][RTW89_ACMA][0][32] = -8, + [0][0][RTW89_CHILE][1][32] = -18, + [0][0][RTW89_QATAR][1][32] = 32, + [0][0][RTW89_QATAR][0][32] = -8, + [0][0][RTW89_UK][1][32] = 32, + [0][0][RTW89_UK][0][32] = -8, + [0][0][RTW89_FCC][1][34] = -18, + [0][0][RTW89_FCC][2][34] = 54, + [0][0][RTW89_ETSI][1][34] = 32, + [0][0][RTW89_ETSI][0][34] = -8, + [0][0][RTW89_MKK][1][34] = 30, + [0][0][RTW89_MKK][0][34] = -8, + [0][0][RTW89_IC][1][34] = -18, + [0][0][RTW89_KCC][1][34] = -2, + [0][0][RTW89_KCC][0][34] = -2, + [0][0][RTW89_ACMA][1][34] = 32, + [0][0][RTW89_ACMA][0][34] = -8, + [0][0][RTW89_CHILE][1][34] = -18, + [0][0][RTW89_QATAR][1][34] = 32, + [0][0][RTW89_QATAR][0][34] = -8, + [0][0][RTW89_UK][1][34] = 32, + [0][0][RTW89_UK][0][34] = -8, + [0][0][RTW89_FCC][1][36] = -18, + [0][0][RTW89_FCC][2][36] = 54, + [0][0][RTW89_ETSI][1][36] = 32, + [0][0][RTW89_ETSI][0][36] = -8, + [0][0][RTW89_MKK][1][36] = 30, + [0][0][RTW89_MKK][0][36] = -8, + [0][0][RTW89_IC][1][36] = -18, + [0][0][RTW89_KCC][1][36] = -2, + [0][0][RTW89_KCC][0][36] = -2, + [0][0][RTW89_ACMA][1][36] = 32, + [0][0][RTW89_ACMA][0][36] = -8, + [0][0][RTW89_CHILE][1][36] = -18, + [0][0][RTW89_QATAR][1][36] = 32, + [0][0][RTW89_QATAR][0][36] = -8, + [0][0][RTW89_UK][1][36] = 32, + [0][0][RTW89_UK][0][36] = -8, + [0][0][RTW89_FCC][1][38] = -18, + [0][0][RTW89_FCC][2][38] = 54, + [0][0][RTW89_ETSI][1][38] = 32, + [0][0][RTW89_ETSI][0][38] = -8, + [0][0][RTW89_MKK][1][38] = 30, + [0][0][RTW89_MKK][0][38] = -8, + [0][0][RTW89_IC][1][38] = -18, + [0][0][RTW89_KCC][1][38] = -2, + [0][0][RTW89_KCC][0][38] = -2, + [0][0][RTW89_ACMA][1][38] = 32, + [0][0][RTW89_ACMA][0][38] = -8, + [0][0][RTW89_CHILE][1][38] = -18, + [0][0][RTW89_QATAR][1][38] = 32, + [0][0][RTW89_QATAR][0][38] = -8, + [0][0][RTW89_UK][1][38] = 32, + [0][0][RTW89_UK][0][38] = -8, + [0][0][RTW89_FCC][1][40] = -18, + [0][0][RTW89_FCC][2][40] = 54, + [0][0][RTW89_ETSI][1][40] = 32, + [0][0][RTW89_ETSI][0][40] = -8, + [0][0][RTW89_MKK][1][40] = 30, + [0][0][RTW89_MKK][0][40] = -8, + [0][0][RTW89_IC][1][40] = -18, + [0][0][RTW89_KCC][1][40] = -2, + [0][0][RTW89_KCC][0][40] = -2, + [0][0][RTW89_ACMA][1][40] = 32, + [0][0][RTW89_ACMA][0][40] = -8, + [0][0][RTW89_CHILE][1][40] = -18, + [0][0][RTW89_QATAR][1][40] = 32, + [0][0][RTW89_QATAR][0][40] = -8, + [0][0][RTW89_UK][1][40] = 32, + [0][0][RTW89_UK][0][40] = -8, + [0][0][RTW89_FCC][1][42] = -18, + [0][0][RTW89_FCC][2][42] = 54, + [0][0][RTW89_ETSI][1][42] = 32, + [0][0][RTW89_ETSI][0][42] = -8, + [0][0][RTW89_MKK][1][42] = 30, + [0][0][RTW89_MKK][0][42] = -8, + [0][0][RTW89_IC][1][42] = -18, + [0][0][RTW89_KCC][1][42] = -2, + [0][0][RTW89_KCC][0][42] = -2, + [0][0][RTW89_ACMA][1][42] = 32, + [0][0][RTW89_ACMA][0][42] = -8, + [0][0][RTW89_CHILE][1][42] = -18, + [0][0][RTW89_QATAR][1][42] = 32, + [0][0][RTW89_QATAR][0][42] = -8, + [0][0][RTW89_UK][1][42] = 32, + [0][0][RTW89_UK][0][42] = -8, + [0][0][RTW89_FCC][1][44] = -16, + [0][0][RTW89_FCC][2][44] = 56, + [0][0][RTW89_ETSI][1][44] = 32, + [0][0][RTW89_ETSI][0][44] = -6, + [0][0][RTW89_MKK][1][44] = 8, + [0][0][RTW89_MKK][0][44] = -10, + [0][0][RTW89_IC][1][44] = -16, + [0][0][RTW89_KCC][1][44] = -2, + [0][0][RTW89_KCC][0][44] = -2, + [0][0][RTW89_ACMA][1][44] = 32, + [0][0][RTW89_ACMA][0][44] = -6, + [0][0][RTW89_CHILE][1][44] = -16, + [0][0][RTW89_QATAR][1][44] = 32, + [0][0][RTW89_QATAR][0][44] = -6, + [0][0][RTW89_UK][1][44] = 32, + [0][0][RTW89_UK][0][44] = -6, + [0][0][RTW89_FCC][1][45] = -16, + [0][0][RTW89_FCC][2][45] = 127, + [0][0][RTW89_ETSI][1][45] = 127, + [0][0][RTW89_ETSI][0][45] = 127, + [0][0][RTW89_MKK][1][45] = 127, + [0][0][RTW89_MKK][0][45] = 127, + [0][0][RTW89_IC][1][45] = -16, + [0][0][RTW89_KCC][1][45] = -2, + [0][0][RTW89_KCC][0][45] = 127, + [0][0][RTW89_ACMA][1][45] = 127, + [0][0][RTW89_ACMA][0][45] = 127, + [0][0][RTW89_CHILE][1][45] = 127, + [0][0][RTW89_QATAR][1][45] = 127, + [0][0][RTW89_QATAR][0][45] = 127, + [0][0][RTW89_UK][1][45] = 127, + [0][0][RTW89_UK][0][45] = 127, + [0][0][RTW89_FCC][1][47] = -18, + [0][0][RTW89_FCC][2][47] = 127, + [0][0][RTW89_ETSI][1][47] = 127, + [0][0][RTW89_ETSI][0][47] = 127, + [0][0][RTW89_MKK][1][47] = 127, + [0][0][RTW89_MKK][0][47] = 127, + [0][0][RTW89_IC][1][47] = -18, + [0][0][RTW89_KCC][1][47] = -2, + [0][0][RTW89_KCC][0][47] = 127, + [0][0][RTW89_ACMA][1][47] = 127, + [0][0][RTW89_ACMA][0][47] = 127, + [0][0][RTW89_CHILE][1][47] = 127, + [0][0][RTW89_QATAR][1][47] = 127, + [0][0][RTW89_QATAR][0][47] = 127, + [0][0][RTW89_UK][1][47] = 127, + [0][0][RTW89_UK][0][47] = 127, + [0][0][RTW89_FCC][1][49] = -18, + [0][0][RTW89_FCC][2][49] = 127, + [0][0][RTW89_ETSI][1][49] = 127, + [0][0][RTW89_ETSI][0][49] = 127, + [0][0][RTW89_MKK][1][49] = 127, + [0][0][RTW89_MKK][0][49] = 127, + [0][0][RTW89_IC][1][49] = -18, + [0][0][RTW89_KCC][1][49] = -2, + [0][0][RTW89_KCC][0][49] = 127, + [0][0][RTW89_ACMA][1][49] = 127, + [0][0][RTW89_ACMA][0][49] = 127, + [0][0][RTW89_CHILE][1][49] = 127, + [0][0][RTW89_QATAR][1][49] = 127, + [0][0][RTW89_QATAR][0][49] = 127, + [0][0][RTW89_UK][1][49] = 127, + [0][0][RTW89_UK][0][49] = 127, + [0][0][RTW89_FCC][1][51] = -18, + [0][0][RTW89_FCC][2][51] = 127, + [0][0][RTW89_ETSI][1][51] = 127, + [0][0][RTW89_ETSI][0][51] = 127, + [0][0][RTW89_MKK][1][51] = 127, + [0][0][RTW89_MKK][0][51] = 127, + [0][0][RTW89_IC][1][51] = -18, + [0][0][RTW89_KCC][1][51] = -2, + [0][0][RTW89_KCC][0][51] = 127, + [0][0][RTW89_ACMA][1][51] = 127, + [0][0][RTW89_ACMA][0][51] = 127, + [0][0][RTW89_CHILE][1][51] = 127, + [0][0][RTW89_QATAR][1][51] = 127, + [0][0][RTW89_QATAR][0][51] = 127, + [0][0][RTW89_UK][1][51] = 127, + [0][0][RTW89_UK][0][51] = 127, + [0][0][RTW89_FCC][1][53] = -16, + [0][0][RTW89_FCC][2][53] = 127, + [0][0][RTW89_ETSI][1][53] = 127, + [0][0][RTW89_ETSI][0][53] = 127, + [0][0][RTW89_MKK][1][53] = 127, + [0][0][RTW89_MKK][0][53] = 127, + [0][0][RTW89_IC][1][53] = -16, + [0][0][RTW89_KCC][1][53] = -2, + [0][0][RTW89_KCC][0][53] = 127, + [0][0][RTW89_ACMA][1][53] = 127, + [0][0][RTW89_ACMA][0][53] = 127, + [0][0][RTW89_CHILE][1][53] = 127, + [0][0][RTW89_QATAR][1][53] = 127, + [0][0][RTW89_QATAR][0][53] = 127, + [0][0][RTW89_UK][1][53] = 127, + [0][0][RTW89_UK][0][53] = 127, + [0][0][RTW89_FCC][1][55] = -18, + [0][0][RTW89_FCC][2][55] = 56, + [0][0][RTW89_ETSI][1][55] = 127, + [0][0][RTW89_ETSI][0][55] = 127, + [0][0][RTW89_MKK][1][55] = 127, + [0][0][RTW89_MKK][0][55] = 127, + [0][0][RTW89_IC][1][55] = -18, + [0][0][RTW89_KCC][1][55] = -2, + [0][0][RTW89_KCC][0][55] = 127, + [0][0][RTW89_ACMA][1][55] = 127, + [0][0][RTW89_ACMA][0][55] = 127, + [0][0][RTW89_CHILE][1][55] = 127, + [0][0][RTW89_QATAR][1][55] = 127, + [0][0][RTW89_QATAR][0][55] = 127, + [0][0][RTW89_UK][1][55] = 127, + [0][0][RTW89_UK][0][55] = 127, + [0][0][RTW89_FCC][1][57] = -18, + [0][0][RTW89_FCC][2][57] = 56, + [0][0][RTW89_ETSI][1][57] = 127, + [0][0][RTW89_ETSI][0][57] = 127, + [0][0][RTW89_MKK][1][57] = 127, + [0][0][RTW89_MKK][0][57] = 127, + [0][0][RTW89_IC][1][57] = -18, + [0][0][RTW89_KCC][1][57] = -2, + [0][0][RTW89_KCC][0][57] = 127, + [0][0][RTW89_ACMA][1][57] = 127, + [0][0][RTW89_ACMA][0][57] = 127, + [0][0][RTW89_CHILE][1][57] = 127, + [0][0][RTW89_QATAR][1][57] = 127, + [0][0][RTW89_QATAR][0][57] = 127, + [0][0][RTW89_UK][1][57] = 127, + [0][0][RTW89_UK][0][57] = 127, + [0][0][RTW89_FCC][1][59] = -18, + [0][0][RTW89_FCC][2][59] = 56, + [0][0][RTW89_ETSI][1][59] = 127, + [0][0][RTW89_ETSI][0][59] = 127, + [0][0][RTW89_MKK][1][59] = 127, + [0][0][RTW89_MKK][0][59] = 127, + [0][0][RTW89_IC][1][59] = -18, + [0][0][RTW89_KCC][1][59] = -2, + [0][0][RTW89_KCC][0][59] = 127, + [0][0][RTW89_ACMA][1][59] = 127, + [0][0][RTW89_ACMA][0][59] = 127, + [0][0][RTW89_CHILE][1][59] = 127, + [0][0][RTW89_QATAR][1][59] = 127, + [0][0][RTW89_QATAR][0][59] = 127, + [0][0][RTW89_UK][1][59] = 127, + [0][0][RTW89_UK][0][59] = 127, + [0][0][RTW89_FCC][1][60] = -18, + [0][0][RTW89_FCC][2][60] = 56, + [0][0][RTW89_ETSI][1][60] = 127, + [0][0][RTW89_ETSI][0][60] = 127, + [0][0][RTW89_MKK][1][60] = 127, + [0][0][RTW89_MKK][0][60] = 127, + [0][0][RTW89_IC][1][60] = -18, + [0][0][RTW89_KCC][1][60] = -2, + [0][0][RTW89_KCC][0][60] = 127, + [0][0][RTW89_ACMA][1][60] = 127, + [0][0][RTW89_ACMA][0][60] = 127, + [0][0][RTW89_CHILE][1][60] = 127, + [0][0][RTW89_QATAR][1][60] = 127, + [0][0][RTW89_QATAR][0][60] = 127, + [0][0][RTW89_UK][1][60] = 127, + [0][0][RTW89_UK][0][60] = 127, + [0][0][RTW89_FCC][1][62] = -18, + [0][0][RTW89_FCC][2][62] = 56, + [0][0][RTW89_ETSI][1][62] = 127, + [0][0][RTW89_ETSI][0][62] = 127, + [0][0][RTW89_MKK][1][62] = 127, + [0][0][RTW89_MKK][0][62] = 127, + [0][0][RTW89_IC][1][62] = -18, + [0][0][RTW89_KCC][1][62] = -2, + [0][0][RTW89_KCC][0][62] = 127, + [0][0][RTW89_ACMA][1][62] = 127, + [0][0][RTW89_ACMA][0][62] = 127, + [0][0][RTW89_CHILE][1][62] = 127, + [0][0][RTW89_QATAR][1][62] = 127, + [0][0][RTW89_QATAR][0][62] = 127, + [0][0][RTW89_UK][1][62] = 127, + [0][0][RTW89_UK][0][62] = 127, + [0][0][RTW89_FCC][1][64] = -18, + [0][0][RTW89_FCC][2][64] = 56, + [0][0][RTW89_ETSI][1][64] = 127, + [0][0][RTW89_ETSI][0][64] = 127, + [0][0][RTW89_MKK][1][64] = 127, + [0][0][RTW89_MKK][0][64] = 127, + [0][0][RTW89_IC][1][64] = -18, + [0][0][RTW89_KCC][1][64] = -2, + [0][0][RTW89_KCC][0][64] = 127, + [0][0][RTW89_ACMA][1][64] = 127, + [0][0][RTW89_ACMA][0][64] = 127, + [0][0][RTW89_CHILE][1][64] = 127, + [0][0][RTW89_QATAR][1][64] = 127, + [0][0][RTW89_QATAR][0][64] = 127, + [0][0][RTW89_UK][1][64] = 127, + [0][0][RTW89_UK][0][64] = 127, + [0][0][RTW89_FCC][1][66] = -18, + [0][0][RTW89_FCC][2][66] = 56, + [0][0][RTW89_ETSI][1][66] = 127, + [0][0][RTW89_ETSI][0][66] = 127, + [0][0][RTW89_MKK][1][66] = 127, + [0][0][RTW89_MKK][0][66] = 127, + [0][0][RTW89_IC][1][66] = -18, + [0][0][RTW89_KCC][1][66] = -2, + [0][0][RTW89_KCC][0][66] = 127, + [0][0][RTW89_ACMA][1][66] = 127, + [0][0][RTW89_ACMA][0][66] = 127, + [0][0][RTW89_CHILE][1][66] = 127, + [0][0][RTW89_QATAR][1][66] = 127, + [0][0][RTW89_QATAR][0][66] = 127, + [0][0][RTW89_UK][1][66] = 127, + [0][0][RTW89_UK][0][66] = 127, + [0][0][RTW89_FCC][1][68] = -18, + [0][0][RTW89_FCC][2][68] = 56, + [0][0][RTW89_ETSI][1][68] = 127, + [0][0][RTW89_ETSI][0][68] = 127, + [0][0][RTW89_MKK][1][68] = 127, + [0][0][RTW89_MKK][0][68] = 127, + [0][0][RTW89_IC][1][68] = -18, + [0][0][RTW89_KCC][1][68] = -2, + [0][0][RTW89_KCC][0][68] = 127, + [0][0][RTW89_ACMA][1][68] = 127, + [0][0][RTW89_ACMA][0][68] = 127, + [0][0][RTW89_CHILE][1][68] = 127, + [0][0][RTW89_QATAR][1][68] = 127, + [0][0][RTW89_QATAR][0][68] = 127, + [0][0][RTW89_UK][1][68] = 127, + [0][0][RTW89_UK][0][68] = 127, + [0][0][RTW89_FCC][1][70] = -16, + [0][0][RTW89_FCC][2][70] = 56, + [0][0][RTW89_ETSI][1][70] = 127, + [0][0][RTW89_ETSI][0][70] = 127, + [0][0][RTW89_MKK][1][70] = 127, + [0][0][RTW89_MKK][0][70] = 127, + [0][0][RTW89_IC][1][70] = -16, + [0][0][RTW89_KCC][1][70] = -2, + [0][0][RTW89_KCC][0][70] = 127, + [0][0][RTW89_ACMA][1][70] = 127, + [0][0][RTW89_ACMA][0][70] = 127, + [0][0][RTW89_CHILE][1][70] = 127, + [0][0][RTW89_QATAR][1][70] = 127, + [0][0][RTW89_QATAR][0][70] = 127, + [0][0][RTW89_UK][1][70] = 127, + [0][0][RTW89_UK][0][70] = 127, + [0][0][RTW89_FCC][1][72] = -18, + [0][0][RTW89_FCC][2][72] = 56, + [0][0][RTW89_ETSI][1][72] = 127, + [0][0][RTW89_ETSI][0][72] = 127, + [0][0][RTW89_MKK][1][72] = 127, + [0][0][RTW89_MKK][0][72] = 127, + [0][0][RTW89_IC][1][72] = -18, + [0][0][RTW89_KCC][1][72] = -2, + [0][0][RTW89_KCC][0][72] = 127, + [0][0][RTW89_ACMA][1][72] = 127, + [0][0][RTW89_ACMA][0][72] = 127, + [0][0][RTW89_CHILE][1][72] = 127, + [0][0][RTW89_QATAR][1][72] = 127, + [0][0][RTW89_QATAR][0][72] = 127, + [0][0][RTW89_UK][1][72] = 127, + [0][0][RTW89_UK][0][72] = 127, + [0][0][RTW89_FCC][1][74] = -18, + [0][0][RTW89_FCC][2][74] = 56, + [0][0][RTW89_ETSI][1][74] = 127, + [0][0][RTW89_ETSI][0][74] = 127, + [0][0][RTW89_MKK][1][74] = 127, + [0][0][RTW89_MKK][0][74] = 127, + [0][0][RTW89_IC][1][74] = -18, + [0][0][RTW89_KCC][1][74] = -2, + [0][0][RTW89_KCC][0][74] = 127, + [0][0][RTW89_ACMA][1][74] = 127, + [0][0][RTW89_ACMA][0][74] = 127, + [0][0][RTW89_CHILE][1][74] = 127, + [0][0][RTW89_QATAR][1][74] = 127, + [0][0][RTW89_QATAR][0][74] = 127, + [0][0][RTW89_UK][1][74] = 127, + [0][0][RTW89_UK][0][74] = 127, + [0][0][RTW89_FCC][1][75] = -18, + [0][0][RTW89_FCC][2][75] = 56, + [0][0][RTW89_ETSI][1][75] = 127, + [0][0][RTW89_ETSI][0][75] = 127, + [0][0][RTW89_MKK][1][75] = 127, + [0][0][RTW89_MKK][0][75] = 127, + [0][0][RTW89_IC][1][75] = -18, + [0][0][RTW89_KCC][1][75] = -2, + [0][0][RTW89_KCC][0][75] = 127, + [0][0][RTW89_ACMA][1][75] = 127, + [0][0][RTW89_ACMA][0][75] = 127, + [0][0][RTW89_CHILE][1][75] = 127, + [0][0][RTW89_QATAR][1][75] = 127, + [0][0][RTW89_QATAR][0][75] = 127, + [0][0][RTW89_UK][1][75] = 127, + [0][0][RTW89_UK][0][75] = 127, + [0][0][RTW89_FCC][1][77] = -18, + [0][0][RTW89_FCC][2][77] = 56, + [0][0][RTW89_ETSI][1][77] = 127, + [0][0][RTW89_ETSI][0][77] = 127, + [0][0][RTW89_MKK][1][77] = 127, + [0][0][RTW89_MKK][0][77] = 127, + [0][0][RTW89_IC][1][77] = -18, + [0][0][RTW89_KCC][1][77] = -2, + [0][0][RTW89_KCC][0][77] = 127, + [0][0][RTW89_ACMA][1][77] = 127, + [0][0][RTW89_ACMA][0][77] = 127, + [0][0][RTW89_CHILE][1][77] = 127, + [0][0][RTW89_QATAR][1][77] = 127, + [0][0][RTW89_QATAR][0][77] = 127, + [0][0][RTW89_UK][1][77] = 127, + [0][0][RTW89_UK][0][77] = 127, + [0][0][RTW89_FCC][1][79] = -18, + [0][0][RTW89_FCC][2][79] = 56, + [0][0][RTW89_ETSI][1][79] = 127, + [0][0][RTW89_ETSI][0][79] = 127, + [0][0][RTW89_MKK][1][79] = 127, + [0][0][RTW89_MKK][0][79] = 127, + [0][0][RTW89_IC][1][79] = -18, + [0][0][RTW89_KCC][1][79] = -2, + [0][0][RTW89_KCC][0][79] = 127, + [0][0][RTW89_ACMA][1][79] = 127, + [0][0][RTW89_ACMA][0][79] = 127, + [0][0][RTW89_CHILE][1][79] = 127, + [0][0][RTW89_QATAR][1][79] = 127, + [0][0][RTW89_QATAR][0][79] = 127, + [0][0][RTW89_UK][1][79] = 127, + [0][0][RTW89_UK][0][79] = 127, + [0][0][RTW89_FCC][1][81] = -18, + [0][0][RTW89_FCC][2][81] = 56, + [0][0][RTW89_ETSI][1][81] = 127, + [0][0][RTW89_ETSI][0][81] = 127, + [0][0][RTW89_MKK][1][81] = 127, + [0][0][RTW89_MKK][0][81] = 127, + [0][0][RTW89_IC][1][81] = -18, + [0][0][RTW89_KCC][1][81] = -2, + [0][0][RTW89_KCC][0][81] = 127, + [0][0][RTW89_ACMA][1][81] = 127, + [0][0][RTW89_ACMA][0][81] = 127, + [0][0][RTW89_CHILE][1][81] = 127, + [0][0][RTW89_QATAR][1][81] = 127, + [0][0][RTW89_QATAR][0][81] = 127, + [0][0][RTW89_UK][1][81] = 127, + [0][0][RTW89_UK][0][81] = 127, + [0][0][RTW89_FCC][1][83] = -18, + [0][0][RTW89_FCC][2][83] = 56, + [0][0][RTW89_ETSI][1][83] = 127, + [0][0][RTW89_ETSI][0][83] = 127, + [0][0][RTW89_MKK][1][83] = 127, + [0][0][RTW89_MKK][0][83] = 127, + [0][0][RTW89_IC][1][83] = -18, + [0][0][RTW89_KCC][1][83] = -2, + [0][0][RTW89_KCC][0][83] = 127, + [0][0][RTW89_ACMA][1][83] = 127, + [0][0][RTW89_ACMA][0][83] = 127, + [0][0][RTW89_CHILE][1][83] = 127, + [0][0][RTW89_QATAR][1][83] = 127, + [0][0][RTW89_QATAR][0][83] = 127, + [0][0][RTW89_UK][1][83] = 127, + [0][0][RTW89_UK][0][83] = 127, + [0][0][RTW89_FCC][1][85] = -18, + [0][0][RTW89_FCC][2][85] = 56, + [0][0][RTW89_ETSI][1][85] = 127, + [0][0][RTW89_ETSI][0][85] = 127, + [0][0][RTW89_MKK][1][85] = 127, + [0][0][RTW89_MKK][0][85] = 127, + [0][0][RTW89_IC][1][85] = -18, + [0][0][RTW89_KCC][1][85] = -2, + [0][0][RTW89_KCC][0][85] = 127, + [0][0][RTW89_ACMA][1][85] = 127, + [0][0][RTW89_ACMA][0][85] = 127, + [0][0][RTW89_CHILE][1][85] = 127, + [0][0][RTW89_QATAR][1][85] = 127, + [0][0][RTW89_QATAR][0][85] = 127, + [0][0][RTW89_UK][1][85] = 127, + [0][0][RTW89_UK][0][85] = 127, + [0][0][RTW89_FCC][1][87] = -16, + [0][0][RTW89_FCC][2][87] = 127, + [0][0][RTW89_ETSI][1][87] = 127, + [0][0][RTW89_ETSI][0][87] = 127, + [0][0][RTW89_MKK][1][87] = 127, + [0][0][RTW89_MKK][0][87] = 127, + [0][0][RTW89_IC][1][87] = -16, + [0][0][RTW89_KCC][1][87] = -2, + [0][0][RTW89_KCC][0][87] = 127, + [0][0][RTW89_ACMA][1][87] = 127, + [0][0][RTW89_ACMA][0][87] = 127, + [0][0][RTW89_CHILE][1][87] = 127, + [0][0][RTW89_QATAR][1][87] = 127, + [0][0][RTW89_QATAR][0][87] = 127, + [0][0][RTW89_UK][1][87] = 127, + [0][0][RTW89_UK][0][87] = 127, + [0][0][RTW89_FCC][1][89] = -16, + [0][0][RTW89_FCC][2][89] = 127, + [0][0][RTW89_ETSI][1][89] = 127, + [0][0][RTW89_ETSI][0][89] = 127, + [0][0][RTW89_MKK][1][89] = 127, + [0][0][RTW89_MKK][0][89] = 127, + [0][0][RTW89_IC][1][89] = -16, + [0][0][RTW89_KCC][1][89] = -2, + [0][0][RTW89_KCC][0][89] = 127, + [0][0][RTW89_ACMA][1][89] = 127, + [0][0][RTW89_ACMA][0][89] = 127, + [0][0][RTW89_CHILE][1][89] = 127, + [0][0][RTW89_QATAR][1][89] = 127, + [0][0][RTW89_QATAR][0][89] = 127, + [0][0][RTW89_UK][1][89] = 127, + [0][0][RTW89_UK][0][89] = 127, + [0][0][RTW89_FCC][1][90] = -16, + [0][0][RTW89_FCC][2][90] = 127, + [0][0][RTW89_ETSI][1][90] = 127, + [0][0][RTW89_ETSI][0][90] = 127, + [0][0][RTW89_MKK][1][90] = 127, + [0][0][RTW89_MKK][0][90] = 127, + [0][0][RTW89_IC][1][90] = -16, + [0][0][RTW89_KCC][1][90] = -2, + [0][0][RTW89_KCC][0][90] = 127, + [0][0][RTW89_ACMA][1][90] = 127, + [0][0][RTW89_ACMA][0][90] = 127, + [0][0][RTW89_CHILE][1][90] = 127, + [0][0][RTW89_QATAR][1][90] = 127, + [0][0][RTW89_QATAR][0][90] = 127, + [0][0][RTW89_UK][1][90] = 127, + [0][0][RTW89_UK][0][90] = 127, + [0][0][RTW89_FCC][1][92] = -16, + [0][0][RTW89_FCC][2][92] = 127, + [0][0][RTW89_ETSI][1][92] = 127, + [0][0][RTW89_ETSI][0][92] = 127, + [0][0][RTW89_MKK][1][92] = 127, + [0][0][RTW89_MKK][0][92] = 127, + [0][0][RTW89_IC][1][92] = -16, + [0][0][RTW89_KCC][1][92] = -2, + [0][0][RTW89_KCC][0][92] = 127, + [0][0][RTW89_ACMA][1][92] = 127, + [0][0][RTW89_ACMA][0][92] = 127, + [0][0][RTW89_CHILE][1][92] = 127, + [0][0][RTW89_QATAR][1][92] = 127, + [0][0][RTW89_QATAR][0][92] = 127, + [0][0][RTW89_UK][1][92] = 127, + [0][0][RTW89_UK][0][92] = 127, + [0][0][RTW89_FCC][1][94] = -16, + [0][0][RTW89_FCC][2][94] = 127, + [0][0][RTW89_ETSI][1][94] = 127, + [0][0][RTW89_ETSI][0][94] = 127, + [0][0][RTW89_MKK][1][94] = 127, + [0][0][RTW89_MKK][0][94] = 127, + [0][0][RTW89_IC][1][94] = -16, + [0][0][RTW89_KCC][1][94] = -2, + [0][0][RTW89_KCC][0][94] = 127, + [0][0][RTW89_ACMA][1][94] = 127, + [0][0][RTW89_ACMA][0][94] = 127, + [0][0][RTW89_CHILE][1][94] = 127, + [0][0][RTW89_QATAR][1][94] = 127, + [0][0][RTW89_QATAR][0][94] = 127, + [0][0][RTW89_UK][1][94] = 127, + [0][0][RTW89_UK][0][94] = 127, + [0][0][RTW89_FCC][1][96] = -16, + [0][0][RTW89_FCC][2][96] = 127, + [0][0][RTW89_ETSI][1][96] = 127, + [0][0][RTW89_ETSI][0][96] = 127, + [0][0][RTW89_MKK][1][96] = 127, + [0][0][RTW89_MKK][0][96] = 127, + [0][0][RTW89_IC][1][96] = -16, + [0][0][RTW89_KCC][1][96] = -2, + [0][0][RTW89_KCC][0][96] = 127, + [0][0][RTW89_ACMA][1][96] = 127, + [0][0][RTW89_ACMA][0][96] = 127, + [0][0][RTW89_CHILE][1][96] = 127, + [0][0][RTW89_QATAR][1][96] = 127, + [0][0][RTW89_QATAR][0][96] = 127, + [0][0][RTW89_UK][1][96] = 127, + [0][0][RTW89_UK][0][96] = 127, + [0][0][RTW89_FCC][1][98] = -16, + [0][0][RTW89_FCC][2][98] = 127, + [0][0][RTW89_ETSI][1][98] = 127, + [0][0][RTW89_ETSI][0][98] = 127, + [0][0][RTW89_MKK][1][98] = 127, + [0][0][RTW89_MKK][0][98] = 127, + [0][0][RTW89_IC][1][98] = -16, + [0][0][RTW89_KCC][1][98] = -2, + [0][0][RTW89_KCC][0][98] = 127, + [0][0][RTW89_ACMA][1][98] = 127, + [0][0][RTW89_ACMA][0][98] = 127, + [0][0][RTW89_CHILE][1][98] = 127, + [0][0][RTW89_QATAR][1][98] = 127, + [0][0][RTW89_QATAR][0][98] = 127, + [0][0][RTW89_UK][1][98] = 127, + [0][0][RTW89_UK][0][98] = 127, + [0][0][RTW89_FCC][1][100] = -16, + [0][0][RTW89_FCC][2][100] = 127, + [0][0][RTW89_ETSI][1][100] = 127, + [0][0][RTW89_ETSI][0][100] = 127, + [0][0][RTW89_MKK][1][100] = 127, + [0][0][RTW89_MKK][0][100] = 127, + [0][0][RTW89_IC][1][100] = -16, + [0][0][RTW89_KCC][1][100] = -2, + [0][0][RTW89_KCC][0][100] = 127, + [0][0][RTW89_ACMA][1][100] = 127, + [0][0][RTW89_ACMA][0][100] = 127, + [0][0][RTW89_CHILE][1][100] = 127, + [0][0][RTW89_QATAR][1][100] = 127, + [0][0][RTW89_QATAR][0][100] = 127, + [0][0][RTW89_UK][1][100] = 127, + [0][0][RTW89_UK][0][100] = 127, + [0][0][RTW89_FCC][1][102] = -16, + [0][0][RTW89_FCC][2][102] = 127, + [0][0][RTW89_ETSI][1][102] = 127, + [0][0][RTW89_ETSI][0][102] = 127, + [0][0][RTW89_MKK][1][102] = 127, + [0][0][RTW89_MKK][0][102] = 127, + [0][0][RTW89_IC][1][102] = -16, + [0][0][RTW89_KCC][1][102] = -2, + [0][0][RTW89_KCC][0][102] = 127, + [0][0][RTW89_ACMA][1][102] = 127, + [0][0][RTW89_ACMA][0][102] = 127, + [0][0][RTW89_CHILE][1][102] = 127, + [0][0][RTW89_QATAR][1][102] = 127, + [0][0][RTW89_QATAR][0][102] = 127, + [0][0][RTW89_UK][1][102] = 127, + [0][0][RTW89_UK][0][102] = 127, + [0][0][RTW89_FCC][1][104] = -16, + [0][0][RTW89_FCC][2][104] = 127, + [0][0][RTW89_ETSI][1][104] = 127, + [0][0][RTW89_ETSI][0][104] = 127, + [0][0][RTW89_MKK][1][104] = 127, + [0][0][RTW89_MKK][0][104] = 127, + [0][0][RTW89_IC][1][104] = -16, + [0][0][RTW89_KCC][1][104] = -2, + [0][0][RTW89_KCC][0][104] = 127, + [0][0][RTW89_ACMA][1][104] = 127, + [0][0][RTW89_ACMA][0][104] = 127, + [0][0][RTW89_CHILE][1][104] = 127, + [0][0][RTW89_QATAR][1][104] = 127, + [0][0][RTW89_QATAR][0][104] = 127, + [0][0][RTW89_UK][1][104] = 127, + [0][0][RTW89_UK][0][104] = 127, + [0][0][RTW89_FCC][1][105] = -16, + [0][0][RTW89_FCC][2][105] = 127, + [0][0][RTW89_ETSI][1][105] = 127, + [0][0][RTW89_ETSI][0][105] = 127, + [0][0][RTW89_MKK][1][105] = 127, + [0][0][RTW89_MKK][0][105] = 127, + [0][0][RTW89_IC][1][105] = -16, + [0][0][RTW89_KCC][1][105] = -2, + [0][0][RTW89_KCC][0][105] = 127, + [0][0][RTW89_ACMA][1][105] = 127, + [0][0][RTW89_ACMA][0][105] = 127, + [0][0][RTW89_CHILE][1][105] = 127, + [0][0][RTW89_QATAR][1][105] = 127, + [0][0][RTW89_QATAR][0][105] = 127, + [0][0][RTW89_UK][1][105] = 127, + [0][0][RTW89_UK][0][105] = 127, + [0][0][RTW89_FCC][1][107] = -12, + [0][0][RTW89_FCC][2][107] = 127, + [0][0][RTW89_ETSI][1][107] = 127, + [0][0][RTW89_ETSI][0][107] = 127, + [0][0][RTW89_MKK][1][107] = 127, + [0][0][RTW89_MKK][0][107] = 127, + [0][0][RTW89_IC][1][107] = -12, + [0][0][RTW89_KCC][1][107] = -2, + [0][0][RTW89_KCC][0][107] = 127, + [0][0][RTW89_ACMA][1][107] = 127, + [0][0][RTW89_ACMA][0][107] = 127, + [0][0][RTW89_CHILE][1][107] = 127, + [0][0][RTW89_QATAR][1][107] = 127, + [0][0][RTW89_QATAR][0][107] = 127, + [0][0][RTW89_UK][1][107] = 127, + [0][0][RTW89_UK][0][107] = 127, + [0][0][RTW89_FCC][1][109] = -12, + [0][0][RTW89_FCC][2][109] = 127, + [0][0][RTW89_ETSI][1][109] = 127, + [0][0][RTW89_ETSI][0][109] = 127, + [0][0][RTW89_MKK][1][109] = 127, + [0][0][RTW89_MKK][0][109] = 127, + [0][0][RTW89_IC][1][109] = -12, + [0][0][RTW89_KCC][1][109] = 127, + [0][0][RTW89_KCC][0][109] = 127, + [0][0][RTW89_ACMA][1][109] = 127, + [0][0][RTW89_ACMA][0][109] = 127, + [0][0][RTW89_CHILE][1][109] = 127, + [0][0][RTW89_QATAR][1][109] = 127, + [0][0][RTW89_QATAR][0][109] = 127, + [0][0][RTW89_UK][1][109] = 127, + [0][0][RTW89_UK][0][109] = 127, + [0][0][RTW89_FCC][1][111] = 127, + [0][0][RTW89_FCC][2][111] = 127, + [0][0][RTW89_ETSI][1][111] = 127, + [0][0][RTW89_ETSI][0][111] = 127, + [0][0][RTW89_MKK][1][111] = 127, + [0][0][RTW89_MKK][0][111] = 127, + [0][0][RTW89_IC][1][111] = 127, + [0][0][RTW89_KCC][1][111] = 127, + [0][0][RTW89_KCC][0][111] = 127, + [0][0][RTW89_ACMA][1][111] = 127, + [0][0][RTW89_ACMA][0][111] = 127, + [0][0][RTW89_CHILE][1][111] = 127, + [0][0][RTW89_QATAR][1][111] = 127, + [0][0][RTW89_QATAR][0][111] = 127, + [0][0][RTW89_UK][1][111] = 127, + [0][0][RTW89_UK][0][111] = 127, + [0][0][RTW89_FCC][1][113] = 127, + [0][0][RTW89_FCC][2][113] = 127, + [0][0][RTW89_ETSI][1][113] = 127, + [0][0][RTW89_ETSI][0][113] = 127, + [0][0][RTW89_MKK][1][113] = 127, + [0][0][RTW89_MKK][0][113] = 127, + [0][0][RTW89_IC][1][113] = 127, + [0][0][RTW89_KCC][1][113] = 127, + [0][0][RTW89_KCC][0][113] = 127, + [0][0][RTW89_ACMA][1][113] = 127, + [0][0][RTW89_ACMA][0][113] = 127, + [0][0][RTW89_CHILE][1][113] = 127, + [0][0][RTW89_QATAR][1][113] = 127, + [0][0][RTW89_QATAR][0][113] = 127, + [0][0][RTW89_UK][1][113] = 127, + [0][0][RTW89_UK][0][113] = 127, + [0][0][RTW89_FCC][1][115] = 127, + [0][0][RTW89_FCC][2][115] = 127, + [0][0][RTW89_ETSI][1][115] = 127, + [0][0][RTW89_ETSI][0][115] = 127, + [0][0][RTW89_MKK][1][115] = 127, + [0][0][RTW89_MKK][0][115] = 127, + [0][0][RTW89_IC][1][115] = 127, + [0][0][RTW89_KCC][1][115] = 127, + [0][0][RTW89_KCC][0][115] = 127, + [0][0][RTW89_ACMA][1][115] = 127, + [0][0][RTW89_ACMA][0][115] = 127, + [0][0][RTW89_CHILE][1][115] = 127, + [0][0][RTW89_QATAR][1][115] = 127, + [0][0][RTW89_QATAR][0][115] = 127, + [0][0][RTW89_UK][1][115] = 127, + [0][0][RTW89_UK][0][115] = 127, + [0][0][RTW89_FCC][1][117] = 127, + [0][0][RTW89_FCC][2][117] = 127, + [0][0][RTW89_ETSI][1][117] = 127, + [0][0][RTW89_ETSI][0][117] = 127, + [0][0][RTW89_MKK][1][117] = 127, + [0][0][RTW89_MKK][0][117] = 127, + [0][0][RTW89_IC][1][117] = 127, + [0][0][RTW89_KCC][1][117] = 127, + [0][0][RTW89_KCC][0][117] = 127, + [0][0][RTW89_ACMA][1][117] = 127, + [0][0][RTW89_ACMA][0][117] = 127, + [0][0][RTW89_CHILE][1][117] = 127, + [0][0][RTW89_QATAR][1][117] = 127, + [0][0][RTW89_QATAR][0][117] = 127, + [0][0][RTW89_UK][1][117] = 127, + [0][0][RTW89_UK][0][117] = 127, + [0][0][RTW89_FCC][1][119] = 127, + [0][0][RTW89_FCC][2][119] = 127, + [0][0][RTW89_ETSI][1][119] = 127, + [0][0][RTW89_ETSI][0][119] = 127, + [0][0][RTW89_MKK][1][119] = 127, + [0][0][RTW89_MKK][0][119] = 127, + [0][0][RTW89_IC][1][119] = 127, + [0][0][RTW89_KCC][1][119] = 127, + [0][0][RTW89_KCC][0][119] = 127, + [0][0][RTW89_ACMA][1][119] = 127, + [0][0][RTW89_ACMA][0][119] = 127, + [0][0][RTW89_CHILE][1][119] = 127, + [0][0][RTW89_QATAR][1][119] = 127, + [0][0][RTW89_QATAR][0][119] = 127, + [0][0][RTW89_UK][1][119] = 127, + [0][0][RTW89_UK][0][119] = 127, + [0][1][RTW89_FCC][1][0] = -40, + [0][1][RTW89_FCC][2][0] = 32, + [0][1][RTW89_ETSI][1][0] = 20, + [0][1][RTW89_ETSI][0][0] = -18, + [0][1][RTW89_MKK][1][0] = 18, + [0][1][RTW89_MKK][0][0] = -20, + [0][1][RTW89_IC][1][0] = -40, + [0][1][RTW89_KCC][1][0] = -14, + [0][1][RTW89_KCC][0][0] = -14, + [0][1][RTW89_ACMA][1][0] = 20, + [0][1][RTW89_ACMA][0][0] = -18, + [0][1][RTW89_CHILE][1][0] = -40, + [0][1][RTW89_QATAR][1][0] = 20, + [0][1][RTW89_QATAR][0][0] = -18, + [0][1][RTW89_UK][1][0] = 20, + [0][1][RTW89_UK][0][0] = -18, + [0][1][RTW89_FCC][1][2] = -40, + [0][1][RTW89_FCC][2][2] = 32, + [0][1][RTW89_ETSI][1][2] = 20, + [0][1][RTW89_ETSI][0][2] = -18, + [0][1][RTW89_MKK][1][2] = 18, + [0][1][RTW89_MKK][0][2] = -22, + [0][1][RTW89_IC][1][2] = -40, + [0][1][RTW89_KCC][1][2] = -14, + [0][1][RTW89_KCC][0][2] = -14, + [0][1][RTW89_ACMA][1][2] = 20, + [0][1][RTW89_ACMA][0][2] = -18, + [0][1][RTW89_CHILE][1][2] = -40, + [0][1][RTW89_QATAR][1][2] = 20, + [0][1][RTW89_QATAR][0][2] = -18, + [0][1][RTW89_UK][1][2] = 20, + [0][1][RTW89_UK][0][2] = -18, + [0][1][RTW89_FCC][1][4] = -40, + [0][1][RTW89_FCC][2][4] = 32, + [0][1][RTW89_ETSI][1][4] = 20, + [0][1][RTW89_ETSI][0][4] = -18, + [0][1][RTW89_MKK][1][4] = 18, + [0][1][RTW89_MKK][0][4] = -22, + [0][1][RTW89_IC][1][4] = -40, + [0][1][RTW89_KCC][1][4] = -14, + [0][1][RTW89_KCC][0][4] = -14, + [0][1][RTW89_ACMA][1][4] = 20, + [0][1][RTW89_ACMA][0][4] = -18, + [0][1][RTW89_CHILE][1][4] = -40, + [0][1][RTW89_QATAR][1][4] = 20, + [0][1][RTW89_QATAR][0][4] = -18, + [0][1][RTW89_UK][1][4] = 20, + [0][1][RTW89_UK][0][4] = -18, + [0][1][RTW89_FCC][1][6] = -40, + [0][1][RTW89_FCC][2][6] = 32, + [0][1][RTW89_ETSI][1][6] = 20, + [0][1][RTW89_ETSI][0][6] = -18, + [0][1][RTW89_MKK][1][6] = 18, + [0][1][RTW89_MKK][0][6] = -22, + [0][1][RTW89_IC][1][6] = -40, + [0][1][RTW89_KCC][1][6] = -14, + [0][1][RTW89_KCC][0][6] = -14, + [0][1][RTW89_ACMA][1][6] = 20, + [0][1][RTW89_ACMA][0][6] = -18, + [0][1][RTW89_CHILE][1][6] = -40, + [0][1][RTW89_QATAR][1][6] = 20, + [0][1][RTW89_QATAR][0][6] = -18, + [0][1][RTW89_UK][1][6] = 20, + [0][1][RTW89_UK][0][6] = -18, + [0][1][RTW89_FCC][1][8] = -40, + [0][1][RTW89_FCC][2][8] = 32, + [0][1][RTW89_ETSI][1][8] = 20, + [0][1][RTW89_ETSI][0][8] = -18, + [0][1][RTW89_MKK][1][8] = 18, + [0][1][RTW89_MKK][0][8] = -22, + [0][1][RTW89_IC][1][8] = -40, + [0][1][RTW89_KCC][1][8] = -14, + [0][1][RTW89_KCC][0][8] = -14, + [0][1][RTW89_ACMA][1][8] = 20, + [0][1][RTW89_ACMA][0][8] = -18, + [0][1][RTW89_CHILE][1][8] = -40, + [0][1][RTW89_QATAR][1][8] = 20, + [0][1][RTW89_QATAR][0][8] = -18, + [0][1][RTW89_UK][1][8] = 20, + [0][1][RTW89_UK][0][8] = -18, + [0][1][RTW89_FCC][1][10] = -40, + [0][1][RTW89_FCC][2][10] = 32, + [0][1][RTW89_ETSI][1][10] = 20, + [0][1][RTW89_ETSI][0][10] = -18, + [0][1][RTW89_MKK][1][10] = 18, + [0][1][RTW89_MKK][0][10] = -22, + [0][1][RTW89_IC][1][10] = -40, + [0][1][RTW89_KCC][1][10] = -14, + [0][1][RTW89_KCC][0][10] = -14, + [0][1][RTW89_ACMA][1][10] = 20, + [0][1][RTW89_ACMA][0][10] = -18, + [0][1][RTW89_CHILE][1][10] = -40, + [0][1][RTW89_QATAR][1][10] = 20, + [0][1][RTW89_QATAR][0][10] = -18, + [0][1][RTW89_UK][1][10] = 20, + [0][1][RTW89_UK][0][10] = -18, + [0][1][RTW89_FCC][1][12] = -40, + [0][1][RTW89_FCC][2][12] = 32, + [0][1][RTW89_ETSI][1][12] = 20, + [0][1][RTW89_ETSI][0][12] = -18, + [0][1][RTW89_MKK][1][12] = 18, + [0][1][RTW89_MKK][0][12] = -22, + [0][1][RTW89_IC][1][12] = -40, + [0][1][RTW89_KCC][1][12] = -14, + [0][1][RTW89_KCC][0][12] = -14, + [0][1][RTW89_ACMA][1][12] = 20, + [0][1][RTW89_ACMA][0][12] = -18, + [0][1][RTW89_CHILE][1][12] = -40, + [0][1][RTW89_QATAR][1][12] = 20, + [0][1][RTW89_QATAR][0][12] = -18, + [0][1][RTW89_UK][1][12] = 20, + [0][1][RTW89_UK][0][12] = -18, + [0][1][RTW89_FCC][1][14] = -40, + [0][1][RTW89_FCC][2][14] = 32, + [0][1][RTW89_ETSI][1][14] = 20, + [0][1][RTW89_ETSI][0][14] = -18, + [0][1][RTW89_MKK][1][14] = 18, + [0][1][RTW89_MKK][0][14] = -22, + [0][1][RTW89_IC][1][14] = -40, + [0][1][RTW89_KCC][1][14] = -14, + [0][1][RTW89_KCC][0][14] = -14, + [0][1][RTW89_ACMA][1][14] = 20, + [0][1][RTW89_ACMA][0][14] = -18, + [0][1][RTW89_CHILE][1][14] = -40, + [0][1][RTW89_QATAR][1][14] = 20, + [0][1][RTW89_QATAR][0][14] = -18, + [0][1][RTW89_UK][1][14] = 20, + [0][1][RTW89_UK][0][14] = -18, + [0][1][RTW89_FCC][1][15] = -40, + [0][1][RTW89_FCC][2][15] = 32, + [0][1][RTW89_ETSI][1][15] = 20, + [0][1][RTW89_ETSI][0][15] = -18, + [0][1][RTW89_MKK][1][15] = 18, + [0][1][RTW89_MKK][0][15] = -22, + [0][1][RTW89_IC][1][15] = -40, + [0][1][RTW89_KCC][1][15] = -14, + [0][1][RTW89_KCC][0][15] = -14, + [0][1][RTW89_ACMA][1][15] = 20, + [0][1][RTW89_ACMA][0][15] = -18, + [0][1][RTW89_CHILE][1][15] = -40, + [0][1][RTW89_QATAR][1][15] = 20, + [0][1][RTW89_QATAR][0][15] = -18, + [0][1][RTW89_UK][1][15] = 20, + [0][1][RTW89_UK][0][15] = -18, + [0][1][RTW89_FCC][1][17] = -40, + [0][1][RTW89_FCC][2][17] = 32, + [0][1][RTW89_ETSI][1][17] = 20, + [0][1][RTW89_ETSI][0][17] = -18, + [0][1][RTW89_MKK][1][17] = 18, + [0][1][RTW89_MKK][0][17] = -22, + [0][1][RTW89_IC][1][17] = -40, + [0][1][RTW89_KCC][1][17] = -14, + [0][1][RTW89_KCC][0][17] = -14, + [0][1][RTW89_ACMA][1][17] = 20, + [0][1][RTW89_ACMA][0][17] = -18, + [0][1][RTW89_CHILE][1][17] = -40, + [0][1][RTW89_QATAR][1][17] = 20, + [0][1][RTW89_QATAR][0][17] = -18, + [0][1][RTW89_UK][1][17] = 20, + [0][1][RTW89_UK][0][17] = -18, + [0][1][RTW89_FCC][1][19] = -40, + [0][1][RTW89_FCC][2][19] = 32, + [0][1][RTW89_ETSI][1][19] = 20, + [0][1][RTW89_ETSI][0][19] = -18, + [0][1][RTW89_MKK][1][19] = 18, + [0][1][RTW89_MKK][0][19] = -22, + [0][1][RTW89_IC][1][19] = -40, + [0][1][RTW89_KCC][1][19] = -14, + [0][1][RTW89_KCC][0][19] = -14, + [0][1][RTW89_ACMA][1][19] = 20, + [0][1][RTW89_ACMA][0][19] = -18, + [0][1][RTW89_CHILE][1][19] = -40, + [0][1][RTW89_QATAR][1][19] = 20, + [0][1][RTW89_QATAR][0][19] = -18, + [0][1][RTW89_UK][1][19] = 20, + [0][1][RTW89_UK][0][19] = -18, + [0][1][RTW89_FCC][1][21] = -40, + [0][1][RTW89_FCC][2][21] = 32, + [0][1][RTW89_ETSI][1][21] = 20, + [0][1][RTW89_ETSI][0][21] = -18, + [0][1][RTW89_MKK][1][21] = 18, + [0][1][RTW89_MKK][0][21] = -22, + [0][1][RTW89_IC][1][21] = -40, + [0][1][RTW89_KCC][1][21] = -14, + [0][1][RTW89_KCC][0][21] = -14, + [0][1][RTW89_ACMA][1][21] = 20, + [0][1][RTW89_ACMA][0][21] = -18, + [0][1][RTW89_CHILE][1][21] = -40, + [0][1][RTW89_QATAR][1][21] = 20, + [0][1][RTW89_QATAR][0][21] = -18, + [0][1][RTW89_UK][1][21] = 20, + [0][1][RTW89_UK][0][21] = -18, + [0][1][RTW89_FCC][1][23] = -40, + [0][1][RTW89_FCC][2][23] = 32, + [0][1][RTW89_ETSI][1][23] = 20, + [0][1][RTW89_ETSI][0][23] = -18, + [0][1][RTW89_MKK][1][23] = 18, + [0][1][RTW89_MKK][0][23] = -22, + [0][1][RTW89_IC][1][23] = -40, + [0][1][RTW89_KCC][1][23] = -14, + [0][1][RTW89_KCC][0][23] = -14, + [0][1][RTW89_ACMA][1][23] = 20, + [0][1][RTW89_ACMA][0][23] = -18, + [0][1][RTW89_CHILE][1][23] = -40, + [0][1][RTW89_QATAR][1][23] = 20, + [0][1][RTW89_QATAR][0][23] = -18, + [0][1][RTW89_UK][1][23] = 20, + [0][1][RTW89_UK][0][23] = -18, + [0][1][RTW89_FCC][1][25] = -40, + [0][1][RTW89_FCC][2][25] = 32, + [0][1][RTW89_ETSI][1][25] = 20, + [0][1][RTW89_ETSI][0][25] = -18, + [0][1][RTW89_MKK][1][25] = -4, + [0][1][RTW89_MKK][0][25] = -22, + [0][1][RTW89_IC][1][25] = -40, + [0][1][RTW89_KCC][1][25] = -14, + [0][1][RTW89_KCC][0][25] = -14, + [0][1][RTW89_ACMA][1][25] = 20, + [0][1][RTW89_ACMA][0][25] = -18, + [0][1][RTW89_CHILE][1][25] = -40, + [0][1][RTW89_QATAR][1][25] = 20, + [0][1][RTW89_QATAR][0][25] = -18, + [0][1][RTW89_UK][1][25] = 20, + [0][1][RTW89_UK][0][25] = -18, + [0][1][RTW89_FCC][1][27] = -40, + [0][1][RTW89_FCC][2][27] = 32, + [0][1][RTW89_ETSI][1][27] = 20, + [0][1][RTW89_ETSI][0][27] = -18, + [0][1][RTW89_MKK][1][27] = -4, + [0][1][RTW89_MKK][0][27] = -22, + [0][1][RTW89_IC][1][27] = -40, + [0][1][RTW89_KCC][1][27] = -14, + [0][1][RTW89_KCC][0][27] = -14, + [0][1][RTW89_ACMA][1][27] = 20, + [0][1][RTW89_ACMA][0][27] = -18, + [0][1][RTW89_CHILE][1][27] = -40, + [0][1][RTW89_QATAR][1][27] = 20, + [0][1][RTW89_QATAR][0][27] = -18, + [0][1][RTW89_UK][1][27] = 20, + [0][1][RTW89_UK][0][27] = -18, + [0][1][RTW89_FCC][1][29] = -40, + [0][1][RTW89_FCC][2][29] = 32, + [0][1][RTW89_ETSI][1][29] = 20, + [0][1][RTW89_ETSI][0][29] = -18, + [0][1][RTW89_MKK][1][29] = -4, + [0][1][RTW89_MKK][0][29] = -22, + [0][1][RTW89_IC][1][29] = -40, + [0][1][RTW89_KCC][1][29] = -14, + [0][1][RTW89_KCC][0][29] = -14, + [0][1][RTW89_ACMA][1][29] = 20, + [0][1][RTW89_ACMA][0][29] = -18, + [0][1][RTW89_CHILE][1][29] = -40, + [0][1][RTW89_QATAR][1][29] = 20, + [0][1][RTW89_QATAR][0][29] = -18, + [0][1][RTW89_UK][1][29] = 20, + [0][1][RTW89_UK][0][29] = -18, + [0][1][RTW89_FCC][1][30] = -40, + [0][1][RTW89_FCC][2][30] = 32, + [0][1][RTW89_ETSI][1][30] = 20, + [0][1][RTW89_ETSI][0][30] = -18, + [0][1][RTW89_MKK][1][30] = -4, + [0][1][RTW89_MKK][0][30] = -22, + [0][1][RTW89_IC][1][30] = -40, + [0][1][RTW89_KCC][1][30] = -14, + [0][1][RTW89_KCC][0][30] = -14, + [0][1][RTW89_ACMA][1][30] = 20, + [0][1][RTW89_ACMA][0][30] = -18, + [0][1][RTW89_CHILE][1][30] = -40, + [0][1][RTW89_QATAR][1][30] = 20, + [0][1][RTW89_QATAR][0][30] = -18, + [0][1][RTW89_UK][1][30] = 20, + [0][1][RTW89_UK][0][30] = -18, + [0][1][RTW89_FCC][1][32] = -40, + [0][1][RTW89_FCC][2][32] = 32, + [0][1][RTW89_ETSI][1][32] = 20, + [0][1][RTW89_ETSI][0][32] = -18, + [0][1][RTW89_MKK][1][32] = -4, + [0][1][RTW89_MKK][0][32] = -22, + [0][1][RTW89_IC][1][32] = -40, + [0][1][RTW89_KCC][1][32] = -14, + [0][1][RTW89_KCC][0][32] = -14, + [0][1][RTW89_ACMA][1][32] = 20, + [0][1][RTW89_ACMA][0][32] = -18, + [0][1][RTW89_CHILE][1][32] = -40, + [0][1][RTW89_QATAR][1][32] = 20, + [0][1][RTW89_QATAR][0][32] = -18, + [0][1][RTW89_UK][1][32] = 20, + [0][1][RTW89_UK][0][32] = -18, + [0][1][RTW89_FCC][1][34] = -40, + [0][1][RTW89_FCC][2][34] = 32, + [0][1][RTW89_ETSI][1][34] = 20, + [0][1][RTW89_ETSI][0][34] = -18, + [0][1][RTW89_MKK][1][34] = -4, + [0][1][RTW89_MKK][0][34] = -22, + [0][1][RTW89_IC][1][34] = -40, + [0][1][RTW89_KCC][1][34] = -14, + [0][1][RTW89_KCC][0][34] = -14, + [0][1][RTW89_ACMA][1][34] = 20, + [0][1][RTW89_ACMA][0][34] = -18, + [0][1][RTW89_CHILE][1][34] = -40, + [0][1][RTW89_QATAR][1][34] = 20, + [0][1][RTW89_QATAR][0][34] = -18, + [0][1][RTW89_UK][1][34] = 20, + [0][1][RTW89_UK][0][34] = -18, + [0][1][RTW89_FCC][1][36] = -40, + [0][1][RTW89_FCC][2][36] = 32, + [0][1][RTW89_ETSI][1][36] = 20, + [0][1][RTW89_ETSI][0][36] = -18, + [0][1][RTW89_MKK][1][36] = -4, + [0][1][RTW89_MKK][0][36] = -22, + [0][1][RTW89_IC][1][36] = -40, + [0][1][RTW89_KCC][1][36] = -14, + [0][1][RTW89_KCC][0][36] = -14, + [0][1][RTW89_ACMA][1][36] = 20, + [0][1][RTW89_ACMA][0][36] = -18, + [0][1][RTW89_CHILE][1][36] = -40, + [0][1][RTW89_QATAR][1][36] = 20, + [0][1][RTW89_QATAR][0][36] = -18, + [0][1][RTW89_UK][1][36] = 20, + [0][1][RTW89_UK][0][36] = -18, + [0][1][RTW89_FCC][1][38] = -40, + [0][1][RTW89_FCC][2][38] = 32, + [0][1][RTW89_ETSI][1][38] = 20, + [0][1][RTW89_ETSI][0][38] = -18, + [0][1][RTW89_MKK][1][38] = -4, + [0][1][RTW89_MKK][0][38] = -22, + [0][1][RTW89_IC][1][38] = -40, + [0][1][RTW89_KCC][1][38] = -14, + [0][1][RTW89_KCC][0][38] = -14, + [0][1][RTW89_ACMA][1][38] = 20, + [0][1][RTW89_ACMA][0][38] = -18, + [0][1][RTW89_CHILE][1][38] = -40, + [0][1][RTW89_QATAR][1][38] = 20, + [0][1][RTW89_QATAR][0][38] = -18, + [0][1][RTW89_UK][1][38] = 20, + [0][1][RTW89_UK][0][38] = -18, + [0][1][RTW89_FCC][1][40] = -40, + [0][1][RTW89_FCC][2][40] = 32, + [0][1][RTW89_ETSI][1][40] = 20, + [0][1][RTW89_ETSI][0][40] = -18, + [0][1][RTW89_MKK][1][40] = -4, + [0][1][RTW89_MKK][0][40] = -22, + [0][1][RTW89_IC][1][40] = -40, + [0][1][RTW89_KCC][1][40] = -14, + [0][1][RTW89_KCC][0][40] = -14, + [0][1][RTW89_ACMA][1][40] = 20, + [0][1][RTW89_ACMA][0][40] = -18, + [0][1][RTW89_CHILE][1][40] = -40, + [0][1][RTW89_QATAR][1][40] = 20, + [0][1][RTW89_QATAR][0][40] = -18, + [0][1][RTW89_UK][1][40] = 20, + [0][1][RTW89_UK][0][40] = -18, + [0][1][RTW89_FCC][1][42] = -40, + [0][1][RTW89_FCC][2][42] = 32, + [0][1][RTW89_ETSI][1][42] = 20, + [0][1][RTW89_ETSI][0][42] = -18, + [0][1][RTW89_MKK][1][42] = -4, + [0][1][RTW89_MKK][0][42] = -22, + [0][1][RTW89_IC][1][42] = -40, + [0][1][RTW89_KCC][1][42] = -14, + [0][1][RTW89_KCC][0][42] = -14, + [0][1][RTW89_ACMA][1][42] = 20, + [0][1][RTW89_ACMA][0][42] = -18, + [0][1][RTW89_CHILE][1][42] = -40, + [0][1][RTW89_QATAR][1][42] = 20, + [0][1][RTW89_QATAR][0][42] = -18, + [0][1][RTW89_UK][1][42] = 20, + [0][1][RTW89_UK][0][42] = -18, + [0][1][RTW89_FCC][1][44] = -40, + [0][1][RTW89_FCC][2][44] = 32, + [0][1][RTW89_ETSI][1][44] = 20, + [0][1][RTW89_ETSI][0][44] = -18, + [0][1][RTW89_MKK][1][44] = -4, + [0][1][RTW89_MKK][0][44] = -22, + [0][1][RTW89_IC][1][44] = -40, + [0][1][RTW89_KCC][1][44] = -14, + [0][1][RTW89_KCC][0][44] = -14, + [0][1][RTW89_ACMA][1][44] = 20, + [0][1][RTW89_ACMA][0][44] = -18, + [0][1][RTW89_CHILE][1][44] = -40, + [0][1][RTW89_QATAR][1][44] = 20, + [0][1][RTW89_QATAR][0][44] = -18, + [0][1][RTW89_UK][1][44] = 20, + [0][1][RTW89_UK][0][44] = -18, + [0][1][RTW89_FCC][1][45] = -40, + [0][1][RTW89_FCC][2][45] = 127, + [0][1][RTW89_ETSI][1][45] = 127, + [0][1][RTW89_ETSI][0][45] = 127, + [0][1][RTW89_MKK][1][45] = 127, + [0][1][RTW89_MKK][0][45] = 127, + [0][1][RTW89_IC][1][45] = -40, + [0][1][RTW89_KCC][1][45] = -14, + [0][1][RTW89_KCC][0][45] = 127, + [0][1][RTW89_ACMA][1][45] = 127, + [0][1][RTW89_ACMA][0][45] = 127, + [0][1][RTW89_CHILE][1][45] = 127, + [0][1][RTW89_QATAR][1][45] = 127, + [0][1][RTW89_QATAR][0][45] = 127, + [0][1][RTW89_UK][1][45] = 127, + [0][1][RTW89_UK][0][45] = 127, + [0][1][RTW89_FCC][1][47] = -40, + [0][1][RTW89_FCC][2][47] = 127, + [0][1][RTW89_ETSI][1][47] = 127, + [0][1][RTW89_ETSI][0][47] = 127, + [0][1][RTW89_MKK][1][47] = 127, + [0][1][RTW89_MKK][0][47] = 127, + [0][1][RTW89_IC][1][47] = -40, + [0][1][RTW89_KCC][1][47] = -14, + [0][1][RTW89_KCC][0][47] = 127, + [0][1][RTW89_ACMA][1][47] = 127, + [0][1][RTW89_ACMA][0][47] = 127, + [0][1][RTW89_CHILE][1][47] = 127, + [0][1][RTW89_QATAR][1][47] = 127, + [0][1][RTW89_QATAR][0][47] = 127, + [0][1][RTW89_UK][1][47] = 127, + [0][1][RTW89_UK][0][47] = 127, + [0][1][RTW89_FCC][1][49] = -40, + [0][1][RTW89_FCC][2][49] = 127, + [0][1][RTW89_ETSI][1][49] = 127, + [0][1][RTW89_ETSI][0][49] = 127, + [0][1][RTW89_MKK][1][49] = 127, + [0][1][RTW89_MKK][0][49] = 127, + [0][1][RTW89_IC][1][49] = -40, + [0][1][RTW89_KCC][1][49] = -14, + [0][1][RTW89_KCC][0][49] = 127, + [0][1][RTW89_ACMA][1][49] = 127, + [0][1][RTW89_ACMA][0][49] = 127, + [0][1][RTW89_CHILE][1][49] = 127, + [0][1][RTW89_QATAR][1][49] = 127, + [0][1][RTW89_QATAR][0][49] = 127, + [0][1][RTW89_UK][1][49] = 127, + [0][1][RTW89_UK][0][49] = 127, + [0][1][RTW89_FCC][1][51] = -40, + [0][1][RTW89_FCC][2][51] = 127, + [0][1][RTW89_ETSI][1][51] = 127, + [0][1][RTW89_ETSI][0][51] = 127, + [0][1][RTW89_MKK][1][51] = 127, + [0][1][RTW89_MKK][0][51] = 127, + [0][1][RTW89_IC][1][51] = -40, + [0][1][RTW89_KCC][1][51] = -14, + [0][1][RTW89_KCC][0][51] = 127, + [0][1][RTW89_ACMA][1][51] = 127, + [0][1][RTW89_ACMA][0][51] = 127, + [0][1][RTW89_CHILE][1][51] = 127, + [0][1][RTW89_QATAR][1][51] = 127, + [0][1][RTW89_QATAR][0][51] = 127, + [0][1][RTW89_UK][1][51] = 127, + [0][1][RTW89_UK][0][51] = 127, + [0][1][RTW89_FCC][1][53] = -40, + [0][1][RTW89_FCC][2][53] = 127, + [0][1][RTW89_ETSI][1][53] = 127, + [0][1][RTW89_ETSI][0][53] = 127, + [0][1][RTW89_MKK][1][53] = 127, + [0][1][RTW89_MKK][0][53] = 127, + [0][1][RTW89_IC][1][53] = -40, + [0][1][RTW89_KCC][1][53] = -14, + [0][1][RTW89_KCC][0][53] = 127, + [0][1][RTW89_ACMA][1][53] = 127, + [0][1][RTW89_ACMA][0][53] = 127, + [0][1][RTW89_CHILE][1][53] = 127, + [0][1][RTW89_QATAR][1][53] = 127, + [0][1][RTW89_QATAR][0][53] = 127, + [0][1][RTW89_UK][1][53] = 127, + [0][1][RTW89_UK][0][53] = 127, + [0][1][RTW89_FCC][1][55] = -40, + [0][1][RTW89_FCC][2][55] = 30, + [0][1][RTW89_ETSI][1][55] = 127, + [0][1][RTW89_ETSI][0][55] = 127, + [0][1][RTW89_MKK][1][55] = 127, + [0][1][RTW89_MKK][0][55] = 127, + [0][1][RTW89_IC][1][55] = -40, + [0][1][RTW89_KCC][1][55] = -14, + [0][1][RTW89_KCC][0][55] = 127, + [0][1][RTW89_ACMA][1][55] = 127, + [0][1][RTW89_ACMA][0][55] = 127, + [0][1][RTW89_CHILE][1][55] = 127, + [0][1][RTW89_QATAR][1][55] = 127, + [0][1][RTW89_QATAR][0][55] = 127, + [0][1][RTW89_UK][1][55] = 127, + [0][1][RTW89_UK][0][55] = 127, + [0][1][RTW89_FCC][1][57] = -40, + [0][1][RTW89_FCC][2][57] = 30, + [0][1][RTW89_ETSI][1][57] = 127, + [0][1][RTW89_ETSI][0][57] = 127, + [0][1][RTW89_MKK][1][57] = 127, + [0][1][RTW89_MKK][0][57] = 127, + [0][1][RTW89_IC][1][57] = -40, + [0][1][RTW89_KCC][1][57] = -14, + [0][1][RTW89_KCC][0][57] = 127, + [0][1][RTW89_ACMA][1][57] = 127, + [0][1][RTW89_ACMA][0][57] = 127, + [0][1][RTW89_CHILE][1][57] = 127, + [0][1][RTW89_QATAR][1][57] = 127, + [0][1][RTW89_QATAR][0][57] = 127, + [0][1][RTW89_UK][1][57] = 127, + [0][1][RTW89_UK][0][57] = 127, + [0][1][RTW89_FCC][1][59] = -40, + [0][1][RTW89_FCC][2][59] = 30, + [0][1][RTW89_ETSI][1][59] = 127, + [0][1][RTW89_ETSI][0][59] = 127, + [0][1][RTW89_MKK][1][59] = 127, + [0][1][RTW89_MKK][0][59] = 127, + [0][1][RTW89_IC][1][59] = -40, + [0][1][RTW89_KCC][1][59] = -14, + [0][1][RTW89_KCC][0][59] = 127, + [0][1][RTW89_ACMA][1][59] = 127, + [0][1][RTW89_ACMA][0][59] = 127, + [0][1][RTW89_CHILE][1][59] = 127, + [0][1][RTW89_QATAR][1][59] = 127, + [0][1][RTW89_QATAR][0][59] = 127, + [0][1][RTW89_UK][1][59] = 127, + [0][1][RTW89_UK][0][59] = 127, + [0][1][RTW89_FCC][1][60] = -40, + [0][1][RTW89_FCC][2][60] = 30, + [0][1][RTW89_ETSI][1][60] = 127, + [0][1][RTW89_ETSI][0][60] = 127, + [0][1][RTW89_MKK][1][60] = 127, + [0][1][RTW89_MKK][0][60] = 127, + [0][1][RTW89_IC][1][60] = -40, + [0][1][RTW89_KCC][1][60] = -14, + [0][1][RTW89_KCC][0][60] = 127, + [0][1][RTW89_ACMA][1][60] = 127, + [0][1][RTW89_ACMA][0][60] = 127, + [0][1][RTW89_CHILE][1][60] = 127, + [0][1][RTW89_QATAR][1][60] = 127, + [0][1][RTW89_QATAR][0][60] = 127, + [0][1][RTW89_UK][1][60] = 127, + [0][1][RTW89_UK][0][60] = 127, + [0][1][RTW89_FCC][1][62] = -40, + [0][1][RTW89_FCC][2][62] = 30, + [0][1][RTW89_ETSI][1][62] = 127, + [0][1][RTW89_ETSI][0][62] = 127, + [0][1][RTW89_MKK][1][62] = 127, + [0][1][RTW89_MKK][0][62] = 127, + [0][1][RTW89_IC][1][62] = -40, + [0][1][RTW89_KCC][1][62] = -14, + [0][1][RTW89_KCC][0][62] = 127, + [0][1][RTW89_ACMA][1][62] = 127, + [0][1][RTW89_ACMA][0][62] = 127, + [0][1][RTW89_CHILE][1][62] = 127, + [0][1][RTW89_QATAR][1][62] = 127, + [0][1][RTW89_QATAR][0][62] = 127, + [0][1][RTW89_UK][1][62] = 127, + [0][1][RTW89_UK][0][62] = 127, + [0][1][RTW89_FCC][1][64] = -40, + [0][1][RTW89_FCC][2][64] = 30, + [0][1][RTW89_ETSI][1][64] = 127, + [0][1][RTW89_ETSI][0][64] = 127, + [0][1][RTW89_MKK][1][64] = 127, + [0][1][RTW89_MKK][0][64] = 127, + [0][1][RTW89_IC][1][64] = -40, + [0][1][RTW89_KCC][1][64] = -14, + [0][1][RTW89_KCC][0][64] = 127, + [0][1][RTW89_ACMA][1][64] = 127, + [0][1][RTW89_ACMA][0][64] = 127, + [0][1][RTW89_CHILE][1][64] = 127, + [0][1][RTW89_QATAR][1][64] = 127, + [0][1][RTW89_QATAR][0][64] = 127, + [0][1][RTW89_UK][1][64] = 127, + [0][1][RTW89_UK][0][64] = 127, + [0][1][RTW89_FCC][1][66] = -40, + [0][1][RTW89_FCC][2][66] = 30, + [0][1][RTW89_ETSI][1][66] = 127, + [0][1][RTW89_ETSI][0][66] = 127, + [0][1][RTW89_MKK][1][66] = 127, + [0][1][RTW89_MKK][0][66] = 127, + [0][1][RTW89_IC][1][66] = -40, + [0][1][RTW89_KCC][1][66] = -14, + [0][1][RTW89_KCC][0][66] = 127, + [0][1][RTW89_ACMA][1][66] = 127, + [0][1][RTW89_ACMA][0][66] = 127, + [0][1][RTW89_CHILE][1][66] = 127, + [0][1][RTW89_QATAR][1][66] = 127, + [0][1][RTW89_QATAR][0][66] = 127, + [0][1][RTW89_UK][1][66] = 127, + [0][1][RTW89_UK][0][66] = 127, + [0][1][RTW89_FCC][1][68] = -40, + [0][1][RTW89_FCC][2][68] = 30, + [0][1][RTW89_ETSI][1][68] = 127, + [0][1][RTW89_ETSI][0][68] = 127, + [0][1][RTW89_MKK][1][68] = 127, + [0][1][RTW89_MKK][0][68] = 127, + [0][1][RTW89_IC][1][68] = -40, + [0][1][RTW89_KCC][1][68] = -14, + [0][1][RTW89_KCC][0][68] = 127, + [0][1][RTW89_ACMA][1][68] = 127, + [0][1][RTW89_ACMA][0][68] = 127, + [0][1][RTW89_CHILE][1][68] = 127, + [0][1][RTW89_QATAR][1][68] = 127, + [0][1][RTW89_QATAR][0][68] = 127, + [0][1][RTW89_UK][1][68] = 127, + [0][1][RTW89_UK][0][68] = 127, + [0][1][RTW89_FCC][1][70] = -38, + [0][1][RTW89_FCC][2][70] = 30, + [0][1][RTW89_ETSI][1][70] = 127, + [0][1][RTW89_ETSI][0][70] = 127, + [0][1][RTW89_MKK][1][70] = 127, + [0][1][RTW89_MKK][0][70] = 127, + [0][1][RTW89_IC][1][70] = -38, + [0][1][RTW89_KCC][1][70] = -14, + [0][1][RTW89_KCC][0][70] = 127, + [0][1][RTW89_ACMA][1][70] = 127, + [0][1][RTW89_ACMA][0][70] = 127, + [0][1][RTW89_CHILE][1][70] = 127, + [0][1][RTW89_QATAR][1][70] = 127, + [0][1][RTW89_QATAR][0][70] = 127, + [0][1][RTW89_UK][1][70] = 127, + [0][1][RTW89_UK][0][70] = 127, + [0][1][RTW89_FCC][1][72] = -38, + [0][1][RTW89_FCC][2][72] = 30, + [0][1][RTW89_ETSI][1][72] = 127, + [0][1][RTW89_ETSI][0][72] = 127, + [0][1][RTW89_MKK][1][72] = 127, + [0][1][RTW89_MKK][0][72] = 127, + [0][1][RTW89_IC][1][72] = -38, + [0][1][RTW89_KCC][1][72] = -14, + [0][1][RTW89_KCC][0][72] = 127, + [0][1][RTW89_ACMA][1][72] = 127, + [0][1][RTW89_ACMA][0][72] = 127, + [0][1][RTW89_CHILE][1][72] = 127, + [0][1][RTW89_QATAR][1][72] = 127, + [0][1][RTW89_QATAR][0][72] = 127, + [0][1][RTW89_UK][1][72] = 127, + [0][1][RTW89_UK][0][72] = 127, + [0][1][RTW89_FCC][1][74] = -38, + [0][1][RTW89_FCC][2][74] = 30, + [0][1][RTW89_ETSI][1][74] = 127, + [0][1][RTW89_ETSI][0][74] = 127, + [0][1][RTW89_MKK][1][74] = 127, + [0][1][RTW89_MKK][0][74] = 127, + [0][1][RTW89_IC][1][74] = -38, + [0][1][RTW89_KCC][1][74] = -14, + [0][1][RTW89_KCC][0][74] = 127, + [0][1][RTW89_ACMA][1][74] = 127, + [0][1][RTW89_ACMA][0][74] = 127, + [0][1][RTW89_CHILE][1][74] = 127, + [0][1][RTW89_QATAR][1][74] = 127, + [0][1][RTW89_QATAR][0][74] = 127, + [0][1][RTW89_UK][1][74] = 127, + [0][1][RTW89_UK][0][74] = 127, + [0][1][RTW89_FCC][1][75] = -38, + [0][1][RTW89_FCC][2][75] = 30, + [0][1][RTW89_ETSI][1][75] = 127, + [0][1][RTW89_ETSI][0][75] = 127, + [0][1][RTW89_MKK][1][75] = 127, + [0][1][RTW89_MKK][0][75] = 127, + [0][1][RTW89_IC][1][75] = -38, + [0][1][RTW89_KCC][1][75] = -14, + [0][1][RTW89_KCC][0][75] = 127, + [0][1][RTW89_ACMA][1][75] = 127, + [0][1][RTW89_ACMA][0][75] = 127, + [0][1][RTW89_CHILE][1][75] = 127, + [0][1][RTW89_QATAR][1][75] = 127, + [0][1][RTW89_QATAR][0][75] = 127, + [0][1][RTW89_UK][1][75] = 127, + [0][1][RTW89_UK][0][75] = 127, + [0][1][RTW89_FCC][1][77] = -38, + [0][1][RTW89_FCC][2][77] = 30, + [0][1][RTW89_ETSI][1][77] = 127, + [0][1][RTW89_ETSI][0][77] = 127, + [0][1][RTW89_MKK][1][77] = 127, + [0][1][RTW89_MKK][0][77] = 127, + [0][1][RTW89_IC][1][77] = -38, + [0][1][RTW89_KCC][1][77] = -14, + [0][1][RTW89_KCC][0][77] = 127, + [0][1][RTW89_ACMA][1][77] = 127, + [0][1][RTW89_ACMA][0][77] = 127, + [0][1][RTW89_CHILE][1][77] = 127, + [0][1][RTW89_QATAR][1][77] = 127, + [0][1][RTW89_QATAR][0][77] = 127, + [0][1][RTW89_UK][1][77] = 127, + [0][1][RTW89_UK][0][77] = 127, + [0][1][RTW89_FCC][1][79] = -38, + [0][1][RTW89_FCC][2][79] = 30, + [0][1][RTW89_ETSI][1][79] = 127, + [0][1][RTW89_ETSI][0][79] = 127, + [0][1][RTW89_MKK][1][79] = 127, + [0][1][RTW89_MKK][0][79] = 127, + [0][1][RTW89_IC][1][79] = -38, + [0][1][RTW89_KCC][1][79] = -14, + [0][1][RTW89_KCC][0][79] = 127, + [0][1][RTW89_ACMA][1][79] = 127, + [0][1][RTW89_ACMA][0][79] = 127, + [0][1][RTW89_CHILE][1][79] = 127, + [0][1][RTW89_QATAR][1][79] = 127, + [0][1][RTW89_QATAR][0][79] = 127, + [0][1][RTW89_UK][1][79] = 127, + [0][1][RTW89_UK][0][79] = 127, + [0][1][RTW89_FCC][1][81] = -38, + [0][1][RTW89_FCC][2][81] = 30, + [0][1][RTW89_ETSI][1][81] = 127, + [0][1][RTW89_ETSI][0][81] = 127, + [0][1][RTW89_MKK][1][81] = 127, + [0][1][RTW89_MKK][0][81] = 127, + [0][1][RTW89_IC][1][81] = -38, + [0][1][RTW89_KCC][1][81] = -14, + [0][1][RTW89_KCC][0][81] = 127, + [0][1][RTW89_ACMA][1][81] = 127, + [0][1][RTW89_ACMA][0][81] = 127, + [0][1][RTW89_CHILE][1][81] = 127, + [0][1][RTW89_QATAR][1][81] = 127, + [0][1][RTW89_QATAR][0][81] = 127, + [0][1][RTW89_UK][1][81] = 127, + [0][1][RTW89_UK][0][81] = 127, + [0][1][RTW89_FCC][1][83] = -38, + [0][1][RTW89_FCC][2][83] = 30, + [0][1][RTW89_ETSI][1][83] = 127, + [0][1][RTW89_ETSI][0][83] = 127, + [0][1][RTW89_MKK][1][83] = 127, + [0][1][RTW89_MKK][0][83] = 127, + [0][1][RTW89_IC][1][83] = -38, + [0][1][RTW89_KCC][1][83] = -14, + [0][1][RTW89_KCC][0][83] = 127, + [0][1][RTW89_ACMA][1][83] = 127, + [0][1][RTW89_ACMA][0][83] = 127, + [0][1][RTW89_CHILE][1][83] = 127, + [0][1][RTW89_QATAR][1][83] = 127, + [0][1][RTW89_QATAR][0][83] = 127, + [0][1][RTW89_UK][1][83] = 127, + [0][1][RTW89_UK][0][83] = 127, + [0][1][RTW89_FCC][1][85] = -38, + [0][1][RTW89_FCC][2][85] = 30, + [0][1][RTW89_ETSI][1][85] = 127, + [0][1][RTW89_ETSI][0][85] = 127, + [0][1][RTW89_MKK][1][85] = 127, + [0][1][RTW89_MKK][0][85] = 127, + [0][1][RTW89_IC][1][85] = -38, + [0][1][RTW89_KCC][1][85] = -14, + [0][1][RTW89_KCC][0][85] = 127, + [0][1][RTW89_ACMA][1][85] = 127, + [0][1][RTW89_ACMA][0][85] = 127, + [0][1][RTW89_CHILE][1][85] = 127, + [0][1][RTW89_QATAR][1][85] = 127, + [0][1][RTW89_QATAR][0][85] = 127, + [0][1][RTW89_UK][1][85] = 127, + [0][1][RTW89_UK][0][85] = 127, + [0][1][RTW89_FCC][1][87] = -40, + [0][1][RTW89_FCC][2][87] = 127, + [0][1][RTW89_ETSI][1][87] = 127, + [0][1][RTW89_ETSI][0][87] = 127, + [0][1][RTW89_MKK][1][87] = 127, + [0][1][RTW89_MKK][0][87] = 127, + [0][1][RTW89_IC][1][87] = -40, + [0][1][RTW89_KCC][1][87] = -14, + [0][1][RTW89_KCC][0][87] = 127, + [0][1][RTW89_ACMA][1][87] = 127, + [0][1][RTW89_ACMA][0][87] = 127, + [0][1][RTW89_CHILE][1][87] = 127, + [0][1][RTW89_QATAR][1][87] = 127, + [0][1][RTW89_QATAR][0][87] = 127, + [0][1][RTW89_UK][1][87] = 127, + [0][1][RTW89_UK][0][87] = 127, + [0][1][RTW89_FCC][1][89] = -38, + [0][1][RTW89_FCC][2][89] = 127, + [0][1][RTW89_ETSI][1][89] = 127, + [0][1][RTW89_ETSI][0][89] = 127, + [0][1][RTW89_MKK][1][89] = 127, + [0][1][RTW89_MKK][0][89] = 127, + [0][1][RTW89_IC][1][89] = -38, + [0][1][RTW89_KCC][1][89] = -14, + [0][1][RTW89_KCC][0][89] = 127, + [0][1][RTW89_ACMA][1][89] = 127, + [0][1][RTW89_ACMA][0][89] = 127, + [0][1][RTW89_CHILE][1][89] = 127, + [0][1][RTW89_QATAR][1][89] = 127, + [0][1][RTW89_QATAR][0][89] = 127, + [0][1][RTW89_UK][1][89] = 127, + [0][1][RTW89_UK][0][89] = 127, + [0][1][RTW89_FCC][1][90] = -38, + [0][1][RTW89_FCC][2][90] = 127, + [0][1][RTW89_ETSI][1][90] = 127, + [0][1][RTW89_ETSI][0][90] = 127, + [0][1][RTW89_MKK][1][90] = 127, + [0][1][RTW89_MKK][0][90] = 127, + [0][1][RTW89_IC][1][90] = -38, + [0][1][RTW89_KCC][1][90] = -14, + [0][1][RTW89_KCC][0][90] = 127, + [0][1][RTW89_ACMA][1][90] = 127, + [0][1][RTW89_ACMA][0][90] = 127, + [0][1][RTW89_CHILE][1][90] = 127, + [0][1][RTW89_QATAR][1][90] = 127, + [0][1][RTW89_QATAR][0][90] = 127, + [0][1][RTW89_UK][1][90] = 127, + [0][1][RTW89_UK][0][90] = 127, + [0][1][RTW89_FCC][1][92] = -38, + [0][1][RTW89_FCC][2][92] = 127, + [0][1][RTW89_ETSI][1][92] = 127, + [0][1][RTW89_ETSI][0][92] = 127, + [0][1][RTW89_MKK][1][92] = 127, + [0][1][RTW89_MKK][0][92] = 127, + [0][1][RTW89_IC][1][92] = -38, + [0][1][RTW89_KCC][1][92] = -14, + [0][1][RTW89_KCC][0][92] = 127, + [0][1][RTW89_ACMA][1][92] = 127, + [0][1][RTW89_ACMA][0][92] = 127, + [0][1][RTW89_CHILE][1][92] = 127, + [0][1][RTW89_QATAR][1][92] = 127, + [0][1][RTW89_QATAR][0][92] = 127, + [0][1][RTW89_UK][1][92] = 127, + [0][1][RTW89_UK][0][92] = 127, + [0][1][RTW89_FCC][1][94] = -38, + [0][1][RTW89_FCC][2][94] = 127, + [0][1][RTW89_ETSI][1][94] = 127, + [0][1][RTW89_ETSI][0][94] = 127, + [0][1][RTW89_MKK][1][94] = 127, + [0][1][RTW89_MKK][0][94] = 127, + [0][1][RTW89_IC][1][94] = -38, + [0][1][RTW89_KCC][1][94] = -14, + [0][1][RTW89_KCC][0][94] = 127, + [0][1][RTW89_ACMA][1][94] = 127, + [0][1][RTW89_ACMA][0][94] = 127, + [0][1][RTW89_CHILE][1][94] = 127, + [0][1][RTW89_QATAR][1][94] = 127, + [0][1][RTW89_QATAR][0][94] = 127, + [0][1][RTW89_UK][1][94] = 127, + [0][1][RTW89_UK][0][94] = 127, + [0][1][RTW89_FCC][1][96] = -38, + [0][1][RTW89_FCC][2][96] = 127, + [0][1][RTW89_ETSI][1][96] = 127, + [0][1][RTW89_ETSI][0][96] = 127, + [0][1][RTW89_MKK][1][96] = 127, + [0][1][RTW89_MKK][0][96] = 127, + [0][1][RTW89_IC][1][96] = -38, + [0][1][RTW89_KCC][1][96] = -14, + [0][1][RTW89_KCC][0][96] = 127, + [0][1][RTW89_ACMA][1][96] = 127, + [0][1][RTW89_ACMA][0][96] = 127, + [0][1][RTW89_CHILE][1][96] = 127, + [0][1][RTW89_QATAR][1][96] = 127, + [0][1][RTW89_QATAR][0][96] = 127, + [0][1][RTW89_UK][1][96] = 127, + [0][1][RTW89_UK][0][96] = 127, + [0][1][RTW89_FCC][1][98] = -38, + [0][1][RTW89_FCC][2][98] = 127, + [0][1][RTW89_ETSI][1][98] = 127, + [0][1][RTW89_ETSI][0][98] = 127, + [0][1][RTW89_MKK][1][98] = 127, + [0][1][RTW89_MKK][0][98] = 127, + [0][1][RTW89_IC][1][98] = -38, + [0][1][RTW89_KCC][1][98] = -14, + [0][1][RTW89_KCC][0][98] = 127, + [0][1][RTW89_ACMA][1][98] = 127, + [0][1][RTW89_ACMA][0][98] = 127, + [0][1][RTW89_CHILE][1][98] = 127, + [0][1][RTW89_QATAR][1][98] = 127, + [0][1][RTW89_QATAR][0][98] = 127, + [0][1][RTW89_UK][1][98] = 127, + [0][1][RTW89_UK][0][98] = 127, + [0][1][RTW89_FCC][1][100] = -38, + [0][1][RTW89_FCC][2][100] = 127, + [0][1][RTW89_ETSI][1][100] = 127, + [0][1][RTW89_ETSI][0][100] = 127, + [0][1][RTW89_MKK][1][100] = 127, + [0][1][RTW89_MKK][0][100] = 127, + [0][1][RTW89_IC][1][100] = -38, + [0][1][RTW89_KCC][1][100] = -14, + [0][1][RTW89_KCC][0][100] = 127, + [0][1][RTW89_ACMA][1][100] = 127, + [0][1][RTW89_ACMA][0][100] = 127, + [0][1][RTW89_CHILE][1][100] = 127, + [0][1][RTW89_QATAR][1][100] = 127, + [0][1][RTW89_QATAR][0][100] = 127, + [0][1][RTW89_UK][1][100] = 127, + [0][1][RTW89_UK][0][100] = 127, + [0][1][RTW89_FCC][1][102] = -38, + [0][1][RTW89_FCC][2][102] = 127, + [0][1][RTW89_ETSI][1][102] = 127, + [0][1][RTW89_ETSI][0][102] = 127, + [0][1][RTW89_MKK][1][102] = 127, + [0][1][RTW89_MKK][0][102] = 127, + [0][1][RTW89_IC][1][102] = -38, + [0][1][RTW89_KCC][1][102] = -14, + [0][1][RTW89_KCC][0][102] = 127, + [0][1][RTW89_ACMA][1][102] = 127, + [0][1][RTW89_ACMA][0][102] = 127, + [0][1][RTW89_CHILE][1][102] = 127, + [0][1][RTW89_QATAR][1][102] = 127, + [0][1][RTW89_QATAR][0][102] = 127, + [0][1][RTW89_UK][1][102] = 127, + [0][1][RTW89_UK][0][102] = 127, + [0][1][RTW89_FCC][1][104] = -38, + [0][1][RTW89_FCC][2][104] = 127, + [0][1][RTW89_ETSI][1][104] = 127, + [0][1][RTW89_ETSI][0][104] = 127, + [0][1][RTW89_MKK][1][104] = 127, + [0][1][RTW89_MKK][0][104] = 127, + [0][1][RTW89_IC][1][104] = -38, + [0][1][RTW89_KCC][1][104] = -14, + [0][1][RTW89_KCC][0][104] = 127, + [0][1][RTW89_ACMA][1][104] = 127, + [0][1][RTW89_ACMA][0][104] = 127, + [0][1][RTW89_CHILE][1][104] = 127, + [0][1][RTW89_QATAR][1][104] = 127, + [0][1][RTW89_QATAR][0][104] = 127, + [0][1][RTW89_UK][1][104] = 127, + [0][1][RTW89_UK][0][104] = 127, + [0][1][RTW89_FCC][1][105] = -38, + [0][1][RTW89_FCC][2][105] = 127, + [0][1][RTW89_ETSI][1][105] = 127, + [0][1][RTW89_ETSI][0][105] = 127, + [0][1][RTW89_MKK][1][105] = 127, + [0][1][RTW89_MKK][0][105] = 127, + [0][1][RTW89_IC][1][105] = -38, + [0][1][RTW89_KCC][1][105] = -14, + [0][1][RTW89_KCC][0][105] = 127, + [0][1][RTW89_ACMA][1][105] = 127, + [0][1][RTW89_ACMA][0][105] = 127, + [0][1][RTW89_CHILE][1][105] = 127, + [0][1][RTW89_QATAR][1][105] = 127, + [0][1][RTW89_QATAR][0][105] = 127, + [0][1][RTW89_UK][1][105] = 127, + [0][1][RTW89_UK][0][105] = 127, + [0][1][RTW89_FCC][1][107] = -34, + [0][1][RTW89_FCC][2][107] = 127, + [0][1][RTW89_ETSI][1][107] = 127, + [0][1][RTW89_ETSI][0][107] = 127, + [0][1][RTW89_MKK][1][107] = 127, + [0][1][RTW89_MKK][0][107] = 127, + [0][1][RTW89_IC][1][107] = -34, + [0][1][RTW89_KCC][1][107] = -14, + [0][1][RTW89_KCC][0][107] = 127, + [0][1][RTW89_ACMA][1][107] = 127, + [0][1][RTW89_ACMA][0][107] = 127, + [0][1][RTW89_CHILE][1][107] = 127, + [0][1][RTW89_QATAR][1][107] = 127, + [0][1][RTW89_QATAR][0][107] = 127, + [0][1][RTW89_UK][1][107] = 127, + [0][1][RTW89_UK][0][107] = 127, + [0][1][RTW89_FCC][1][109] = -34, + [0][1][RTW89_FCC][2][109] = 127, + [0][1][RTW89_ETSI][1][109] = 127, + [0][1][RTW89_ETSI][0][109] = 127, + [0][1][RTW89_MKK][1][109] = 127, + [0][1][RTW89_MKK][0][109] = 127, + [0][1][RTW89_IC][1][109] = -34, + [0][1][RTW89_KCC][1][109] = 127, + [0][1][RTW89_KCC][0][109] = 127, + [0][1][RTW89_ACMA][1][109] = 127, + [0][1][RTW89_ACMA][0][109] = 127, + [0][1][RTW89_CHILE][1][109] = 127, + [0][1][RTW89_QATAR][1][109] = 127, + [0][1][RTW89_QATAR][0][109] = 127, + [0][1][RTW89_UK][1][109] = 127, + [0][1][RTW89_UK][0][109] = 127, + [0][1][RTW89_FCC][1][111] = 127, + [0][1][RTW89_FCC][2][111] = 127, + [0][1][RTW89_ETSI][1][111] = 127, + [0][1][RTW89_ETSI][0][111] = 127, + [0][1][RTW89_MKK][1][111] = 127, + [0][1][RTW89_MKK][0][111] = 127, + [0][1][RTW89_IC][1][111] = 127, + [0][1][RTW89_KCC][1][111] = 127, + [0][1][RTW89_KCC][0][111] = 127, + [0][1][RTW89_ACMA][1][111] = 127, + [0][1][RTW89_ACMA][0][111] = 127, + [0][1][RTW89_CHILE][1][111] = 127, + [0][1][RTW89_QATAR][1][111] = 127, + [0][1][RTW89_QATAR][0][111] = 127, + [0][1][RTW89_UK][1][111] = 127, + [0][1][RTW89_UK][0][111] = 127, + [0][1][RTW89_FCC][1][113] = 127, + [0][1][RTW89_FCC][2][113] = 127, + [0][1][RTW89_ETSI][1][113] = 127, + [0][1][RTW89_ETSI][0][113] = 127, + [0][1][RTW89_MKK][1][113] = 127, + [0][1][RTW89_MKK][0][113] = 127, + [0][1][RTW89_IC][1][113] = 127, + [0][1][RTW89_KCC][1][113] = 127, + [0][1][RTW89_KCC][0][113] = 127, + [0][1][RTW89_ACMA][1][113] = 127, + [0][1][RTW89_ACMA][0][113] = 127, + [0][1][RTW89_CHILE][1][113] = 127, + [0][1][RTW89_QATAR][1][113] = 127, + [0][1][RTW89_QATAR][0][113] = 127, + [0][1][RTW89_UK][1][113] = 127, + [0][1][RTW89_UK][0][113] = 127, + [0][1][RTW89_FCC][1][115] = 127, + [0][1][RTW89_FCC][2][115] = 127, + [0][1][RTW89_ETSI][1][115] = 127, + [0][1][RTW89_ETSI][0][115] = 127, + [0][1][RTW89_MKK][1][115] = 127, + [0][1][RTW89_MKK][0][115] = 127, + [0][1][RTW89_IC][1][115] = 127, + [0][1][RTW89_KCC][1][115] = 127, + [0][1][RTW89_KCC][0][115] = 127, + [0][1][RTW89_ACMA][1][115] = 127, + [0][1][RTW89_ACMA][0][115] = 127, + [0][1][RTW89_CHILE][1][115] = 127, + [0][1][RTW89_QATAR][1][115] = 127, + [0][1][RTW89_QATAR][0][115] = 127, + [0][1][RTW89_UK][1][115] = 127, + [0][1][RTW89_UK][0][115] = 127, + [0][1][RTW89_FCC][1][117] = 127, + [0][1][RTW89_FCC][2][117] = 127, + [0][1][RTW89_ETSI][1][117] = 127, + [0][1][RTW89_ETSI][0][117] = 127, + [0][1][RTW89_MKK][1][117] = 127, + [0][1][RTW89_MKK][0][117] = 127, + [0][1][RTW89_IC][1][117] = 127, + [0][1][RTW89_KCC][1][117] = 127, + [0][1][RTW89_KCC][0][117] = 127, + [0][1][RTW89_ACMA][1][117] = 127, + [0][1][RTW89_ACMA][0][117] = 127, + [0][1][RTW89_CHILE][1][117] = 127, + [0][1][RTW89_QATAR][1][117] = 127, + [0][1][RTW89_QATAR][0][117] = 127, + [0][1][RTW89_UK][1][117] = 127, + [0][1][RTW89_UK][0][117] = 127, + [0][1][RTW89_FCC][1][119] = 127, + [0][1][RTW89_FCC][2][119] = 127, + [0][1][RTW89_ETSI][1][119] = 127, + [0][1][RTW89_ETSI][0][119] = 127, + [0][1][RTW89_MKK][1][119] = 127, + [0][1][RTW89_MKK][0][119] = 127, + [0][1][RTW89_IC][1][119] = 127, + [0][1][RTW89_KCC][1][119] = 127, + [0][1][RTW89_KCC][0][119] = 127, + [0][1][RTW89_ACMA][1][119] = 127, + [0][1][RTW89_ACMA][0][119] = 127, + [0][1][RTW89_CHILE][1][119] = 127, + [0][1][RTW89_QATAR][1][119] = 127, + [0][1][RTW89_QATAR][0][119] = 127, + [0][1][RTW89_UK][1][119] = 127, + [0][1][RTW89_UK][0][119] = 127, + [1][0][RTW89_FCC][1][0] = -4, + [1][0][RTW89_FCC][2][0] = 52, + [1][0][RTW89_ETSI][1][0] = 46, + [1][0][RTW89_ETSI][0][0] = 6, + [1][0][RTW89_MKK][1][0] = 42, + [1][0][RTW89_MKK][0][0] = 2, + [1][0][RTW89_IC][1][0] = -4, + [1][0][RTW89_KCC][1][0] = -2, + [1][0][RTW89_KCC][0][0] = -2, + [1][0][RTW89_ACMA][1][0] = 46, + [1][0][RTW89_ACMA][0][0] = 6, + [1][0][RTW89_CHILE][1][0] = -4, + [1][0][RTW89_QATAR][1][0] = 46, + [1][0][RTW89_QATAR][0][0] = 6, + [1][0][RTW89_UK][1][0] = 46, + [1][0][RTW89_UK][0][0] = 6, + [1][0][RTW89_FCC][1][2] = -4, + [1][0][RTW89_FCC][2][2] = 52, + [1][0][RTW89_ETSI][1][2] = 46, + [1][0][RTW89_ETSI][0][2] = 6, + [1][0][RTW89_MKK][1][2] = 42, + [1][0][RTW89_MKK][0][2] = 2, + [1][0][RTW89_IC][1][2] = -4, + [1][0][RTW89_KCC][1][2] = -2, + [1][0][RTW89_KCC][0][2] = -2, + [1][0][RTW89_ACMA][1][2] = 46, + [1][0][RTW89_ACMA][0][2] = 6, + [1][0][RTW89_CHILE][1][2] = -4, + [1][0][RTW89_QATAR][1][2] = 46, + [1][0][RTW89_QATAR][0][2] = 6, + [1][0][RTW89_UK][1][2] = 46, + [1][0][RTW89_UK][0][2] = 6, + [1][0][RTW89_FCC][1][4] = -4, + [1][0][RTW89_FCC][2][4] = 52, + [1][0][RTW89_ETSI][1][4] = 46, + [1][0][RTW89_ETSI][0][4] = 6, + [1][0][RTW89_MKK][1][4] = 42, + [1][0][RTW89_MKK][0][4] = 2, + [1][0][RTW89_IC][1][4] = -4, + [1][0][RTW89_KCC][1][4] = -2, + [1][0][RTW89_KCC][0][4] = -2, + [1][0][RTW89_ACMA][1][4] = 46, + [1][0][RTW89_ACMA][0][4] = 6, + [1][0][RTW89_CHILE][1][4] = -4, + [1][0][RTW89_QATAR][1][4] = 46, + [1][0][RTW89_QATAR][0][4] = 6, + [1][0][RTW89_UK][1][4] = 46, + [1][0][RTW89_UK][0][4] = 6, + [1][0][RTW89_FCC][1][6] = -4, + [1][0][RTW89_FCC][2][6] = 52, + [1][0][RTW89_ETSI][1][6] = 46, + [1][0][RTW89_ETSI][0][6] = 6, + [1][0][RTW89_MKK][1][6] = 42, + [1][0][RTW89_MKK][0][6] = 2, + [1][0][RTW89_IC][1][6] = -4, + [1][0][RTW89_KCC][1][6] = -2, + [1][0][RTW89_KCC][0][6] = -2, + [1][0][RTW89_ACMA][1][6] = 46, + [1][0][RTW89_ACMA][0][6] = 6, + [1][0][RTW89_CHILE][1][6] = -4, + [1][0][RTW89_QATAR][1][6] = 46, + [1][0][RTW89_QATAR][0][6] = 6, + [1][0][RTW89_UK][1][6] = 46, + [1][0][RTW89_UK][0][6] = 6, + [1][0][RTW89_FCC][1][8] = -4, + [1][0][RTW89_FCC][2][8] = 52, + [1][0][RTW89_ETSI][1][8] = 46, + [1][0][RTW89_ETSI][0][8] = 6, + [1][0][RTW89_MKK][1][8] = 42, + [1][0][RTW89_MKK][0][8] = 2, + [1][0][RTW89_IC][1][8] = -4, + [1][0][RTW89_KCC][1][8] = -2, + [1][0][RTW89_KCC][0][8] = -2, + [1][0][RTW89_ACMA][1][8] = 46, + [1][0][RTW89_ACMA][0][8] = 6, + [1][0][RTW89_CHILE][1][8] = -4, + [1][0][RTW89_QATAR][1][8] = 46, + [1][0][RTW89_QATAR][0][8] = 6, + [1][0][RTW89_UK][1][8] = 46, + [1][0][RTW89_UK][0][8] = 6, + [1][0][RTW89_FCC][1][10] = -4, + [1][0][RTW89_FCC][2][10] = 52, + [1][0][RTW89_ETSI][1][10] = 46, + [1][0][RTW89_ETSI][0][10] = 6, + [1][0][RTW89_MKK][1][10] = 42, + [1][0][RTW89_MKK][0][10] = 2, + [1][0][RTW89_IC][1][10] = -4, + [1][0][RTW89_KCC][1][10] = -2, + [1][0][RTW89_KCC][0][10] = -2, + [1][0][RTW89_ACMA][1][10] = 46, + [1][0][RTW89_ACMA][0][10] = 6, + [1][0][RTW89_CHILE][1][10] = -4, + [1][0][RTW89_QATAR][1][10] = 46, + [1][0][RTW89_QATAR][0][10] = 6, + [1][0][RTW89_UK][1][10] = 46, + [1][0][RTW89_UK][0][10] = 6, + [1][0][RTW89_FCC][1][12] = -4, + [1][0][RTW89_FCC][2][12] = 52, + [1][0][RTW89_ETSI][1][12] = 46, + [1][0][RTW89_ETSI][0][12] = 6, + [1][0][RTW89_MKK][1][12] = 42, + [1][0][RTW89_MKK][0][12] = 2, + [1][0][RTW89_IC][1][12] = -4, + [1][0][RTW89_KCC][1][12] = -2, + [1][0][RTW89_KCC][0][12] = -2, + [1][0][RTW89_ACMA][1][12] = 46, + [1][0][RTW89_ACMA][0][12] = 6, + [1][0][RTW89_CHILE][1][12] = -4, + [1][0][RTW89_QATAR][1][12] = 46, + [1][0][RTW89_QATAR][0][12] = 6, + [1][0][RTW89_UK][1][12] = 46, + [1][0][RTW89_UK][0][12] = 6, + [1][0][RTW89_FCC][1][14] = -4, + [1][0][RTW89_FCC][2][14] = 52, + [1][0][RTW89_ETSI][1][14] = 46, + [1][0][RTW89_ETSI][0][14] = 6, + [1][0][RTW89_MKK][1][14] = 42, + [1][0][RTW89_MKK][0][14] = 2, + [1][0][RTW89_IC][1][14] = -4, + [1][0][RTW89_KCC][1][14] = -2, + [1][0][RTW89_KCC][0][14] = -2, + [1][0][RTW89_ACMA][1][14] = 46, + [1][0][RTW89_ACMA][0][14] = 6, + [1][0][RTW89_CHILE][1][14] = -4, + [1][0][RTW89_QATAR][1][14] = 46, + [1][0][RTW89_QATAR][0][14] = 6, + [1][0][RTW89_UK][1][14] = 46, + [1][0][RTW89_UK][0][14] = 6, + [1][0][RTW89_FCC][1][15] = -4, + [1][0][RTW89_FCC][2][15] = 52, + [1][0][RTW89_ETSI][1][15] = 46, + [1][0][RTW89_ETSI][0][15] = 6, + [1][0][RTW89_MKK][1][15] = 42, + [1][0][RTW89_MKK][0][15] = 2, + [1][0][RTW89_IC][1][15] = -4, + [1][0][RTW89_KCC][1][15] = -2, + [1][0][RTW89_KCC][0][15] = -2, + [1][0][RTW89_ACMA][1][15] = 46, + [1][0][RTW89_ACMA][0][15] = 6, + [1][0][RTW89_CHILE][1][15] = -4, + [1][0][RTW89_QATAR][1][15] = 46, + [1][0][RTW89_QATAR][0][15] = 6, + [1][0][RTW89_UK][1][15] = 46, + [1][0][RTW89_UK][0][15] = 6, + [1][0][RTW89_FCC][1][17] = -4, + [1][0][RTW89_FCC][2][17] = 52, + [1][0][RTW89_ETSI][1][17] = 46, + [1][0][RTW89_ETSI][0][17] = 6, + [1][0][RTW89_MKK][1][17] = 42, + [1][0][RTW89_MKK][0][17] = 2, + [1][0][RTW89_IC][1][17] = -4, + [1][0][RTW89_KCC][1][17] = -2, + [1][0][RTW89_KCC][0][17] = -2, + [1][0][RTW89_ACMA][1][17] = 46, + [1][0][RTW89_ACMA][0][17] = 6, + [1][0][RTW89_CHILE][1][17] = -4, + [1][0][RTW89_QATAR][1][17] = 46, + [1][0][RTW89_QATAR][0][17] = 6, + [1][0][RTW89_UK][1][17] = 46, + [1][0][RTW89_UK][0][17] = 6, + [1][0][RTW89_FCC][1][19] = -4, + [1][0][RTW89_FCC][2][19] = 52, + [1][0][RTW89_ETSI][1][19] = 46, + [1][0][RTW89_ETSI][0][19] = 6, + [1][0][RTW89_MKK][1][19] = 42, + [1][0][RTW89_MKK][0][19] = 2, + [1][0][RTW89_IC][1][19] = -4, + [1][0][RTW89_KCC][1][19] = -2, + [1][0][RTW89_KCC][0][19] = -2, + [1][0][RTW89_ACMA][1][19] = 46, + [1][0][RTW89_ACMA][0][19] = 6, + [1][0][RTW89_CHILE][1][19] = -4, + [1][0][RTW89_QATAR][1][19] = 46, + [1][0][RTW89_QATAR][0][19] = 6, + [1][0][RTW89_UK][1][19] = 46, + [1][0][RTW89_UK][0][19] = 6, + [1][0][RTW89_FCC][1][21] = -4, + [1][0][RTW89_FCC][2][21] = 52, + [1][0][RTW89_ETSI][1][21] = 46, + [1][0][RTW89_ETSI][0][21] = 6, + [1][0][RTW89_MKK][1][21] = 42, + [1][0][RTW89_MKK][0][21] = 2, + [1][0][RTW89_IC][1][21] = -4, + [1][0][RTW89_KCC][1][21] = -2, + [1][0][RTW89_KCC][0][21] = -2, + [1][0][RTW89_ACMA][1][21] = 46, + [1][0][RTW89_ACMA][0][21] = 6, + [1][0][RTW89_CHILE][1][21] = -4, + [1][0][RTW89_QATAR][1][21] = 46, + [1][0][RTW89_QATAR][0][21] = 6, + [1][0][RTW89_UK][1][21] = 46, + [1][0][RTW89_UK][0][21] = 6, + [1][0][RTW89_FCC][1][23] = -4, + [1][0][RTW89_FCC][2][23] = 66, + [1][0][RTW89_ETSI][1][23] = 46, + [1][0][RTW89_ETSI][0][23] = 6, + [1][0][RTW89_MKK][1][23] = 42, + [1][0][RTW89_MKK][0][23] = 2, + [1][0][RTW89_IC][1][23] = -4, + [1][0][RTW89_KCC][1][23] = -2, + [1][0][RTW89_KCC][0][23] = -2, + [1][0][RTW89_ACMA][1][23] = 46, + [1][0][RTW89_ACMA][0][23] = 6, + [1][0][RTW89_CHILE][1][23] = -4, + [1][0][RTW89_QATAR][1][23] = 46, + [1][0][RTW89_QATAR][0][23] = 6, + [1][0][RTW89_UK][1][23] = 46, + [1][0][RTW89_UK][0][23] = 6, + [1][0][RTW89_FCC][1][25] = -4, + [1][0][RTW89_FCC][2][25] = 66, + [1][0][RTW89_ETSI][1][25] = 46, + [1][0][RTW89_ETSI][0][25] = 6, + [1][0][RTW89_MKK][1][25] = 42, + [1][0][RTW89_MKK][0][25] = 2, + [1][0][RTW89_IC][1][25] = -4, + [1][0][RTW89_KCC][1][25] = -2, + [1][0][RTW89_KCC][0][25] = -2, + [1][0][RTW89_ACMA][1][25] = 46, + [1][0][RTW89_ACMA][0][25] = 6, + [1][0][RTW89_CHILE][1][25] = -4, + [1][0][RTW89_QATAR][1][25] = 46, + [1][0][RTW89_QATAR][0][25] = 6, + [1][0][RTW89_UK][1][25] = 46, + [1][0][RTW89_UK][0][25] = 6, + [1][0][RTW89_FCC][1][27] = -4, + [1][0][RTW89_FCC][2][27] = 66, + [1][0][RTW89_ETSI][1][27] = 46, + [1][0][RTW89_ETSI][0][27] = 6, + [1][0][RTW89_MKK][1][27] = 42, + [1][0][RTW89_MKK][0][27] = 2, + [1][0][RTW89_IC][1][27] = -4, + [1][0][RTW89_KCC][1][27] = -2, + [1][0][RTW89_KCC][0][27] = -2, + [1][0][RTW89_ACMA][1][27] = 46, + [1][0][RTW89_ACMA][0][27] = 6, + [1][0][RTW89_CHILE][1][27] = -4, + [1][0][RTW89_QATAR][1][27] = 46, + [1][0][RTW89_QATAR][0][27] = 6, + [1][0][RTW89_UK][1][27] = 46, + [1][0][RTW89_UK][0][27] = 6, + [1][0][RTW89_FCC][1][29] = -4, + [1][0][RTW89_FCC][2][29] = 66, + [1][0][RTW89_ETSI][1][29] = 46, + [1][0][RTW89_ETSI][0][29] = 6, + [1][0][RTW89_MKK][1][29] = 42, + [1][0][RTW89_MKK][0][29] = 2, + [1][0][RTW89_IC][1][29] = -4, + [1][0][RTW89_KCC][1][29] = -2, + [1][0][RTW89_KCC][0][29] = -2, + [1][0][RTW89_ACMA][1][29] = 46, + [1][0][RTW89_ACMA][0][29] = 6, + [1][0][RTW89_CHILE][1][29] = -4, + [1][0][RTW89_QATAR][1][29] = 46, + [1][0][RTW89_QATAR][0][29] = 6, + [1][0][RTW89_UK][1][29] = 46, + [1][0][RTW89_UK][0][29] = 6, + [1][0][RTW89_FCC][1][30] = -4, + [1][0][RTW89_FCC][2][30] = 66, + [1][0][RTW89_ETSI][1][30] = 46, + [1][0][RTW89_ETSI][0][30] = 6, + [1][0][RTW89_MKK][1][30] = 42, + [1][0][RTW89_MKK][0][30] = 2, + [1][0][RTW89_IC][1][30] = -4, + [1][0][RTW89_KCC][1][30] = -2, + [1][0][RTW89_KCC][0][30] = -2, + [1][0][RTW89_ACMA][1][30] = 46, + [1][0][RTW89_ACMA][0][30] = 6, + [1][0][RTW89_CHILE][1][30] = -4, + [1][0][RTW89_QATAR][1][30] = 46, + [1][0][RTW89_QATAR][0][30] = 6, + [1][0][RTW89_UK][1][30] = 46, + [1][0][RTW89_UK][0][30] = 6, + [1][0][RTW89_FCC][1][32] = -4, + [1][0][RTW89_FCC][2][32] = 66, + [1][0][RTW89_ETSI][1][32] = 46, + [1][0][RTW89_ETSI][0][32] = 6, + [1][0][RTW89_MKK][1][32] = 42, + [1][0][RTW89_MKK][0][32] = 2, + [1][0][RTW89_IC][1][32] = -4, + [1][0][RTW89_KCC][1][32] = -2, + [1][0][RTW89_KCC][0][32] = -2, + [1][0][RTW89_ACMA][1][32] = 46, + [1][0][RTW89_ACMA][0][32] = 6, + [1][0][RTW89_CHILE][1][32] = -4, + [1][0][RTW89_QATAR][1][32] = 46, + [1][0][RTW89_QATAR][0][32] = 6, + [1][0][RTW89_UK][1][32] = 46, + [1][0][RTW89_UK][0][32] = 6, + [1][0][RTW89_FCC][1][34] = -4, + [1][0][RTW89_FCC][2][34] = 66, + [1][0][RTW89_ETSI][1][34] = 46, + [1][0][RTW89_ETSI][0][34] = 6, + [1][0][RTW89_MKK][1][34] = 42, + [1][0][RTW89_MKK][0][34] = 2, + [1][0][RTW89_IC][1][34] = -4, + [1][0][RTW89_KCC][1][34] = -2, + [1][0][RTW89_KCC][0][34] = -2, + [1][0][RTW89_ACMA][1][34] = 46, + [1][0][RTW89_ACMA][0][34] = 6, + [1][0][RTW89_CHILE][1][34] = -4, + [1][0][RTW89_QATAR][1][34] = 46, + [1][0][RTW89_QATAR][0][34] = 6, + [1][0][RTW89_UK][1][34] = 46, + [1][0][RTW89_UK][0][34] = 6, + [1][0][RTW89_FCC][1][36] = -4, + [1][0][RTW89_FCC][2][36] = 66, + [1][0][RTW89_ETSI][1][36] = 46, + [1][0][RTW89_ETSI][0][36] = 6, + [1][0][RTW89_MKK][1][36] = 42, + [1][0][RTW89_MKK][0][36] = 2, + [1][0][RTW89_IC][1][36] = -4, + [1][0][RTW89_KCC][1][36] = -2, + [1][0][RTW89_KCC][0][36] = -2, + [1][0][RTW89_ACMA][1][36] = 46, + [1][0][RTW89_ACMA][0][36] = 6, + [1][0][RTW89_CHILE][1][36] = -4, + [1][0][RTW89_QATAR][1][36] = 46, + [1][0][RTW89_QATAR][0][36] = 6, + [1][0][RTW89_UK][1][36] = 46, + [1][0][RTW89_UK][0][36] = 6, + [1][0][RTW89_FCC][1][38] = -4, + [1][0][RTW89_FCC][2][38] = 66, + [1][0][RTW89_ETSI][1][38] = 46, + [1][0][RTW89_ETSI][0][38] = 6, + [1][0][RTW89_MKK][1][38] = 42, + [1][0][RTW89_MKK][0][38] = 2, + [1][0][RTW89_IC][1][38] = -4, + [1][0][RTW89_KCC][1][38] = -2, + [1][0][RTW89_KCC][0][38] = -2, + [1][0][RTW89_ACMA][1][38] = 46, + [1][0][RTW89_ACMA][0][38] = 6, + [1][0][RTW89_CHILE][1][38] = -4, + [1][0][RTW89_QATAR][1][38] = 46, + [1][0][RTW89_QATAR][0][38] = 6, + [1][0][RTW89_UK][1][38] = 46, + [1][0][RTW89_UK][0][38] = 6, + [1][0][RTW89_FCC][1][40] = -4, + [1][0][RTW89_FCC][2][40] = 66, + [1][0][RTW89_ETSI][1][40] = 46, + [1][0][RTW89_ETSI][0][40] = 6, + [1][0][RTW89_MKK][1][40] = 42, + [1][0][RTW89_MKK][0][40] = 2, + [1][0][RTW89_IC][1][40] = -4, + [1][0][RTW89_KCC][1][40] = -2, + [1][0][RTW89_KCC][0][40] = -2, + [1][0][RTW89_ACMA][1][40] = 46, + [1][0][RTW89_ACMA][0][40] = 6, + [1][0][RTW89_CHILE][1][40] = -4, + [1][0][RTW89_QATAR][1][40] = 46, + [1][0][RTW89_QATAR][0][40] = 6, + [1][0][RTW89_UK][1][40] = 46, + [1][0][RTW89_UK][0][40] = 6, + [1][0][RTW89_FCC][1][42] = -4, + [1][0][RTW89_FCC][2][42] = 66, + [1][0][RTW89_ETSI][1][42] = 46, + [1][0][RTW89_ETSI][0][42] = 6, + [1][0][RTW89_MKK][1][42] = 42, + [1][0][RTW89_MKK][0][42] = 2, + [1][0][RTW89_IC][1][42] = -4, + [1][0][RTW89_KCC][1][42] = -2, + [1][0][RTW89_KCC][0][42] = -2, + [1][0][RTW89_ACMA][1][42] = 46, + [1][0][RTW89_ACMA][0][42] = 6, + [1][0][RTW89_CHILE][1][42] = -4, + [1][0][RTW89_QATAR][1][42] = 46, + [1][0][RTW89_QATAR][0][42] = 6, + [1][0][RTW89_UK][1][42] = 46, + [1][0][RTW89_UK][0][42] = 6, + [1][0][RTW89_FCC][1][44] = -4, + [1][0][RTW89_FCC][2][44] = 66, + [1][0][RTW89_ETSI][1][44] = 46, + [1][0][RTW89_ETSI][0][44] = 8, + [1][0][RTW89_MKK][1][44] = 22, + [1][0][RTW89_MKK][0][44] = 4, + [1][0][RTW89_IC][1][44] = -4, + [1][0][RTW89_KCC][1][44] = -2, + [1][0][RTW89_KCC][0][44] = -2, + [1][0][RTW89_ACMA][1][44] = 46, + [1][0][RTW89_ACMA][0][44] = 8, + [1][0][RTW89_CHILE][1][44] = -4, + [1][0][RTW89_QATAR][1][44] = 46, + [1][0][RTW89_QATAR][0][44] = 8, + [1][0][RTW89_UK][1][44] = 46, + [1][0][RTW89_UK][0][44] = 8, + [1][0][RTW89_FCC][1][45] = -4, + [1][0][RTW89_FCC][2][45] = 127, + [1][0][RTW89_ETSI][1][45] = 127, + [1][0][RTW89_ETSI][0][45] = 127, + [1][0][RTW89_MKK][1][45] = 127, + [1][0][RTW89_MKK][0][45] = 127, + [1][0][RTW89_IC][1][45] = -4, + [1][0][RTW89_KCC][1][45] = -2, + [1][0][RTW89_KCC][0][45] = 127, + [1][0][RTW89_ACMA][1][45] = 127, + [1][0][RTW89_ACMA][0][45] = 127, + [1][0][RTW89_CHILE][1][45] = 127, + [1][0][RTW89_QATAR][1][45] = 127, + [1][0][RTW89_QATAR][0][45] = 127, + [1][0][RTW89_UK][1][45] = 127, + [1][0][RTW89_UK][0][45] = 127, + [1][0][RTW89_FCC][1][47] = -4, + [1][0][RTW89_FCC][2][47] = 127, + [1][0][RTW89_ETSI][1][47] = 127, + [1][0][RTW89_ETSI][0][47] = 127, + [1][0][RTW89_MKK][1][47] = 127, + [1][0][RTW89_MKK][0][47] = 127, + [1][0][RTW89_IC][1][47] = -4, + [1][0][RTW89_KCC][1][47] = -2, + [1][0][RTW89_KCC][0][47] = 127, + [1][0][RTW89_ACMA][1][47] = 127, + [1][0][RTW89_ACMA][0][47] = 127, + [1][0][RTW89_CHILE][1][47] = 127, + [1][0][RTW89_QATAR][1][47] = 127, + [1][0][RTW89_QATAR][0][47] = 127, + [1][0][RTW89_UK][1][47] = 127, + [1][0][RTW89_UK][0][47] = 127, + [1][0][RTW89_FCC][1][49] = -4, + [1][0][RTW89_FCC][2][49] = 127, + [1][0][RTW89_ETSI][1][49] = 127, + [1][0][RTW89_ETSI][0][49] = 127, + [1][0][RTW89_MKK][1][49] = 127, + [1][0][RTW89_MKK][0][49] = 127, + [1][0][RTW89_IC][1][49] = -4, + [1][0][RTW89_KCC][1][49] = -2, + [1][0][RTW89_KCC][0][49] = 127, + [1][0][RTW89_ACMA][1][49] = 127, + [1][0][RTW89_ACMA][0][49] = 127, + [1][0][RTW89_CHILE][1][49] = 127, + [1][0][RTW89_QATAR][1][49] = 127, + [1][0][RTW89_QATAR][0][49] = 127, + [1][0][RTW89_UK][1][49] = 127, + [1][0][RTW89_UK][0][49] = 127, + [1][0][RTW89_FCC][1][51] = -4, + [1][0][RTW89_FCC][2][51] = 127, + [1][0][RTW89_ETSI][1][51] = 127, + [1][0][RTW89_ETSI][0][51] = 127, + [1][0][RTW89_MKK][1][51] = 127, + [1][0][RTW89_MKK][0][51] = 127, + [1][0][RTW89_IC][1][51] = -4, + [1][0][RTW89_KCC][1][51] = -2, + [1][0][RTW89_KCC][0][51] = 127, + [1][0][RTW89_ACMA][1][51] = 127, + [1][0][RTW89_ACMA][0][51] = 127, + [1][0][RTW89_CHILE][1][51] = 127, + [1][0][RTW89_QATAR][1][51] = 127, + [1][0][RTW89_QATAR][0][51] = 127, + [1][0][RTW89_UK][1][51] = 127, + [1][0][RTW89_UK][0][51] = 127, + [1][0][RTW89_FCC][1][53] = -4, + [1][0][RTW89_FCC][2][53] = 127, + [1][0][RTW89_ETSI][1][53] = 127, + [1][0][RTW89_ETSI][0][53] = 127, + [1][0][RTW89_MKK][1][53] = 127, + [1][0][RTW89_MKK][0][53] = 127, + [1][0][RTW89_IC][1][53] = -4, + [1][0][RTW89_KCC][1][53] = -2, + [1][0][RTW89_KCC][0][53] = 127, + [1][0][RTW89_ACMA][1][53] = 127, + [1][0][RTW89_ACMA][0][53] = 127, + [1][0][RTW89_CHILE][1][53] = 127, + [1][0][RTW89_QATAR][1][53] = 127, + [1][0][RTW89_QATAR][0][53] = 127, + [1][0][RTW89_UK][1][53] = 127, + [1][0][RTW89_UK][0][53] = 127, + [1][0][RTW89_FCC][1][55] = -4, + [1][0][RTW89_FCC][2][55] = 68, + [1][0][RTW89_ETSI][1][55] = 127, + [1][0][RTW89_ETSI][0][55] = 127, + [1][0][RTW89_MKK][1][55] = 127, + [1][0][RTW89_MKK][0][55] = 127, + [1][0][RTW89_IC][1][55] = -4, + [1][0][RTW89_KCC][1][55] = -2, + [1][0][RTW89_KCC][0][55] = 127, + [1][0][RTW89_ACMA][1][55] = 127, + [1][0][RTW89_ACMA][0][55] = 127, + [1][0][RTW89_CHILE][1][55] = 127, + [1][0][RTW89_QATAR][1][55] = 127, + [1][0][RTW89_QATAR][0][55] = 127, + [1][0][RTW89_UK][1][55] = 127, + [1][0][RTW89_UK][0][55] = 127, + [1][0][RTW89_FCC][1][57] = -4, + [1][0][RTW89_FCC][2][57] = 68, + [1][0][RTW89_ETSI][1][57] = 127, + [1][0][RTW89_ETSI][0][57] = 127, + [1][0][RTW89_MKK][1][57] = 127, + [1][0][RTW89_MKK][0][57] = 127, + [1][0][RTW89_IC][1][57] = -4, + [1][0][RTW89_KCC][1][57] = -2, + [1][0][RTW89_KCC][0][57] = 127, + [1][0][RTW89_ACMA][1][57] = 127, + [1][0][RTW89_ACMA][0][57] = 127, + [1][0][RTW89_CHILE][1][57] = 127, + [1][0][RTW89_QATAR][1][57] = 127, + [1][0][RTW89_QATAR][0][57] = 127, + [1][0][RTW89_UK][1][57] = 127, + [1][0][RTW89_UK][0][57] = 127, + [1][0][RTW89_FCC][1][59] = -4, + [1][0][RTW89_FCC][2][59] = 68, + [1][0][RTW89_ETSI][1][59] = 127, + [1][0][RTW89_ETSI][0][59] = 127, + [1][0][RTW89_MKK][1][59] = 127, + [1][0][RTW89_MKK][0][59] = 127, + [1][0][RTW89_IC][1][59] = -4, + [1][0][RTW89_KCC][1][59] = -2, + [1][0][RTW89_KCC][0][59] = 127, + [1][0][RTW89_ACMA][1][59] = 127, + [1][0][RTW89_ACMA][0][59] = 127, + [1][0][RTW89_CHILE][1][59] = 127, + [1][0][RTW89_QATAR][1][59] = 127, + [1][0][RTW89_QATAR][0][59] = 127, + [1][0][RTW89_UK][1][59] = 127, + [1][0][RTW89_UK][0][59] = 127, + [1][0][RTW89_FCC][1][60] = -4, + [1][0][RTW89_FCC][2][60] = 68, + [1][0][RTW89_ETSI][1][60] = 127, + [1][0][RTW89_ETSI][0][60] = 127, + [1][0][RTW89_MKK][1][60] = 127, + [1][0][RTW89_MKK][0][60] = 127, + [1][0][RTW89_IC][1][60] = -4, + [1][0][RTW89_KCC][1][60] = -2, + [1][0][RTW89_KCC][0][60] = 127, + [1][0][RTW89_ACMA][1][60] = 127, + [1][0][RTW89_ACMA][0][60] = 127, + [1][0][RTW89_CHILE][1][60] = 127, + [1][0][RTW89_QATAR][1][60] = 127, + [1][0][RTW89_QATAR][0][60] = 127, + [1][0][RTW89_UK][1][60] = 127, + [1][0][RTW89_UK][0][60] = 127, + [1][0][RTW89_FCC][1][62] = -4, + [1][0][RTW89_FCC][2][62] = 68, + [1][0][RTW89_ETSI][1][62] = 127, + [1][0][RTW89_ETSI][0][62] = 127, + [1][0][RTW89_MKK][1][62] = 127, + [1][0][RTW89_MKK][0][62] = 127, + [1][0][RTW89_IC][1][62] = -4, + [1][0][RTW89_KCC][1][62] = -2, + [1][0][RTW89_KCC][0][62] = 127, + [1][0][RTW89_ACMA][1][62] = 127, + [1][0][RTW89_ACMA][0][62] = 127, + [1][0][RTW89_CHILE][1][62] = 127, + [1][0][RTW89_QATAR][1][62] = 127, + [1][0][RTW89_QATAR][0][62] = 127, + [1][0][RTW89_UK][1][62] = 127, + [1][0][RTW89_UK][0][62] = 127, + [1][0][RTW89_FCC][1][64] = -4, + [1][0][RTW89_FCC][2][64] = 68, + [1][0][RTW89_ETSI][1][64] = 127, + [1][0][RTW89_ETSI][0][64] = 127, + [1][0][RTW89_MKK][1][64] = 127, + [1][0][RTW89_MKK][0][64] = 127, + [1][0][RTW89_IC][1][64] = -4, + [1][0][RTW89_KCC][1][64] = -2, + [1][0][RTW89_KCC][0][64] = 127, + [1][0][RTW89_ACMA][1][64] = 127, + [1][0][RTW89_ACMA][0][64] = 127, + [1][0][RTW89_CHILE][1][64] = 127, + [1][0][RTW89_QATAR][1][64] = 127, + [1][0][RTW89_QATAR][0][64] = 127, + [1][0][RTW89_UK][1][64] = 127, + [1][0][RTW89_UK][0][64] = 127, + [1][0][RTW89_FCC][1][66] = -4, + [1][0][RTW89_FCC][2][66] = 68, + [1][0][RTW89_ETSI][1][66] = 127, + [1][0][RTW89_ETSI][0][66] = 127, + [1][0][RTW89_MKK][1][66] = 127, + [1][0][RTW89_MKK][0][66] = 127, + [1][0][RTW89_IC][1][66] = -4, + [1][0][RTW89_KCC][1][66] = -2, + [1][0][RTW89_KCC][0][66] = 127, + [1][0][RTW89_ACMA][1][66] = 127, + [1][0][RTW89_ACMA][0][66] = 127, + [1][0][RTW89_CHILE][1][66] = 127, + [1][0][RTW89_QATAR][1][66] = 127, + [1][0][RTW89_QATAR][0][66] = 127, + [1][0][RTW89_UK][1][66] = 127, + [1][0][RTW89_UK][0][66] = 127, + [1][0][RTW89_FCC][1][68] = -4, + [1][0][RTW89_FCC][2][68] = 68, + [1][0][RTW89_ETSI][1][68] = 127, + [1][0][RTW89_ETSI][0][68] = 127, + [1][0][RTW89_MKK][1][68] = 127, + [1][0][RTW89_MKK][0][68] = 127, + [1][0][RTW89_IC][1][68] = -4, + [1][0][RTW89_KCC][1][68] = -2, + [1][0][RTW89_KCC][0][68] = 127, + [1][0][RTW89_ACMA][1][68] = 127, + [1][0][RTW89_ACMA][0][68] = 127, + [1][0][RTW89_CHILE][1][68] = 127, + [1][0][RTW89_QATAR][1][68] = 127, + [1][0][RTW89_QATAR][0][68] = 127, + [1][0][RTW89_UK][1][68] = 127, + [1][0][RTW89_UK][0][68] = 127, + [1][0][RTW89_FCC][1][70] = -4, + [1][0][RTW89_FCC][2][70] = 68, + [1][0][RTW89_ETSI][1][70] = 127, + [1][0][RTW89_ETSI][0][70] = 127, + [1][0][RTW89_MKK][1][70] = 127, + [1][0][RTW89_MKK][0][70] = 127, + [1][0][RTW89_IC][1][70] = -4, + [1][0][RTW89_KCC][1][70] = -2, + [1][0][RTW89_KCC][0][70] = 127, + [1][0][RTW89_ACMA][1][70] = 127, + [1][0][RTW89_ACMA][0][70] = 127, + [1][0][RTW89_CHILE][1][70] = 127, + [1][0][RTW89_QATAR][1][70] = 127, + [1][0][RTW89_QATAR][0][70] = 127, + [1][0][RTW89_UK][1][70] = 127, + [1][0][RTW89_UK][0][70] = 127, + [1][0][RTW89_FCC][1][72] = -4, + [1][0][RTW89_FCC][2][72] = 68, + [1][0][RTW89_ETSI][1][72] = 127, + [1][0][RTW89_ETSI][0][72] = 127, + [1][0][RTW89_MKK][1][72] = 127, + [1][0][RTW89_MKK][0][72] = 127, + [1][0][RTW89_IC][1][72] = -4, + [1][0][RTW89_KCC][1][72] = -2, + [1][0][RTW89_KCC][0][72] = 127, + [1][0][RTW89_ACMA][1][72] = 127, + [1][0][RTW89_ACMA][0][72] = 127, + [1][0][RTW89_CHILE][1][72] = 127, + [1][0][RTW89_QATAR][1][72] = 127, + [1][0][RTW89_QATAR][0][72] = 127, + [1][0][RTW89_UK][1][72] = 127, + [1][0][RTW89_UK][0][72] = 127, + [1][0][RTW89_FCC][1][74] = -4, + [1][0][RTW89_FCC][2][74] = 68, + [1][0][RTW89_ETSI][1][74] = 127, + [1][0][RTW89_ETSI][0][74] = 127, + [1][0][RTW89_MKK][1][74] = 127, + [1][0][RTW89_MKK][0][74] = 127, + [1][0][RTW89_IC][1][74] = -4, + [1][0][RTW89_KCC][1][74] = -2, + [1][0][RTW89_KCC][0][74] = 127, + [1][0][RTW89_ACMA][1][74] = 127, + [1][0][RTW89_ACMA][0][74] = 127, + [1][0][RTW89_CHILE][1][74] = 127, + [1][0][RTW89_QATAR][1][74] = 127, + [1][0][RTW89_QATAR][0][74] = 127, + [1][0][RTW89_UK][1][74] = 127, + [1][0][RTW89_UK][0][74] = 127, + [1][0][RTW89_FCC][1][75] = -4, + [1][0][RTW89_FCC][2][75] = 68, + [1][0][RTW89_ETSI][1][75] = 127, + [1][0][RTW89_ETSI][0][75] = 127, + [1][0][RTW89_MKK][1][75] = 127, + [1][0][RTW89_MKK][0][75] = 127, + [1][0][RTW89_IC][1][75] = -4, + [1][0][RTW89_KCC][1][75] = -2, + [1][0][RTW89_KCC][0][75] = 127, + [1][0][RTW89_ACMA][1][75] = 127, + [1][0][RTW89_ACMA][0][75] = 127, + [1][0][RTW89_CHILE][1][75] = 127, + [1][0][RTW89_QATAR][1][75] = 127, + [1][0][RTW89_QATAR][0][75] = 127, + [1][0][RTW89_UK][1][75] = 127, + [1][0][RTW89_UK][0][75] = 127, + [1][0][RTW89_FCC][1][77] = -4, + [1][0][RTW89_FCC][2][77] = 68, + [1][0][RTW89_ETSI][1][77] = 127, + [1][0][RTW89_ETSI][0][77] = 127, + [1][0][RTW89_MKK][1][77] = 127, + [1][0][RTW89_MKK][0][77] = 127, + [1][0][RTW89_IC][1][77] = -4, + [1][0][RTW89_KCC][1][77] = -2, + [1][0][RTW89_KCC][0][77] = 127, + [1][0][RTW89_ACMA][1][77] = 127, + [1][0][RTW89_ACMA][0][77] = 127, + [1][0][RTW89_CHILE][1][77] = 127, + [1][0][RTW89_QATAR][1][77] = 127, + [1][0][RTW89_QATAR][0][77] = 127, + [1][0][RTW89_UK][1][77] = 127, + [1][0][RTW89_UK][0][77] = 127, + [1][0][RTW89_FCC][1][79] = -4, + [1][0][RTW89_FCC][2][79] = 68, + [1][0][RTW89_ETSI][1][79] = 127, + [1][0][RTW89_ETSI][0][79] = 127, + [1][0][RTW89_MKK][1][79] = 127, + [1][0][RTW89_MKK][0][79] = 127, + [1][0][RTW89_IC][1][79] = -4, + [1][0][RTW89_KCC][1][79] = -2, + [1][0][RTW89_KCC][0][79] = 127, + [1][0][RTW89_ACMA][1][79] = 127, + [1][0][RTW89_ACMA][0][79] = 127, + [1][0][RTW89_CHILE][1][79] = 127, + [1][0][RTW89_QATAR][1][79] = 127, + [1][0][RTW89_QATAR][0][79] = 127, + [1][0][RTW89_UK][1][79] = 127, + [1][0][RTW89_UK][0][79] = 127, + [1][0][RTW89_FCC][1][81] = -4, + [1][0][RTW89_FCC][2][81] = 68, + [1][0][RTW89_ETSI][1][81] = 127, + [1][0][RTW89_ETSI][0][81] = 127, + [1][0][RTW89_MKK][1][81] = 127, + [1][0][RTW89_MKK][0][81] = 127, + [1][0][RTW89_IC][1][81] = -4, + [1][0][RTW89_KCC][1][81] = -2, + [1][0][RTW89_KCC][0][81] = 127, + [1][0][RTW89_ACMA][1][81] = 127, + [1][0][RTW89_ACMA][0][81] = 127, + [1][0][RTW89_CHILE][1][81] = 127, + [1][0][RTW89_QATAR][1][81] = 127, + [1][0][RTW89_QATAR][0][81] = 127, + [1][0][RTW89_UK][1][81] = 127, + [1][0][RTW89_UK][0][81] = 127, + [1][0][RTW89_FCC][1][83] = -4, + [1][0][RTW89_FCC][2][83] = 68, + [1][0][RTW89_ETSI][1][83] = 127, + [1][0][RTW89_ETSI][0][83] = 127, + [1][0][RTW89_MKK][1][83] = 127, + [1][0][RTW89_MKK][0][83] = 127, + [1][0][RTW89_IC][1][83] = -4, + [1][0][RTW89_KCC][1][83] = -2, + [1][0][RTW89_KCC][0][83] = 127, + [1][0][RTW89_ACMA][1][83] = 127, + [1][0][RTW89_ACMA][0][83] = 127, + [1][0][RTW89_CHILE][1][83] = 127, + [1][0][RTW89_QATAR][1][83] = 127, + [1][0][RTW89_QATAR][0][83] = 127, + [1][0][RTW89_UK][1][83] = 127, + [1][0][RTW89_UK][0][83] = 127, + [1][0][RTW89_FCC][1][85] = -4, + [1][0][RTW89_FCC][2][85] = 68, + [1][0][RTW89_ETSI][1][85] = 127, + [1][0][RTW89_ETSI][0][85] = 127, + [1][0][RTW89_MKK][1][85] = 127, + [1][0][RTW89_MKK][0][85] = 127, + [1][0][RTW89_IC][1][85] = -4, + [1][0][RTW89_KCC][1][85] = -2, + [1][0][RTW89_KCC][0][85] = 127, + [1][0][RTW89_ACMA][1][85] = 127, + [1][0][RTW89_ACMA][0][85] = 127, + [1][0][RTW89_CHILE][1][85] = 127, + [1][0][RTW89_QATAR][1][85] = 127, + [1][0][RTW89_QATAR][0][85] = 127, + [1][0][RTW89_UK][1][85] = 127, + [1][0][RTW89_UK][0][85] = 127, + [1][0][RTW89_FCC][1][87] = -4, + [1][0][RTW89_FCC][2][87] = 127, + [1][0][RTW89_ETSI][1][87] = 127, + [1][0][RTW89_ETSI][0][87] = 127, + [1][0][RTW89_MKK][1][87] = 127, + [1][0][RTW89_MKK][0][87] = 127, + [1][0][RTW89_IC][1][87] = -4, + [1][0][RTW89_KCC][1][87] = -2, + [1][0][RTW89_KCC][0][87] = 127, + [1][0][RTW89_ACMA][1][87] = 127, + [1][0][RTW89_ACMA][0][87] = 127, + [1][0][RTW89_CHILE][1][87] = 127, + [1][0][RTW89_QATAR][1][87] = 127, + [1][0][RTW89_QATAR][0][87] = 127, + [1][0][RTW89_UK][1][87] = 127, + [1][0][RTW89_UK][0][87] = 127, + [1][0][RTW89_FCC][1][89] = -4, + [1][0][RTW89_FCC][2][89] = 127, + [1][0][RTW89_ETSI][1][89] = 127, + [1][0][RTW89_ETSI][0][89] = 127, + [1][0][RTW89_MKK][1][89] = 127, + [1][0][RTW89_MKK][0][89] = 127, + [1][0][RTW89_IC][1][89] = -4, + [1][0][RTW89_KCC][1][89] = -2, + [1][0][RTW89_KCC][0][89] = 127, + [1][0][RTW89_ACMA][1][89] = 127, + [1][0][RTW89_ACMA][0][89] = 127, + [1][0][RTW89_CHILE][1][89] = 127, + [1][0][RTW89_QATAR][1][89] = 127, + [1][0][RTW89_QATAR][0][89] = 127, + [1][0][RTW89_UK][1][89] = 127, + [1][0][RTW89_UK][0][89] = 127, + [1][0][RTW89_FCC][1][90] = -4, + [1][0][RTW89_FCC][2][90] = 127, + [1][0][RTW89_ETSI][1][90] = 127, + [1][0][RTW89_ETSI][0][90] = 127, + [1][0][RTW89_MKK][1][90] = 127, + [1][0][RTW89_MKK][0][90] = 127, + [1][0][RTW89_IC][1][90] = -4, + [1][0][RTW89_KCC][1][90] = -2, + [1][0][RTW89_KCC][0][90] = 127, + [1][0][RTW89_ACMA][1][90] = 127, + [1][0][RTW89_ACMA][0][90] = 127, + [1][0][RTW89_CHILE][1][90] = 127, + [1][0][RTW89_QATAR][1][90] = 127, + [1][0][RTW89_QATAR][0][90] = 127, + [1][0][RTW89_UK][1][90] = 127, + [1][0][RTW89_UK][0][90] = 127, + [1][0][RTW89_FCC][1][92] = -4, + [1][0][RTW89_FCC][2][92] = 127, + [1][0][RTW89_ETSI][1][92] = 127, + [1][0][RTW89_ETSI][0][92] = 127, + [1][0][RTW89_MKK][1][92] = 127, + [1][0][RTW89_MKK][0][92] = 127, + [1][0][RTW89_IC][1][92] = -4, + [1][0][RTW89_KCC][1][92] = -2, + [1][0][RTW89_KCC][0][92] = 127, + [1][0][RTW89_ACMA][1][92] = 127, + [1][0][RTW89_ACMA][0][92] = 127, + [1][0][RTW89_CHILE][1][92] = 127, + [1][0][RTW89_QATAR][1][92] = 127, + [1][0][RTW89_QATAR][0][92] = 127, + [1][0][RTW89_UK][1][92] = 127, + [1][0][RTW89_UK][0][92] = 127, + [1][0][RTW89_FCC][1][94] = -4, + [1][0][RTW89_FCC][2][94] = 127, + [1][0][RTW89_ETSI][1][94] = 127, + [1][0][RTW89_ETSI][0][94] = 127, + [1][0][RTW89_MKK][1][94] = 127, + [1][0][RTW89_MKK][0][94] = 127, + [1][0][RTW89_IC][1][94] = -4, + [1][0][RTW89_KCC][1][94] = -2, + [1][0][RTW89_KCC][0][94] = 127, + [1][0][RTW89_ACMA][1][94] = 127, + [1][0][RTW89_ACMA][0][94] = 127, + [1][0][RTW89_CHILE][1][94] = 127, + [1][0][RTW89_QATAR][1][94] = 127, + [1][0][RTW89_QATAR][0][94] = 127, + [1][0][RTW89_UK][1][94] = 127, + [1][0][RTW89_UK][0][94] = 127, + [1][0][RTW89_FCC][1][96] = -4, + [1][0][RTW89_FCC][2][96] = 127, + [1][0][RTW89_ETSI][1][96] = 127, + [1][0][RTW89_ETSI][0][96] = 127, + [1][0][RTW89_MKK][1][96] = 127, + [1][0][RTW89_MKK][0][96] = 127, + [1][0][RTW89_IC][1][96] = -4, + [1][0][RTW89_KCC][1][96] = -2, + [1][0][RTW89_KCC][0][96] = 127, + [1][0][RTW89_ACMA][1][96] = 127, + [1][0][RTW89_ACMA][0][96] = 127, + [1][0][RTW89_CHILE][1][96] = 127, + [1][0][RTW89_QATAR][1][96] = 127, + [1][0][RTW89_QATAR][0][96] = 127, + [1][0][RTW89_UK][1][96] = 127, + [1][0][RTW89_UK][0][96] = 127, + [1][0][RTW89_FCC][1][98] = -4, + [1][0][RTW89_FCC][2][98] = 127, + [1][0][RTW89_ETSI][1][98] = 127, + [1][0][RTW89_ETSI][0][98] = 127, + [1][0][RTW89_MKK][1][98] = 127, + [1][0][RTW89_MKK][0][98] = 127, + [1][0][RTW89_IC][1][98] = -4, + [1][0][RTW89_KCC][1][98] = -2, + [1][0][RTW89_KCC][0][98] = 127, + [1][0][RTW89_ACMA][1][98] = 127, + [1][0][RTW89_ACMA][0][98] = 127, + [1][0][RTW89_CHILE][1][98] = 127, + [1][0][RTW89_QATAR][1][98] = 127, + [1][0][RTW89_QATAR][0][98] = 127, + [1][0][RTW89_UK][1][98] = 127, + [1][0][RTW89_UK][0][98] = 127, + [1][0][RTW89_FCC][1][100] = -4, + [1][0][RTW89_FCC][2][100] = 127, + [1][0][RTW89_ETSI][1][100] = 127, + [1][0][RTW89_ETSI][0][100] = 127, + [1][0][RTW89_MKK][1][100] = 127, + [1][0][RTW89_MKK][0][100] = 127, + [1][0][RTW89_IC][1][100] = -4, + [1][0][RTW89_KCC][1][100] = -2, + [1][0][RTW89_KCC][0][100] = 127, + [1][0][RTW89_ACMA][1][100] = 127, + [1][0][RTW89_ACMA][0][100] = 127, + [1][0][RTW89_CHILE][1][100] = 127, + [1][0][RTW89_QATAR][1][100] = 127, + [1][0][RTW89_QATAR][0][100] = 127, + [1][0][RTW89_UK][1][100] = 127, + [1][0][RTW89_UK][0][100] = 127, + [1][0][RTW89_FCC][1][102] = -4, + [1][0][RTW89_FCC][2][102] = 127, + [1][0][RTW89_ETSI][1][102] = 127, + [1][0][RTW89_ETSI][0][102] = 127, + [1][0][RTW89_MKK][1][102] = 127, + [1][0][RTW89_MKK][0][102] = 127, + [1][0][RTW89_IC][1][102] = -4, + [1][0][RTW89_KCC][1][102] = -2, + [1][0][RTW89_KCC][0][102] = 127, + [1][0][RTW89_ACMA][1][102] = 127, + [1][0][RTW89_ACMA][0][102] = 127, + [1][0][RTW89_CHILE][1][102] = 127, + [1][0][RTW89_QATAR][1][102] = 127, + [1][0][RTW89_QATAR][0][102] = 127, + [1][0][RTW89_UK][1][102] = 127, + [1][0][RTW89_UK][0][102] = 127, + [1][0][RTW89_FCC][1][104] = -4, + [1][0][RTW89_FCC][2][104] = 127, + [1][0][RTW89_ETSI][1][104] = 127, + [1][0][RTW89_ETSI][0][104] = 127, + [1][0][RTW89_MKK][1][104] = 127, + [1][0][RTW89_MKK][0][104] = 127, + [1][0][RTW89_IC][1][104] = -4, + [1][0][RTW89_KCC][1][104] = -2, + [1][0][RTW89_KCC][0][104] = 127, + [1][0][RTW89_ACMA][1][104] = 127, + [1][0][RTW89_ACMA][0][104] = 127, + [1][0][RTW89_CHILE][1][104] = 127, + [1][0][RTW89_QATAR][1][104] = 127, + [1][0][RTW89_QATAR][0][104] = 127, + [1][0][RTW89_UK][1][104] = 127, + [1][0][RTW89_UK][0][104] = 127, + [1][0][RTW89_FCC][1][105] = -4, + [1][0][RTW89_FCC][2][105] = 127, + [1][0][RTW89_ETSI][1][105] = 127, + [1][0][RTW89_ETSI][0][105] = 127, + [1][0][RTW89_MKK][1][105] = 127, + [1][0][RTW89_MKK][0][105] = 127, + [1][0][RTW89_IC][1][105] = -4, + [1][0][RTW89_KCC][1][105] = -2, + [1][0][RTW89_KCC][0][105] = 127, + [1][0][RTW89_ACMA][1][105] = 127, + [1][0][RTW89_ACMA][0][105] = 127, + [1][0][RTW89_CHILE][1][105] = 127, + [1][0][RTW89_QATAR][1][105] = 127, + [1][0][RTW89_QATAR][0][105] = 127, + [1][0][RTW89_UK][1][105] = 127, + [1][0][RTW89_UK][0][105] = 127, + [1][0][RTW89_FCC][1][107] = 1, + [1][0][RTW89_FCC][2][107] = 127, + [1][0][RTW89_ETSI][1][107] = 127, + [1][0][RTW89_ETSI][0][107] = 127, + [1][0][RTW89_MKK][1][107] = 127, + [1][0][RTW89_MKK][0][107] = 127, + [1][0][RTW89_IC][1][107] = 1, + [1][0][RTW89_KCC][1][107] = -2, + [1][0][RTW89_KCC][0][107] = 127, + [1][0][RTW89_ACMA][1][107] = 127, + [1][0][RTW89_ACMA][0][107] = 127, + [1][0][RTW89_CHILE][1][107] = 127, + [1][0][RTW89_QATAR][1][107] = 127, + [1][0][RTW89_QATAR][0][107] = 127, + [1][0][RTW89_UK][1][107] = 127, + [1][0][RTW89_UK][0][107] = 127, + [1][0][RTW89_FCC][1][109] = 2, + [1][0][RTW89_FCC][2][109] = 127, + [1][0][RTW89_ETSI][1][109] = 127, + [1][0][RTW89_ETSI][0][109] = 127, + [1][0][RTW89_MKK][1][109] = 127, + [1][0][RTW89_MKK][0][109] = 127, + [1][0][RTW89_IC][1][109] = 2, + [1][0][RTW89_KCC][1][109] = 127, + [1][0][RTW89_KCC][0][109] = 127, + [1][0][RTW89_ACMA][1][109] = 127, + [1][0][RTW89_ACMA][0][109] = 127, + [1][0][RTW89_CHILE][1][109] = 127, + [1][0][RTW89_QATAR][1][109] = 127, + [1][0][RTW89_QATAR][0][109] = 127, + [1][0][RTW89_UK][1][109] = 127, + [1][0][RTW89_UK][0][109] = 127, + [1][0][RTW89_FCC][1][111] = 127, + [1][0][RTW89_FCC][2][111] = 127, + [1][0][RTW89_ETSI][1][111] = 127, + [1][0][RTW89_ETSI][0][111] = 127, + [1][0][RTW89_MKK][1][111] = 127, + [1][0][RTW89_MKK][0][111] = 127, + [1][0][RTW89_IC][1][111] = 127, + [1][0][RTW89_KCC][1][111] = 127, + [1][0][RTW89_KCC][0][111] = 127, + [1][0][RTW89_ACMA][1][111] = 127, + [1][0][RTW89_ACMA][0][111] = 127, + [1][0][RTW89_CHILE][1][111] = 127, + [1][0][RTW89_QATAR][1][111] = 127, + [1][0][RTW89_QATAR][0][111] = 127, + [1][0][RTW89_UK][1][111] = 127, + [1][0][RTW89_UK][0][111] = 127, + [1][0][RTW89_FCC][1][113] = 127, + [1][0][RTW89_FCC][2][113] = 127, + [1][0][RTW89_ETSI][1][113] = 127, + [1][0][RTW89_ETSI][0][113] = 127, + [1][0][RTW89_MKK][1][113] = 127, + [1][0][RTW89_MKK][0][113] = 127, + [1][0][RTW89_IC][1][113] = 127, + [1][0][RTW89_KCC][1][113] = 127, + [1][0][RTW89_KCC][0][113] = 127, + [1][0][RTW89_ACMA][1][113] = 127, + [1][0][RTW89_ACMA][0][113] = 127, + [1][0][RTW89_CHILE][1][113] = 127, + [1][0][RTW89_QATAR][1][113] = 127, + [1][0][RTW89_QATAR][0][113] = 127, + [1][0][RTW89_UK][1][113] = 127, + [1][0][RTW89_UK][0][113] = 127, + [1][0][RTW89_FCC][1][115] = 127, + [1][0][RTW89_FCC][2][115] = 127, + [1][0][RTW89_ETSI][1][115] = 127, + [1][0][RTW89_ETSI][0][115] = 127, + [1][0][RTW89_MKK][1][115] = 127, + [1][0][RTW89_MKK][0][115] = 127, + [1][0][RTW89_IC][1][115] = 127, + [1][0][RTW89_KCC][1][115] = 127, + [1][0][RTW89_KCC][0][115] = 127, + [1][0][RTW89_ACMA][1][115] = 127, + [1][0][RTW89_ACMA][0][115] = 127, + [1][0][RTW89_CHILE][1][115] = 127, + [1][0][RTW89_QATAR][1][115] = 127, + [1][0][RTW89_QATAR][0][115] = 127, + [1][0][RTW89_UK][1][115] = 127, + [1][0][RTW89_UK][0][115] = 127, + [1][0][RTW89_FCC][1][117] = 127, + [1][0][RTW89_FCC][2][117] = 127, + [1][0][RTW89_ETSI][1][117] = 127, + [1][0][RTW89_ETSI][0][117] = 127, + [1][0][RTW89_MKK][1][117] = 127, + [1][0][RTW89_MKK][0][117] = 127, + [1][0][RTW89_IC][1][117] = 127, + [1][0][RTW89_KCC][1][117] = 127, + [1][0][RTW89_KCC][0][117] = 127, + [1][0][RTW89_ACMA][1][117] = 127, + [1][0][RTW89_ACMA][0][117] = 127, + [1][0][RTW89_CHILE][1][117] = 127, + [1][0][RTW89_QATAR][1][117] = 127, + [1][0][RTW89_QATAR][0][117] = 127, + [1][0][RTW89_UK][1][117] = 127, + [1][0][RTW89_UK][0][117] = 127, + [1][0][RTW89_FCC][1][119] = 127, + [1][0][RTW89_FCC][2][119] = 127, + [1][0][RTW89_ETSI][1][119] = 127, + [1][0][RTW89_ETSI][0][119] = 127, + [1][0][RTW89_MKK][1][119] = 127, + [1][0][RTW89_MKK][0][119] = 127, + [1][0][RTW89_IC][1][119] = 127, + [1][0][RTW89_KCC][1][119] = 127, + [1][0][RTW89_KCC][0][119] = 127, + [1][0][RTW89_ACMA][1][119] = 127, + [1][0][RTW89_ACMA][0][119] = 127, + [1][0][RTW89_CHILE][1][119] = 127, + [1][0][RTW89_QATAR][1][119] = 127, + [1][0][RTW89_QATAR][0][119] = 127, + [1][0][RTW89_UK][1][119] = 127, + [1][0][RTW89_UK][0][119] = 127, + [1][1][RTW89_FCC][1][0] = -26, + [1][1][RTW89_FCC][2][0] = 44, + [1][1][RTW89_ETSI][1][0] = 32, + [1][1][RTW89_ETSI][0][0] = -6, + [1][1][RTW89_MKK][1][0] = 30, + [1][1][RTW89_MKK][0][0] = -10, + [1][1][RTW89_IC][1][0] = -26, + [1][1][RTW89_KCC][1][0] = -14, + [1][1][RTW89_KCC][0][0] = -14, + [1][1][RTW89_ACMA][1][0] = 32, + [1][1][RTW89_ACMA][0][0] = -6, + [1][1][RTW89_CHILE][1][0] = -26, + [1][1][RTW89_QATAR][1][0] = 32, + [1][1][RTW89_QATAR][0][0] = -6, + [1][1][RTW89_UK][1][0] = 32, + [1][1][RTW89_UK][0][0] = -6, + [1][1][RTW89_FCC][1][2] = -28, + [1][1][RTW89_FCC][2][2] = 44, + [1][1][RTW89_ETSI][1][2] = 32, + [1][1][RTW89_ETSI][0][2] = -6, + [1][1][RTW89_MKK][1][2] = 30, + [1][1][RTW89_MKK][0][2] = -10, + [1][1][RTW89_IC][1][2] = -28, + [1][1][RTW89_KCC][1][2] = -14, + [1][1][RTW89_KCC][0][2] = -14, + [1][1][RTW89_ACMA][1][2] = 32, + [1][1][RTW89_ACMA][0][2] = -6, + [1][1][RTW89_CHILE][1][2] = -28, + [1][1][RTW89_QATAR][1][2] = 32, + [1][1][RTW89_QATAR][0][2] = -6, + [1][1][RTW89_UK][1][2] = 32, + [1][1][RTW89_UK][0][2] = -6, + [1][1][RTW89_FCC][1][4] = -28, + [1][1][RTW89_FCC][2][4] = 44, + [1][1][RTW89_ETSI][1][4] = 32, + [1][1][RTW89_ETSI][0][4] = -6, + [1][1][RTW89_MKK][1][4] = 30, + [1][1][RTW89_MKK][0][4] = -10, + [1][1][RTW89_IC][1][4] = -28, + [1][1][RTW89_KCC][1][4] = -14, + [1][1][RTW89_KCC][0][4] = -14, + [1][1][RTW89_ACMA][1][4] = 32, + [1][1][RTW89_ACMA][0][4] = -6, + [1][1][RTW89_CHILE][1][4] = -28, + [1][1][RTW89_QATAR][1][4] = 32, + [1][1][RTW89_QATAR][0][4] = -6, + [1][1][RTW89_UK][1][4] = 32, + [1][1][RTW89_UK][0][4] = -6, + [1][1][RTW89_FCC][1][6] = -28, + [1][1][RTW89_FCC][2][6] = 44, + [1][1][RTW89_ETSI][1][6] = 32, + [1][1][RTW89_ETSI][0][6] = -6, + [1][1][RTW89_MKK][1][6] = 30, + [1][1][RTW89_MKK][0][6] = -10, + [1][1][RTW89_IC][1][6] = -28, + [1][1][RTW89_KCC][1][6] = -14, + [1][1][RTW89_KCC][0][6] = -14, + [1][1][RTW89_ACMA][1][6] = 32, + [1][1][RTW89_ACMA][0][6] = -6, + [1][1][RTW89_CHILE][1][6] = -28, + [1][1][RTW89_QATAR][1][6] = 32, + [1][1][RTW89_QATAR][0][6] = -6, + [1][1][RTW89_UK][1][6] = 32, + [1][1][RTW89_UK][0][6] = -6, + [1][1][RTW89_FCC][1][8] = -28, + [1][1][RTW89_FCC][2][8] = 44, + [1][1][RTW89_ETSI][1][8] = 32, + [1][1][RTW89_ETSI][0][8] = -6, + [1][1][RTW89_MKK][1][8] = 30, + [1][1][RTW89_MKK][0][8] = -10, + [1][1][RTW89_IC][1][8] = -28, + [1][1][RTW89_KCC][1][8] = -14, + [1][1][RTW89_KCC][0][8] = -14, + [1][1][RTW89_ACMA][1][8] = 32, + [1][1][RTW89_ACMA][0][8] = -6, + [1][1][RTW89_CHILE][1][8] = -28, + [1][1][RTW89_QATAR][1][8] = 32, + [1][1][RTW89_QATAR][0][8] = -6, + [1][1][RTW89_UK][1][8] = 32, + [1][1][RTW89_UK][0][8] = -6, + [1][1][RTW89_FCC][1][10] = -28, + [1][1][RTW89_FCC][2][10] = 44, + [1][1][RTW89_ETSI][1][10] = 32, + [1][1][RTW89_ETSI][0][10] = -6, + [1][1][RTW89_MKK][1][10] = 30, + [1][1][RTW89_MKK][0][10] = -10, + [1][1][RTW89_IC][1][10] = -28, + [1][1][RTW89_KCC][1][10] = -14, + [1][1][RTW89_KCC][0][10] = -14, + [1][1][RTW89_ACMA][1][10] = 32, + [1][1][RTW89_ACMA][0][10] = -6, + [1][1][RTW89_CHILE][1][10] = -28, + [1][1][RTW89_QATAR][1][10] = 32, + [1][1][RTW89_QATAR][0][10] = -6, + [1][1][RTW89_UK][1][10] = 32, + [1][1][RTW89_UK][0][10] = -6, + [1][1][RTW89_FCC][1][12] = -28, + [1][1][RTW89_FCC][2][12] = 44, + [1][1][RTW89_ETSI][1][12] = 32, + [1][1][RTW89_ETSI][0][12] = -6, + [1][1][RTW89_MKK][1][12] = 30, + [1][1][RTW89_MKK][0][12] = -10, + [1][1][RTW89_IC][1][12] = -28, + [1][1][RTW89_KCC][1][12] = -14, + [1][1][RTW89_KCC][0][12] = -14, + [1][1][RTW89_ACMA][1][12] = 32, + [1][1][RTW89_ACMA][0][12] = -6, + [1][1][RTW89_CHILE][1][12] = -28, + [1][1][RTW89_QATAR][1][12] = 32, + [1][1][RTW89_QATAR][0][12] = -6, + [1][1][RTW89_UK][1][12] = 32, + [1][1][RTW89_UK][0][12] = -6, + [1][1][RTW89_FCC][1][14] = -28, + [1][1][RTW89_FCC][2][14] = 44, + [1][1][RTW89_ETSI][1][14] = 32, + [1][1][RTW89_ETSI][0][14] = -6, + [1][1][RTW89_MKK][1][14] = 30, + [1][1][RTW89_MKK][0][14] = -10, + [1][1][RTW89_IC][1][14] = -28, + [1][1][RTW89_KCC][1][14] = -14, + [1][1][RTW89_KCC][0][14] = -14, + [1][1][RTW89_ACMA][1][14] = 32, + [1][1][RTW89_ACMA][0][14] = -6, + [1][1][RTW89_CHILE][1][14] = -28, + [1][1][RTW89_QATAR][1][14] = 32, + [1][1][RTW89_QATAR][0][14] = -6, + [1][1][RTW89_UK][1][14] = 32, + [1][1][RTW89_UK][0][14] = -6, + [1][1][RTW89_FCC][1][15] = -28, + [1][1][RTW89_FCC][2][15] = 44, + [1][1][RTW89_ETSI][1][15] = 32, + [1][1][RTW89_ETSI][0][15] = -6, + [1][1][RTW89_MKK][1][15] = 30, + [1][1][RTW89_MKK][0][15] = -10, + [1][1][RTW89_IC][1][15] = -28, + [1][1][RTW89_KCC][1][15] = -14, + [1][1][RTW89_KCC][0][15] = -14, + [1][1][RTW89_ACMA][1][15] = 32, + [1][1][RTW89_ACMA][0][15] = -6, + [1][1][RTW89_CHILE][1][15] = -28, + [1][1][RTW89_QATAR][1][15] = 32, + [1][1][RTW89_QATAR][0][15] = -6, + [1][1][RTW89_UK][1][15] = 32, + [1][1][RTW89_UK][0][15] = -6, + [1][1][RTW89_FCC][1][17] = -28, + [1][1][RTW89_FCC][2][17] = 44, + [1][1][RTW89_ETSI][1][17] = 32, + [1][1][RTW89_ETSI][0][17] = -6, + [1][1][RTW89_MKK][1][17] = 30, + [1][1][RTW89_MKK][0][17] = -10, + [1][1][RTW89_IC][1][17] = -28, + [1][1][RTW89_KCC][1][17] = -14, + [1][1][RTW89_KCC][0][17] = -14, + [1][1][RTW89_ACMA][1][17] = 32, + [1][1][RTW89_ACMA][0][17] = -6, + [1][1][RTW89_CHILE][1][17] = -28, + [1][1][RTW89_QATAR][1][17] = 32, + [1][1][RTW89_QATAR][0][17] = -6, + [1][1][RTW89_UK][1][17] = 32, + [1][1][RTW89_UK][0][17] = -6, + [1][1][RTW89_FCC][1][19] = -28, + [1][1][RTW89_FCC][2][19] = 44, + [1][1][RTW89_ETSI][1][19] = 32, + [1][1][RTW89_ETSI][0][19] = -6, + [1][1][RTW89_MKK][1][19] = 30, + [1][1][RTW89_MKK][0][19] = -10, + [1][1][RTW89_IC][1][19] = -28, + [1][1][RTW89_KCC][1][19] = -14, + [1][1][RTW89_KCC][0][19] = -14, + [1][1][RTW89_ACMA][1][19] = 32, + [1][1][RTW89_ACMA][0][19] = -6, + [1][1][RTW89_CHILE][1][19] = -28, + [1][1][RTW89_QATAR][1][19] = 32, + [1][1][RTW89_QATAR][0][19] = -6, + [1][1][RTW89_UK][1][19] = 32, + [1][1][RTW89_UK][0][19] = -6, + [1][1][RTW89_FCC][1][21] = -28, + [1][1][RTW89_FCC][2][21] = 44, + [1][1][RTW89_ETSI][1][21] = 32, + [1][1][RTW89_ETSI][0][21] = -6, + [1][1][RTW89_MKK][1][21] = 30, + [1][1][RTW89_MKK][0][21] = -10, + [1][1][RTW89_IC][1][21] = -28, + [1][1][RTW89_KCC][1][21] = -14, + [1][1][RTW89_KCC][0][21] = -14, + [1][1][RTW89_ACMA][1][21] = 32, + [1][1][RTW89_ACMA][0][21] = -6, + [1][1][RTW89_CHILE][1][21] = -28, + [1][1][RTW89_QATAR][1][21] = 32, + [1][1][RTW89_QATAR][0][21] = -6, + [1][1][RTW89_UK][1][21] = 32, + [1][1][RTW89_UK][0][21] = -6, + [1][1][RTW89_FCC][1][23] = -28, + [1][1][RTW89_FCC][2][23] = 44, + [1][1][RTW89_ETSI][1][23] = 32, + [1][1][RTW89_ETSI][0][23] = -6, + [1][1][RTW89_MKK][1][23] = 32, + [1][1][RTW89_MKK][0][23] = -10, + [1][1][RTW89_IC][1][23] = -28, + [1][1][RTW89_KCC][1][23] = -14, + [1][1][RTW89_KCC][0][23] = -14, + [1][1][RTW89_ACMA][1][23] = 32, + [1][1][RTW89_ACMA][0][23] = -6, + [1][1][RTW89_CHILE][1][23] = -28, + [1][1][RTW89_QATAR][1][23] = 32, + [1][1][RTW89_QATAR][0][23] = -6, + [1][1][RTW89_UK][1][23] = 32, + [1][1][RTW89_UK][0][23] = -6, + [1][1][RTW89_FCC][1][25] = -28, + [1][1][RTW89_FCC][2][25] = 44, + [1][1][RTW89_ETSI][1][25] = 32, + [1][1][RTW89_ETSI][0][25] = -6, + [1][1][RTW89_MKK][1][25] = 32, + [1][1][RTW89_MKK][0][25] = -10, + [1][1][RTW89_IC][1][25] = -28, + [1][1][RTW89_KCC][1][25] = -14, + [1][1][RTW89_KCC][0][25] = -14, + [1][1][RTW89_ACMA][1][25] = 32, + [1][1][RTW89_ACMA][0][25] = -6, + [1][1][RTW89_CHILE][1][25] = -28, + [1][1][RTW89_QATAR][1][25] = 32, + [1][1][RTW89_QATAR][0][25] = -6, + [1][1][RTW89_UK][1][25] = 32, + [1][1][RTW89_UK][0][25] = -6, + [1][1][RTW89_FCC][1][27] = -28, + [1][1][RTW89_FCC][2][27] = 44, + [1][1][RTW89_ETSI][1][27] = 32, + [1][1][RTW89_ETSI][0][27] = -6, + [1][1][RTW89_MKK][1][27] = 32, + [1][1][RTW89_MKK][0][27] = -10, + [1][1][RTW89_IC][1][27] = -28, + [1][1][RTW89_KCC][1][27] = -14, + [1][1][RTW89_KCC][0][27] = -14, + [1][1][RTW89_ACMA][1][27] = 32, + [1][1][RTW89_ACMA][0][27] = -6, + [1][1][RTW89_CHILE][1][27] = -28, + [1][1][RTW89_QATAR][1][27] = 32, + [1][1][RTW89_QATAR][0][27] = -6, + [1][1][RTW89_UK][1][27] = 32, + [1][1][RTW89_UK][0][27] = -6, + [1][1][RTW89_FCC][1][29] = -28, + [1][1][RTW89_FCC][2][29] = 44, + [1][1][RTW89_ETSI][1][29] = 32, + [1][1][RTW89_ETSI][0][29] = -6, + [1][1][RTW89_MKK][1][29] = 32, + [1][1][RTW89_MKK][0][29] = -10, + [1][1][RTW89_IC][1][29] = -28, + [1][1][RTW89_KCC][1][29] = -14, + [1][1][RTW89_KCC][0][29] = -14, + [1][1][RTW89_ACMA][1][29] = 32, + [1][1][RTW89_ACMA][0][29] = -6, + [1][1][RTW89_CHILE][1][29] = -28, + [1][1][RTW89_QATAR][1][29] = 32, + [1][1][RTW89_QATAR][0][29] = -6, + [1][1][RTW89_UK][1][29] = 32, + [1][1][RTW89_UK][0][29] = -6, + [1][1][RTW89_FCC][1][30] = -28, + [1][1][RTW89_FCC][2][30] = 44, + [1][1][RTW89_ETSI][1][30] = 32, + [1][1][RTW89_ETSI][0][30] = -6, + [1][1][RTW89_MKK][1][30] = 32, + [1][1][RTW89_MKK][0][30] = -10, + [1][1][RTW89_IC][1][30] = -28, + [1][1][RTW89_KCC][1][30] = -14, + [1][1][RTW89_KCC][0][30] = -14, + [1][1][RTW89_ACMA][1][30] = 32, + [1][1][RTW89_ACMA][0][30] = -6, + [1][1][RTW89_CHILE][1][30] = -28, + [1][1][RTW89_QATAR][1][30] = 32, + [1][1][RTW89_QATAR][0][30] = -6, + [1][1][RTW89_UK][1][30] = 32, + [1][1][RTW89_UK][0][30] = -6, + [1][1][RTW89_FCC][1][32] = -28, + [1][1][RTW89_FCC][2][32] = 44, + [1][1][RTW89_ETSI][1][32] = 32, + [1][1][RTW89_ETSI][0][32] = -6, + [1][1][RTW89_MKK][1][32] = 32, + [1][1][RTW89_MKK][0][32] = -10, + [1][1][RTW89_IC][1][32] = -28, + [1][1][RTW89_KCC][1][32] = -14, + [1][1][RTW89_KCC][0][32] = -14, + [1][1][RTW89_ACMA][1][32] = 32, + [1][1][RTW89_ACMA][0][32] = -6, + [1][1][RTW89_CHILE][1][32] = -28, + [1][1][RTW89_QATAR][1][32] = 32, + [1][1][RTW89_QATAR][0][32] = -6, + [1][1][RTW89_UK][1][32] = 32, + [1][1][RTW89_UK][0][32] = -6, + [1][1][RTW89_FCC][1][34] = -28, + [1][1][RTW89_FCC][2][34] = 44, + [1][1][RTW89_ETSI][1][34] = 32, + [1][1][RTW89_ETSI][0][34] = -6, + [1][1][RTW89_MKK][1][34] = 32, + [1][1][RTW89_MKK][0][34] = -10, + [1][1][RTW89_IC][1][34] = -28, + [1][1][RTW89_KCC][1][34] = -14, + [1][1][RTW89_KCC][0][34] = -14, + [1][1][RTW89_ACMA][1][34] = 32, + [1][1][RTW89_ACMA][0][34] = -6, + [1][1][RTW89_CHILE][1][34] = -28, + [1][1][RTW89_QATAR][1][34] = 32, + [1][1][RTW89_QATAR][0][34] = -6, + [1][1][RTW89_UK][1][34] = 32, + [1][1][RTW89_UK][0][34] = -6, + [1][1][RTW89_FCC][1][36] = -28, + [1][1][RTW89_FCC][2][36] = 44, + [1][1][RTW89_ETSI][1][36] = 32, + [1][1][RTW89_ETSI][0][36] = -6, + [1][1][RTW89_MKK][1][36] = 32, + [1][1][RTW89_MKK][0][36] = -10, + [1][1][RTW89_IC][1][36] = -28, + [1][1][RTW89_KCC][1][36] = -14, + [1][1][RTW89_KCC][0][36] = -14, + [1][1][RTW89_ACMA][1][36] = 32, + [1][1][RTW89_ACMA][0][36] = -6, + [1][1][RTW89_CHILE][1][36] = -28, + [1][1][RTW89_QATAR][1][36] = 32, + [1][1][RTW89_QATAR][0][36] = -6, + [1][1][RTW89_UK][1][36] = 32, + [1][1][RTW89_UK][0][36] = -6, + [1][1][RTW89_FCC][1][38] = -28, + [1][1][RTW89_FCC][2][38] = 44, + [1][1][RTW89_ETSI][1][38] = 32, + [1][1][RTW89_ETSI][0][38] = -6, + [1][1][RTW89_MKK][1][38] = 32, + [1][1][RTW89_MKK][0][38] = -10, + [1][1][RTW89_IC][1][38] = -28, + [1][1][RTW89_KCC][1][38] = -14, + [1][1][RTW89_KCC][0][38] = -14, + [1][1][RTW89_ACMA][1][38] = 32, + [1][1][RTW89_ACMA][0][38] = -6, + [1][1][RTW89_CHILE][1][38] = -28, + [1][1][RTW89_QATAR][1][38] = 32, + [1][1][RTW89_QATAR][0][38] = -6, + [1][1][RTW89_UK][1][38] = 32, + [1][1][RTW89_UK][0][38] = -6, + [1][1][RTW89_FCC][1][40] = -28, + [1][1][RTW89_FCC][2][40] = 44, + [1][1][RTW89_ETSI][1][40] = 32, + [1][1][RTW89_ETSI][0][40] = -6, + [1][1][RTW89_MKK][1][40] = 32, + [1][1][RTW89_MKK][0][40] = -10, + [1][1][RTW89_IC][1][40] = -28, + [1][1][RTW89_KCC][1][40] = -14, + [1][1][RTW89_KCC][0][40] = -14, + [1][1][RTW89_ACMA][1][40] = 32, + [1][1][RTW89_ACMA][0][40] = -6, + [1][1][RTW89_CHILE][1][40] = -28, + [1][1][RTW89_QATAR][1][40] = 32, + [1][1][RTW89_QATAR][0][40] = -6, + [1][1][RTW89_UK][1][40] = 32, + [1][1][RTW89_UK][0][40] = -6, + [1][1][RTW89_FCC][1][42] = -28, + [1][1][RTW89_FCC][2][42] = 44, + [1][1][RTW89_ETSI][1][42] = 32, + [1][1][RTW89_ETSI][0][42] = -6, + [1][1][RTW89_MKK][1][42] = 32, + [1][1][RTW89_MKK][0][42] = -10, + [1][1][RTW89_IC][1][42] = -28, + [1][1][RTW89_KCC][1][42] = -14, + [1][1][RTW89_KCC][0][42] = -14, + [1][1][RTW89_ACMA][1][42] = 32, + [1][1][RTW89_ACMA][0][42] = -6, + [1][1][RTW89_CHILE][1][42] = -28, + [1][1][RTW89_QATAR][1][42] = 32, + [1][1][RTW89_QATAR][0][42] = -6, + [1][1][RTW89_UK][1][42] = 32, + [1][1][RTW89_UK][0][42] = -6, + [1][1][RTW89_FCC][1][44] = -28, + [1][1][RTW89_FCC][2][44] = 44, + [1][1][RTW89_ETSI][1][44] = 34, + [1][1][RTW89_ETSI][0][44] = -4, + [1][1][RTW89_MKK][1][44] = 4, + [1][1][RTW89_MKK][0][44] = -8, + [1][1][RTW89_IC][1][44] = -28, + [1][1][RTW89_KCC][1][44] = -14, + [1][1][RTW89_KCC][0][44] = -14, + [1][1][RTW89_ACMA][1][44] = 34, + [1][1][RTW89_ACMA][0][44] = -4, + [1][1][RTW89_CHILE][1][44] = -28, + [1][1][RTW89_QATAR][1][44] = 34, + [1][1][RTW89_QATAR][0][44] = -4, + [1][1][RTW89_UK][1][44] = 34, + [1][1][RTW89_UK][0][44] = -4, + [1][1][RTW89_FCC][1][45] = -26, + [1][1][RTW89_FCC][2][45] = 127, + [1][1][RTW89_ETSI][1][45] = 127, + [1][1][RTW89_ETSI][0][45] = 127, + [1][1][RTW89_MKK][1][45] = 127, + [1][1][RTW89_MKK][0][45] = 127, + [1][1][RTW89_IC][1][45] = -26, + [1][1][RTW89_KCC][1][45] = -14, + [1][1][RTW89_KCC][0][45] = 127, + [1][1][RTW89_ACMA][1][45] = 127, + [1][1][RTW89_ACMA][0][45] = 127, + [1][1][RTW89_CHILE][1][45] = 127, + [1][1][RTW89_QATAR][1][45] = 127, + [1][1][RTW89_QATAR][0][45] = 127, + [1][1][RTW89_UK][1][45] = 127, + [1][1][RTW89_UK][0][45] = 127, + [1][1][RTW89_FCC][1][47] = -28, + [1][1][RTW89_FCC][2][47] = 127, + [1][1][RTW89_ETSI][1][47] = 127, + [1][1][RTW89_ETSI][0][47] = 127, + [1][1][RTW89_MKK][1][47] = 127, + [1][1][RTW89_MKK][0][47] = 127, + [1][1][RTW89_IC][1][47] = -28, + [1][1][RTW89_KCC][1][47] = -14, + [1][1][RTW89_KCC][0][47] = 127, + [1][1][RTW89_ACMA][1][47] = 127, + [1][1][RTW89_ACMA][0][47] = 127, + [1][1][RTW89_CHILE][1][47] = 127, + [1][1][RTW89_QATAR][1][47] = 127, + [1][1][RTW89_QATAR][0][47] = 127, + [1][1][RTW89_UK][1][47] = 127, + [1][1][RTW89_UK][0][47] = 127, + [1][1][RTW89_FCC][1][49] = -28, + [1][1][RTW89_FCC][2][49] = 127, + [1][1][RTW89_ETSI][1][49] = 127, + [1][1][RTW89_ETSI][0][49] = 127, + [1][1][RTW89_MKK][1][49] = 127, + [1][1][RTW89_MKK][0][49] = 127, + [1][1][RTW89_IC][1][49] = -28, + [1][1][RTW89_KCC][1][49] = -14, + [1][1][RTW89_KCC][0][49] = 127, + [1][1][RTW89_ACMA][1][49] = 127, + [1][1][RTW89_ACMA][0][49] = 127, + [1][1][RTW89_CHILE][1][49] = 127, + [1][1][RTW89_QATAR][1][49] = 127, + [1][1][RTW89_QATAR][0][49] = 127, + [1][1][RTW89_UK][1][49] = 127, + [1][1][RTW89_UK][0][49] = 127, + [1][1][RTW89_FCC][1][51] = -28, + [1][1][RTW89_FCC][2][51] = 127, + [1][1][RTW89_ETSI][1][51] = 127, + [1][1][RTW89_ETSI][0][51] = 127, + [1][1][RTW89_MKK][1][51] = 127, + [1][1][RTW89_MKK][0][51] = 127, + [1][1][RTW89_IC][1][51] = -28, + [1][1][RTW89_KCC][1][51] = -14, + [1][1][RTW89_KCC][0][51] = 127, + [1][1][RTW89_ACMA][1][51] = 127, + [1][1][RTW89_ACMA][0][51] = 127, + [1][1][RTW89_CHILE][1][51] = 127, + [1][1][RTW89_QATAR][1][51] = 127, + [1][1][RTW89_QATAR][0][51] = 127, + [1][1][RTW89_UK][1][51] = 127, + [1][1][RTW89_UK][0][51] = 127, + [1][1][RTW89_FCC][1][53] = -26, + [1][1][RTW89_FCC][2][53] = 127, + [1][1][RTW89_ETSI][1][53] = 127, + [1][1][RTW89_ETSI][0][53] = 127, + [1][1][RTW89_MKK][1][53] = 127, + [1][1][RTW89_MKK][0][53] = 127, + [1][1][RTW89_IC][1][53] = -26, + [1][1][RTW89_KCC][1][53] = -14, + [1][1][RTW89_KCC][0][53] = 127, + [1][1][RTW89_ACMA][1][53] = 127, + [1][1][RTW89_ACMA][0][53] = 127, + [1][1][RTW89_CHILE][1][53] = 127, + [1][1][RTW89_QATAR][1][53] = 127, + [1][1][RTW89_QATAR][0][53] = 127, + [1][1][RTW89_UK][1][53] = 127, + [1][1][RTW89_UK][0][53] = 127, + [1][1][RTW89_FCC][1][55] = -28, + [1][1][RTW89_FCC][2][55] = 44, + [1][1][RTW89_ETSI][1][55] = 127, + [1][1][RTW89_ETSI][0][55] = 127, + [1][1][RTW89_MKK][1][55] = 127, + [1][1][RTW89_MKK][0][55] = 127, + [1][1][RTW89_IC][1][55] = -28, + [1][1][RTW89_KCC][1][55] = -14, + [1][1][RTW89_KCC][0][55] = 127, + [1][1][RTW89_ACMA][1][55] = 127, + [1][1][RTW89_ACMA][0][55] = 127, + [1][1][RTW89_CHILE][1][55] = 127, + [1][1][RTW89_QATAR][1][55] = 127, + [1][1][RTW89_QATAR][0][55] = 127, + [1][1][RTW89_UK][1][55] = 127, + [1][1][RTW89_UK][0][55] = 127, + [1][1][RTW89_FCC][1][57] = -28, + [1][1][RTW89_FCC][2][57] = 44, + [1][1][RTW89_ETSI][1][57] = 127, + [1][1][RTW89_ETSI][0][57] = 127, + [1][1][RTW89_MKK][1][57] = 127, + [1][1][RTW89_MKK][0][57] = 127, + [1][1][RTW89_IC][1][57] = -28, + [1][1][RTW89_KCC][1][57] = -14, + [1][1][RTW89_KCC][0][57] = 127, + [1][1][RTW89_ACMA][1][57] = 127, + [1][1][RTW89_ACMA][0][57] = 127, + [1][1][RTW89_CHILE][1][57] = 127, + [1][1][RTW89_QATAR][1][57] = 127, + [1][1][RTW89_QATAR][0][57] = 127, + [1][1][RTW89_UK][1][57] = 127, + [1][1][RTW89_UK][0][57] = 127, + [1][1][RTW89_FCC][1][59] = -28, + [1][1][RTW89_FCC][2][59] = 44, + [1][1][RTW89_ETSI][1][59] = 127, + [1][1][RTW89_ETSI][0][59] = 127, + [1][1][RTW89_MKK][1][59] = 127, + [1][1][RTW89_MKK][0][59] = 127, + [1][1][RTW89_IC][1][59] = -28, + [1][1][RTW89_KCC][1][59] = -14, + [1][1][RTW89_KCC][0][59] = 127, + [1][1][RTW89_ACMA][1][59] = 127, + [1][1][RTW89_ACMA][0][59] = 127, + [1][1][RTW89_CHILE][1][59] = 127, + [1][1][RTW89_QATAR][1][59] = 127, + [1][1][RTW89_QATAR][0][59] = 127, + [1][1][RTW89_UK][1][59] = 127, + [1][1][RTW89_UK][0][59] = 127, + [1][1][RTW89_FCC][1][60] = -28, + [1][1][RTW89_FCC][2][60] = 44, + [1][1][RTW89_ETSI][1][60] = 127, + [1][1][RTW89_ETSI][0][60] = 127, + [1][1][RTW89_MKK][1][60] = 127, + [1][1][RTW89_MKK][0][60] = 127, + [1][1][RTW89_IC][1][60] = -28, + [1][1][RTW89_KCC][1][60] = -14, + [1][1][RTW89_KCC][0][60] = 127, + [1][1][RTW89_ACMA][1][60] = 127, + [1][1][RTW89_ACMA][0][60] = 127, + [1][1][RTW89_CHILE][1][60] = 127, + [1][1][RTW89_QATAR][1][60] = 127, + [1][1][RTW89_QATAR][0][60] = 127, + [1][1][RTW89_UK][1][60] = 127, + [1][1][RTW89_UK][0][60] = 127, + [1][1][RTW89_FCC][1][62] = -28, + [1][1][RTW89_FCC][2][62] = 44, + [1][1][RTW89_ETSI][1][62] = 127, + [1][1][RTW89_ETSI][0][62] = 127, + [1][1][RTW89_MKK][1][62] = 127, + [1][1][RTW89_MKK][0][62] = 127, + [1][1][RTW89_IC][1][62] = -28, + [1][1][RTW89_KCC][1][62] = -14, + [1][1][RTW89_KCC][0][62] = 127, + [1][1][RTW89_ACMA][1][62] = 127, + [1][1][RTW89_ACMA][0][62] = 127, + [1][1][RTW89_CHILE][1][62] = 127, + [1][1][RTW89_QATAR][1][62] = 127, + [1][1][RTW89_QATAR][0][62] = 127, + [1][1][RTW89_UK][1][62] = 127, + [1][1][RTW89_UK][0][62] = 127, + [1][1][RTW89_FCC][1][64] = -28, + [1][1][RTW89_FCC][2][64] = 44, + [1][1][RTW89_ETSI][1][64] = 127, + [1][1][RTW89_ETSI][0][64] = 127, + [1][1][RTW89_MKK][1][64] = 127, + [1][1][RTW89_MKK][0][64] = 127, + [1][1][RTW89_IC][1][64] = -28, + [1][1][RTW89_KCC][1][64] = -14, + [1][1][RTW89_KCC][0][64] = 127, + [1][1][RTW89_ACMA][1][64] = 127, + [1][1][RTW89_ACMA][0][64] = 127, + [1][1][RTW89_CHILE][1][64] = 127, + [1][1][RTW89_QATAR][1][64] = 127, + [1][1][RTW89_QATAR][0][64] = 127, + [1][1][RTW89_UK][1][64] = 127, + [1][1][RTW89_UK][0][64] = 127, + [1][1][RTW89_FCC][1][66] = -28, + [1][1][RTW89_FCC][2][66] = 44, + [1][1][RTW89_ETSI][1][66] = 127, + [1][1][RTW89_ETSI][0][66] = 127, + [1][1][RTW89_MKK][1][66] = 127, + [1][1][RTW89_MKK][0][66] = 127, + [1][1][RTW89_IC][1][66] = -28, + [1][1][RTW89_KCC][1][66] = -14, + [1][1][RTW89_KCC][0][66] = 127, + [1][1][RTW89_ACMA][1][66] = 127, + [1][1][RTW89_ACMA][0][66] = 127, + [1][1][RTW89_CHILE][1][66] = 127, + [1][1][RTW89_QATAR][1][66] = 127, + [1][1][RTW89_QATAR][0][66] = 127, + [1][1][RTW89_UK][1][66] = 127, + [1][1][RTW89_UK][0][66] = 127, + [1][1][RTW89_FCC][1][68] = -28, + [1][1][RTW89_FCC][2][68] = 44, + [1][1][RTW89_ETSI][1][68] = 127, + [1][1][RTW89_ETSI][0][68] = 127, + [1][1][RTW89_MKK][1][68] = 127, + [1][1][RTW89_MKK][0][68] = 127, + [1][1][RTW89_IC][1][68] = -28, + [1][1][RTW89_KCC][1][68] = -14, + [1][1][RTW89_KCC][0][68] = 127, + [1][1][RTW89_ACMA][1][68] = 127, + [1][1][RTW89_ACMA][0][68] = 127, + [1][1][RTW89_CHILE][1][68] = 127, + [1][1][RTW89_QATAR][1][68] = 127, + [1][1][RTW89_QATAR][0][68] = 127, + [1][1][RTW89_UK][1][68] = 127, + [1][1][RTW89_UK][0][68] = 127, + [1][1][RTW89_FCC][1][70] = -26, + [1][1][RTW89_FCC][2][70] = 44, + [1][1][RTW89_ETSI][1][70] = 127, + [1][1][RTW89_ETSI][0][70] = 127, + [1][1][RTW89_MKK][1][70] = 127, + [1][1][RTW89_MKK][0][70] = 127, + [1][1][RTW89_IC][1][70] = -26, + [1][1][RTW89_KCC][1][70] = -14, + [1][1][RTW89_KCC][0][70] = 127, + [1][1][RTW89_ACMA][1][70] = 127, + [1][1][RTW89_ACMA][0][70] = 127, + [1][1][RTW89_CHILE][1][70] = 127, + [1][1][RTW89_QATAR][1][70] = 127, + [1][1][RTW89_QATAR][0][70] = 127, + [1][1][RTW89_UK][1][70] = 127, + [1][1][RTW89_UK][0][70] = 127, + [1][1][RTW89_FCC][1][72] = -28, + [1][1][RTW89_FCC][2][72] = 44, + [1][1][RTW89_ETSI][1][72] = 127, + [1][1][RTW89_ETSI][0][72] = 127, + [1][1][RTW89_MKK][1][72] = 127, + [1][1][RTW89_MKK][0][72] = 127, + [1][1][RTW89_IC][1][72] = -28, + [1][1][RTW89_KCC][1][72] = -14, + [1][1][RTW89_KCC][0][72] = 127, + [1][1][RTW89_ACMA][1][72] = 127, + [1][1][RTW89_ACMA][0][72] = 127, + [1][1][RTW89_CHILE][1][72] = 127, + [1][1][RTW89_QATAR][1][72] = 127, + [1][1][RTW89_QATAR][0][72] = 127, + [1][1][RTW89_UK][1][72] = 127, + [1][1][RTW89_UK][0][72] = 127, + [1][1][RTW89_FCC][1][74] = -28, + [1][1][RTW89_FCC][2][74] = 44, + [1][1][RTW89_ETSI][1][74] = 127, + [1][1][RTW89_ETSI][0][74] = 127, + [1][1][RTW89_MKK][1][74] = 127, + [1][1][RTW89_MKK][0][74] = 127, + [1][1][RTW89_IC][1][74] = -28, + [1][1][RTW89_KCC][1][74] = -14, + [1][1][RTW89_KCC][0][74] = 127, + [1][1][RTW89_ACMA][1][74] = 127, + [1][1][RTW89_ACMA][0][74] = 127, + [1][1][RTW89_CHILE][1][74] = 127, + [1][1][RTW89_QATAR][1][74] = 127, + [1][1][RTW89_QATAR][0][74] = 127, + [1][1][RTW89_UK][1][74] = 127, + [1][1][RTW89_UK][0][74] = 127, + [1][1][RTW89_FCC][1][75] = -28, + [1][1][RTW89_FCC][2][75] = 44, + [1][1][RTW89_ETSI][1][75] = 127, + [1][1][RTW89_ETSI][0][75] = 127, + [1][1][RTW89_MKK][1][75] = 127, + [1][1][RTW89_MKK][0][75] = 127, + [1][1][RTW89_IC][1][75] = -28, + [1][1][RTW89_KCC][1][75] = -14, + [1][1][RTW89_KCC][0][75] = 127, + [1][1][RTW89_ACMA][1][75] = 127, + [1][1][RTW89_ACMA][0][75] = 127, + [1][1][RTW89_CHILE][1][75] = 127, + [1][1][RTW89_QATAR][1][75] = 127, + [1][1][RTW89_QATAR][0][75] = 127, + [1][1][RTW89_UK][1][75] = 127, + [1][1][RTW89_UK][0][75] = 127, + [1][1][RTW89_FCC][1][77] = -28, + [1][1][RTW89_FCC][2][77] = 44, + [1][1][RTW89_ETSI][1][77] = 127, + [1][1][RTW89_ETSI][0][77] = 127, + [1][1][RTW89_MKK][1][77] = 127, + [1][1][RTW89_MKK][0][77] = 127, + [1][1][RTW89_IC][1][77] = -28, + [1][1][RTW89_KCC][1][77] = -14, + [1][1][RTW89_KCC][0][77] = 127, + [1][1][RTW89_ACMA][1][77] = 127, + [1][1][RTW89_ACMA][0][77] = 127, + [1][1][RTW89_CHILE][1][77] = 127, + [1][1][RTW89_QATAR][1][77] = 127, + [1][1][RTW89_QATAR][0][77] = 127, + [1][1][RTW89_UK][1][77] = 127, + [1][1][RTW89_UK][0][77] = 127, + [1][1][RTW89_FCC][1][79] = -28, + [1][1][RTW89_FCC][2][79] = 44, + [1][1][RTW89_ETSI][1][79] = 127, + [1][1][RTW89_ETSI][0][79] = 127, + [1][1][RTW89_MKK][1][79] = 127, + [1][1][RTW89_MKK][0][79] = 127, + [1][1][RTW89_IC][1][79] = -28, + [1][1][RTW89_KCC][1][79] = -14, + [1][1][RTW89_KCC][0][79] = 127, + [1][1][RTW89_ACMA][1][79] = 127, + [1][1][RTW89_ACMA][0][79] = 127, + [1][1][RTW89_CHILE][1][79] = 127, + [1][1][RTW89_QATAR][1][79] = 127, + [1][1][RTW89_QATAR][0][79] = 127, + [1][1][RTW89_UK][1][79] = 127, + [1][1][RTW89_UK][0][79] = 127, + [1][1][RTW89_FCC][1][81] = -28, + [1][1][RTW89_FCC][2][81] = 44, + [1][1][RTW89_ETSI][1][81] = 127, + [1][1][RTW89_ETSI][0][81] = 127, + [1][1][RTW89_MKK][1][81] = 127, + [1][1][RTW89_MKK][0][81] = 127, + [1][1][RTW89_IC][1][81] = -28, + [1][1][RTW89_KCC][1][81] = -14, + [1][1][RTW89_KCC][0][81] = 127, + [1][1][RTW89_ACMA][1][81] = 127, + [1][1][RTW89_ACMA][0][81] = 127, + [1][1][RTW89_CHILE][1][81] = 127, + [1][1][RTW89_QATAR][1][81] = 127, + [1][1][RTW89_QATAR][0][81] = 127, + [1][1][RTW89_UK][1][81] = 127, + [1][1][RTW89_UK][0][81] = 127, + [1][1][RTW89_FCC][1][83] = -28, + [1][1][RTW89_FCC][2][83] = 44, + [1][1][RTW89_ETSI][1][83] = 127, + [1][1][RTW89_ETSI][0][83] = 127, + [1][1][RTW89_MKK][1][83] = 127, + [1][1][RTW89_MKK][0][83] = 127, + [1][1][RTW89_IC][1][83] = -28, + [1][1][RTW89_KCC][1][83] = -14, + [1][1][RTW89_KCC][0][83] = 127, + [1][1][RTW89_ACMA][1][83] = 127, + [1][1][RTW89_ACMA][0][83] = 127, + [1][1][RTW89_CHILE][1][83] = 127, + [1][1][RTW89_QATAR][1][83] = 127, + [1][1][RTW89_QATAR][0][83] = 127, + [1][1][RTW89_UK][1][83] = 127, + [1][1][RTW89_UK][0][83] = 127, + [1][1][RTW89_FCC][1][85] = -28, + [1][1][RTW89_FCC][2][85] = 44, + [1][1][RTW89_ETSI][1][85] = 127, + [1][1][RTW89_ETSI][0][85] = 127, + [1][1][RTW89_MKK][1][85] = 127, + [1][1][RTW89_MKK][0][85] = 127, + [1][1][RTW89_IC][1][85] = -28, + [1][1][RTW89_KCC][1][85] = -14, + [1][1][RTW89_KCC][0][85] = 127, + [1][1][RTW89_ACMA][1][85] = 127, + [1][1][RTW89_ACMA][0][85] = 127, + [1][1][RTW89_CHILE][1][85] = 127, + [1][1][RTW89_QATAR][1][85] = 127, + [1][1][RTW89_QATAR][0][85] = 127, + [1][1][RTW89_UK][1][85] = 127, + [1][1][RTW89_UK][0][85] = 127, + [1][1][RTW89_FCC][1][87] = -28, + [1][1][RTW89_FCC][2][87] = 127, + [1][1][RTW89_ETSI][1][87] = 127, + [1][1][RTW89_ETSI][0][87] = 127, + [1][1][RTW89_MKK][1][87] = 127, + [1][1][RTW89_MKK][0][87] = 127, + [1][1][RTW89_IC][1][87] = -28, + [1][1][RTW89_KCC][1][87] = -14, + [1][1][RTW89_KCC][0][87] = 127, + [1][1][RTW89_ACMA][1][87] = 127, + [1][1][RTW89_ACMA][0][87] = 127, + [1][1][RTW89_CHILE][1][87] = 127, + [1][1][RTW89_QATAR][1][87] = 127, + [1][1][RTW89_QATAR][0][87] = 127, + [1][1][RTW89_UK][1][87] = 127, + [1][1][RTW89_UK][0][87] = 127, + [1][1][RTW89_FCC][1][89] = -26, + [1][1][RTW89_FCC][2][89] = 127, + [1][1][RTW89_ETSI][1][89] = 127, + [1][1][RTW89_ETSI][0][89] = 127, + [1][1][RTW89_MKK][1][89] = 127, + [1][1][RTW89_MKK][0][89] = 127, + [1][1][RTW89_IC][1][89] = -26, + [1][1][RTW89_KCC][1][89] = -14, + [1][1][RTW89_KCC][0][89] = 127, + [1][1][RTW89_ACMA][1][89] = 127, + [1][1][RTW89_ACMA][0][89] = 127, + [1][1][RTW89_CHILE][1][89] = 127, + [1][1][RTW89_QATAR][1][89] = 127, + [1][1][RTW89_QATAR][0][89] = 127, + [1][1][RTW89_UK][1][89] = 127, + [1][1][RTW89_UK][0][89] = 127, + [1][1][RTW89_FCC][1][90] = -26, + [1][1][RTW89_FCC][2][90] = 127, + [1][1][RTW89_ETSI][1][90] = 127, + [1][1][RTW89_ETSI][0][90] = 127, + [1][1][RTW89_MKK][1][90] = 127, + [1][1][RTW89_MKK][0][90] = 127, + [1][1][RTW89_IC][1][90] = -26, + [1][1][RTW89_KCC][1][90] = -14, + [1][1][RTW89_KCC][0][90] = 127, + [1][1][RTW89_ACMA][1][90] = 127, + [1][1][RTW89_ACMA][0][90] = 127, + [1][1][RTW89_CHILE][1][90] = 127, + [1][1][RTW89_QATAR][1][90] = 127, + [1][1][RTW89_QATAR][0][90] = 127, + [1][1][RTW89_UK][1][90] = 127, + [1][1][RTW89_UK][0][90] = 127, + [1][1][RTW89_FCC][1][92] = -26, + [1][1][RTW89_FCC][2][92] = 127, + [1][1][RTW89_ETSI][1][92] = 127, + [1][1][RTW89_ETSI][0][92] = 127, + [1][1][RTW89_MKK][1][92] = 127, + [1][1][RTW89_MKK][0][92] = 127, + [1][1][RTW89_IC][1][92] = -26, + [1][1][RTW89_KCC][1][92] = -14, + [1][1][RTW89_KCC][0][92] = 127, + [1][1][RTW89_ACMA][1][92] = 127, + [1][1][RTW89_ACMA][0][92] = 127, + [1][1][RTW89_CHILE][1][92] = 127, + [1][1][RTW89_QATAR][1][92] = 127, + [1][1][RTW89_QATAR][0][92] = 127, + [1][1][RTW89_UK][1][92] = 127, + [1][1][RTW89_UK][0][92] = 127, + [1][1][RTW89_FCC][1][94] = -26, + [1][1][RTW89_FCC][2][94] = 127, + [1][1][RTW89_ETSI][1][94] = 127, + [1][1][RTW89_ETSI][0][94] = 127, + [1][1][RTW89_MKK][1][94] = 127, + [1][1][RTW89_MKK][0][94] = 127, + [1][1][RTW89_IC][1][94] = -26, + [1][1][RTW89_KCC][1][94] = -14, + [1][1][RTW89_KCC][0][94] = 127, + [1][1][RTW89_ACMA][1][94] = 127, + [1][1][RTW89_ACMA][0][94] = 127, + [1][1][RTW89_CHILE][1][94] = 127, + [1][1][RTW89_QATAR][1][94] = 127, + [1][1][RTW89_QATAR][0][94] = 127, + [1][1][RTW89_UK][1][94] = 127, + [1][1][RTW89_UK][0][94] = 127, + [1][1][RTW89_FCC][1][96] = -26, + [1][1][RTW89_FCC][2][96] = 127, + [1][1][RTW89_ETSI][1][96] = 127, + [1][1][RTW89_ETSI][0][96] = 127, + [1][1][RTW89_MKK][1][96] = 127, + [1][1][RTW89_MKK][0][96] = 127, + [1][1][RTW89_IC][1][96] = -26, + [1][1][RTW89_KCC][1][96] = -14, + [1][1][RTW89_KCC][0][96] = 127, + [1][1][RTW89_ACMA][1][96] = 127, + [1][1][RTW89_ACMA][0][96] = 127, + [1][1][RTW89_CHILE][1][96] = 127, + [1][1][RTW89_QATAR][1][96] = 127, + [1][1][RTW89_QATAR][0][96] = 127, + [1][1][RTW89_UK][1][96] = 127, + [1][1][RTW89_UK][0][96] = 127, + [1][1][RTW89_FCC][1][98] = -26, + [1][1][RTW89_FCC][2][98] = 127, + [1][1][RTW89_ETSI][1][98] = 127, + [1][1][RTW89_ETSI][0][98] = 127, + [1][1][RTW89_MKK][1][98] = 127, + [1][1][RTW89_MKK][0][98] = 127, + [1][1][RTW89_IC][1][98] = -26, + [1][1][RTW89_KCC][1][98] = -14, + [1][1][RTW89_KCC][0][98] = 127, + [1][1][RTW89_ACMA][1][98] = 127, + [1][1][RTW89_ACMA][0][98] = 127, + [1][1][RTW89_CHILE][1][98] = 127, + [1][1][RTW89_QATAR][1][98] = 127, + [1][1][RTW89_QATAR][0][98] = 127, + [1][1][RTW89_UK][1][98] = 127, + [1][1][RTW89_UK][0][98] = 127, + [1][1][RTW89_FCC][1][100] = -26, + [1][1][RTW89_FCC][2][100] = 127, + [1][1][RTW89_ETSI][1][100] = 127, + [1][1][RTW89_ETSI][0][100] = 127, + [1][1][RTW89_MKK][1][100] = 127, + [1][1][RTW89_MKK][0][100] = 127, + [1][1][RTW89_IC][1][100] = -26, + [1][1][RTW89_KCC][1][100] = -14, + [1][1][RTW89_KCC][0][100] = 127, + [1][1][RTW89_ACMA][1][100] = 127, + [1][1][RTW89_ACMA][0][100] = 127, + [1][1][RTW89_CHILE][1][100] = 127, + [1][1][RTW89_QATAR][1][100] = 127, + [1][1][RTW89_QATAR][0][100] = 127, + [1][1][RTW89_UK][1][100] = 127, + [1][1][RTW89_UK][0][100] = 127, + [1][1][RTW89_FCC][1][102] = -26, + [1][1][RTW89_FCC][2][102] = 127, + [1][1][RTW89_ETSI][1][102] = 127, + [1][1][RTW89_ETSI][0][102] = 127, + [1][1][RTW89_MKK][1][102] = 127, + [1][1][RTW89_MKK][0][102] = 127, + [1][1][RTW89_IC][1][102] = -26, + [1][1][RTW89_KCC][1][102] = -14, + [1][1][RTW89_KCC][0][102] = 127, + [1][1][RTW89_ACMA][1][102] = 127, + [1][1][RTW89_ACMA][0][102] = 127, + [1][1][RTW89_CHILE][1][102] = 127, + [1][1][RTW89_QATAR][1][102] = 127, + [1][1][RTW89_QATAR][0][102] = 127, + [1][1][RTW89_UK][1][102] = 127, + [1][1][RTW89_UK][0][102] = 127, + [1][1][RTW89_FCC][1][104] = -26, + [1][1][RTW89_FCC][2][104] = 127, + [1][1][RTW89_ETSI][1][104] = 127, + [1][1][RTW89_ETSI][0][104] = 127, + [1][1][RTW89_MKK][1][104] = 127, + [1][1][RTW89_MKK][0][104] = 127, + [1][1][RTW89_IC][1][104] = -26, + [1][1][RTW89_KCC][1][104] = -14, + [1][1][RTW89_KCC][0][104] = 127, + [1][1][RTW89_ACMA][1][104] = 127, + [1][1][RTW89_ACMA][0][104] = 127, + [1][1][RTW89_CHILE][1][104] = 127, + [1][1][RTW89_QATAR][1][104] = 127, + [1][1][RTW89_QATAR][0][104] = 127, + [1][1][RTW89_UK][1][104] = 127, + [1][1][RTW89_UK][0][104] = 127, + [1][1][RTW89_FCC][1][105] = -26, + [1][1][RTW89_FCC][2][105] = 127, + [1][1][RTW89_ETSI][1][105] = 127, + [1][1][RTW89_ETSI][0][105] = 127, + [1][1][RTW89_MKK][1][105] = 127, + [1][1][RTW89_MKK][0][105] = 127, + [1][1][RTW89_IC][1][105] = -26, + [1][1][RTW89_KCC][1][105] = -14, + [1][1][RTW89_KCC][0][105] = 127, + [1][1][RTW89_ACMA][1][105] = 127, + [1][1][RTW89_ACMA][0][105] = 127, + [1][1][RTW89_CHILE][1][105] = 127, + [1][1][RTW89_QATAR][1][105] = 127, + [1][1][RTW89_QATAR][0][105] = 127, + [1][1][RTW89_UK][1][105] = 127, + [1][1][RTW89_UK][0][105] = 127, + [1][1][RTW89_FCC][1][107] = -22, + [1][1][RTW89_FCC][2][107] = 127, + [1][1][RTW89_ETSI][1][107] = 127, + [1][1][RTW89_ETSI][0][107] = 127, + [1][1][RTW89_MKK][1][107] = 127, + [1][1][RTW89_MKK][0][107] = 127, + [1][1][RTW89_IC][1][107] = -22, + [1][1][RTW89_KCC][1][107] = -14, + [1][1][RTW89_KCC][0][107] = 127, + [1][1][RTW89_ACMA][1][107] = 127, + [1][1][RTW89_ACMA][0][107] = 127, + [1][1][RTW89_CHILE][1][107] = 127, + [1][1][RTW89_QATAR][1][107] = 127, + [1][1][RTW89_QATAR][0][107] = 127, + [1][1][RTW89_UK][1][107] = 127, + [1][1][RTW89_UK][0][107] = 127, + [1][1][RTW89_FCC][1][109] = -22, + [1][1][RTW89_FCC][2][109] = 127, + [1][1][RTW89_ETSI][1][109] = 127, + [1][1][RTW89_ETSI][0][109] = 127, + [1][1][RTW89_MKK][1][109] = 127, + [1][1][RTW89_MKK][0][109] = 127, + [1][1][RTW89_IC][1][109] = -22, + [1][1][RTW89_KCC][1][109] = 127, + [1][1][RTW89_KCC][0][109] = 127, + [1][1][RTW89_ACMA][1][109] = 127, + [1][1][RTW89_ACMA][0][109] = 127, + [1][1][RTW89_CHILE][1][109] = 127, + [1][1][RTW89_QATAR][1][109] = 127, + [1][1][RTW89_QATAR][0][109] = 127, + [1][1][RTW89_UK][1][109] = 127, + [1][1][RTW89_UK][0][109] = 127, + [1][1][RTW89_FCC][1][111] = 127, + [1][1][RTW89_FCC][2][111] = 127, + [1][1][RTW89_ETSI][1][111] = 127, + [1][1][RTW89_ETSI][0][111] = 127, + [1][1][RTW89_MKK][1][111] = 127, + [1][1][RTW89_MKK][0][111] = 127, + [1][1][RTW89_IC][1][111] = 127, + [1][1][RTW89_KCC][1][111] = 127, + [1][1][RTW89_KCC][0][111] = 127, + [1][1][RTW89_ACMA][1][111] = 127, + [1][1][RTW89_ACMA][0][111] = 127, + [1][1][RTW89_CHILE][1][111] = 127, + [1][1][RTW89_QATAR][1][111] = 127, + [1][1][RTW89_QATAR][0][111] = 127, + [1][1][RTW89_UK][1][111] = 127, + [1][1][RTW89_UK][0][111] = 127, + [1][1][RTW89_FCC][1][113] = 127, + [1][1][RTW89_FCC][2][113] = 127, + [1][1][RTW89_ETSI][1][113] = 127, + [1][1][RTW89_ETSI][0][113] = 127, + [1][1][RTW89_MKK][1][113] = 127, + [1][1][RTW89_MKK][0][113] = 127, + [1][1][RTW89_IC][1][113] = 127, + [1][1][RTW89_KCC][1][113] = 127, + [1][1][RTW89_KCC][0][113] = 127, + [1][1][RTW89_ACMA][1][113] = 127, + [1][1][RTW89_ACMA][0][113] = 127, + [1][1][RTW89_CHILE][1][113] = 127, + [1][1][RTW89_QATAR][1][113] = 127, + [1][1][RTW89_QATAR][0][113] = 127, + [1][1][RTW89_UK][1][113] = 127, + [1][1][RTW89_UK][0][113] = 127, + [1][1][RTW89_FCC][1][115] = 127, + [1][1][RTW89_FCC][2][115] = 127, + [1][1][RTW89_ETSI][1][115] = 127, + [1][1][RTW89_ETSI][0][115] = 127, + [1][1][RTW89_MKK][1][115] = 127, + [1][1][RTW89_MKK][0][115] = 127, + [1][1][RTW89_IC][1][115] = 127, + [1][1][RTW89_KCC][1][115] = 127, + [1][1][RTW89_KCC][0][115] = 127, + [1][1][RTW89_ACMA][1][115] = 127, + [1][1][RTW89_ACMA][0][115] = 127, + [1][1][RTW89_CHILE][1][115] = 127, + [1][1][RTW89_QATAR][1][115] = 127, + [1][1][RTW89_QATAR][0][115] = 127, + [1][1][RTW89_UK][1][115] = 127, + [1][1][RTW89_UK][0][115] = 127, + [1][1][RTW89_FCC][1][117] = 127, + [1][1][RTW89_FCC][2][117] = 127, + [1][1][RTW89_ETSI][1][117] = 127, + [1][1][RTW89_ETSI][0][117] = 127, + [1][1][RTW89_MKK][1][117] = 127, + [1][1][RTW89_MKK][0][117] = 127, + [1][1][RTW89_IC][1][117] = 127, + [1][1][RTW89_KCC][1][117] = 127, + [1][1][RTW89_KCC][0][117] = 127, + [1][1][RTW89_ACMA][1][117] = 127, + [1][1][RTW89_ACMA][0][117] = 127, + [1][1][RTW89_CHILE][1][117] = 127, + [1][1][RTW89_QATAR][1][117] = 127, + [1][1][RTW89_QATAR][0][117] = 127, + [1][1][RTW89_UK][1][117] = 127, + [1][1][RTW89_UK][0][117] = 127, + [1][1][RTW89_FCC][1][119] = 127, + [1][1][RTW89_FCC][2][119] = 127, + [1][1][RTW89_ETSI][1][119] = 127, + [1][1][RTW89_ETSI][0][119] = 127, + [1][1][RTW89_MKK][1][119] = 127, + [1][1][RTW89_MKK][0][119] = 127, + [1][1][RTW89_IC][1][119] = 127, + [1][1][RTW89_KCC][1][119] = 127, + [1][1][RTW89_KCC][0][119] = 127, + [1][1][RTW89_ACMA][1][119] = 127, + [1][1][RTW89_ACMA][0][119] = 127, + [1][1][RTW89_CHILE][1][119] = 127, + [1][1][RTW89_QATAR][1][119] = 127, + [1][1][RTW89_QATAR][0][119] = 127, + [1][1][RTW89_UK][1][119] = 127, + [1][1][RTW89_UK][0][119] = 127, + [2][0][RTW89_FCC][1][0] = 8, + [2][0][RTW89_FCC][2][0] = 60, + [2][0][RTW89_ETSI][1][0] = 56, + [2][0][RTW89_ETSI][0][0] = 18, + [2][0][RTW89_MKK][1][0] = 54, + [2][0][RTW89_MKK][0][0] = 14, + [2][0][RTW89_IC][1][0] = 8, + [2][0][RTW89_KCC][1][0] = -2, + [2][0][RTW89_KCC][0][0] = -2, + [2][0][RTW89_ACMA][1][0] = 56, + [2][0][RTW89_ACMA][0][0] = 18, + [2][0][RTW89_CHILE][1][0] = 8, + [2][0][RTW89_QATAR][1][0] = 56, + [2][0][RTW89_QATAR][0][0] = 18, + [2][0][RTW89_UK][1][0] = 56, + [2][0][RTW89_UK][0][0] = 18, + [2][0][RTW89_FCC][1][2] = 8, + [2][0][RTW89_FCC][2][2] = 60, + [2][0][RTW89_ETSI][1][2] = 56, + [2][0][RTW89_ETSI][0][2] = 18, + [2][0][RTW89_MKK][1][2] = 54, + [2][0][RTW89_MKK][0][2] = 14, + [2][0][RTW89_IC][1][2] = 8, + [2][0][RTW89_KCC][1][2] = -2, + [2][0][RTW89_KCC][0][2] = -2, + [2][0][RTW89_ACMA][1][2] = 56, + [2][0][RTW89_ACMA][0][2] = 18, + [2][0][RTW89_CHILE][1][2] = 8, + [2][0][RTW89_QATAR][1][2] = 56, + [2][0][RTW89_QATAR][0][2] = 18, + [2][0][RTW89_UK][1][2] = 56, + [2][0][RTW89_UK][0][2] = 18, + [2][0][RTW89_FCC][1][4] = 8, + [2][0][RTW89_FCC][2][4] = 60, + [2][0][RTW89_ETSI][1][4] = 56, + [2][0][RTW89_ETSI][0][4] = 18, + [2][0][RTW89_MKK][1][4] = 54, + [2][0][RTW89_MKK][0][4] = 14, + [2][0][RTW89_IC][1][4] = 8, + [2][0][RTW89_KCC][1][4] = -2, + [2][0][RTW89_KCC][0][4] = -2, + [2][0][RTW89_ACMA][1][4] = 56, + [2][0][RTW89_ACMA][0][4] = 18, + [2][0][RTW89_CHILE][1][4] = 8, + [2][0][RTW89_QATAR][1][4] = 56, + [2][0][RTW89_QATAR][0][4] = 18, + [2][0][RTW89_UK][1][4] = 56, + [2][0][RTW89_UK][0][4] = 18, + [2][0][RTW89_FCC][1][6] = 8, + [2][0][RTW89_FCC][2][6] = 60, + [2][0][RTW89_ETSI][1][6] = 56, + [2][0][RTW89_ETSI][0][6] = 18, + [2][0][RTW89_MKK][1][6] = 54, + [2][0][RTW89_MKK][0][6] = 14, + [2][0][RTW89_IC][1][6] = 8, + [2][0][RTW89_KCC][1][6] = -2, + [2][0][RTW89_KCC][0][6] = -2, + [2][0][RTW89_ACMA][1][6] = 56, + [2][0][RTW89_ACMA][0][6] = 18, + [2][0][RTW89_CHILE][1][6] = 8, + [2][0][RTW89_QATAR][1][6] = 56, + [2][0][RTW89_QATAR][0][6] = 18, + [2][0][RTW89_UK][1][6] = 56, + [2][0][RTW89_UK][0][6] = 18, + [2][0][RTW89_FCC][1][8] = 8, + [2][0][RTW89_FCC][2][8] = 60, + [2][0][RTW89_ETSI][1][8] = 56, + [2][0][RTW89_ETSI][0][8] = 18, + [2][0][RTW89_MKK][1][8] = 54, + [2][0][RTW89_MKK][0][8] = 14, + [2][0][RTW89_IC][1][8] = 8, + [2][0][RTW89_KCC][1][8] = -2, + [2][0][RTW89_KCC][0][8] = -2, + [2][0][RTW89_ACMA][1][8] = 56, + [2][0][RTW89_ACMA][0][8] = 18, + [2][0][RTW89_CHILE][1][8] = 8, + [2][0][RTW89_QATAR][1][8] = 56, + [2][0][RTW89_QATAR][0][8] = 18, + [2][0][RTW89_UK][1][8] = 56, + [2][0][RTW89_UK][0][8] = 18, + [2][0][RTW89_FCC][1][10] = 8, + [2][0][RTW89_FCC][2][10] = 60, + [2][0][RTW89_ETSI][1][10] = 56, + [2][0][RTW89_ETSI][0][10] = 18, + [2][0][RTW89_MKK][1][10] = 54, + [2][0][RTW89_MKK][0][10] = 14, + [2][0][RTW89_IC][1][10] = 8, + [2][0][RTW89_KCC][1][10] = -2, + [2][0][RTW89_KCC][0][10] = -2, + [2][0][RTW89_ACMA][1][10] = 56, + [2][0][RTW89_ACMA][0][10] = 18, + [2][0][RTW89_CHILE][1][10] = 8, + [2][0][RTW89_QATAR][1][10] = 56, + [2][0][RTW89_QATAR][0][10] = 18, + [2][0][RTW89_UK][1][10] = 56, + [2][0][RTW89_UK][0][10] = 18, + [2][0][RTW89_FCC][1][12] = 8, + [2][0][RTW89_FCC][2][12] = 60, + [2][0][RTW89_ETSI][1][12] = 56, + [2][0][RTW89_ETSI][0][12] = 18, + [2][0][RTW89_MKK][1][12] = 54, + [2][0][RTW89_MKK][0][12] = 14, + [2][0][RTW89_IC][1][12] = 8, + [2][0][RTW89_KCC][1][12] = -2, + [2][0][RTW89_KCC][0][12] = -2, + [2][0][RTW89_ACMA][1][12] = 56, + [2][0][RTW89_ACMA][0][12] = 18, + [2][0][RTW89_CHILE][1][12] = 8, + [2][0][RTW89_QATAR][1][12] = 56, + [2][0][RTW89_QATAR][0][12] = 18, + [2][0][RTW89_UK][1][12] = 56, + [2][0][RTW89_UK][0][12] = 18, + [2][0][RTW89_FCC][1][14] = 8, + [2][0][RTW89_FCC][2][14] = 60, + [2][0][RTW89_ETSI][1][14] = 56, + [2][0][RTW89_ETSI][0][14] = 18, + [2][0][RTW89_MKK][1][14] = 54, + [2][0][RTW89_MKK][0][14] = 14, + [2][0][RTW89_IC][1][14] = 8, + [2][0][RTW89_KCC][1][14] = -2, + [2][0][RTW89_KCC][0][14] = -2, + [2][0][RTW89_ACMA][1][14] = 56, + [2][0][RTW89_ACMA][0][14] = 18, + [2][0][RTW89_CHILE][1][14] = 8, + [2][0][RTW89_QATAR][1][14] = 56, + [2][0][RTW89_QATAR][0][14] = 18, + [2][0][RTW89_UK][1][14] = 56, + [2][0][RTW89_UK][0][14] = 18, + [2][0][RTW89_FCC][1][15] = 8, + [2][0][RTW89_FCC][2][15] = 60, + [2][0][RTW89_ETSI][1][15] = 56, + [2][0][RTW89_ETSI][0][15] = 18, + [2][0][RTW89_MKK][1][15] = 54, + [2][0][RTW89_MKK][0][15] = 14, + [2][0][RTW89_IC][1][15] = 8, + [2][0][RTW89_KCC][1][15] = -2, + [2][0][RTW89_KCC][0][15] = -2, + [2][0][RTW89_ACMA][1][15] = 56, + [2][0][RTW89_ACMA][0][15] = 18, + [2][0][RTW89_CHILE][1][15] = 8, + [2][0][RTW89_QATAR][1][15] = 56, + [2][0][RTW89_QATAR][0][15] = 18, + [2][0][RTW89_UK][1][15] = 56, + [2][0][RTW89_UK][0][15] = 18, + [2][0][RTW89_FCC][1][17] = 8, + [2][0][RTW89_FCC][2][17] = 60, + [2][0][RTW89_ETSI][1][17] = 56, + [2][0][RTW89_ETSI][0][17] = 18, + [2][0][RTW89_MKK][1][17] = 54, + [2][0][RTW89_MKK][0][17] = 14, + [2][0][RTW89_IC][1][17] = 8, + [2][0][RTW89_KCC][1][17] = -2, + [2][0][RTW89_KCC][0][17] = -2, + [2][0][RTW89_ACMA][1][17] = 56, + [2][0][RTW89_ACMA][0][17] = 18, + [2][0][RTW89_CHILE][1][17] = 8, + [2][0][RTW89_QATAR][1][17] = 56, + [2][0][RTW89_QATAR][0][17] = 18, + [2][0][RTW89_UK][1][17] = 56, + [2][0][RTW89_UK][0][17] = 18, + [2][0][RTW89_FCC][1][19] = 8, + [2][0][RTW89_FCC][2][19] = 60, + [2][0][RTW89_ETSI][1][19] = 56, + [2][0][RTW89_ETSI][0][19] = 18, + [2][0][RTW89_MKK][1][19] = 54, + [2][0][RTW89_MKK][0][19] = 14, + [2][0][RTW89_IC][1][19] = 8, + [2][0][RTW89_KCC][1][19] = -2, + [2][0][RTW89_KCC][0][19] = -2, + [2][0][RTW89_ACMA][1][19] = 56, + [2][0][RTW89_ACMA][0][19] = 18, + [2][0][RTW89_CHILE][1][19] = 8, + [2][0][RTW89_QATAR][1][19] = 56, + [2][0][RTW89_QATAR][0][19] = 18, + [2][0][RTW89_UK][1][19] = 56, + [2][0][RTW89_UK][0][19] = 18, + [2][0][RTW89_FCC][1][21] = 8, + [2][0][RTW89_FCC][2][21] = 60, + [2][0][RTW89_ETSI][1][21] = 56, + [2][0][RTW89_ETSI][0][21] = 18, + [2][0][RTW89_MKK][1][21] = 54, + [2][0][RTW89_MKK][0][21] = 14, + [2][0][RTW89_IC][1][21] = 8, + [2][0][RTW89_KCC][1][21] = -2, + [2][0][RTW89_KCC][0][21] = -2, + [2][0][RTW89_ACMA][1][21] = 56, + [2][0][RTW89_ACMA][0][21] = 18, + [2][0][RTW89_CHILE][1][21] = 8, + [2][0][RTW89_QATAR][1][21] = 56, + [2][0][RTW89_QATAR][0][21] = 18, + [2][0][RTW89_UK][1][21] = 56, + [2][0][RTW89_UK][0][21] = 18, + [2][0][RTW89_FCC][1][23] = 8, + [2][0][RTW89_FCC][2][23] = 78, + [2][0][RTW89_ETSI][1][23] = 56, + [2][0][RTW89_ETSI][0][23] = 18, + [2][0][RTW89_MKK][1][23] = 56, + [2][0][RTW89_MKK][0][23] = 14, + [2][0][RTW89_IC][1][23] = 8, + [2][0][RTW89_KCC][1][23] = -2, + [2][0][RTW89_KCC][0][23] = -2, + [2][0][RTW89_ACMA][1][23] = 56, + [2][0][RTW89_ACMA][0][23] = 18, + [2][0][RTW89_CHILE][1][23] = 8, + [2][0][RTW89_QATAR][1][23] = 56, + [2][0][RTW89_QATAR][0][23] = 18, + [2][0][RTW89_UK][1][23] = 56, + [2][0][RTW89_UK][0][23] = 18, + [2][0][RTW89_FCC][1][25] = 8, + [2][0][RTW89_FCC][2][25] = 78, + [2][0][RTW89_ETSI][1][25] = 56, + [2][0][RTW89_ETSI][0][25] = 18, + [2][0][RTW89_MKK][1][25] = 56, + [2][0][RTW89_MKK][0][25] = 14, + [2][0][RTW89_IC][1][25] = 8, + [2][0][RTW89_KCC][1][25] = -2, + [2][0][RTW89_KCC][0][25] = -2, + [2][0][RTW89_ACMA][1][25] = 56, + [2][0][RTW89_ACMA][0][25] = 18, + [2][0][RTW89_CHILE][1][25] = 8, + [2][0][RTW89_QATAR][1][25] = 56, + [2][0][RTW89_QATAR][0][25] = 18, + [2][0][RTW89_UK][1][25] = 56, + [2][0][RTW89_UK][0][25] = 18, + [2][0][RTW89_FCC][1][27] = 8, + [2][0][RTW89_FCC][2][27] = 78, + [2][0][RTW89_ETSI][1][27] = 56, + [2][0][RTW89_ETSI][0][27] = 18, + [2][0][RTW89_MKK][1][27] = 56, + [2][0][RTW89_MKK][0][27] = 14, + [2][0][RTW89_IC][1][27] = 8, + [2][0][RTW89_KCC][1][27] = -2, + [2][0][RTW89_KCC][0][27] = -2, + [2][0][RTW89_ACMA][1][27] = 56, + [2][0][RTW89_ACMA][0][27] = 18, + [2][0][RTW89_CHILE][1][27] = 8, + [2][0][RTW89_QATAR][1][27] = 56, + [2][0][RTW89_QATAR][0][27] = 18, + [2][0][RTW89_UK][1][27] = 56, + [2][0][RTW89_UK][0][27] = 18, + [2][0][RTW89_FCC][1][29] = 8, + [2][0][RTW89_FCC][2][29] = 78, + [2][0][RTW89_ETSI][1][29] = 56, + [2][0][RTW89_ETSI][0][29] = 18, + [2][0][RTW89_MKK][1][29] = 56, + [2][0][RTW89_MKK][0][29] = 14, + [2][0][RTW89_IC][1][29] = 8, + [2][0][RTW89_KCC][1][29] = -2, + [2][0][RTW89_KCC][0][29] = -2, + [2][0][RTW89_ACMA][1][29] = 56, + [2][0][RTW89_ACMA][0][29] = 18, + [2][0][RTW89_CHILE][1][29] = 8, + [2][0][RTW89_QATAR][1][29] = 56, + [2][0][RTW89_QATAR][0][29] = 18, + [2][0][RTW89_UK][1][29] = 56, + [2][0][RTW89_UK][0][29] = 18, + [2][0][RTW89_FCC][1][30] = 8, + [2][0][RTW89_FCC][2][30] = 78, + [2][0][RTW89_ETSI][1][30] = 56, + [2][0][RTW89_ETSI][0][30] = 18, + [2][0][RTW89_MKK][1][30] = 56, + [2][0][RTW89_MKK][0][30] = 14, + [2][0][RTW89_IC][1][30] = 8, + [2][0][RTW89_KCC][1][30] = -2, + [2][0][RTW89_KCC][0][30] = -2, + [2][0][RTW89_ACMA][1][30] = 56, + [2][0][RTW89_ACMA][0][30] = 18, + [2][0][RTW89_CHILE][1][30] = 8, + [2][0][RTW89_QATAR][1][30] = 56, + [2][0][RTW89_QATAR][0][30] = 18, + [2][0][RTW89_UK][1][30] = 56, + [2][0][RTW89_UK][0][30] = 18, + [2][0][RTW89_FCC][1][32] = 8, + [2][0][RTW89_FCC][2][32] = 78, + [2][0][RTW89_ETSI][1][32] = 56, + [2][0][RTW89_ETSI][0][32] = 18, + [2][0][RTW89_MKK][1][32] = 56, + [2][0][RTW89_MKK][0][32] = 14, + [2][0][RTW89_IC][1][32] = 8, + [2][0][RTW89_KCC][1][32] = -2, + [2][0][RTW89_KCC][0][32] = -2, + [2][0][RTW89_ACMA][1][32] = 56, + [2][0][RTW89_ACMA][0][32] = 18, + [2][0][RTW89_CHILE][1][32] = 8, + [2][0][RTW89_QATAR][1][32] = 56, + [2][0][RTW89_QATAR][0][32] = 18, + [2][0][RTW89_UK][1][32] = 56, + [2][0][RTW89_UK][0][32] = 18, + [2][0][RTW89_FCC][1][34] = 8, + [2][0][RTW89_FCC][2][34] = 78, + [2][0][RTW89_ETSI][1][34] = 56, + [2][0][RTW89_ETSI][0][34] = 18, + [2][0][RTW89_MKK][1][34] = 56, + [2][0][RTW89_MKK][0][34] = 14, + [2][0][RTW89_IC][1][34] = 8, + [2][0][RTW89_KCC][1][34] = -2, + [2][0][RTW89_KCC][0][34] = -2, + [2][0][RTW89_ACMA][1][34] = 56, + [2][0][RTW89_ACMA][0][34] = 18, + [2][0][RTW89_CHILE][1][34] = 8, + [2][0][RTW89_QATAR][1][34] = 56, + [2][0][RTW89_QATAR][0][34] = 18, + [2][0][RTW89_UK][1][34] = 56, + [2][0][RTW89_UK][0][34] = 18, + [2][0][RTW89_FCC][1][36] = 8, + [2][0][RTW89_FCC][2][36] = 78, + [2][0][RTW89_ETSI][1][36] = 56, + [2][0][RTW89_ETSI][0][36] = 18, + [2][0][RTW89_MKK][1][36] = 56, + [2][0][RTW89_MKK][0][36] = 14, + [2][0][RTW89_IC][1][36] = 8, + [2][0][RTW89_KCC][1][36] = -2, + [2][0][RTW89_KCC][0][36] = -2, + [2][0][RTW89_ACMA][1][36] = 56, + [2][0][RTW89_ACMA][0][36] = 18, + [2][0][RTW89_CHILE][1][36] = 8, + [2][0][RTW89_QATAR][1][36] = 56, + [2][0][RTW89_QATAR][0][36] = 18, + [2][0][RTW89_UK][1][36] = 56, + [2][0][RTW89_UK][0][36] = 18, + [2][0][RTW89_FCC][1][38] = 8, + [2][0][RTW89_FCC][2][38] = 78, + [2][0][RTW89_ETSI][1][38] = 56, + [2][0][RTW89_ETSI][0][38] = 18, + [2][0][RTW89_MKK][1][38] = 56, + [2][0][RTW89_MKK][0][38] = 14, + [2][0][RTW89_IC][1][38] = 8, + [2][0][RTW89_KCC][1][38] = -2, + [2][0][RTW89_KCC][0][38] = -2, + [2][0][RTW89_ACMA][1][38] = 56, + [2][0][RTW89_ACMA][0][38] = 18, + [2][0][RTW89_CHILE][1][38] = 8, + [2][0][RTW89_QATAR][1][38] = 56, + [2][0][RTW89_QATAR][0][38] = 18, + [2][0][RTW89_UK][1][38] = 56, + [2][0][RTW89_UK][0][38] = 18, + [2][0][RTW89_FCC][1][40] = 8, + [2][0][RTW89_FCC][2][40] = 78, + [2][0][RTW89_ETSI][1][40] = 56, + [2][0][RTW89_ETSI][0][40] = 18, + [2][0][RTW89_MKK][1][40] = 56, + [2][0][RTW89_MKK][0][40] = 14, + [2][0][RTW89_IC][1][40] = 8, + [2][0][RTW89_KCC][1][40] = -2, + [2][0][RTW89_KCC][0][40] = -2, + [2][0][RTW89_ACMA][1][40] = 56, + [2][0][RTW89_ACMA][0][40] = 18, + [2][0][RTW89_CHILE][1][40] = 8, + [2][0][RTW89_QATAR][1][40] = 56, + [2][0][RTW89_QATAR][0][40] = 18, + [2][0][RTW89_UK][1][40] = 56, + [2][0][RTW89_UK][0][40] = 18, + [2][0][RTW89_FCC][1][42] = 8, + [2][0][RTW89_FCC][2][42] = 78, + [2][0][RTW89_ETSI][1][42] = 56, + [2][0][RTW89_ETSI][0][42] = 18, + [2][0][RTW89_MKK][1][42] = 56, + [2][0][RTW89_MKK][0][42] = 14, + [2][0][RTW89_IC][1][42] = 8, + [2][0][RTW89_KCC][1][42] = -2, + [2][0][RTW89_KCC][0][42] = -2, + [2][0][RTW89_ACMA][1][42] = 56, + [2][0][RTW89_ACMA][0][42] = 18, + [2][0][RTW89_CHILE][1][42] = 8, + [2][0][RTW89_QATAR][1][42] = 56, + [2][0][RTW89_QATAR][0][42] = 18, + [2][0][RTW89_UK][1][42] = 56, + [2][0][RTW89_UK][0][42] = 18, + [2][0][RTW89_FCC][1][44] = 8, + [2][0][RTW89_FCC][2][44] = 78, + [2][0][RTW89_ETSI][1][44] = 56, + [2][0][RTW89_ETSI][0][44] = 18, + [2][0][RTW89_MKK][1][44] = 32, + [2][0][RTW89_MKK][0][44] = 14, + [2][0][RTW89_IC][1][44] = 8, + [2][0][RTW89_KCC][1][44] = -2, + [2][0][RTW89_KCC][0][44] = -2, + [2][0][RTW89_ACMA][1][44] = 56, + [2][0][RTW89_ACMA][0][44] = 18, + [2][0][RTW89_CHILE][1][44] = 8, + [2][0][RTW89_QATAR][1][44] = 56, + [2][0][RTW89_QATAR][0][44] = 18, + [2][0][RTW89_UK][1][44] = 56, + [2][0][RTW89_UK][0][44] = 18, + [2][0][RTW89_FCC][1][45] = 8, + [2][0][RTW89_FCC][2][45] = 127, + [2][0][RTW89_ETSI][1][45] = 127, + [2][0][RTW89_ETSI][0][45] = 127, + [2][0][RTW89_MKK][1][45] = 127, + [2][0][RTW89_MKK][0][45] = 127, + [2][0][RTW89_IC][1][45] = 8, + [2][0][RTW89_KCC][1][45] = -2, + [2][0][RTW89_KCC][0][45] = 127, + [2][0][RTW89_ACMA][1][45] = 127, + [2][0][RTW89_ACMA][0][45] = 127, + [2][0][RTW89_CHILE][1][45] = 127, + [2][0][RTW89_QATAR][1][45] = 127, + [2][0][RTW89_QATAR][0][45] = 127, + [2][0][RTW89_UK][1][45] = 127, + [2][0][RTW89_UK][0][45] = 127, + [2][0][RTW89_FCC][1][47] = 8, + [2][0][RTW89_FCC][2][47] = 127, + [2][0][RTW89_ETSI][1][47] = 127, + [2][0][RTW89_ETSI][0][47] = 127, + [2][0][RTW89_MKK][1][47] = 127, + [2][0][RTW89_MKK][0][47] = 127, + [2][0][RTW89_IC][1][47] = 8, + [2][0][RTW89_KCC][1][47] = -2, + [2][0][RTW89_KCC][0][47] = 127, + [2][0][RTW89_ACMA][1][47] = 127, + [2][0][RTW89_ACMA][0][47] = 127, + [2][0][RTW89_CHILE][1][47] = 127, + [2][0][RTW89_QATAR][1][47] = 127, + [2][0][RTW89_QATAR][0][47] = 127, + [2][0][RTW89_UK][1][47] = 127, + [2][0][RTW89_UK][0][47] = 127, + [2][0][RTW89_FCC][1][49] = 8, + [2][0][RTW89_FCC][2][49] = 127, + [2][0][RTW89_ETSI][1][49] = 127, + [2][0][RTW89_ETSI][0][49] = 127, + [2][0][RTW89_MKK][1][49] = 127, + [2][0][RTW89_MKK][0][49] = 127, + [2][0][RTW89_IC][1][49] = 8, + [2][0][RTW89_KCC][1][49] = -2, + [2][0][RTW89_KCC][0][49] = 127, + [2][0][RTW89_ACMA][1][49] = 127, + [2][0][RTW89_ACMA][0][49] = 127, + [2][0][RTW89_CHILE][1][49] = 127, + [2][0][RTW89_QATAR][1][49] = 127, + [2][0][RTW89_QATAR][0][49] = 127, + [2][0][RTW89_UK][1][49] = 127, + [2][0][RTW89_UK][0][49] = 127, + [2][0][RTW89_FCC][1][51] = 8, + [2][0][RTW89_FCC][2][51] = 127, + [2][0][RTW89_ETSI][1][51] = 127, + [2][0][RTW89_ETSI][0][51] = 127, + [2][0][RTW89_MKK][1][51] = 127, + [2][0][RTW89_MKK][0][51] = 127, + [2][0][RTW89_IC][1][51] = 8, + [2][0][RTW89_KCC][1][51] = -2, + [2][0][RTW89_KCC][0][51] = 127, + [2][0][RTW89_ACMA][1][51] = 127, + [2][0][RTW89_ACMA][0][51] = 127, + [2][0][RTW89_CHILE][1][51] = 127, + [2][0][RTW89_QATAR][1][51] = 127, + [2][0][RTW89_QATAR][0][51] = 127, + [2][0][RTW89_UK][1][51] = 127, + [2][0][RTW89_UK][0][51] = 127, + [2][0][RTW89_FCC][1][53] = 8, + [2][0][RTW89_FCC][2][53] = 127, + [2][0][RTW89_ETSI][1][53] = 127, + [2][0][RTW89_ETSI][0][53] = 127, + [2][0][RTW89_MKK][1][53] = 127, + [2][0][RTW89_MKK][0][53] = 127, + [2][0][RTW89_IC][1][53] = 8, + [2][0][RTW89_KCC][1][53] = -2, + [2][0][RTW89_KCC][0][53] = 127, + [2][0][RTW89_ACMA][1][53] = 127, + [2][0][RTW89_ACMA][0][53] = 127, + [2][0][RTW89_CHILE][1][53] = 127, + [2][0][RTW89_QATAR][1][53] = 127, + [2][0][RTW89_QATAR][0][53] = 127, + [2][0][RTW89_UK][1][53] = 127, + [2][0][RTW89_UK][0][53] = 127, + [2][0][RTW89_FCC][1][55] = 8, + [2][0][RTW89_FCC][2][55] = 78, + [2][0][RTW89_ETSI][1][55] = 127, + [2][0][RTW89_ETSI][0][55] = 127, + [2][0][RTW89_MKK][1][55] = 127, + [2][0][RTW89_MKK][0][55] = 127, + [2][0][RTW89_IC][1][55] = 8, + [2][0][RTW89_KCC][1][55] = -2, + [2][0][RTW89_KCC][0][55] = 127, + [2][0][RTW89_ACMA][1][55] = 127, + [2][0][RTW89_ACMA][0][55] = 127, + [2][0][RTW89_CHILE][1][55] = 127, + [2][0][RTW89_QATAR][1][55] = 127, + [2][0][RTW89_QATAR][0][55] = 127, + [2][0][RTW89_UK][1][55] = 127, + [2][0][RTW89_UK][0][55] = 127, + [2][0][RTW89_FCC][1][57] = 8, + [2][0][RTW89_FCC][2][57] = 78, + [2][0][RTW89_ETSI][1][57] = 127, + [2][0][RTW89_ETSI][0][57] = 127, + [2][0][RTW89_MKK][1][57] = 127, + [2][0][RTW89_MKK][0][57] = 127, + [2][0][RTW89_IC][1][57] = 8, + [2][0][RTW89_KCC][1][57] = -2, + [2][0][RTW89_KCC][0][57] = 127, + [2][0][RTW89_ACMA][1][57] = 127, + [2][0][RTW89_ACMA][0][57] = 127, + [2][0][RTW89_CHILE][1][57] = 127, + [2][0][RTW89_QATAR][1][57] = 127, + [2][0][RTW89_QATAR][0][57] = 127, + [2][0][RTW89_UK][1][57] = 127, + [2][0][RTW89_UK][0][57] = 127, + [2][0][RTW89_FCC][1][59] = 8, + [2][0][RTW89_FCC][2][59] = 78, + [2][0][RTW89_ETSI][1][59] = 127, + [2][0][RTW89_ETSI][0][59] = 127, + [2][0][RTW89_MKK][1][59] = 127, + [2][0][RTW89_MKK][0][59] = 127, + [2][0][RTW89_IC][1][59] = 8, + [2][0][RTW89_KCC][1][59] = -2, + [2][0][RTW89_KCC][0][59] = 127, + [2][0][RTW89_ACMA][1][59] = 127, + [2][0][RTW89_ACMA][0][59] = 127, + [2][0][RTW89_CHILE][1][59] = 127, + [2][0][RTW89_QATAR][1][59] = 127, + [2][0][RTW89_QATAR][0][59] = 127, + [2][0][RTW89_UK][1][59] = 127, + [2][0][RTW89_UK][0][59] = 127, + [2][0][RTW89_FCC][1][60] = 8, + [2][0][RTW89_FCC][2][60] = 78, + [2][0][RTW89_ETSI][1][60] = 127, + [2][0][RTW89_ETSI][0][60] = 127, + [2][0][RTW89_MKK][1][60] = 127, + [2][0][RTW89_MKK][0][60] = 127, + [2][0][RTW89_IC][1][60] = 8, + [2][0][RTW89_KCC][1][60] = -2, + [2][0][RTW89_KCC][0][60] = 127, + [2][0][RTW89_ACMA][1][60] = 127, + [2][0][RTW89_ACMA][0][60] = 127, + [2][0][RTW89_CHILE][1][60] = 127, + [2][0][RTW89_QATAR][1][60] = 127, + [2][0][RTW89_QATAR][0][60] = 127, + [2][0][RTW89_UK][1][60] = 127, + [2][0][RTW89_UK][0][60] = 127, + [2][0][RTW89_FCC][1][62] = 8, + [2][0][RTW89_FCC][2][62] = 78, + [2][0][RTW89_ETSI][1][62] = 127, + [2][0][RTW89_ETSI][0][62] = 127, + [2][0][RTW89_MKK][1][62] = 127, + [2][0][RTW89_MKK][0][62] = 127, + [2][0][RTW89_IC][1][62] = 8, + [2][0][RTW89_KCC][1][62] = -2, + [2][0][RTW89_KCC][0][62] = 127, + [2][0][RTW89_ACMA][1][62] = 127, + [2][0][RTW89_ACMA][0][62] = 127, + [2][0][RTW89_CHILE][1][62] = 127, + [2][0][RTW89_QATAR][1][62] = 127, + [2][0][RTW89_QATAR][0][62] = 127, + [2][0][RTW89_UK][1][62] = 127, + [2][0][RTW89_UK][0][62] = 127, + [2][0][RTW89_FCC][1][64] = 8, + [2][0][RTW89_FCC][2][64] = 78, + [2][0][RTW89_ETSI][1][64] = 127, + [2][0][RTW89_ETSI][0][64] = 127, + [2][0][RTW89_MKK][1][64] = 127, + [2][0][RTW89_MKK][0][64] = 127, + [2][0][RTW89_IC][1][64] = 8, + [2][0][RTW89_KCC][1][64] = -2, + [2][0][RTW89_KCC][0][64] = 127, + [2][0][RTW89_ACMA][1][64] = 127, + [2][0][RTW89_ACMA][0][64] = 127, + [2][0][RTW89_CHILE][1][64] = 127, + [2][0][RTW89_QATAR][1][64] = 127, + [2][0][RTW89_QATAR][0][64] = 127, + [2][0][RTW89_UK][1][64] = 127, + [2][0][RTW89_UK][0][64] = 127, + [2][0][RTW89_FCC][1][66] = 8, + [2][0][RTW89_FCC][2][66] = 78, + [2][0][RTW89_ETSI][1][66] = 127, + [2][0][RTW89_ETSI][0][66] = 127, + [2][0][RTW89_MKK][1][66] = 127, + [2][0][RTW89_MKK][0][66] = 127, + [2][0][RTW89_IC][1][66] = 8, + [2][0][RTW89_KCC][1][66] = -2, + [2][0][RTW89_KCC][0][66] = 127, + [2][0][RTW89_ACMA][1][66] = 127, + [2][0][RTW89_ACMA][0][66] = 127, + [2][0][RTW89_CHILE][1][66] = 127, + [2][0][RTW89_QATAR][1][66] = 127, + [2][0][RTW89_QATAR][0][66] = 127, + [2][0][RTW89_UK][1][66] = 127, + [2][0][RTW89_UK][0][66] = 127, + [2][0][RTW89_FCC][1][68] = 8, + [2][0][RTW89_FCC][2][68] = 78, + [2][0][RTW89_ETSI][1][68] = 127, + [2][0][RTW89_ETSI][0][68] = 127, + [2][0][RTW89_MKK][1][68] = 127, + [2][0][RTW89_MKK][0][68] = 127, + [2][0][RTW89_IC][1][68] = 8, + [2][0][RTW89_KCC][1][68] = -2, + [2][0][RTW89_KCC][0][68] = 127, + [2][0][RTW89_ACMA][1][68] = 127, + [2][0][RTW89_ACMA][0][68] = 127, + [2][0][RTW89_CHILE][1][68] = 127, + [2][0][RTW89_QATAR][1][68] = 127, + [2][0][RTW89_QATAR][0][68] = 127, + [2][0][RTW89_UK][1][68] = 127, + [2][0][RTW89_UK][0][68] = 127, + [2][0][RTW89_FCC][1][70] = 8, + [2][0][RTW89_FCC][2][70] = 78, + [2][0][RTW89_ETSI][1][70] = 127, + [2][0][RTW89_ETSI][0][70] = 127, + [2][0][RTW89_MKK][1][70] = 127, + [2][0][RTW89_MKK][0][70] = 127, + [2][0][RTW89_IC][1][70] = 8, + [2][0][RTW89_KCC][1][70] = -2, + [2][0][RTW89_KCC][0][70] = 127, + [2][0][RTW89_ACMA][1][70] = 127, + [2][0][RTW89_ACMA][0][70] = 127, + [2][0][RTW89_CHILE][1][70] = 127, + [2][0][RTW89_QATAR][1][70] = 127, + [2][0][RTW89_QATAR][0][70] = 127, + [2][0][RTW89_UK][1][70] = 127, + [2][0][RTW89_UK][0][70] = 127, + [2][0][RTW89_FCC][1][72] = 8, + [2][0][RTW89_FCC][2][72] = 78, + [2][0][RTW89_ETSI][1][72] = 127, + [2][0][RTW89_ETSI][0][72] = 127, + [2][0][RTW89_MKK][1][72] = 127, + [2][0][RTW89_MKK][0][72] = 127, + [2][0][RTW89_IC][1][72] = 8, + [2][0][RTW89_KCC][1][72] = -2, + [2][0][RTW89_KCC][0][72] = 127, + [2][0][RTW89_ACMA][1][72] = 127, + [2][0][RTW89_ACMA][0][72] = 127, + [2][0][RTW89_CHILE][1][72] = 127, + [2][0][RTW89_QATAR][1][72] = 127, + [2][0][RTW89_QATAR][0][72] = 127, + [2][0][RTW89_UK][1][72] = 127, + [2][0][RTW89_UK][0][72] = 127, + [2][0][RTW89_FCC][1][74] = 8, + [2][0][RTW89_FCC][2][74] = 78, + [2][0][RTW89_ETSI][1][74] = 127, + [2][0][RTW89_ETSI][0][74] = 127, + [2][0][RTW89_MKK][1][74] = 127, + [2][0][RTW89_MKK][0][74] = 127, + [2][0][RTW89_IC][1][74] = 8, + [2][0][RTW89_KCC][1][74] = -2, + [2][0][RTW89_KCC][0][74] = 127, + [2][0][RTW89_ACMA][1][74] = 127, + [2][0][RTW89_ACMA][0][74] = 127, + [2][0][RTW89_CHILE][1][74] = 127, + [2][0][RTW89_QATAR][1][74] = 127, + [2][0][RTW89_QATAR][0][74] = 127, + [2][0][RTW89_UK][1][74] = 127, + [2][0][RTW89_UK][0][74] = 127, + [2][0][RTW89_FCC][1][75] = 8, + [2][0][RTW89_FCC][2][75] = 78, + [2][0][RTW89_ETSI][1][75] = 127, + [2][0][RTW89_ETSI][0][75] = 127, + [2][0][RTW89_MKK][1][75] = 127, + [2][0][RTW89_MKK][0][75] = 127, + [2][0][RTW89_IC][1][75] = 8, + [2][0][RTW89_KCC][1][75] = -2, + [2][0][RTW89_KCC][0][75] = 127, + [2][0][RTW89_ACMA][1][75] = 127, + [2][0][RTW89_ACMA][0][75] = 127, + [2][0][RTW89_CHILE][1][75] = 127, + [2][0][RTW89_QATAR][1][75] = 127, + [2][0][RTW89_QATAR][0][75] = 127, + [2][0][RTW89_UK][1][75] = 127, + [2][0][RTW89_UK][0][75] = 127, + [2][0][RTW89_FCC][1][77] = 8, + [2][0][RTW89_FCC][2][77] = 78, + [2][0][RTW89_ETSI][1][77] = 127, + [2][0][RTW89_ETSI][0][77] = 127, + [2][0][RTW89_MKK][1][77] = 127, + [2][0][RTW89_MKK][0][77] = 127, + [2][0][RTW89_IC][1][77] = 8, + [2][0][RTW89_KCC][1][77] = -2, + [2][0][RTW89_KCC][0][77] = 127, + [2][0][RTW89_ACMA][1][77] = 127, + [2][0][RTW89_ACMA][0][77] = 127, + [2][0][RTW89_CHILE][1][77] = 127, + [2][0][RTW89_QATAR][1][77] = 127, + [2][0][RTW89_QATAR][0][77] = 127, + [2][0][RTW89_UK][1][77] = 127, + [2][0][RTW89_UK][0][77] = 127, + [2][0][RTW89_FCC][1][79] = 8, + [2][0][RTW89_FCC][2][79] = 78, + [2][0][RTW89_ETSI][1][79] = 127, + [2][0][RTW89_ETSI][0][79] = 127, + [2][0][RTW89_MKK][1][79] = 127, + [2][0][RTW89_MKK][0][79] = 127, + [2][0][RTW89_IC][1][79] = 8, + [2][0][RTW89_KCC][1][79] = -2, + [2][0][RTW89_KCC][0][79] = 127, + [2][0][RTW89_ACMA][1][79] = 127, + [2][0][RTW89_ACMA][0][79] = 127, + [2][0][RTW89_CHILE][1][79] = 127, + [2][0][RTW89_QATAR][1][79] = 127, + [2][0][RTW89_QATAR][0][79] = 127, + [2][0][RTW89_UK][1][79] = 127, + [2][0][RTW89_UK][0][79] = 127, + [2][0][RTW89_FCC][1][81] = 8, + [2][0][RTW89_FCC][2][81] = 78, + [2][0][RTW89_ETSI][1][81] = 127, + [2][0][RTW89_ETSI][0][81] = 127, + [2][0][RTW89_MKK][1][81] = 127, + [2][0][RTW89_MKK][0][81] = 127, + [2][0][RTW89_IC][1][81] = 8, + [2][0][RTW89_KCC][1][81] = -2, + [2][0][RTW89_KCC][0][81] = 127, + [2][0][RTW89_ACMA][1][81] = 127, + [2][0][RTW89_ACMA][0][81] = 127, + [2][0][RTW89_CHILE][1][81] = 127, + [2][0][RTW89_QATAR][1][81] = 127, + [2][0][RTW89_QATAR][0][81] = 127, + [2][0][RTW89_UK][1][81] = 127, + [2][0][RTW89_UK][0][81] = 127, + [2][0][RTW89_FCC][1][83] = 8, + [2][0][RTW89_FCC][2][83] = 78, + [2][0][RTW89_ETSI][1][83] = 127, + [2][0][RTW89_ETSI][0][83] = 127, + [2][0][RTW89_MKK][1][83] = 127, + [2][0][RTW89_MKK][0][83] = 127, + [2][0][RTW89_IC][1][83] = 8, + [2][0][RTW89_KCC][1][83] = -2, + [2][0][RTW89_KCC][0][83] = 127, + [2][0][RTW89_ACMA][1][83] = 127, + [2][0][RTW89_ACMA][0][83] = 127, + [2][0][RTW89_CHILE][1][83] = 127, + [2][0][RTW89_QATAR][1][83] = 127, + [2][0][RTW89_QATAR][0][83] = 127, + [2][0][RTW89_UK][1][83] = 127, + [2][0][RTW89_UK][0][83] = 127, + [2][0][RTW89_FCC][1][85] = 8, + [2][0][RTW89_FCC][2][85] = 78, + [2][0][RTW89_ETSI][1][85] = 127, + [2][0][RTW89_ETSI][0][85] = 127, + [2][0][RTW89_MKK][1][85] = 127, + [2][0][RTW89_MKK][0][85] = 127, + [2][0][RTW89_IC][1][85] = 8, + [2][0][RTW89_KCC][1][85] = -2, + [2][0][RTW89_KCC][0][85] = 127, + [2][0][RTW89_ACMA][1][85] = 127, + [2][0][RTW89_ACMA][0][85] = 127, + [2][0][RTW89_CHILE][1][85] = 127, + [2][0][RTW89_QATAR][1][85] = 127, + [2][0][RTW89_QATAR][0][85] = 127, + [2][0][RTW89_UK][1][85] = 127, + [2][0][RTW89_UK][0][85] = 127, + [2][0][RTW89_FCC][1][87] = 8, + [2][0][RTW89_FCC][2][87] = 127, + [2][0][RTW89_ETSI][1][87] = 127, + [2][0][RTW89_ETSI][0][87] = 127, + [2][0][RTW89_MKK][1][87] = 127, + [2][0][RTW89_MKK][0][87] = 127, + [2][0][RTW89_IC][1][87] = 8, + [2][0][RTW89_KCC][1][87] = -2, + [2][0][RTW89_KCC][0][87] = 127, + [2][0][RTW89_ACMA][1][87] = 127, + [2][0][RTW89_ACMA][0][87] = 127, + [2][0][RTW89_CHILE][1][87] = 127, + [2][0][RTW89_QATAR][1][87] = 127, + [2][0][RTW89_QATAR][0][87] = 127, + [2][0][RTW89_UK][1][87] = 127, + [2][0][RTW89_UK][0][87] = 127, + [2][0][RTW89_FCC][1][89] = 8, + [2][0][RTW89_FCC][2][89] = 127, + [2][0][RTW89_ETSI][1][89] = 127, + [2][0][RTW89_ETSI][0][89] = 127, + [2][0][RTW89_MKK][1][89] = 127, + [2][0][RTW89_MKK][0][89] = 127, + [2][0][RTW89_IC][1][89] = 8, + [2][0][RTW89_KCC][1][89] = -2, + [2][0][RTW89_KCC][0][89] = 127, + [2][0][RTW89_ACMA][1][89] = 127, + [2][0][RTW89_ACMA][0][89] = 127, + [2][0][RTW89_CHILE][1][89] = 127, + [2][0][RTW89_QATAR][1][89] = 127, + [2][0][RTW89_QATAR][0][89] = 127, + [2][0][RTW89_UK][1][89] = 127, + [2][0][RTW89_UK][0][89] = 127, + [2][0][RTW89_FCC][1][90] = 8, + [2][0][RTW89_FCC][2][90] = 127, + [2][0][RTW89_ETSI][1][90] = 127, + [2][0][RTW89_ETSI][0][90] = 127, + [2][0][RTW89_MKK][1][90] = 127, + [2][0][RTW89_MKK][0][90] = 127, + [2][0][RTW89_IC][1][90] = 8, + [2][0][RTW89_KCC][1][90] = -2, + [2][0][RTW89_KCC][0][90] = 127, + [2][0][RTW89_ACMA][1][90] = 127, + [2][0][RTW89_ACMA][0][90] = 127, + [2][0][RTW89_CHILE][1][90] = 127, + [2][0][RTW89_QATAR][1][90] = 127, + [2][0][RTW89_QATAR][0][90] = 127, + [2][0][RTW89_UK][1][90] = 127, + [2][0][RTW89_UK][0][90] = 127, + [2][0][RTW89_FCC][1][92] = 8, + [2][0][RTW89_FCC][2][92] = 127, + [2][0][RTW89_ETSI][1][92] = 127, + [2][0][RTW89_ETSI][0][92] = 127, + [2][0][RTW89_MKK][1][92] = 127, + [2][0][RTW89_MKK][0][92] = 127, + [2][0][RTW89_IC][1][92] = 8, + [2][0][RTW89_KCC][1][92] = -2, + [2][0][RTW89_KCC][0][92] = 127, + [2][0][RTW89_ACMA][1][92] = 127, + [2][0][RTW89_ACMA][0][92] = 127, + [2][0][RTW89_CHILE][1][92] = 127, + [2][0][RTW89_QATAR][1][92] = 127, + [2][0][RTW89_QATAR][0][92] = 127, + [2][0][RTW89_UK][1][92] = 127, + [2][0][RTW89_UK][0][92] = 127, + [2][0][RTW89_FCC][1][94] = 8, + [2][0][RTW89_FCC][2][94] = 127, + [2][0][RTW89_ETSI][1][94] = 127, + [2][0][RTW89_ETSI][0][94] = 127, + [2][0][RTW89_MKK][1][94] = 127, + [2][0][RTW89_MKK][0][94] = 127, + [2][0][RTW89_IC][1][94] = 8, + [2][0][RTW89_KCC][1][94] = -2, + [2][0][RTW89_KCC][0][94] = 127, + [2][0][RTW89_ACMA][1][94] = 127, + [2][0][RTW89_ACMA][0][94] = 127, + [2][0][RTW89_CHILE][1][94] = 127, + [2][0][RTW89_QATAR][1][94] = 127, + [2][0][RTW89_QATAR][0][94] = 127, + [2][0][RTW89_UK][1][94] = 127, + [2][0][RTW89_UK][0][94] = 127, + [2][0][RTW89_FCC][1][96] = 8, + [2][0][RTW89_FCC][2][96] = 127, + [2][0][RTW89_ETSI][1][96] = 127, + [2][0][RTW89_ETSI][0][96] = 127, + [2][0][RTW89_MKK][1][96] = 127, + [2][0][RTW89_MKK][0][96] = 127, + [2][0][RTW89_IC][1][96] = 8, + [2][0][RTW89_KCC][1][96] = -2, + [2][0][RTW89_KCC][0][96] = 127, + [2][0][RTW89_ACMA][1][96] = 127, + [2][0][RTW89_ACMA][0][96] = 127, + [2][0][RTW89_CHILE][1][96] = 127, + [2][0][RTW89_QATAR][1][96] = 127, + [2][0][RTW89_QATAR][0][96] = 127, + [2][0][RTW89_UK][1][96] = 127, + [2][0][RTW89_UK][0][96] = 127, + [2][0][RTW89_FCC][1][98] = 8, + [2][0][RTW89_FCC][2][98] = 127, + [2][0][RTW89_ETSI][1][98] = 127, + [2][0][RTW89_ETSI][0][98] = 127, + [2][0][RTW89_MKK][1][98] = 127, + [2][0][RTW89_MKK][0][98] = 127, + [2][0][RTW89_IC][1][98] = 8, + [2][0][RTW89_KCC][1][98] = -2, + [2][0][RTW89_KCC][0][98] = 127, + [2][0][RTW89_ACMA][1][98] = 127, + [2][0][RTW89_ACMA][0][98] = 127, + [2][0][RTW89_CHILE][1][98] = 127, + [2][0][RTW89_QATAR][1][98] = 127, + [2][0][RTW89_QATAR][0][98] = 127, + [2][0][RTW89_UK][1][98] = 127, + [2][0][RTW89_UK][0][98] = 127, + [2][0][RTW89_FCC][1][100] = 8, + [2][0][RTW89_FCC][2][100] = 127, + [2][0][RTW89_ETSI][1][100] = 127, + [2][0][RTW89_ETSI][0][100] = 127, + [2][0][RTW89_MKK][1][100] = 127, + [2][0][RTW89_MKK][0][100] = 127, + [2][0][RTW89_IC][1][100] = 8, + [2][0][RTW89_KCC][1][100] = -2, + [2][0][RTW89_KCC][0][100] = 127, + [2][0][RTW89_ACMA][1][100] = 127, + [2][0][RTW89_ACMA][0][100] = 127, + [2][0][RTW89_CHILE][1][100] = 127, + [2][0][RTW89_QATAR][1][100] = 127, + [2][0][RTW89_QATAR][0][100] = 127, + [2][0][RTW89_UK][1][100] = 127, + [2][0][RTW89_UK][0][100] = 127, + [2][0][RTW89_FCC][1][102] = 8, + [2][0][RTW89_FCC][2][102] = 127, + [2][0][RTW89_ETSI][1][102] = 127, + [2][0][RTW89_ETSI][0][102] = 127, + [2][0][RTW89_MKK][1][102] = 127, + [2][0][RTW89_MKK][0][102] = 127, + [2][0][RTW89_IC][1][102] = 8, + [2][0][RTW89_KCC][1][102] = -2, + [2][0][RTW89_KCC][0][102] = 127, + [2][0][RTW89_ACMA][1][102] = 127, + [2][0][RTW89_ACMA][0][102] = 127, + [2][0][RTW89_CHILE][1][102] = 127, + [2][0][RTW89_QATAR][1][102] = 127, + [2][0][RTW89_QATAR][0][102] = 127, + [2][0][RTW89_UK][1][102] = 127, + [2][0][RTW89_UK][0][102] = 127, + [2][0][RTW89_FCC][1][104] = 8, + [2][0][RTW89_FCC][2][104] = 127, + [2][0][RTW89_ETSI][1][104] = 127, + [2][0][RTW89_ETSI][0][104] = 127, + [2][0][RTW89_MKK][1][104] = 127, + [2][0][RTW89_MKK][0][104] = 127, + [2][0][RTW89_IC][1][104] = 8, + [2][0][RTW89_KCC][1][104] = -2, + [2][0][RTW89_KCC][0][104] = 127, + [2][0][RTW89_ACMA][1][104] = 127, + [2][0][RTW89_ACMA][0][104] = 127, + [2][0][RTW89_CHILE][1][104] = 127, + [2][0][RTW89_QATAR][1][104] = 127, + [2][0][RTW89_QATAR][0][104] = 127, + [2][0][RTW89_UK][1][104] = 127, + [2][0][RTW89_UK][0][104] = 127, + [2][0][RTW89_FCC][1][105] = 8, + [2][0][RTW89_FCC][2][105] = 127, + [2][0][RTW89_ETSI][1][105] = 127, + [2][0][RTW89_ETSI][0][105] = 127, + [2][0][RTW89_MKK][1][105] = 127, + [2][0][RTW89_MKK][0][105] = 127, + [2][0][RTW89_IC][1][105] = 8, + [2][0][RTW89_KCC][1][105] = -2, + [2][0][RTW89_KCC][0][105] = 127, + [2][0][RTW89_ACMA][1][105] = 127, + [2][0][RTW89_ACMA][0][105] = 127, + [2][0][RTW89_CHILE][1][105] = 127, + [2][0][RTW89_QATAR][1][105] = 127, + [2][0][RTW89_QATAR][0][105] = 127, + [2][0][RTW89_UK][1][105] = 127, + [2][0][RTW89_UK][0][105] = 127, + [2][0][RTW89_FCC][1][107] = 10, + [2][0][RTW89_FCC][2][107] = 127, + [2][0][RTW89_ETSI][1][107] = 127, + [2][0][RTW89_ETSI][0][107] = 127, + [2][0][RTW89_MKK][1][107] = 127, + [2][0][RTW89_MKK][0][107] = 127, + [2][0][RTW89_IC][1][107] = 10, + [2][0][RTW89_KCC][1][107] = -2, + [2][0][RTW89_KCC][0][107] = 127, + [2][0][RTW89_ACMA][1][107] = 127, + [2][0][RTW89_ACMA][0][107] = 127, + [2][0][RTW89_CHILE][1][107] = 127, + [2][0][RTW89_QATAR][1][107] = 127, + [2][0][RTW89_QATAR][0][107] = 127, + [2][0][RTW89_UK][1][107] = 127, + [2][0][RTW89_UK][0][107] = 127, + [2][0][RTW89_FCC][1][109] = 12, + [2][0][RTW89_FCC][2][109] = 127, + [2][0][RTW89_ETSI][1][109] = 127, + [2][0][RTW89_ETSI][0][109] = 127, + [2][0][RTW89_MKK][1][109] = 127, + [2][0][RTW89_MKK][0][109] = 127, + [2][0][RTW89_IC][1][109] = 12, + [2][0][RTW89_KCC][1][109] = 127, + [2][0][RTW89_KCC][0][109] = 127, + [2][0][RTW89_ACMA][1][109] = 127, + [2][0][RTW89_ACMA][0][109] = 127, + [2][0][RTW89_CHILE][1][109] = 127, + [2][0][RTW89_QATAR][1][109] = 127, + [2][0][RTW89_QATAR][0][109] = 127, + [2][0][RTW89_UK][1][109] = 127, + [2][0][RTW89_UK][0][109] = 127, + [2][0][RTW89_FCC][1][111] = 127, + [2][0][RTW89_FCC][2][111] = 127, + [2][0][RTW89_ETSI][1][111] = 127, + [2][0][RTW89_ETSI][0][111] = 127, + [2][0][RTW89_MKK][1][111] = 127, + [2][0][RTW89_MKK][0][111] = 127, + [2][0][RTW89_IC][1][111] = 127, + [2][0][RTW89_KCC][1][111] = 127, + [2][0][RTW89_KCC][0][111] = 127, + [2][0][RTW89_ACMA][1][111] = 127, + [2][0][RTW89_ACMA][0][111] = 127, + [2][0][RTW89_CHILE][1][111] = 127, + [2][0][RTW89_QATAR][1][111] = 127, + [2][0][RTW89_QATAR][0][111] = 127, + [2][0][RTW89_UK][1][111] = 127, + [2][0][RTW89_UK][0][111] = 127, + [2][0][RTW89_FCC][1][113] = 127, + [2][0][RTW89_FCC][2][113] = 127, + [2][0][RTW89_ETSI][1][113] = 127, + [2][0][RTW89_ETSI][0][113] = 127, + [2][0][RTW89_MKK][1][113] = 127, + [2][0][RTW89_MKK][0][113] = 127, + [2][0][RTW89_IC][1][113] = 127, + [2][0][RTW89_KCC][1][113] = 127, + [2][0][RTW89_KCC][0][113] = 127, + [2][0][RTW89_ACMA][1][113] = 127, + [2][0][RTW89_ACMA][0][113] = 127, + [2][0][RTW89_CHILE][1][113] = 127, + [2][0][RTW89_QATAR][1][113] = 127, + [2][0][RTW89_QATAR][0][113] = 127, + [2][0][RTW89_UK][1][113] = 127, + [2][0][RTW89_UK][0][113] = 127, + [2][0][RTW89_FCC][1][115] = 127, + [2][0][RTW89_FCC][2][115] = 127, + [2][0][RTW89_ETSI][1][115] = 127, + [2][0][RTW89_ETSI][0][115] = 127, + [2][0][RTW89_MKK][1][115] = 127, + [2][0][RTW89_MKK][0][115] = 127, + [2][0][RTW89_IC][1][115] = 127, + [2][0][RTW89_KCC][1][115] = 127, + [2][0][RTW89_KCC][0][115] = 127, + [2][0][RTW89_ACMA][1][115] = 127, + [2][0][RTW89_ACMA][0][115] = 127, + [2][0][RTW89_CHILE][1][115] = 127, + [2][0][RTW89_QATAR][1][115] = 127, + [2][0][RTW89_QATAR][0][115] = 127, + [2][0][RTW89_UK][1][115] = 127, + [2][0][RTW89_UK][0][115] = 127, + [2][0][RTW89_FCC][1][117] = 127, + [2][0][RTW89_FCC][2][117] = 127, + [2][0][RTW89_ETSI][1][117] = 127, + [2][0][RTW89_ETSI][0][117] = 127, + [2][0][RTW89_MKK][1][117] = 127, + [2][0][RTW89_MKK][0][117] = 127, + [2][0][RTW89_IC][1][117] = 127, + [2][0][RTW89_KCC][1][117] = 127, + [2][0][RTW89_KCC][0][117] = 127, + [2][0][RTW89_ACMA][1][117] = 127, + [2][0][RTW89_ACMA][0][117] = 127, + [2][0][RTW89_CHILE][1][117] = 127, + [2][0][RTW89_QATAR][1][117] = 127, + [2][0][RTW89_QATAR][0][117] = 127, + [2][0][RTW89_UK][1][117] = 127, + [2][0][RTW89_UK][0][117] = 127, + [2][0][RTW89_FCC][1][119] = 127, + [2][0][RTW89_FCC][2][119] = 127, + [2][0][RTW89_ETSI][1][119] = 127, + [2][0][RTW89_ETSI][0][119] = 127, + [2][0][RTW89_MKK][1][119] = 127, + [2][0][RTW89_MKK][0][119] = 127, + [2][0][RTW89_IC][1][119] = 127, + [2][0][RTW89_KCC][1][119] = 127, + [2][0][RTW89_KCC][0][119] = 127, + [2][0][RTW89_ACMA][1][119] = 127, + [2][0][RTW89_ACMA][0][119] = 127, + [2][0][RTW89_CHILE][1][119] = 127, + [2][0][RTW89_QATAR][1][119] = 127, + [2][0][RTW89_QATAR][0][119] = 127, + [2][0][RTW89_UK][1][119] = 127, + [2][0][RTW89_UK][0][119] = 127, + [2][1][RTW89_FCC][1][0] = -16, + [2][1][RTW89_FCC][2][0] = 54, + [2][1][RTW89_ETSI][1][0] = 44, + [2][1][RTW89_ETSI][0][0] = 6, + [2][1][RTW89_MKK][1][0] = 42, + [2][1][RTW89_MKK][0][0] = 2, + [2][1][RTW89_IC][1][0] = -16, + [2][1][RTW89_KCC][1][0] = -14, + [2][1][RTW89_KCC][0][0] = -14, + [2][1][RTW89_ACMA][1][0] = 44, + [2][1][RTW89_ACMA][0][0] = 6, + [2][1][RTW89_CHILE][1][0] = -16, + [2][1][RTW89_QATAR][1][0] = 44, + [2][1][RTW89_QATAR][0][0] = 6, + [2][1][RTW89_UK][1][0] = 44, + [2][1][RTW89_UK][0][0] = 6, + [2][1][RTW89_FCC][1][2] = -16, + [2][1][RTW89_FCC][2][2] = 54, + [2][1][RTW89_ETSI][1][2] = 44, + [2][1][RTW89_ETSI][0][2] = 6, + [2][1][RTW89_MKK][1][2] = 40, + [2][1][RTW89_MKK][0][2] = 2, + [2][1][RTW89_IC][1][2] = -16, + [2][1][RTW89_KCC][1][2] = -14, + [2][1][RTW89_KCC][0][2] = -14, + [2][1][RTW89_ACMA][1][2] = 44, + [2][1][RTW89_ACMA][0][2] = 6, + [2][1][RTW89_CHILE][1][2] = -16, + [2][1][RTW89_QATAR][1][2] = 44, + [2][1][RTW89_QATAR][0][2] = 6, + [2][1][RTW89_UK][1][2] = 44, + [2][1][RTW89_UK][0][2] = 6, + [2][1][RTW89_FCC][1][4] = -16, + [2][1][RTW89_FCC][2][4] = 54, + [2][1][RTW89_ETSI][1][4] = 44, + [2][1][RTW89_ETSI][0][4] = 6, + [2][1][RTW89_MKK][1][4] = 40, + [2][1][RTW89_MKK][0][4] = 2, + [2][1][RTW89_IC][1][4] = -16, + [2][1][RTW89_KCC][1][4] = -14, + [2][1][RTW89_KCC][0][4] = -14, + [2][1][RTW89_ACMA][1][4] = 44, + [2][1][RTW89_ACMA][0][4] = 6, + [2][1][RTW89_CHILE][1][4] = -16, + [2][1][RTW89_QATAR][1][4] = 44, + [2][1][RTW89_QATAR][0][4] = 6, + [2][1][RTW89_UK][1][4] = 44, + [2][1][RTW89_UK][0][4] = 6, + [2][1][RTW89_FCC][1][6] = -16, + [2][1][RTW89_FCC][2][6] = 54, + [2][1][RTW89_ETSI][1][6] = 44, + [2][1][RTW89_ETSI][0][6] = 6, + [2][1][RTW89_MKK][1][6] = 40, + [2][1][RTW89_MKK][0][6] = 2, + [2][1][RTW89_IC][1][6] = -16, + [2][1][RTW89_KCC][1][6] = -14, + [2][1][RTW89_KCC][0][6] = -14, + [2][1][RTW89_ACMA][1][6] = 44, + [2][1][RTW89_ACMA][0][6] = 6, + [2][1][RTW89_CHILE][1][6] = -16, + [2][1][RTW89_QATAR][1][6] = 44, + [2][1][RTW89_QATAR][0][6] = 6, + [2][1][RTW89_UK][1][6] = 44, + [2][1][RTW89_UK][0][6] = 6, + [2][1][RTW89_FCC][1][8] = -16, + [2][1][RTW89_FCC][2][8] = 54, + [2][1][RTW89_ETSI][1][8] = 44, + [2][1][RTW89_ETSI][0][8] = 6, + [2][1][RTW89_MKK][1][8] = 40, + [2][1][RTW89_MKK][0][8] = 2, + [2][1][RTW89_IC][1][8] = -16, + [2][1][RTW89_KCC][1][8] = -14, + [2][1][RTW89_KCC][0][8] = -14, + [2][1][RTW89_ACMA][1][8] = 44, + [2][1][RTW89_ACMA][0][8] = 6, + [2][1][RTW89_CHILE][1][8] = -16, + [2][1][RTW89_QATAR][1][8] = 44, + [2][1][RTW89_QATAR][0][8] = 6, + [2][1][RTW89_UK][1][8] = 44, + [2][1][RTW89_UK][0][8] = 6, + [2][1][RTW89_FCC][1][10] = -16, + [2][1][RTW89_FCC][2][10] = 54, + [2][1][RTW89_ETSI][1][10] = 44, + [2][1][RTW89_ETSI][0][10] = 6, + [2][1][RTW89_MKK][1][10] = 40, + [2][1][RTW89_MKK][0][10] = 2, + [2][1][RTW89_IC][1][10] = -16, + [2][1][RTW89_KCC][1][10] = -14, + [2][1][RTW89_KCC][0][10] = -14, + [2][1][RTW89_ACMA][1][10] = 44, + [2][1][RTW89_ACMA][0][10] = 6, + [2][1][RTW89_CHILE][1][10] = -16, + [2][1][RTW89_QATAR][1][10] = 44, + [2][1][RTW89_QATAR][0][10] = 6, + [2][1][RTW89_UK][1][10] = 44, + [2][1][RTW89_UK][0][10] = 6, + [2][1][RTW89_FCC][1][12] = -16, + [2][1][RTW89_FCC][2][12] = 54, + [2][1][RTW89_ETSI][1][12] = 44, + [2][1][RTW89_ETSI][0][12] = 6, + [2][1][RTW89_MKK][1][12] = 40, + [2][1][RTW89_MKK][0][12] = 2, + [2][1][RTW89_IC][1][12] = -16, + [2][1][RTW89_KCC][1][12] = -14, + [2][1][RTW89_KCC][0][12] = -14, + [2][1][RTW89_ACMA][1][12] = 44, + [2][1][RTW89_ACMA][0][12] = 6, + [2][1][RTW89_CHILE][1][12] = -16, + [2][1][RTW89_QATAR][1][12] = 44, + [2][1][RTW89_QATAR][0][12] = 6, + [2][1][RTW89_UK][1][12] = 44, + [2][1][RTW89_UK][0][12] = 6, + [2][1][RTW89_FCC][1][14] = -16, + [2][1][RTW89_FCC][2][14] = 54, + [2][1][RTW89_ETSI][1][14] = 44, + [2][1][RTW89_ETSI][0][14] = 6, + [2][1][RTW89_MKK][1][14] = 40, + [2][1][RTW89_MKK][0][14] = 2, + [2][1][RTW89_IC][1][14] = -16, + [2][1][RTW89_KCC][1][14] = -14, + [2][1][RTW89_KCC][0][14] = -14, + [2][1][RTW89_ACMA][1][14] = 44, + [2][1][RTW89_ACMA][0][14] = 6, + [2][1][RTW89_CHILE][1][14] = -16, + [2][1][RTW89_QATAR][1][14] = 44, + [2][1][RTW89_QATAR][0][14] = 6, + [2][1][RTW89_UK][1][14] = 44, + [2][1][RTW89_UK][0][14] = 6, + [2][1][RTW89_FCC][1][15] = -16, + [2][1][RTW89_FCC][2][15] = 54, + [2][1][RTW89_ETSI][1][15] = 44, + [2][1][RTW89_ETSI][0][15] = 6, + [2][1][RTW89_MKK][1][15] = 40, + [2][1][RTW89_MKK][0][15] = 2, + [2][1][RTW89_IC][1][15] = -16, + [2][1][RTW89_KCC][1][15] = -14, + [2][1][RTW89_KCC][0][15] = -14, + [2][1][RTW89_ACMA][1][15] = 44, + [2][1][RTW89_ACMA][0][15] = 6, + [2][1][RTW89_CHILE][1][15] = -16, + [2][1][RTW89_QATAR][1][15] = 44, + [2][1][RTW89_QATAR][0][15] = 6, + [2][1][RTW89_UK][1][15] = 44, + [2][1][RTW89_UK][0][15] = 6, + [2][1][RTW89_FCC][1][17] = -16, + [2][1][RTW89_FCC][2][17] = 54, + [2][1][RTW89_ETSI][1][17] = 44, + [2][1][RTW89_ETSI][0][17] = 6, + [2][1][RTW89_MKK][1][17] = 40, + [2][1][RTW89_MKK][0][17] = 2, + [2][1][RTW89_IC][1][17] = -16, + [2][1][RTW89_KCC][1][17] = -14, + [2][1][RTW89_KCC][0][17] = -14, + [2][1][RTW89_ACMA][1][17] = 44, + [2][1][RTW89_ACMA][0][17] = 6, + [2][1][RTW89_CHILE][1][17] = -16, + [2][1][RTW89_QATAR][1][17] = 44, + [2][1][RTW89_QATAR][0][17] = 6, + [2][1][RTW89_UK][1][17] = 44, + [2][1][RTW89_UK][0][17] = 6, + [2][1][RTW89_FCC][1][19] = -16, + [2][1][RTW89_FCC][2][19] = 54, + [2][1][RTW89_ETSI][1][19] = 44, + [2][1][RTW89_ETSI][0][19] = 6, + [2][1][RTW89_MKK][1][19] = 40, + [2][1][RTW89_MKK][0][19] = 2, + [2][1][RTW89_IC][1][19] = -16, + [2][1][RTW89_KCC][1][19] = -14, + [2][1][RTW89_KCC][0][19] = -14, + [2][1][RTW89_ACMA][1][19] = 44, + [2][1][RTW89_ACMA][0][19] = 6, + [2][1][RTW89_CHILE][1][19] = -16, + [2][1][RTW89_QATAR][1][19] = 44, + [2][1][RTW89_QATAR][0][19] = 6, + [2][1][RTW89_UK][1][19] = 44, + [2][1][RTW89_UK][0][19] = 6, + [2][1][RTW89_FCC][1][21] = -16, + [2][1][RTW89_FCC][2][21] = 54, + [2][1][RTW89_ETSI][1][21] = 44, + [2][1][RTW89_ETSI][0][21] = 6, + [2][1][RTW89_MKK][1][21] = 40, + [2][1][RTW89_MKK][0][21] = 2, + [2][1][RTW89_IC][1][21] = -16, + [2][1][RTW89_KCC][1][21] = -14, + [2][1][RTW89_KCC][0][21] = -14, + [2][1][RTW89_ACMA][1][21] = 44, + [2][1][RTW89_ACMA][0][21] = 6, + [2][1][RTW89_CHILE][1][21] = -16, + [2][1][RTW89_QATAR][1][21] = 44, + [2][1][RTW89_QATAR][0][21] = 6, + [2][1][RTW89_UK][1][21] = 44, + [2][1][RTW89_UK][0][21] = 6, + [2][1][RTW89_FCC][1][23] = -16, + [2][1][RTW89_FCC][2][23] = 54, + [2][1][RTW89_ETSI][1][23] = 44, + [2][1][RTW89_ETSI][0][23] = 6, + [2][1][RTW89_MKK][1][23] = 40, + [2][1][RTW89_MKK][0][23] = 2, + [2][1][RTW89_IC][1][23] = -16, + [2][1][RTW89_KCC][1][23] = -14, + [2][1][RTW89_KCC][0][23] = -14, + [2][1][RTW89_ACMA][1][23] = 44, + [2][1][RTW89_ACMA][0][23] = 6, + [2][1][RTW89_CHILE][1][23] = -16, + [2][1][RTW89_QATAR][1][23] = 44, + [2][1][RTW89_QATAR][0][23] = 6, + [2][1][RTW89_UK][1][23] = 44, + [2][1][RTW89_UK][0][23] = 6, + [2][1][RTW89_FCC][1][25] = -16, + [2][1][RTW89_FCC][2][25] = 54, + [2][1][RTW89_ETSI][1][25] = 44, + [2][1][RTW89_ETSI][0][25] = 6, + [2][1][RTW89_MKK][1][25] = 40, + [2][1][RTW89_MKK][0][25] = 2, + [2][1][RTW89_IC][1][25] = -16, + [2][1][RTW89_KCC][1][25] = -14, + [2][1][RTW89_KCC][0][25] = -14, + [2][1][RTW89_ACMA][1][25] = 44, + [2][1][RTW89_ACMA][0][25] = 6, + [2][1][RTW89_CHILE][1][25] = -16, + [2][1][RTW89_QATAR][1][25] = 44, + [2][1][RTW89_QATAR][0][25] = 6, + [2][1][RTW89_UK][1][25] = 44, + [2][1][RTW89_UK][0][25] = 6, + [2][1][RTW89_FCC][1][27] = -16, + [2][1][RTW89_FCC][2][27] = 54, + [2][1][RTW89_ETSI][1][27] = 44, + [2][1][RTW89_ETSI][0][27] = 6, + [2][1][RTW89_MKK][1][27] = 40, + [2][1][RTW89_MKK][0][27] = 2, + [2][1][RTW89_IC][1][27] = -16, + [2][1][RTW89_KCC][1][27] = -14, + [2][1][RTW89_KCC][0][27] = -14, + [2][1][RTW89_ACMA][1][27] = 44, + [2][1][RTW89_ACMA][0][27] = 6, + [2][1][RTW89_CHILE][1][27] = -16, + [2][1][RTW89_QATAR][1][27] = 44, + [2][1][RTW89_QATAR][0][27] = 6, + [2][1][RTW89_UK][1][27] = 44, + [2][1][RTW89_UK][0][27] = 6, + [2][1][RTW89_FCC][1][29] = -16, + [2][1][RTW89_FCC][2][29] = 54, + [2][1][RTW89_ETSI][1][29] = 44, + [2][1][RTW89_ETSI][0][29] = 6, + [2][1][RTW89_MKK][1][29] = 40, + [2][1][RTW89_MKK][0][29] = 2, + [2][1][RTW89_IC][1][29] = -16, + [2][1][RTW89_KCC][1][29] = -14, + [2][1][RTW89_KCC][0][29] = -14, + [2][1][RTW89_ACMA][1][29] = 44, + [2][1][RTW89_ACMA][0][29] = 6, + [2][1][RTW89_CHILE][1][29] = -16, + [2][1][RTW89_QATAR][1][29] = 44, + [2][1][RTW89_QATAR][0][29] = 6, + [2][1][RTW89_UK][1][29] = 44, + [2][1][RTW89_UK][0][29] = 6, + [2][1][RTW89_FCC][1][30] = -16, + [2][1][RTW89_FCC][2][30] = 54, + [2][1][RTW89_ETSI][1][30] = 44, + [2][1][RTW89_ETSI][0][30] = 6, + [2][1][RTW89_MKK][1][30] = 40, + [2][1][RTW89_MKK][0][30] = 2, + [2][1][RTW89_IC][1][30] = -16, + [2][1][RTW89_KCC][1][30] = -14, + [2][1][RTW89_KCC][0][30] = -14, + [2][1][RTW89_ACMA][1][30] = 44, + [2][1][RTW89_ACMA][0][30] = 6, + [2][1][RTW89_CHILE][1][30] = -16, + [2][1][RTW89_QATAR][1][30] = 44, + [2][1][RTW89_QATAR][0][30] = 6, + [2][1][RTW89_UK][1][30] = 44, + [2][1][RTW89_UK][0][30] = 6, + [2][1][RTW89_FCC][1][32] = -16, + [2][1][RTW89_FCC][2][32] = 54, + [2][1][RTW89_ETSI][1][32] = 44, + [2][1][RTW89_ETSI][0][32] = 6, + [2][1][RTW89_MKK][1][32] = 40, + [2][1][RTW89_MKK][0][32] = 2, + [2][1][RTW89_IC][1][32] = -16, + [2][1][RTW89_KCC][1][32] = -14, + [2][1][RTW89_KCC][0][32] = -14, + [2][1][RTW89_ACMA][1][32] = 44, + [2][1][RTW89_ACMA][0][32] = 6, + [2][1][RTW89_CHILE][1][32] = -16, + [2][1][RTW89_QATAR][1][32] = 44, + [2][1][RTW89_QATAR][0][32] = 6, + [2][1][RTW89_UK][1][32] = 44, + [2][1][RTW89_UK][0][32] = 6, + [2][1][RTW89_FCC][1][34] = -16, + [2][1][RTW89_FCC][2][34] = 54, + [2][1][RTW89_ETSI][1][34] = 44, + [2][1][RTW89_ETSI][0][34] = 6, + [2][1][RTW89_MKK][1][34] = 40, + [2][1][RTW89_MKK][0][34] = 2, + [2][1][RTW89_IC][1][34] = -16, + [2][1][RTW89_KCC][1][34] = -14, + [2][1][RTW89_KCC][0][34] = -14, + [2][1][RTW89_ACMA][1][34] = 44, + [2][1][RTW89_ACMA][0][34] = 6, + [2][1][RTW89_CHILE][1][34] = -16, + [2][1][RTW89_QATAR][1][34] = 44, + [2][1][RTW89_QATAR][0][34] = 6, + [2][1][RTW89_UK][1][34] = 44, + [2][1][RTW89_UK][0][34] = 6, + [2][1][RTW89_FCC][1][36] = -16, + [2][1][RTW89_FCC][2][36] = 54, + [2][1][RTW89_ETSI][1][36] = 44, + [2][1][RTW89_ETSI][0][36] = 6, + [2][1][RTW89_MKK][1][36] = 40, + [2][1][RTW89_MKK][0][36] = 2, + [2][1][RTW89_IC][1][36] = -16, + [2][1][RTW89_KCC][1][36] = -14, + [2][1][RTW89_KCC][0][36] = -14, + [2][1][RTW89_ACMA][1][36] = 44, + [2][1][RTW89_ACMA][0][36] = 6, + [2][1][RTW89_CHILE][1][36] = -16, + [2][1][RTW89_QATAR][1][36] = 44, + [2][1][RTW89_QATAR][0][36] = 6, + [2][1][RTW89_UK][1][36] = 44, + [2][1][RTW89_UK][0][36] = 6, + [2][1][RTW89_FCC][1][38] = -16, + [2][1][RTW89_FCC][2][38] = 54, + [2][1][RTW89_ETSI][1][38] = 44, + [2][1][RTW89_ETSI][0][38] = 6, + [2][1][RTW89_MKK][1][38] = 40, + [2][1][RTW89_MKK][0][38] = 2, + [2][1][RTW89_IC][1][38] = -16, + [2][1][RTW89_KCC][1][38] = -14, + [2][1][RTW89_KCC][0][38] = -14, + [2][1][RTW89_ACMA][1][38] = 44, + [2][1][RTW89_ACMA][0][38] = 6, + [2][1][RTW89_CHILE][1][38] = -16, + [2][1][RTW89_QATAR][1][38] = 44, + [2][1][RTW89_QATAR][0][38] = 6, + [2][1][RTW89_UK][1][38] = 44, + [2][1][RTW89_UK][0][38] = 6, + [2][1][RTW89_FCC][1][40] = -16, + [2][1][RTW89_FCC][2][40] = 54, + [2][1][RTW89_ETSI][1][40] = 44, + [2][1][RTW89_ETSI][0][40] = 6, + [2][1][RTW89_MKK][1][40] = 40, + [2][1][RTW89_MKK][0][40] = 2, + [2][1][RTW89_IC][1][40] = -16, + [2][1][RTW89_KCC][1][40] = -14, + [2][1][RTW89_KCC][0][40] = -14, + [2][1][RTW89_ACMA][1][40] = 44, + [2][1][RTW89_ACMA][0][40] = 6, + [2][1][RTW89_CHILE][1][40] = -16, + [2][1][RTW89_QATAR][1][40] = 44, + [2][1][RTW89_QATAR][0][40] = 6, + [2][1][RTW89_UK][1][40] = 44, + [2][1][RTW89_UK][0][40] = 6, + [2][1][RTW89_FCC][1][42] = -16, + [2][1][RTW89_FCC][2][42] = 54, + [2][1][RTW89_ETSI][1][42] = 44, + [2][1][RTW89_ETSI][0][42] = 6, + [2][1][RTW89_MKK][1][42] = 40, + [2][1][RTW89_MKK][0][42] = 2, + [2][1][RTW89_IC][1][42] = -16, + [2][1][RTW89_KCC][1][42] = -14, + [2][1][RTW89_KCC][0][42] = -14, + [2][1][RTW89_ACMA][1][42] = 44, + [2][1][RTW89_ACMA][0][42] = 6, + [2][1][RTW89_CHILE][1][42] = -16, + [2][1][RTW89_QATAR][1][42] = 44, + [2][1][RTW89_QATAR][0][42] = 6, + [2][1][RTW89_UK][1][42] = 44, + [2][1][RTW89_UK][0][42] = 6, + [2][1][RTW89_FCC][1][44] = -16, + [2][1][RTW89_FCC][2][44] = 54, + [2][1][RTW89_ETSI][1][44] = 44, + [2][1][RTW89_ETSI][0][44] = 6, + [2][1][RTW89_MKK][1][44] = 16, + [2][1][RTW89_MKK][0][44] = 2, + [2][1][RTW89_IC][1][44] = -16, + [2][1][RTW89_KCC][1][44] = -14, + [2][1][RTW89_KCC][0][44] = -14, + [2][1][RTW89_ACMA][1][44] = 44, + [2][1][RTW89_ACMA][0][44] = 6, + [2][1][RTW89_CHILE][1][44] = -16, + [2][1][RTW89_QATAR][1][44] = 44, + [2][1][RTW89_QATAR][0][44] = 6, + [2][1][RTW89_UK][1][44] = 44, + [2][1][RTW89_UK][0][44] = 6, + [2][1][RTW89_FCC][1][45] = -16, + [2][1][RTW89_FCC][2][45] = 127, + [2][1][RTW89_ETSI][1][45] = 127, + [2][1][RTW89_ETSI][0][45] = 127, + [2][1][RTW89_MKK][1][45] = 127, + [2][1][RTW89_MKK][0][45] = 127, + [2][1][RTW89_IC][1][45] = -16, + [2][1][RTW89_KCC][1][45] = -14, + [2][1][RTW89_KCC][0][45] = 127, + [2][1][RTW89_ACMA][1][45] = 127, + [2][1][RTW89_ACMA][0][45] = 127, + [2][1][RTW89_CHILE][1][45] = 127, + [2][1][RTW89_QATAR][1][45] = 127, + [2][1][RTW89_QATAR][0][45] = 127, + [2][1][RTW89_UK][1][45] = 127, + [2][1][RTW89_UK][0][45] = 127, + [2][1][RTW89_FCC][1][47] = -16, + [2][1][RTW89_FCC][2][47] = 127, + [2][1][RTW89_ETSI][1][47] = 127, + [2][1][RTW89_ETSI][0][47] = 127, + [2][1][RTW89_MKK][1][47] = 127, + [2][1][RTW89_MKK][0][47] = 127, + [2][1][RTW89_IC][1][47] = -16, + [2][1][RTW89_KCC][1][47] = -14, + [2][1][RTW89_KCC][0][47] = 127, + [2][1][RTW89_ACMA][1][47] = 127, + [2][1][RTW89_ACMA][0][47] = 127, + [2][1][RTW89_CHILE][1][47] = 127, + [2][1][RTW89_QATAR][1][47] = 127, + [2][1][RTW89_QATAR][0][47] = 127, + [2][1][RTW89_UK][1][47] = 127, + [2][1][RTW89_UK][0][47] = 127, + [2][1][RTW89_FCC][1][49] = -16, + [2][1][RTW89_FCC][2][49] = 127, + [2][1][RTW89_ETSI][1][49] = 127, + [2][1][RTW89_ETSI][0][49] = 127, + [2][1][RTW89_MKK][1][49] = 127, + [2][1][RTW89_MKK][0][49] = 127, + [2][1][RTW89_IC][1][49] = -16, + [2][1][RTW89_KCC][1][49] = -14, + [2][1][RTW89_KCC][0][49] = 127, + [2][1][RTW89_ACMA][1][49] = 127, + [2][1][RTW89_ACMA][0][49] = 127, + [2][1][RTW89_CHILE][1][49] = 127, + [2][1][RTW89_QATAR][1][49] = 127, + [2][1][RTW89_QATAR][0][49] = 127, + [2][1][RTW89_UK][1][49] = 127, + [2][1][RTW89_UK][0][49] = 127, + [2][1][RTW89_FCC][1][51] = -16, + [2][1][RTW89_FCC][2][51] = 127, + [2][1][RTW89_ETSI][1][51] = 127, + [2][1][RTW89_ETSI][0][51] = 127, + [2][1][RTW89_MKK][1][51] = 127, + [2][1][RTW89_MKK][0][51] = 127, + [2][1][RTW89_IC][1][51] = -16, + [2][1][RTW89_KCC][1][51] = -14, + [2][1][RTW89_KCC][0][51] = 127, + [2][1][RTW89_ACMA][1][51] = 127, + [2][1][RTW89_ACMA][0][51] = 127, + [2][1][RTW89_CHILE][1][51] = 127, + [2][1][RTW89_QATAR][1][51] = 127, + [2][1][RTW89_QATAR][0][51] = 127, + [2][1][RTW89_UK][1][51] = 127, + [2][1][RTW89_UK][0][51] = 127, + [2][1][RTW89_FCC][1][53] = -16, + [2][1][RTW89_FCC][2][53] = 127, + [2][1][RTW89_ETSI][1][53] = 127, + [2][1][RTW89_ETSI][0][53] = 127, + [2][1][RTW89_MKK][1][53] = 127, + [2][1][RTW89_MKK][0][53] = 127, + [2][1][RTW89_IC][1][53] = -16, + [2][1][RTW89_KCC][1][53] = -14, + [2][1][RTW89_KCC][0][53] = 127, + [2][1][RTW89_ACMA][1][53] = 127, + [2][1][RTW89_ACMA][0][53] = 127, + [2][1][RTW89_CHILE][1][53] = 127, + [2][1][RTW89_QATAR][1][53] = 127, + [2][1][RTW89_QATAR][0][53] = 127, + [2][1][RTW89_UK][1][53] = 127, + [2][1][RTW89_UK][0][53] = 127, + [2][1][RTW89_FCC][1][55] = -16, + [2][1][RTW89_FCC][2][55] = 54, + [2][1][RTW89_ETSI][1][55] = 127, + [2][1][RTW89_ETSI][0][55] = 127, + [2][1][RTW89_MKK][1][55] = 127, + [2][1][RTW89_MKK][0][55] = 127, + [2][1][RTW89_IC][1][55] = -16, + [2][1][RTW89_KCC][1][55] = -14, + [2][1][RTW89_KCC][0][55] = 127, + [2][1][RTW89_ACMA][1][55] = 127, + [2][1][RTW89_ACMA][0][55] = 127, + [2][1][RTW89_CHILE][1][55] = 127, + [2][1][RTW89_QATAR][1][55] = 127, + [2][1][RTW89_QATAR][0][55] = 127, + [2][1][RTW89_UK][1][55] = 127, + [2][1][RTW89_UK][0][55] = 127, + [2][1][RTW89_FCC][1][57] = -16, + [2][1][RTW89_FCC][2][57] = 54, + [2][1][RTW89_ETSI][1][57] = 127, + [2][1][RTW89_ETSI][0][57] = 127, + [2][1][RTW89_MKK][1][57] = 127, + [2][1][RTW89_MKK][0][57] = 127, + [2][1][RTW89_IC][1][57] = -16, + [2][1][RTW89_KCC][1][57] = -14, + [2][1][RTW89_KCC][0][57] = 127, + [2][1][RTW89_ACMA][1][57] = 127, + [2][1][RTW89_ACMA][0][57] = 127, + [2][1][RTW89_CHILE][1][57] = 127, + [2][1][RTW89_QATAR][1][57] = 127, + [2][1][RTW89_QATAR][0][57] = 127, + [2][1][RTW89_UK][1][57] = 127, + [2][1][RTW89_UK][0][57] = 127, + [2][1][RTW89_FCC][1][59] = -16, + [2][1][RTW89_FCC][2][59] = 54, + [2][1][RTW89_ETSI][1][59] = 127, + [2][1][RTW89_ETSI][0][59] = 127, + [2][1][RTW89_MKK][1][59] = 127, + [2][1][RTW89_MKK][0][59] = 127, + [2][1][RTW89_IC][1][59] = -16, + [2][1][RTW89_KCC][1][59] = -14, + [2][1][RTW89_KCC][0][59] = 127, + [2][1][RTW89_ACMA][1][59] = 127, + [2][1][RTW89_ACMA][0][59] = 127, + [2][1][RTW89_CHILE][1][59] = 127, + [2][1][RTW89_QATAR][1][59] = 127, + [2][1][RTW89_QATAR][0][59] = 127, + [2][1][RTW89_UK][1][59] = 127, + [2][1][RTW89_UK][0][59] = 127, + [2][1][RTW89_FCC][1][60] = -16, + [2][1][RTW89_FCC][2][60] = 54, + [2][1][RTW89_ETSI][1][60] = 127, + [2][1][RTW89_ETSI][0][60] = 127, + [2][1][RTW89_MKK][1][60] = 127, + [2][1][RTW89_MKK][0][60] = 127, + [2][1][RTW89_IC][1][60] = -16, + [2][1][RTW89_KCC][1][60] = -14, + [2][1][RTW89_KCC][0][60] = 127, + [2][1][RTW89_ACMA][1][60] = 127, + [2][1][RTW89_ACMA][0][60] = 127, + [2][1][RTW89_CHILE][1][60] = 127, + [2][1][RTW89_QATAR][1][60] = 127, + [2][1][RTW89_QATAR][0][60] = 127, + [2][1][RTW89_UK][1][60] = 127, + [2][1][RTW89_UK][0][60] = 127, + [2][1][RTW89_FCC][1][62] = -16, + [2][1][RTW89_FCC][2][62] = 54, + [2][1][RTW89_ETSI][1][62] = 127, + [2][1][RTW89_ETSI][0][62] = 127, + [2][1][RTW89_MKK][1][62] = 127, + [2][1][RTW89_MKK][0][62] = 127, + [2][1][RTW89_IC][1][62] = -16, + [2][1][RTW89_KCC][1][62] = -14, + [2][1][RTW89_KCC][0][62] = 127, + [2][1][RTW89_ACMA][1][62] = 127, + [2][1][RTW89_ACMA][0][62] = 127, + [2][1][RTW89_CHILE][1][62] = 127, + [2][1][RTW89_QATAR][1][62] = 127, + [2][1][RTW89_QATAR][0][62] = 127, + [2][1][RTW89_UK][1][62] = 127, + [2][1][RTW89_UK][0][62] = 127, + [2][1][RTW89_FCC][1][64] = -16, + [2][1][RTW89_FCC][2][64] = 54, + [2][1][RTW89_ETSI][1][64] = 127, + [2][1][RTW89_ETSI][0][64] = 127, + [2][1][RTW89_MKK][1][64] = 127, + [2][1][RTW89_MKK][0][64] = 127, + [2][1][RTW89_IC][1][64] = -16, + [2][1][RTW89_KCC][1][64] = -14, + [2][1][RTW89_KCC][0][64] = 127, + [2][1][RTW89_ACMA][1][64] = 127, + [2][1][RTW89_ACMA][0][64] = 127, + [2][1][RTW89_CHILE][1][64] = 127, + [2][1][RTW89_QATAR][1][64] = 127, + [2][1][RTW89_QATAR][0][64] = 127, + [2][1][RTW89_UK][1][64] = 127, + [2][1][RTW89_UK][0][64] = 127, + [2][1][RTW89_FCC][1][66] = -16, + [2][1][RTW89_FCC][2][66] = 54, + [2][1][RTW89_ETSI][1][66] = 127, + [2][1][RTW89_ETSI][0][66] = 127, + [2][1][RTW89_MKK][1][66] = 127, + [2][1][RTW89_MKK][0][66] = 127, + [2][1][RTW89_IC][1][66] = -16, + [2][1][RTW89_KCC][1][66] = -14, + [2][1][RTW89_KCC][0][66] = 127, + [2][1][RTW89_ACMA][1][66] = 127, + [2][1][RTW89_ACMA][0][66] = 127, + [2][1][RTW89_CHILE][1][66] = 127, + [2][1][RTW89_QATAR][1][66] = 127, + [2][1][RTW89_QATAR][0][66] = 127, + [2][1][RTW89_UK][1][66] = 127, + [2][1][RTW89_UK][0][66] = 127, + [2][1][RTW89_FCC][1][68] = -16, + [2][1][RTW89_FCC][2][68] = 54, + [2][1][RTW89_ETSI][1][68] = 127, + [2][1][RTW89_ETSI][0][68] = 127, + [2][1][RTW89_MKK][1][68] = 127, + [2][1][RTW89_MKK][0][68] = 127, + [2][1][RTW89_IC][1][68] = -16, + [2][1][RTW89_KCC][1][68] = -14, + [2][1][RTW89_KCC][0][68] = 127, + [2][1][RTW89_ACMA][1][68] = 127, + [2][1][RTW89_ACMA][0][68] = 127, + [2][1][RTW89_CHILE][1][68] = 127, + [2][1][RTW89_QATAR][1][68] = 127, + [2][1][RTW89_QATAR][0][68] = 127, + [2][1][RTW89_UK][1][68] = 127, + [2][1][RTW89_UK][0][68] = 127, + [2][1][RTW89_FCC][1][70] = -16, + [2][1][RTW89_FCC][2][70] = 56, + [2][1][RTW89_ETSI][1][70] = 127, + [2][1][RTW89_ETSI][0][70] = 127, + [2][1][RTW89_MKK][1][70] = 127, + [2][1][RTW89_MKK][0][70] = 127, + [2][1][RTW89_IC][1][70] = -16, + [2][1][RTW89_KCC][1][70] = -14, + [2][1][RTW89_KCC][0][70] = 127, + [2][1][RTW89_ACMA][1][70] = 127, + [2][1][RTW89_ACMA][0][70] = 127, + [2][1][RTW89_CHILE][1][70] = 127, + [2][1][RTW89_QATAR][1][70] = 127, + [2][1][RTW89_QATAR][0][70] = 127, + [2][1][RTW89_UK][1][70] = 127, + [2][1][RTW89_UK][0][70] = 127, + [2][1][RTW89_FCC][1][72] = -16, + [2][1][RTW89_FCC][2][72] = 56, + [2][1][RTW89_ETSI][1][72] = 127, + [2][1][RTW89_ETSI][0][72] = 127, + [2][1][RTW89_MKK][1][72] = 127, + [2][1][RTW89_MKK][0][72] = 127, + [2][1][RTW89_IC][1][72] = -16, + [2][1][RTW89_KCC][1][72] = -14, + [2][1][RTW89_KCC][0][72] = 127, + [2][1][RTW89_ACMA][1][72] = 127, + [2][1][RTW89_ACMA][0][72] = 127, + [2][1][RTW89_CHILE][1][72] = 127, + [2][1][RTW89_QATAR][1][72] = 127, + [2][1][RTW89_QATAR][0][72] = 127, + [2][1][RTW89_UK][1][72] = 127, + [2][1][RTW89_UK][0][72] = 127, + [2][1][RTW89_FCC][1][74] = -16, + [2][1][RTW89_FCC][2][74] = 56, + [2][1][RTW89_ETSI][1][74] = 127, + [2][1][RTW89_ETSI][0][74] = 127, + [2][1][RTW89_MKK][1][74] = 127, + [2][1][RTW89_MKK][0][74] = 127, + [2][1][RTW89_IC][1][74] = -16, + [2][1][RTW89_KCC][1][74] = -14, + [2][1][RTW89_KCC][0][74] = 127, + [2][1][RTW89_ACMA][1][74] = 127, + [2][1][RTW89_ACMA][0][74] = 127, + [2][1][RTW89_CHILE][1][74] = 127, + [2][1][RTW89_QATAR][1][74] = 127, + [2][1][RTW89_QATAR][0][74] = 127, + [2][1][RTW89_UK][1][74] = 127, + [2][1][RTW89_UK][0][74] = 127, + [2][1][RTW89_FCC][1][75] = -16, + [2][1][RTW89_FCC][2][75] = 56, + [2][1][RTW89_ETSI][1][75] = 127, + [2][1][RTW89_ETSI][0][75] = 127, + [2][1][RTW89_MKK][1][75] = 127, + [2][1][RTW89_MKK][0][75] = 127, + [2][1][RTW89_IC][1][75] = -16, + [2][1][RTW89_KCC][1][75] = -14, + [2][1][RTW89_KCC][0][75] = 127, + [2][1][RTW89_ACMA][1][75] = 127, + [2][1][RTW89_ACMA][0][75] = 127, + [2][1][RTW89_CHILE][1][75] = 127, + [2][1][RTW89_QATAR][1][75] = 127, + [2][1][RTW89_QATAR][0][75] = 127, + [2][1][RTW89_UK][1][75] = 127, + [2][1][RTW89_UK][0][75] = 127, + [2][1][RTW89_FCC][1][77] = -16, + [2][1][RTW89_FCC][2][77] = 56, + [2][1][RTW89_ETSI][1][77] = 127, + [2][1][RTW89_ETSI][0][77] = 127, + [2][1][RTW89_MKK][1][77] = 127, + [2][1][RTW89_MKK][0][77] = 127, + [2][1][RTW89_IC][1][77] = -16, + [2][1][RTW89_KCC][1][77] = -14, + [2][1][RTW89_KCC][0][77] = 127, + [2][1][RTW89_ACMA][1][77] = 127, + [2][1][RTW89_ACMA][0][77] = 127, + [2][1][RTW89_CHILE][1][77] = 127, + [2][1][RTW89_QATAR][1][77] = 127, + [2][1][RTW89_QATAR][0][77] = 127, + [2][1][RTW89_UK][1][77] = 127, + [2][1][RTW89_UK][0][77] = 127, + [2][1][RTW89_FCC][1][79] = -16, + [2][1][RTW89_FCC][2][79] = 56, + [2][1][RTW89_ETSI][1][79] = 127, + [2][1][RTW89_ETSI][0][79] = 127, + [2][1][RTW89_MKK][1][79] = 127, + [2][1][RTW89_MKK][0][79] = 127, + [2][1][RTW89_IC][1][79] = -16, + [2][1][RTW89_KCC][1][79] = -14, + [2][1][RTW89_KCC][0][79] = 127, + [2][1][RTW89_ACMA][1][79] = 127, + [2][1][RTW89_ACMA][0][79] = 127, + [2][1][RTW89_CHILE][1][79] = 127, + [2][1][RTW89_QATAR][1][79] = 127, + [2][1][RTW89_QATAR][0][79] = 127, + [2][1][RTW89_UK][1][79] = 127, + [2][1][RTW89_UK][0][79] = 127, + [2][1][RTW89_FCC][1][81] = -16, + [2][1][RTW89_FCC][2][81] = 56, + [2][1][RTW89_ETSI][1][81] = 127, + [2][1][RTW89_ETSI][0][81] = 127, + [2][1][RTW89_MKK][1][81] = 127, + [2][1][RTW89_MKK][0][81] = 127, + [2][1][RTW89_IC][1][81] = -16, + [2][1][RTW89_KCC][1][81] = -14, + [2][1][RTW89_KCC][0][81] = 127, + [2][1][RTW89_ACMA][1][81] = 127, + [2][1][RTW89_ACMA][0][81] = 127, + [2][1][RTW89_CHILE][1][81] = 127, + [2][1][RTW89_QATAR][1][81] = 127, + [2][1][RTW89_QATAR][0][81] = 127, + [2][1][RTW89_UK][1][81] = 127, + [2][1][RTW89_UK][0][81] = 127, + [2][1][RTW89_FCC][1][83] = -16, + [2][1][RTW89_FCC][2][83] = 56, + [2][1][RTW89_ETSI][1][83] = 127, + [2][1][RTW89_ETSI][0][83] = 127, + [2][1][RTW89_MKK][1][83] = 127, + [2][1][RTW89_MKK][0][83] = 127, + [2][1][RTW89_IC][1][83] = -16, + [2][1][RTW89_KCC][1][83] = -14, + [2][1][RTW89_KCC][0][83] = 127, + [2][1][RTW89_ACMA][1][83] = 127, + [2][1][RTW89_ACMA][0][83] = 127, + [2][1][RTW89_CHILE][1][83] = 127, + [2][1][RTW89_QATAR][1][83] = 127, + [2][1][RTW89_QATAR][0][83] = 127, + [2][1][RTW89_UK][1][83] = 127, + [2][1][RTW89_UK][0][83] = 127, + [2][1][RTW89_FCC][1][85] = -18, + [2][1][RTW89_FCC][2][85] = 56, + [2][1][RTW89_ETSI][1][85] = 127, + [2][1][RTW89_ETSI][0][85] = 127, + [2][1][RTW89_MKK][1][85] = 127, + [2][1][RTW89_MKK][0][85] = 127, + [2][1][RTW89_IC][1][85] = -18, + [2][1][RTW89_KCC][1][85] = -14, + [2][1][RTW89_KCC][0][85] = 127, + [2][1][RTW89_ACMA][1][85] = 127, + [2][1][RTW89_ACMA][0][85] = 127, + [2][1][RTW89_CHILE][1][85] = 127, + [2][1][RTW89_QATAR][1][85] = 127, + [2][1][RTW89_QATAR][0][85] = 127, + [2][1][RTW89_UK][1][85] = 127, + [2][1][RTW89_UK][0][85] = 127, + [2][1][RTW89_FCC][1][87] = -16, + [2][1][RTW89_FCC][2][87] = 127, + [2][1][RTW89_ETSI][1][87] = 127, + [2][1][RTW89_ETSI][0][87] = 127, + [2][1][RTW89_MKK][1][87] = 127, + [2][1][RTW89_MKK][0][87] = 127, + [2][1][RTW89_IC][1][87] = -16, + [2][1][RTW89_KCC][1][87] = -14, + [2][1][RTW89_KCC][0][87] = 127, + [2][1][RTW89_ACMA][1][87] = 127, + [2][1][RTW89_ACMA][0][87] = 127, + [2][1][RTW89_CHILE][1][87] = 127, + [2][1][RTW89_QATAR][1][87] = 127, + [2][1][RTW89_QATAR][0][87] = 127, + [2][1][RTW89_UK][1][87] = 127, + [2][1][RTW89_UK][0][87] = 127, + [2][1][RTW89_FCC][1][89] = -16, + [2][1][RTW89_FCC][2][89] = 127, + [2][1][RTW89_ETSI][1][89] = 127, + [2][1][RTW89_ETSI][0][89] = 127, + [2][1][RTW89_MKK][1][89] = 127, + [2][1][RTW89_MKK][0][89] = 127, + [2][1][RTW89_IC][1][89] = -16, + [2][1][RTW89_KCC][1][89] = -14, + [2][1][RTW89_KCC][0][89] = 127, + [2][1][RTW89_ACMA][1][89] = 127, + [2][1][RTW89_ACMA][0][89] = 127, + [2][1][RTW89_CHILE][1][89] = 127, + [2][1][RTW89_QATAR][1][89] = 127, + [2][1][RTW89_QATAR][0][89] = 127, + [2][1][RTW89_UK][1][89] = 127, + [2][1][RTW89_UK][0][89] = 127, + [2][1][RTW89_FCC][1][90] = -16, + [2][1][RTW89_FCC][2][90] = 127, + [2][1][RTW89_ETSI][1][90] = 127, + [2][1][RTW89_ETSI][0][90] = 127, + [2][1][RTW89_MKK][1][90] = 127, + [2][1][RTW89_MKK][0][90] = 127, + [2][1][RTW89_IC][1][90] = -16, + [2][1][RTW89_KCC][1][90] = -14, + [2][1][RTW89_KCC][0][90] = 127, + [2][1][RTW89_ACMA][1][90] = 127, + [2][1][RTW89_ACMA][0][90] = 127, + [2][1][RTW89_CHILE][1][90] = 127, + [2][1][RTW89_QATAR][1][90] = 127, + [2][1][RTW89_QATAR][0][90] = 127, + [2][1][RTW89_UK][1][90] = 127, + [2][1][RTW89_UK][0][90] = 127, + [2][1][RTW89_FCC][1][92] = -16, + [2][1][RTW89_FCC][2][92] = 127, + [2][1][RTW89_ETSI][1][92] = 127, + [2][1][RTW89_ETSI][0][92] = 127, + [2][1][RTW89_MKK][1][92] = 127, + [2][1][RTW89_MKK][0][92] = 127, + [2][1][RTW89_IC][1][92] = -16, + [2][1][RTW89_KCC][1][92] = -14, + [2][1][RTW89_KCC][0][92] = 127, + [2][1][RTW89_ACMA][1][92] = 127, + [2][1][RTW89_ACMA][0][92] = 127, + [2][1][RTW89_CHILE][1][92] = 127, + [2][1][RTW89_QATAR][1][92] = 127, + [2][1][RTW89_QATAR][0][92] = 127, + [2][1][RTW89_UK][1][92] = 127, + [2][1][RTW89_UK][0][92] = 127, + [2][1][RTW89_FCC][1][94] = -16, + [2][1][RTW89_FCC][2][94] = 127, + [2][1][RTW89_ETSI][1][94] = 127, + [2][1][RTW89_ETSI][0][94] = 127, + [2][1][RTW89_MKK][1][94] = 127, + [2][1][RTW89_MKK][0][94] = 127, + [2][1][RTW89_IC][1][94] = -16, + [2][1][RTW89_KCC][1][94] = -14, + [2][1][RTW89_KCC][0][94] = 127, + [2][1][RTW89_ACMA][1][94] = 127, + [2][1][RTW89_ACMA][0][94] = 127, + [2][1][RTW89_CHILE][1][94] = 127, + [2][1][RTW89_QATAR][1][94] = 127, + [2][1][RTW89_QATAR][0][94] = 127, + [2][1][RTW89_UK][1][94] = 127, + [2][1][RTW89_UK][0][94] = 127, + [2][1][RTW89_FCC][1][96] = -16, + [2][1][RTW89_FCC][2][96] = 127, + [2][1][RTW89_ETSI][1][96] = 127, + [2][1][RTW89_ETSI][0][96] = 127, + [2][1][RTW89_MKK][1][96] = 127, + [2][1][RTW89_MKK][0][96] = 127, + [2][1][RTW89_IC][1][96] = -16, + [2][1][RTW89_KCC][1][96] = -14, + [2][1][RTW89_KCC][0][96] = 127, + [2][1][RTW89_ACMA][1][96] = 127, + [2][1][RTW89_ACMA][0][96] = 127, + [2][1][RTW89_CHILE][1][96] = 127, + [2][1][RTW89_QATAR][1][96] = 127, + [2][1][RTW89_QATAR][0][96] = 127, + [2][1][RTW89_UK][1][96] = 127, + [2][1][RTW89_UK][0][96] = 127, + [2][1][RTW89_FCC][1][98] = -16, + [2][1][RTW89_FCC][2][98] = 127, + [2][1][RTW89_ETSI][1][98] = 127, + [2][1][RTW89_ETSI][0][98] = 127, + [2][1][RTW89_MKK][1][98] = 127, + [2][1][RTW89_MKK][0][98] = 127, + [2][1][RTW89_IC][1][98] = -16, + [2][1][RTW89_KCC][1][98] = -14, + [2][1][RTW89_KCC][0][98] = 127, + [2][1][RTW89_ACMA][1][98] = 127, + [2][1][RTW89_ACMA][0][98] = 127, + [2][1][RTW89_CHILE][1][98] = 127, + [2][1][RTW89_QATAR][1][98] = 127, + [2][1][RTW89_QATAR][0][98] = 127, + [2][1][RTW89_UK][1][98] = 127, + [2][1][RTW89_UK][0][98] = 127, + [2][1][RTW89_FCC][1][100] = -16, + [2][1][RTW89_FCC][2][100] = 127, + [2][1][RTW89_ETSI][1][100] = 127, + [2][1][RTW89_ETSI][0][100] = 127, + [2][1][RTW89_MKK][1][100] = 127, + [2][1][RTW89_MKK][0][100] = 127, + [2][1][RTW89_IC][1][100] = -16, + [2][1][RTW89_KCC][1][100] = -14, + [2][1][RTW89_KCC][0][100] = 127, + [2][1][RTW89_ACMA][1][100] = 127, + [2][1][RTW89_ACMA][0][100] = 127, + [2][1][RTW89_CHILE][1][100] = 127, + [2][1][RTW89_QATAR][1][100] = 127, + [2][1][RTW89_QATAR][0][100] = 127, + [2][1][RTW89_UK][1][100] = 127, + [2][1][RTW89_UK][0][100] = 127, + [2][1][RTW89_FCC][1][102] = -16, + [2][1][RTW89_FCC][2][102] = 127, + [2][1][RTW89_ETSI][1][102] = 127, + [2][1][RTW89_ETSI][0][102] = 127, + [2][1][RTW89_MKK][1][102] = 127, + [2][1][RTW89_MKK][0][102] = 127, + [2][1][RTW89_IC][1][102] = -16, + [2][1][RTW89_KCC][1][102] = -14, + [2][1][RTW89_KCC][0][102] = 127, + [2][1][RTW89_ACMA][1][102] = 127, + [2][1][RTW89_ACMA][0][102] = 127, + [2][1][RTW89_CHILE][1][102] = 127, + [2][1][RTW89_QATAR][1][102] = 127, + [2][1][RTW89_QATAR][0][102] = 127, + [2][1][RTW89_UK][1][102] = 127, + [2][1][RTW89_UK][0][102] = 127, + [2][1][RTW89_FCC][1][104] = -16, + [2][1][RTW89_FCC][2][104] = 127, + [2][1][RTW89_ETSI][1][104] = 127, + [2][1][RTW89_ETSI][0][104] = 127, + [2][1][RTW89_MKK][1][104] = 127, + [2][1][RTW89_MKK][0][104] = 127, + [2][1][RTW89_IC][1][104] = -16, + [2][1][RTW89_KCC][1][104] = -14, + [2][1][RTW89_KCC][0][104] = 127, + [2][1][RTW89_ACMA][1][104] = 127, + [2][1][RTW89_ACMA][0][104] = 127, + [2][1][RTW89_CHILE][1][104] = 127, + [2][1][RTW89_QATAR][1][104] = 127, + [2][1][RTW89_QATAR][0][104] = 127, + [2][1][RTW89_UK][1][104] = 127, + [2][1][RTW89_UK][0][104] = 127, + [2][1][RTW89_FCC][1][105] = -16, + [2][1][RTW89_FCC][2][105] = 127, + [2][1][RTW89_ETSI][1][105] = 127, + [2][1][RTW89_ETSI][0][105] = 127, + [2][1][RTW89_MKK][1][105] = 127, + [2][1][RTW89_MKK][0][105] = 127, + [2][1][RTW89_IC][1][105] = -16, + [2][1][RTW89_KCC][1][105] = -14, + [2][1][RTW89_KCC][0][105] = 127, + [2][1][RTW89_ACMA][1][105] = 127, + [2][1][RTW89_ACMA][0][105] = 127, + [2][1][RTW89_CHILE][1][105] = 127, + [2][1][RTW89_QATAR][1][105] = 127, + [2][1][RTW89_QATAR][0][105] = 127, + [2][1][RTW89_UK][1][105] = 127, + [2][1][RTW89_UK][0][105] = 127, + [2][1][RTW89_FCC][1][107] = -12, + [2][1][RTW89_FCC][2][107] = 127, + [2][1][RTW89_ETSI][1][107] = 127, + [2][1][RTW89_ETSI][0][107] = 127, + [2][1][RTW89_MKK][1][107] = 127, + [2][1][RTW89_MKK][0][107] = 127, + [2][1][RTW89_IC][1][107] = -12, + [2][1][RTW89_KCC][1][107] = -14, + [2][1][RTW89_KCC][0][107] = 127, + [2][1][RTW89_ACMA][1][107] = 127, + [2][1][RTW89_ACMA][0][107] = 127, + [2][1][RTW89_CHILE][1][107] = 127, + [2][1][RTW89_QATAR][1][107] = 127, + [2][1][RTW89_QATAR][0][107] = 127, + [2][1][RTW89_UK][1][107] = 127, + [2][1][RTW89_UK][0][107] = 127, + [2][1][RTW89_FCC][1][109] = -10, + [2][1][RTW89_FCC][2][109] = 127, + [2][1][RTW89_ETSI][1][109] = 127, + [2][1][RTW89_ETSI][0][109] = 127, + [2][1][RTW89_MKK][1][109] = 127, + [2][1][RTW89_MKK][0][109] = 127, + [2][1][RTW89_IC][1][109] = -10, + [2][1][RTW89_KCC][1][109] = 127, + [2][1][RTW89_KCC][0][109] = 127, + [2][1][RTW89_ACMA][1][109] = 127, + [2][1][RTW89_ACMA][0][109] = 127, + [2][1][RTW89_CHILE][1][109] = 127, + [2][1][RTW89_QATAR][1][109] = 127, + [2][1][RTW89_QATAR][0][109] = 127, + [2][1][RTW89_UK][1][109] = 127, + [2][1][RTW89_UK][0][109] = 127, + [2][1][RTW89_FCC][1][111] = 127, + [2][1][RTW89_FCC][2][111] = 127, + [2][1][RTW89_ETSI][1][111] = 127, + [2][1][RTW89_ETSI][0][111] = 127, + [2][1][RTW89_MKK][1][111] = 127, + [2][1][RTW89_MKK][0][111] = 127, + [2][1][RTW89_IC][1][111] = 127, + [2][1][RTW89_KCC][1][111] = 127, + [2][1][RTW89_KCC][0][111] = 127, + [2][1][RTW89_ACMA][1][111] = 127, + [2][1][RTW89_ACMA][0][111] = 127, + [2][1][RTW89_CHILE][1][111] = 127, + [2][1][RTW89_QATAR][1][111] = 127, + [2][1][RTW89_QATAR][0][111] = 127, + [2][1][RTW89_UK][1][111] = 127, + [2][1][RTW89_UK][0][111] = 127, + [2][1][RTW89_FCC][1][113] = 127, + [2][1][RTW89_FCC][2][113] = 127, + [2][1][RTW89_ETSI][1][113] = 127, + [2][1][RTW89_ETSI][0][113] = 127, + [2][1][RTW89_MKK][1][113] = 127, + [2][1][RTW89_MKK][0][113] = 127, + [2][1][RTW89_IC][1][113] = 127, + [2][1][RTW89_KCC][1][113] = 127, + [2][1][RTW89_KCC][0][113] = 127, + [2][1][RTW89_ACMA][1][113] = 127, + [2][1][RTW89_ACMA][0][113] = 127, + [2][1][RTW89_CHILE][1][113] = 127, + [2][1][RTW89_QATAR][1][113] = 127, + [2][1][RTW89_QATAR][0][113] = 127, + [2][1][RTW89_UK][1][113] = 127, + [2][1][RTW89_UK][0][113] = 127, + [2][1][RTW89_FCC][1][115] = 127, + [2][1][RTW89_FCC][2][115] = 127, + [2][1][RTW89_ETSI][1][115] = 127, + [2][1][RTW89_ETSI][0][115] = 127, + [2][1][RTW89_MKK][1][115] = 127, + [2][1][RTW89_MKK][0][115] = 127, + [2][1][RTW89_IC][1][115] = 127, + [2][1][RTW89_KCC][1][115] = 127, + [2][1][RTW89_KCC][0][115] = 127, + [2][1][RTW89_ACMA][1][115] = 127, + [2][1][RTW89_ACMA][0][115] = 127, + [2][1][RTW89_CHILE][1][115] = 127, + [2][1][RTW89_QATAR][1][115] = 127, + [2][1][RTW89_QATAR][0][115] = 127, + [2][1][RTW89_UK][1][115] = 127, + [2][1][RTW89_UK][0][115] = 127, + [2][1][RTW89_FCC][1][117] = 127, + [2][1][RTW89_FCC][2][117] = 127, + [2][1][RTW89_ETSI][1][117] = 127, + [2][1][RTW89_ETSI][0][117] = 127, + [2][1][RTW89_MKK][1][117] = 127, + [2][1][RTW89_MKK][0][117] = 127, + [2][1][RTW89_IC][1][117] = 127, + [2][1][RTW89_KCC][1][117] = 127, + [2][1][RTW89_KCC][0][117] = 127, + [2][1][RTW89_ACMA][1][117] = 127, + [2][1][RTW89_ACMA][0][117] = 127, + [2][1][RTW89_CHILE][1][117] = 127, + [2][1][RTW89_QATAR][1][117] = 127, + [2][1][RTW89_QATAR][0][117] = 127, + [2][1][RTW89_UK][1][117] = 127, + [2][1][RTW89_UK][0][117] = 127, + [2][1][RTW89_FCC][1][119] = 127, + [2][1][RTW89_FCC][2][119] = 127, + [2][1][RTW89_ETSI][1][119] = 127, + [2][1][RTW89_ETSI][0][119] = 127, + [2][1][RTW89_MKK][1][119] = 127, + [2][1][RTW89_MKK][0][119] = 127, + [2][1][RTW89_IC][1][119] = 127, + [2][1][RTW89_KCC][1][119] = 127, + [2][1][RTW89_KCC][0][119] = 127, + [2][1][RTW89_ACMA][1][119] = 127, + [2][1][RTW89_ACMA][0][119] = 127, + [2][1][RTW89_CHILE][1][119] = 127, + [2][1][RTW89_QATAR][1][119] = 127, + [2][1][RTW89_QATAR][0][119] = 127, + [2][1][RTW89_UK][1][119] = 127, + [2][1][RTW89_UK][0][119] = 127, }; const struct rtw89_phy_table rtw89_8852c_phy_bb_table = { diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c index 9ba99f3764e7ee..0462ba693f6fdc 100644 --- a/drivers/net/wireless/realtek/rtw89/ser.c +++ b/drivers/net/wireless/realtek/rtw89/ser.c @@ -303,6 +303,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif) rtw89_core_release_bit_map(rtwdev->hw_port, rtwvif->port); rtwvif->net_type = RTW89_NET_TYPE_NO_LINK; rtwvif->trigger = false; + rtwvif->tdls_peer = 0; } static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta) @@ -341,6 +342,8 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev) rtw89_core_release_all_bits_map(rtwdev->mac_id_map, RTW89_MAX_MAC_ID_NUM); rtw89_for_each_rtwvif(rtwdev, rtwvif) ser_reset_vif(rtwdev, rtwvif); + + rtwdev->total_sta_assoc = 0; } /* hal function */ @@ -406,6 +409,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) switch (evt) { case SER_EV_STATE_IN: rtw89_hci_recovery_complete(rtwdev); + clear_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags); clear_bit(RTW89_FLAG_CRASH_SIMULATING, rtwdev->flags); break; case SER_EV_L1_RESET_PREPARE: @@ -418,6 +422,7 @@ static void ser_idle_st_hdl(struct rtw89_ser *ser, u8 evt) ser_state_goto(ser, SER_L2_RESET_ST); break; case SER_EV_STATE_OUT: + set_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags); rtw89_hci_recovery_start(rtwdev); break; default: diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h index d880ecb879ca8d..ec96da36eacc64 100644 --- a/drivers/net/wireless/realtek/rtw89/txrx.h +++ b/drivers/net/wireless/realtek/rtw89/txrx.h @@ -186,118 +186,51 @@ #define AX_RXD_BIP_KEYID BIT(27) #define AX_RXD_BIP_ENC BIT(28) -/* RX DESC helpers */ -/* Short Descriptor */ -#define RTW89_GET_RXWD_LONG_RXD(rxdesc) \ - le32_get_bits((rxdesc)->dword0, BIT(31)) -#define RTW89_GET_RXWD_DRV_INFO_SIZE(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(30, 28)) -#define RTW89_GET_RXWD_RPKT_TYPE(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(27, 24)) -#define RTW89_GET_RXWD_MAC_INFO_VALID(rxdesc) \ - le32_get_bits((rxdesc)->dword0, BIT(23)) -#define RTW89_GET_RXWD_BB_SEL(rxdesc) \ - le32_get_bits((rxdesc)->dword0, BIT(22)) -#define RTW89_GET_RXWD_HD_IV_LEN(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(21, 16)) -#define RTW89_GET_RXWD_SHIFT(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(15, 14)) -#define RTW89_GET_RXWD_PKT_SIZE(rxdesc) \ - le32_get_bits((rxdesc)->dword0, GENMASK(13, 0)) -#define RTW89_GET_RXWD_BW(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(31, 30)) -#define RTW89_GET_RXWD_BW_V1(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(31, 29)) -#define RTW89_GET_RXWD_GI_LTF(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(27, 25)) -#define RTW89_GET_RXWD_DATA_RATE(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(24, 16)) -#define RTW89_GET_RXWD_USER_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(15, 8)) -#define RTW89_GET_RXWD_SR_EN(rxdesc) \ - le32_get_bits((rxdesc)->dword1, BIT(7)) -#define RTW89_GET_RXWD_PPDU_CNT(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(6, 4)) -#define RTW89_GET_RXWD_PPDU_TYPE(rxdesc) \ - le32_get_bits((rxdesc)->dword1, GENMASK(3, 0)) -#define RTW89_GET_RXWD_FREE_RUN_CNT(rxdesc) \ - le32_get_bits((rxdesc)->dword2, GENMASK(31, 0)) -#define RTW89_GET_RXWD_ICV_ERR(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(10)) -#define RTW89_GET_RXWD_CRC32_ERR(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(9)) -#define RTW89_GET_RXWD_HW_DEC(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(2)) -#define RTW89_GET_RXWD_SW_DEC(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(1)) -#define RTW89_GET_RXWD_A1_MATCH(rxdesc) \ - le32_get_bits((rxdesc)->dword3, BIT(0)) - -/* Long Descriptor */ -#define RTW89_GET_RXWD_FRAG(rxdesc) \ - le32_get_bits((rxdesc)->dword4, GENMASK(31, 28)) -#define RTW89_GET_RXWD_SEQ(rxdesc) \ - le32_get_bits((rxdesc)->dword4, GENMASK(27, 16)) -#define RTW89_GET_RXWD_TYPE(rxdesc) \ - le32_get_bits((rxdesc)->dword4, GENMASK(1, 0)) -#define RTW89_GET_RXWD_ADDR_CAM_VLD(rxdesc) \ - le32_get_bits((rxdesc)->dword5, BIT(28)) -#define RTW89_GET_RXWD_RX_PL_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(27, 24)) -#define RTW89_GET_RXWD_MAC_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(23, 16)) -#define RTW89_GET_RXWD_ADDR_CAM_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(15, 8)) -#define RTW89_GET_RXWD_SEC_CAM_ID(rxdesc) \ - le32_get_bits((rxdesc)->dword5, GENMASK(7, 0)) - -#define RTW89_GET_RXINFO_USR_NUM(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(3, 0)) -#define RTW89_GET_RXINFO_FW_DEFINE(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(15, 8)) -#define RTW89_GET_RXINFO_LSIG_LEN(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(27, 16)) -#define RTW89_GET_RXINFO_IS_TO_SELF(rpt) \ - le32_get_bits(*((const __le32 *)rpt), BIT(28)) -#define RTW89_GET_RXINFO_RX_CNT_VLD(rpt) \ - le32_get_bits(*((const __le32 *)rpt), BIT(29)) -#define RTW89_GET_RXINFO_LONG_RXD(rpt) \ - le32_get_bits(*((const __le32 *)rpt), GENMASK(31, 30)) -#define RTW89_GET_RXINFO_SERVICE(rpt) \ - le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(15, 0)) -#define RTW89_GET_RXINFO_PLCP_LEN(rpt) \ - le32_get_bits(*((const __le32 *)(rpt) + 1), GENMASK(23, 16)) -#define RTW89_GET_RXINFO_MAC_ID_VALID(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(0)) -#define RTW89_GET_RXINFO_DATA(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(1)) -#define RTW89_GET_RXINFO_CTRL(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(2)) -#define RTW89_GET_RXINFO_MGMT(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(3)) -#define RTW89_GET_RXINFO_BCM(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), BIT(4)) -#define RTW89_GET_RXINFO_MACID(rpt, usr) \ - le32_get_bits(*((const __le32 *)(rpt) + (usr) + 2), GENMASK(15, 8)) - -#define RTW89_GET_PHY_STS_IE_MAP(sts) \ - le32_get_bits(*((const __le32 *)(sts)), GENMASK(4, 0)) -#define RTW89_GET_PHY_STS_RSSI_A(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(7, 0)) -#define RTW89_GET_PHY_STS_RSSI_B(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(15, 8)) -#define RTW89_GET_PHY_STS_RSSI_C(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(23, 16)) -#define RTW89_GET_PHY_STS_RSSI_D(sts) \ - le32_get_bits(*((const __le32 *)(sts) + 1), GENMASK(31, 24)) -#define RTW89_GET_PHY_STS_LEN(sts) \ - le32_get_bits(*((const __le32 *)sts), GENMASK(15, 8)) -#define RTW89_GET_PHY_STS_RSSI_AVG(sts) \ - le32_get_bits(*((const __le32 *)sts), GENMASK(31, 24)) -#define RTW89_GET_PHY_STS_IE_TYPE(ie) \ - le32_get_bits(*((const __le32 *)ie), GENMASK(4, 0)) -#define RTW89_GET_PHY_STS_IE_LEN(ie) \ - le32_get_bits(*((const __le32 *)ie), GENMASK(11, 5)) +struct rtw89_rxinfo_user { + __le32 w0; +}; + +#define RTW89_RXINFO_USER_MAC_ID_VALID BIT(0) +#define RTW89_RXINFO_USER_DATA BIT(1) +#define RTW89_RXINFO_USER_CTRL BIT(2) +#define RTW89_RXINFO_USER_MGMT BIT(3) +#define RTW89_RXINFO_USER_BCM BIT(4) +#define RTW89_RXINFO_USER_MACID GENMASK(15, 8) + +struct rtw89_rxinfo { + __le32 w0; + __le32 w1; + struct rtw89_rxinfo_user user[]; +} __packed; + +#define RTW89_RXINFO_W0_USR_NUM GENMASK(3, 0) +#define RTW89_RXINFO_W0_FW_DEFINE GENMASK(15, 8) +#define RTW89_RXINFO_W0_LSIG_LEN GENMASK(27, 16) +#define RTW89_RXINFO_W0_IS_TO_SELF BIT(28) +#define RTW89_RXINFO_W0_RX_CNT_VLD BIT(29) +#define RTW89_RXINFO_W0_LONG_RXD GENMASK(31, 30) +#define RTW89_RXINFO_W1_SERVICE GENMASK(15, 0) +#define RTW89_RXINFO_W1_PLCP_LEN GENMASK(23, 16) + +struct rtw89_phy_sts_hdr { + __le32 w0; + __le32 w1; +} __packed; + +#define RTW89_PHY_STS_HDR_W0_IE_MAP GENMASK(4, 0) +#define RTW89_PHY_STS_HDR_W0_LEN GENMASK(15, 8) +#define RTW89_PHY_STS_HDR_W0_RSSI_AVG GENMASK(31, 24) +#define RTW89_PHY_STS_HDR_W1_RSSI_A GENMASK(7, 0) +#define RTW89_PHY_STS_HDR_W1_RSSI_B GENMASK(15, 8) +#define RTW89_PHY_STS_HDR_W1_RSSI_C GENMASK(23, 16) +#define RTW89_PHY_STS_HDR_W1_RSSI_D GENMASK(31, 24) + +struct rtw89_phy_sts_iehdr { + __le32 w0; +}; + +#define RTW89_PHY_STS_IEHDR_TYPE GENMASK(4, 0) +#define RTW89_PHY_STS_IEHDR_LEN GENMASK(11, 5) struct rtw89_phy_sts_ie0 { __le32 w0; diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index d09998796ac08b..1911fef3bbad63 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -1463,10 +1463,8 @@ static void rsi_shutdown(struct device *dev) rsi_dbg(ERR_ZONE, "SDIO Bus shutdown =====>\n"); - if (hw) { - struct cfg80211_wowlan *wowlan = hw->wiphy->wowlan_config; - - if (rsi_config_wowlan(adapter, wowlan)) + if (hw && hw->wiphy && hw->wiphy->wowlan_config) { + if (rsi_config_wowlan(adapter, hw->wiphy->wowlan_config)) rsi_dbg(ERR_ZONE, "Failed to configure WoWLAN\n"); } @@ -1481,9 +1479,6 @@ static void rsi_shutdown(struct device *dev) if (sdev->write_fail) rsi_dbg(INFO_ZONE, "###### Device is not ready #######\n"); - if (rsi_set_sdio_pm_caps(adapter)) - rsi_dbg(INFO_ZONE, "Setting power management caps failed\n"); - rsi_dbg(INFO_ZONE, "***** RSI module shut down *****\n"); } diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c index 89c7a1420381d3..37bf392ae9a2fe 100644 --- a/drivers/net/wireless/virtual/mac80211_hwsim.c +++ b/drivers/net/wireless/virtual/mac80211_hwsim.c @@ -4,7 +4,7 @@ * Copyright (c) 2008, Jouni Malinen * Copyright (c) 2011, Javier Lopez * Copyright (c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2022 Intel Corporation + * Copyright (C) 2018 - 2023 Intel Corporation */ /* @@ -582,8 +582,9 @@ static int mac80211_hwsim_vendor_cmd_test(struct wiphy *wiphy, */ /* Add vendor data */ - nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); - + err = nla_put_u32(skb, QCA_WLAN_VENDOR_ATTR_TEST, val + 1); + if (err) + return err; /* Send the event - this will call nla_nest_end() */ cfg80211_vendor_event(skb, GFP_KERNEL); } @@ -1864,7 +1865,7 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data, WARN_ON(is_multicast_ether_addr(hdr->addr1)); - if (WARN_ON_ONCE(!sta->valid_links)) + if (WARN_ON_ONCE(!sta || !sta->valid_links)) return &vif->bss_conf; for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) { @@ -1940,7 +1941,14 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, hdr, &link_sta); } - if (WARN_ON(!bss_conf)) { + if (unlikely(!bss_conf)) { + /* if it's an MLO STA, it might have deactivated all + * links temporarily - but we don't handle real PS in + * this code yet, so just drop the frame in that case + */ + WARN(link != IEEE80211_LINK_UNSPECIFIED || !sta || !sta->mlo, + "link:%d, sta:%pM, sta->mlo:%d\n", + link, sta ? sta->addr : NULL, sta ? sta->mlo : -1); ieee80211_free_txskb(hw, skb); return; } diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.c b/drivers/net/wwan/iosm/iosm_ipc_imem.c index 829515a601b379..635301d677e186 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.c +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.c @@ -4,6 +4,7 @@ */ #include +#include #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_devlink.h" @@ -631,6 +632,11 @@ static void ipc_imem_run_state_worker(struct work_struct *instance) /* Complete all memory stores after setting bit */ smp_mb__after_atomic(); + if (ipc_imem->pcie->pci->device == INTEL_CP_DEVICE_7560_ID) { + pm_runtime_mark_last_busy(ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_imem->dev); + } + return; err_ipc_mux_deinit: @@ -1234,6 +1240,7 @@ void ipc_imem_cleanup(struct iosm_imem *ipc_imem) /* forward MDM_NOT_READY to listeners */ ipc_uevent_send(ipc_imem->dev, UEVENT_MDM_NOT_READY); + pm_runtime_get_sync(ipc_imem->dev); hrtimer_cancel(&ipc_imem->td_alloc_timer); hrtimer_cancel(&ipc_imem->tdupdate_timer); @@ -1419,6 +1426,16 @@ struct iosm_imem *ipc_imem_init(struct iosm_pcie *pcie, unsigned int device_id, set_bit(IOSM_DEVLINK_INIT, &ipc_imem->flag); } + + if (!pm_runtime_enabled(ipc_imem->dev)) + pm_runtime_enable(ipc_imem->dev); + + pm_runtime_set_autosuspend_delay(ipc_imem->dev, + IPC_MEM_AUTO_SUSPEND_DELAY_MS); + pm_runtime_use_autosuspend(ipc_imem->dev); + pm_runtime_allow(ipc_imem->dev); + pm_runtime_mark_last_busy(ipc_imem->dev); + return ipc_imem; devlink_channel_fail: ipc_devlink_deinit(ipc_imem->ipc_devlink); diff --git a/drivers/net/wwan/iosm/iosm_ipc_imem.h b/drivers/net/wwan/iosm/iosm_ipc_imem.h index 5664ac507c902e..0144b45e2afb39 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_imem.h +++ b/drivers/net/wwan/iosm/iosm_ipc_imem.h @@ -103,6 +103,8 @@ struct ipc_chnl_cfg; #define FULLY_FUNCTIONAL 0 #define IOSM_DEVLINK_INIT 1 +#define IPC_MEM_AUTO_SUSPEND_DELAY_MS 5000 + /* List of the supported UL/DL pipes. */ enum ipc_mem_pipes { IPC_MEM_PIPE_0 = 0, diff --git a/drivers/net/wwan/iosm/iosm_ipc_pcie.c b/drivers/net/wwan/iosm/iosm_ipc_pcie.c index 04517bd3325a2a..3a259c9abefdfa 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_pcie.c +++ b/drivers/net/wwan/iosm/iosm_ipc_pcie.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "iosm_ipc_imem.h" @@ -437,7 +438,8 @@ static int __maybe_unused ipc_pcie_resume_cb(struct device *dev) return 0; } -static SIMPLE_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, ipc_pcie_resume_cb); +static DEFINE_RUNTIME_DEV_PM_OPS(iosm_ipc_pm, ipc_pcie_suspend_cb, + ipc_pcie_resume_cb, NULL); static struct pci_driver iosm_ipc_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/net/wwan/iosm/iosm_ipc_port.c b/drivers/net/wwan/iosm/iosm_ipc_port.c index 5d5b4183e14a3a..2ba1ddca3945b2 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_port.c +++ b/drivers/net/wwan/iosm/iosm_ipc_port.c @@ -3,6 +3,8 @@ * Copyright (C) 2020-21 Intel Corporation. */ +#include + #include "iosm_ipc_chnl_cfg.h" #include "iosm_ipc_imem_ops.h" #include "iosm_ipc_port.h" @@ -13,12 +15,16 @@ static int ipc_port_ctrl_start(struct wwan_port *port) struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); int ret = 0; + pm_runtime_get_sync(ipc_port->ipc_imem->dev); ipc_port->channel = ipc_imem_sys_port_open(ipc_port->ipc_imem, ipc_port->chl_id, IPC_HP_CDEV_OPEN); if (!ipc_port->channel) ret = -EIO; + pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); + return ret; } @@ -27,15 +33,24 @@ static void ipc_port_ctrl_stop(struct wwan_port *port) { struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + pm_runtime_get_sync(ipc_port->ipc_imem->dev); ipc_imem_sys_port_close(ipc_port->ipc_imem, ipc_port->channel); + pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); } /* transfer control data to modem */ static int ipc_port_ctrl_tx(struct wwan_port *port, struct sk_buff *skb) { struct iosm_cdev *ipc_port = wwan_port_get_drvdata(port); + int ret; - return ipc_imem_sys_cdev_write(ipc_port, skb); + pm_runtime_get_sync(ipc_port->ipc_imem->dev); + ret = ipc_imem_sys_cdev_write(ipc_port, skb); + pm_runtime_mark_last_busy(ipc_port->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_port->ipc_imem->dev); + + return ret; } static const struct wwan_port_ops ipc_wwan_ctrl_ops = { diff --git a/drivers/net/wwan/iosm/iosm_ipc_trace.c b/drivers/net/wwan/iosm/iosm_ipc_trace.c index eeecfa3d10c5ab..4368373797b69b 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_trace.c +++ b/drivers/net/wwan/iosm/iosm_ipc_trace.c @@ -3,7 +3,9 @@ * Copyright (C) 2020-2021 Intel Corporation. */ +#include #include + #include "iosm_ipc_trace.h" /* sub buffer size and number of sub buffer */ @@ -97,6 +99,8 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp, if (ret) return ret; + pm_runtime_get_sync(ipc_trace->ipc_imem->dev); + mutex_lock(&ipc_trace->trc_mutex); if (val == TRACE_ENABLE && ipc_trace->mode != TRACE_ENABLE) { ipc_trace->channel = ipc_imem_sys_port_open(ipc_trace->ipc_imem, @@ -117,6 +121,10 @@ static ssize_t ipc_trace_ctrl_file_write(struct file *filp, ret = count; unlock: mutex_unlock(&ipc_trace->trc_mutex); + + pm_runtime_mark_last_busy(ipc_trace->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_trace->ipc_imem->dev); + return ret; } diff --git a/drivers/net/wwan/iosm/iosm_ipc_wwan.c b/drivers/net/wwan/iosm/iosm_ipc_wwan.c index ff747fc79aaf80..93d17de08786c2 100644 --- a/drivers/net/wwan/iosm/iosm_ipc_wwan.c +++ b/drivers/net/wwan/iosm/iosm_ipc_wwan.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -51,11 +52,13 @@ static int ipc_wwan_link_open(struct net_device *netdev) struct iosm_netdev_priv *priv = wwan_netdev_drvpriv(netdev); struct iosm_wwan *ipc_wwan = priv->ipc_wwan; int if_id = priv->if_id; + int ret = 0; if (if_id < IP_MUX_SESSION_START || if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; + pm_runtime_get_sync(ipc_wwan->ipc_imem->dev); /* get channel id */ priv->ch_id = ipc_imem_sys_wwan_open(ipc_wwan->ipc_imem, if_id); @@ -63,7 +66,8 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_err(ipc_wwan->dev, "cannot connect wwan0 & id %d to the IPC mem layer", if_id); - return -ENODEV; + ret = -ENODEV; + goto err_out; } /* enable tx path, DL data may follow */ @@ -72,7 +76,11 @@ static int ipc_wwan_link_open(struct net_device *netdev) dev_dbg(ipc_wwan->dev, "Channel id %d allocated to if_id %d", priv->ch_id, priv->if_id); - return 0; +err_out: + pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); + + return ret; } /* Bring-down the wwan net link */ @@ -82,9 +90,12 @@ static int ipc_wwan_link_stop(struct net_device *netdev) netif_stop_queue(netdev); + pm_runtime_get_sync(priv->ipc_wwan->ipc_imem->dev); ipc_imem_sys_wwan_close(priv->ipc_wwan->ipc_imem, priv->if_id, priv->ch_id); priv->ch_id = -1; + pm_runtime_mark_last_busy(priv->ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(priv->ipc_wwan->ipc_imem->dev); return 0; } @@ -106,6 +117,7 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, if_id >= ARRAY_SIZE(ipc_wwan->sub_netlist)) return -EINVAL; + pm_runtime_get(ipc_wwan->ipc_imem->dev); /* Send the SKB to device for transmission */ ret = ipc_imem_sys_wwan_transmit(ipc_wwan->ipc_imem, if_id, priv->ch_id, skb); @@ -119,9 +131,14 @@ static netdev_tx_t ipc_wwan_link_transmit(struct sk_buff *skb, ret = NETDEV_TX_BUSY; dev_err(ipc_wwan->dev, "unable to push packets"); } else { + pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); goto exit; } + pm_runtime_mark_last_busy(ipc_wwan->ipc_imem->dev); + pm_runtime_put_autosuspend(ipc_wwan->ipc_imem->dev); + return ret; exit: diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c index 1e0f2297f9c665..c1896a1d978cdc 100644 --- a/drivers/nfc/fdp/i2c.c +++ b/drivers/nfc/fdp/i2c.c @@ -359,7 +359,7 @@ static struct i2c_driver fdp_nci_i2c_driver = { .name = FDP_I2C_DRIVER_NAME, .acpi_match_table = fdp_nci_i2c_acpi_match, }, - .probe_new = fdp_nci_i2c_probe, + .probe = fdp_nci_i2c_probe, .remove = fdp_nci_i2c_remove, }; module_i2c_driver(fdp_nci_i2c_driver); diff --git a/drivers/nfc/microread/i2c.c b/drivers/nfc/microread/i2c.c index e72b358a2a1254..642df4e0ce24a6 100644 --- a/drivers/nfc/microread/i2c.c +++ b/drivers/nfc/microread/i2c.c @@ -286,7 +286,7 @@ static struct i2c_driver microread_i2c_driver = { .driver = { .name = MICROREAD_I2C_DRIVER_NAME, }, - .probe_new = microread_i2c_probe, + .probe = microread_i2c_probe, .remove = microread_i2c_remove, .id_table = microread_i2c_id, }; diff --git a/drivers/nfc/nfcmrvl/i2c.c b/drivers/nfc/nfcmrvl/i2c.c index 164e2ab859fd9d..74553134c1b189 100644 --- a/drivers/nfc/nfcmrvl/i2c.c +++ b/drivers/nfc/nfcmrvl/i2c.c @@ -258,7 +258,7 @@ static const struct i2c_device_id nfcmrvl_i2c_id_table[] = { MODULE_DEVICE_TABLE(i2c, nfcmrvl_i2c_id_table); static struct i2c_driver nfcmrvl_i2c_driver = { - .probe_new = nfcmrvl_i2c_probe, + .probe = nfcmrvl_i2c_probe, .id_table = nfcmrvl_i2c_id_table, .remove = nfcmrvl_i2c_remove, .driver = { diff --git a/drivers/nfc/nfcsim.c b/drivers/nfc/nfcsim.c index 44eeb17ae48d91..a55381f80cd6e4 100644 --- a/drivers/nfc/nfcsim.c +++ b/drivers/nfc/nfcsim.c @@ -336,10 +336,6 @@ static struct dentry *nfcsim_debugfs_root; static void nfcsim_debugfs_init(void) { nfcsim_debugfs_root = debugfs_create_dir("nfcsim", NULL); - - if (!nfcsim_debugfs_root) - pr_err("Could not create debugfs entry\n"); - } static void nfcsim_debugfs_remove(void) diff --git a/drivers/nfc/nxp-nci/i2c.c b/drivers/nfc/nxp-nci/i2c.c index d4c299be794994..dca25a0c2f33cc 100644 --- a/drivers/nfc/nxp-nci/i2c.c +++ b/drivers/nfc/nxp-nci/i2c.c @@ -97,8 +97,8 @@ static int nxp_nci_i2c_fw_read(struct nxp_nci_i2c_phy *phy, struct sk_buff **skb) { struct i2c_client *client = phy->i2c_dev; - u16 header; size_t frame_len; + __be16 header; int r; r = i2c_master_recv(client, (u8 *) &header, NXP_NCI_FW_HDR_LEN); @@ -348,7 +348,7 @@ static struct i2c_driver nxp_nci_i2c_driver = { .acpi_match_table = ACPI_PTR(acpi_id), .of_match_table = of_nxp_nci_i2c_match, }, - .probe_new = nxp_nci_i2c_probe, + .probe = nxp_nci_i2c_probe, .id_table = nxp_nci_i2c_id_table, .remove = nxp_nci_i2c_remove, }; diff --git a/drivers/nfc/pn533/i2c.c b/drivers/nfc/pn533/i2c.c index 1503a98f0405ab..438ab9553f7a18 100644 --- a/drivers/nfc/pn533/i2c.c +++ b/drivers/nfc/pn533/i2c.c @@ -259,7 +259,7 @@ static struct i2c_driver pn533_i2c_driver = { .name = PN533_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(of_pn533_i2c_match), }, - .probe_new = pn533_i2c_probe, + .probe = pn533_i2c_probe, .id_table = pn533_i2c_id_table, .remove = pn533_i2c_remove, }; diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c index 8b0d910bee06cd..3f6d74832bac3b 100644 --- a/drivers/nfc/pn544/i2c.c +++ b/drivers/nfc/pn544/i2c.c @@ -953,7 +953,7 @@ static struct i2c_driver pn544_hci_i2c_driver = { .of_match_table = of_match_ptr(of_pn544_i2c_match), .acpi_match_table = ACPI_PTR(pn544_hci_i2c_acpi_match), }, - .probe_new = pn544_hci_i2c_probe, + .probe = pn544_hci_i2c_probe, .id_table = pn544_hci_i2c_id_table, .remove = pn544_hci_i2c_remove, }; diff --git a/drivers/nfc/s3fwrn5/i2c.c b/drivers/nfc/s3fwrn5/i2c.c index 2517ae71f9a4a9..720d4a72493c80 100644 --- a/drivers/nfc/s3fwrn5/i2c.c +++ b/drivers/nfc/s3fwrn5/i2c.c @@ -261,7 +261,7 @@ static struct i2c_driver s3fwrn5_i2c_driver = { .name = S3FWRN5_I2C_DRIVER_NAME, .of_match_table = of_match_ptr(of_s3fwrn5_i2c_match), }, - .probe_new = s3fwrn5_i2c_probe, + .probe = s3fwrn5_i2c_probe, .remove = s3fwrn5_i2c_remove, .id_table = s3fwrn5_i2c_id_table, }; diff --git a/drivers/nfc/st-nci/i2c.c b/drivers/nfc/st-nci/i2c.c index 6b5eed8a1fbe13..d20a337e90b456 100644 --- a/drivers/nfc/st-nci/i2c.c +++ b/drivers/nfc/st-nci/i2c.c @@ -283,7 +283,7 @@ static struct i2c_driver st_nci_i2c_driver = { .of_match_table = of_match_ptr(of_st_nci_i2c_match), .acpi_match_table = ACPI_PTR(st_nci_i2c_acpi_match), }, - .probe_new = st_nci_i2c_probe, + .probe = st_nci_i2c_probe, .id_table = st_nci_i2c_id_table, .remove = st_nci_i2c_remove, }; diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c index 55f7a2391bb1ab..064a63db288bdc 100644 --- a/drivers/nfc/st21nfca/i2c.c +++ b/drivers/nfc/st21nfca/i2c.c @@ -597,7 +597,7 @@ static struct i2c_driver st21nfca_hci_i2c_driver = { .of_match_table = of_match_ptr(of_st21nfca_i2c_match), .acpi_match_table = ACPI_PTR(st21nfca_hci_i2c_acpi_match), }, - .probe_new = st21nfca_hci_i2c_probe, + .probe = st21nfca_hci_i2c_probe, .id_table = st21nfca_hci_i2c_id_table, .remove = st21nfca_hci_i2c_remove, }; diff --git a/drivers/nvme/host/constants.c b/drivers/nvme/host/constants.c index bc523ca0225486..5e4f8848dce08e 100644 --- a/drivers/nvme/host/constants.c +++ b/drivers/nvme/host/constants.c @@ -21,7 +21,7 @@ static const char * const nvme_ops[] = { [nvme_cmd_resv_release] = "Reservation Release", [nvme_cmd_zone_mgmt_send] = "Zone Management Send", [nvme_cmd_zone_mgmt_recv] = "Zone Management Receive", - [nvme_cmd_zone_append] = "Zone Management Append", + [nvme_cmd_zone_append] = "Zone Append", }; static const char * const nvme_admin_ops[] = { diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index ccb6eb1282f82d..3ec38e2b917326 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -397,7 +397,16 @@ void nvme_complete_rq(struct request *req) trace_nvme_complete_rq(req); nvme_cleanup_cmd(req); - if (ctrl->kas) + /* + * Completions of long-running commands should not be able to + * defer sending of periodic keep alives, since the controller + * may have completed processing such commands a long time ago + * (arbitrarily close to command submission time). + * req->deadline - req->timeout is the command submission time + * in jiffies. + */ + if (ctrl->kas && + req->deadline - req->timeout >= ctrl->ka_last_check_time) ctrl->comp_seen = true; switch (nvme_decide_disposition(req)) { @@ -1115,7 +1124,7 @@ u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode) } EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, NVME_TARGET_PASSTHRU); -void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, +void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects, struct nvme_command *cmd, int status) { if (effects & NVME_CMD_EFFECTS_CSE_MASK) { @@ -1132,6 +1141,8 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, nvme_queue_scan(ctrl); flush_work(&ctrl->scan_work); } + if (ns) + return; switch (cmd->common.opcode) { case nvme_admin_set_features: @@ -1161,9 +1172,25 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU); * The host should send Keep Alive commands at half of the Keep Alive Timeout * accounting for transport roundtrip times [..]. */ +static unsigned long nvme_keep_alive_work_period(struct nvme_ctrl *ctrl) +{ + unsigned long delay = ctrl->kato * HZ / 2; + + /* + * When using Traffic Based Keep Alive, we need to run + * nvme_keep_alive_work at twice the normal frequency, as one + * command completion can postpone sending a keep alive command + * by up to twice the delay between runs. + */ + if (ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) + delay /= 2; + return delay; +} + static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl) { - queue_delayed_work(nvme_wq, &ctrl->ka_work, ctrl->kato * HZ / 2); + queue_delayed_work(nvme_wq, &ctrl->ka_work, + nvme_keep_alive_work_period(ctrl)); } static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq, @@ -1172,6 +1199,20 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq, struct nvme_ctrl *ctrl = rq->end_io_data; unsigned long flags; bool startka = false; + unsigned long rtt = jiffies - (rq->deadline - rq->timeout); + unsigned long delay = nvme_keep_alive_work_period(ctrl); + + /* + * Subtract off the keepalive RTT so nvme_keep_alive_work runs + * at the desired frequency. + */ + if (rtt <= delay) { + delay -= rtt; + } else { + dev_warn(ctrl->device, "long keepalive RTT (%u ms)\n", + jiffies_to_msecs(rtt)); + delay = 0; + } blk_mq_free_request(rq); @@ -1182,6 +1223,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq, return RQ_END_IO_NONE; } + ctrl->ka_last_check_time = jiffies; ctrl->comp_seen = false; spin_lock_irqsave(&ctrl->lock, flags); if (ctrl->state == NVME_CTRL_LIVE || @@ -1189,7 +1231,7 @@ static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq, startka = true; spin_unlock_irqrestore(&ctrl->lock, flags); if (startka) - nvme_queue_keep_alive_work(ctrl); + queue_delayed_work(nvme_wq, &ctrl->ka_work, delay); return RQ_END_IO_NONE; } @@ -1200,6 +1242,8 @@ static void nvme_keep_alive_work(struct work_struct *work) bool comp_seen = ctrl->comp_seen; struct request *rq; + ctrl->ka_last_check_time = jiffies; + if ((ctrl->ctratt & NVME_CTRL_ATTR_TBKAS) && comp_seen) { dev_dbg(ctrl->device, "reschedule traffic based keep-alive timer\n"); @@ -3585,6 +3629,9 @@ static ssize_t nvme_sysfs_delete(struct device *dev, { struct nvme_ctrl *ctrl = dev_get_drvdata(dev); + if (!test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags)) + return -EBUSY; + if (device_remove_file_self(dev, attr)) nvme_delete_ctrl_sync(ctrl); return count; @@ -5045,7 +5092,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl) * that were missed. We identify persistent discovery controllers by * checking that they started once before, hence are reconnecting back. */ - if (test_and_set_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) && + if (test_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags) && nvme_discovery_ctrl(ctrl)) nvme_change_uevent(ctrl, "NVME_EVENT=rediscover"); @@ -5056,6 +5103,7 @@ void nvme_start_ctrl(struct nvme_ctrl *ctrl) } nvme_change_uevent(ctrl, "NVME_EVENT=connected"); + set_bit(NVME_CTRL_STARTED_ONCE, &ctrl->flags); } EXPORT_SYMBOL_GPL(nvme_start_ctrl); diff --git a/drivers/nvme/host/hwmon.c b/drivers/nvme/host/hwmon.c index 9e6e56c20ec993..316f3e4ca7cc60 100644 --- a/drivers/nvme/host/hwmon.c +++ b/drivers/nvme/host/hwmon.c @@ -163,7 +163,9 @@ static umode_t nvme_hwmon_is_visible(const void *_data, case hwmon_temp_max: case hwmon_temp_min: if ((!channel && data->ctrl->wctemp) || - (channel && data->log->temp_sensor[channel - 1])) { + (channel && data->log->temp_sensor[channel - 1] && + !(data->ctrl->quirks & + NVME_QUIRK_NO_SECONDARY_TEMP_THRESH))) { if (data->ctrl->quirks & NVME_QUIRK_NO_TEMP_THRESH_CHANGE) return 0444; diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c index 81c5c9e3847747..f15e7330b75ac5 100644 --- a/drivers/nvme/host/ioctl.c +++ b/drivers/nvme/host/ioctl.c @@ -254,7 +254,7 @@ static int nvme_submit_user_cmd(struct request_queue *q, blk_mq_free_request(req); if (effects) - nvme_passthru_end(ctrl, effects, cmd, ret); + nvme_passthru_end(ctrl, ns, effects, cmd, ret); return ret; } diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 9171452e2f6d4e..2bc159a318ff0a 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -884,7 +884,6 @@ void nvme_mpath_remove_disk(struct nvme_ns_head *head) { if (!head->disk) return; - blk_mark_disk_dead(head->disk); /* make sure all pending bios are cleaned up */ kblockd_schedule_work(&head->requeue_work); flush_work(&head->requeue_work); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index bf46f122e9e1e4..8657811f8b8875 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -149,6 +149,11 @@ enum nvme_quirks { * Reports garbage in the namespace identifiers (eui64, nguid, uuid). */ NVME_QUIRK_BOGUS_NID = (1 << 18), + + /* + * No temperature thresholds for channels other than 0 (Composite). + */ + NVME_QUIRK_NO_SECONDARY_TEMP_THRESH = (1 << 19), }; /* @@ -323,6 +328,7 @@ struct nvme_ctrl { struct delayed_work ka_work; struct delayed_work failfast_work; struct nvme_command ka_cmd; + unsigned long ka_last_check_time; struct work_struct fw_act_work; unsigned long events; @@ -1072,7 +1078,7 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode); u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode); int nvme_execute_rq(struct request *rq, bool at_head); -void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects, +void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects, struct nvme_command *cmd, int status); struct nvme_ctrl *nvme_ctrl_from_file(struct file *file); struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index 7f25c0fe3a0bf5..492f319ebdf37a 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -2956,7 +2956,7 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev, * over a single page. */ dev->ctrl.max_hw_sectors = min_t(u32, - NVME_MAX_KB_SZ << 1, dma_max_mapping_size(&pdev->dev) >> 9); + NVME_MAX_KB_SZ << 1, dma_opt_mapping_size(&pdev->dev) >> 9); dev->ctrl.max_segments = NVME_MAX_SEGS; /* @@ -3402,6 +3402,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, { PCI_DEVICE(0x2646, 0x2263), /* KINGSTON A2000 NVMe SSD */ .driver_data = NVME_QUIRK_NO_DEEPEST_PS, }, + { PCI_DEVICE(0x2646, 0x5013), /* Kingston KC3000, Kingston FURY Renegade */ + .driver_data = NVME_QUIRK_NO_SECONDARY_TEMP_THRESH, }, { PCI_DEVICE(0x2646, 0x5018), /* KINGSTON OM8SFP4xxxxP OS21012 NVMe SSD */ .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, }, { PCI_DEVICE(0x2646, 0x5016), /* KINGSTON OM3PGP4xxxxP OS21011 NVMe SSD */ @@ -3422,6 +3424,8 @@ static const struct pci_device_id nvme_id_table[] = { .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1e4B, 0x1202), /* MAXIO MAP1202 */ .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1e4B, 0x1602), /* MAXIO MAP1602 */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1cc1, 0x5350), /* ADATA XPG GAMMIX S50 */ .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(0x1dbe, 0x5236), /* ADATA XPG GAMMIX S70 */ @@ -3441,6 +3445,10 @@ static const struct pci_device_id nvme_id_table[] = { NVME_QUIRK_IGNORE_DEV_SUBNQN, }, { PCI_DEVICE(0x10ec, 0x5763), /* TEAMGROUP T-FORCE CARDEA ZERO Z330 SSD */ .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x1e4b, 0x1602), /* HS-SSD-FUTURE 2048G */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, + { PCI_DEVICE(0x10ec, 0x5765), /* TEAMGROUP MP33 2TB SSD */ + .driver_data = NVME_QUIRK_BOGUS_NID, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0061), .driver_data = NVME_QUIRK_DMA_ADDRESS_BITS_48, }, { PCI_DEVICE(PCI_VENDOR_ID_AMAZON, 0x0065), diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c index 511c980d538df3..71a9c1cc57f59c 100644 --- a/drivers/nvme/target/passthru.c +++ b/drivers/nvme/target/passthru.c @@ -243,7 +243,7 @@ static void nvmet_passthru_execute_cmd_work(struct work_struct *w) blk_mq_free_request(rq); if (effects) - nvme_passthru_end(ctrl, effects, req->cmd, status); + nvme_passthru_end(ctrl, ns, effects, req->cmd, status); } static enum rq_end_io_ret nvmet_passthru_req_done(struct request *rq, diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f4e2a88729fd14..c525867760bf81 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -6003,8 +6003,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x56c1, aspm_l1_acceptable_latency #ifdef CONFIG_PCIE_DPC /* - * Intel Tiger Lake and Alder Lake BIOS has a bug that clears the DPC - * RP PIO Log Size of the integrated Thunderbolt PCIe Root Ports. + * Intel Ice Lake, Tiger Lake and Alder Lake BIOS has a bug that clears + * the DPC RP PIO Log Size of the integrated Thunderbolt PCIe Root + * Ports. */ static void dpc_log_size(struct pci_dev *dev) { @@ -6027,6 +6028,10 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x461f, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x462f, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x463f, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x466e, dpc_log_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a1d, dpc_log_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a1f, dpc_log_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a21, dpc_log_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x8a23, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a23, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a25, dpc_log_size); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9a27, dpc_log_size); diff --git a/drivers/phy/amlogic/phy-meson-g12a-mipi-dphy-analog.c b/drivers/phy/amlogic/phy-meson-g12a-mipi-dphy-analog.c index c14089fa7db495..cabdddbbabfd7d 100644 --- a/drivers/phy/amlogic/phy-meson-g12a-mipi-dphy-analog.c +++ b/drivers/phy/amlogic/phy-meson-g12a-mipi-dphy-analog.c @@ -70,7 +70,7 @@ static int phy_g12a_mipi_dphy_analog_power_on(struct phy *phy) HHI_MIPI_CNTL1_BANDGAP); regmap_write(priv->regmap, HHI_MIPI_CNTL2, - FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL0, 0x459) | + FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL0, 0x45a) | FIELD_PREP(HHI_MIPI_CNTL2_DIF_TX_CTL1, 0x2680)); reg = DSI_LANE_CLK; diff --git a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c index caa953780beebb..8aa7251de4a96e 100644 --- a/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c +++ b/drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c @@ -237,11 +237,11 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw, */ if (tmds_clk < 54 * MEGA) txposdiv = 8; - else if (tmds_clk >= 54 * MEGA && tmds_clk < 148.35 * MEGA) + else if (tmds_clk >= 54 * MEGA && (tmds_clk * 100) < 14835 * MEGA) txposdiv = 4; - else if (tmds_clk >= 148.35 * MEGA && tmds_clk < 296.7 * MEGA) + else if ((tmds_clk * 100) >= 14835 * MEGA && (tmds_clk * 10) < 2967 * MEGA) txposdiv = 2; - else if (tmds_clk >= 296.7 * MEGA && tmds_clk <= 594 * MEGA) + else if ((tmds_clk * 10) >= 2967 * MEGA && tmds_clk <= 594 * MEGA) txposdiv = 1; else return -EINVAL; @@ -324,12 +324,12 @@ static int mtk_hdmi_pll_drv_setting(struct clk_hw *hw) clk_channel_bias = 0x34; /* 20mA */ impedance_en = 0xf; impedance = 0x36; /* 100ohm */ - } else if (pixel_clk >= 74.175 * MEGA && pixel_clk <= 300 * MEGA) { + } else if (((u64)pixel_clk * 1000) >= 74175 * MEGA && pixel_clk <= 300 * MEGA) { data_channel_bias = 0x34; /* 20mA */ clk_channel_bias = 0x2c; /* 16mA */ impedance_en = 0xf; impedance = 0x36; /* 100ohm */ - } else if (pixel_clk >= 27 * MEGA && pixel_clk < 74.175 * MEGA) { + } else if (pixel_clk >= 27 * MEGA && ((u64)pixel_clk * 1000) < 74175 * MEGA) { data_channel_bias = 0x14; /* 10mA */ clk_channel_bias = 0x14; /* 10mA */ impedance_en = 0x0; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c index 6850e04c329b8e..87b17e5877ab8c 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c @@ -2472,7 +2472,7 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); if (ret) { dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); - goto err_unlock; + goto err_decrement_count; } ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets); @@ -2522,7 +2522,8 @@ static int qmp_combo_com_init(struct qmp_combo *qmp) reset_control_bulk_assert(cfg->num_resets, qmp->resets); err_disable_regulators: regulator_bulk_disable(cfg->num_vregs, qmp->vregs); -err_unlock: +err_decrement_count: + qmp->init_count--; mutex_unlock(&qmp->phy_mutex); return ret; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c index 09824be088c96c..0c603bc06e0998 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie-msm8996.c @@ -379,7 +379,7 @@ static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy) ret = regulator_bulk_enable(cfg->num_vregs, qmp->vregs); if (ret) { dev_err(qmp->dev, "failed to enable regulators, err=%d\n", ret); - goto err_unlock; + goto err_decrement_count; } ret = reset_control_bulk_assert(cfg->num_resets, qmp->resets); @@ -409,7 +409,8 @@ static int qmp_pcie_msm8996_com_init(struct qmp_phy *qphy) reset_control_bulk_assert(cfg->num_resets, qmp->resets); err_disable_regulators: regulator_bulk_disable(cfg->num_vregs, qmp->vregs); -err_unlock: +err_decrement_count: + qmp->init_count--; mutex_unlock(&qmp->phy_mutex); return ret; diff --git a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c index a590635962140f..6c237f3cc66db8 100644 --- a/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c +++ b/drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c @@ -115,11 +115,11 @@ struct phy_override_seq { * * @cfg_ahb_clk: AHB2PHY interface clock * @ref_clk: phy reference clock - * @iface_clk: phy interface clock * @phy_reset: phy reset control * @vregs: regulator supplies bulk data * @phy_initialized: if PHY has been initialized correctly * @mode: contains the current mode the PHY is in + * @update_seq_cfg: tuning parameters for phy init */ struct qcom_snps_hsphy { struct phy *phy; diff --git a/drivers/platform/mellanox/mlxbf-pmc.c b/drivers/platform/mellanox/mlxbf-pmc.c index c2c9b0d3244cbf..be967d797c28e0 100644 --- a/drivers/platform/mellanox/mlxbf-pmc.c +++ b/drivers/platform/mellanox/mlxbf-pmc.c @@ -1348,9 +1348,8 @@ static int mlxbf_pmc_map_counters(struct device *dev) for (i = 0; i < pmc->total_blocks; ++i) { if (strstr(pmc->block_name[i], "tile")) { - ret = sscanf(pmc->block_name[i], "tile%d", &tile_num); - if (ret < 0) - return ret; + if (sscanf(pmc->block_name[i], "tile%d", &tile_num) != 1) + return -EINVAL; if (tile_num >= pmc->tile_count) continue; diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c index 535581c0471c50..7fc602e01487d4 100644 --- a/drivers/platform/surface/aggregator/controller.c +++ b/drivers/platform/surface/aggregator/controller.c @@ -825,7 +825,7 @@ static int ssam_cplt_init(struct ssam_cplt *cplt, struct device *dev) cplt->dev = dev; - cplt->wq = create_workqueue(SSAM_CPLT_WQ_NAME); + cplt->wq = alloc_workqueue(SSAM_CPLT_WQ_NAME, WQ_UNBOUND | WQ_MEM_RECLAIM, 0); if (!cplt->wq) return -ENOMEM; diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c index 8f52b62d1c1956..c0a1a5869246ed 100644 --- a/drivers/platform/surface/surface_aggregator_tabletsw.c +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c @@ -210,6 +210,7 @@ enum ssam_kip_cover_state { SSAM_KIP_COVER_STATE_LAPTOP = 0x03, SSAM_KIP_COVER_STATE_FOLDED_CANVAS = 0x04, SSAM_KIP_COVER_STATE_FOLDED_BACK = 0x05, + SSAM_KIP_COVER_STATE_BOOK = 0x06, }; static const char *ssam_kip_cover_state_name(struct ssam_tablet_sw *sw, @@ -231,6 +232,9 @@ static const char *ssam_kip_cover_state_name(struct ssam_tablet_sw *sw, case SSAM_KIP_COVER_STATE_FOLDED_BACK: return "folded-back"; + case SSAM_KIP_COVER_STATE_BOOK: + return "book"; + default: dev_warn(&sw->sdev->dev, "unknown KIP cover state: %u\n", state->state); return ""; @@ -244,6 +248,7 @@ static bool ssam_kip_cover_state_is_tablet_mode(struct ssam_tablet_sw *sw, case SSAM_KIP_COVER_STATE_DISCONNECTED: case SSAM_KIP_COVER_STATE_FOLDED_CANVAS: case SSAM_KIP_COVER_STATE_FOLDED_BACK: + case SSAM_KIP_COVER_STATE_BOOK: return true; case SSAM_KIP_COVER_STATE_CLOSED: @@ -335,6 +340,7 @@ enum ssam_pos_state_cover { SSAM_POS_COVER_LAPTOP = 0x03, SSAM_POS_COVER_FOLDED_CANVAS = 0x04, SSAM_POS_COVER_FOLDED_BACK = 0x05, + SSAM_POS_COVER_BOOK = 0x06, }; enum ssam_pos_state_sls { @@ -367,6 +373,9 @@ static const char *ssam_pos_state_name_cover(struct ssam_tablet_sw *sw, u32 stat case SSAM_POS_COVER_FOLDED_BACK: return "folded-back"; + case SSAM_POS_COVER_BOOK: + return "book"; + default: dev_warn(&sw->sdev->dev, "unknown device posture for type-cover: %u\n", state); return ""; @@ -416,6 +425,7 @@ static bool ssam_pos_state_is_tablet_mode_cover(struct ssam_tablet_sw *sw, u32 s case SSAM_POS_COVER_DISCONNECTED: case SSAM_POS_COVER_FOLDED_CANVAS: case SSAM_POS_COVER_FOLDED_BACK: + case SSAM_POS_COVER_BOOK: return true; case SSAM_POS_COVER_CLOSED: diff --git a/drivers/platform/x86/amd/pmf/core.c b/drivers/platform/x86/amd/pmf/core.c index d5bb775dadcf20..ee5f124f78b6d7 100644 --- a/drivers/platform/x86/amd/pmf/core.c +++ b/drivers/platform/x86/amd/pmf/core.c @@ -245,24 +245,29 @@ static const struct pci_device_id pmf_pci_ids[] = { { } }; -int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) +static void amd_pmf_set_dram_addr(struct amd_pmf_dev *dev) { u64 phys_addr; u32 hi, low; - INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics); + phys_addr = virt_to_phys(dev->buf); + hi = phys_addr >> 32; + low = phys_addr & GENMASK(31, 0); + + amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL); + amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL); +} +int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) +{ /* Get Metrics Table Address */ dev->buf = kzalloc(sizeof(dev->m_table), GFP_KERNEL); if (!dev->buf) return -ENOMEM; - phys_addr = virt_to_phys(dev->buf); - hi = phys_addr >> 32; - low = phys_addr & GENMASK(31, 0); + INIT_DELAYED_WORK(&dev->work_buffer, amd_pmf_get_metrics); - amd_pmf_send_cmd(dev, SET_DRAM_ADDR_HIGH, 0, hi, NULL); - amd_pmf_send_cmd(dev, SET_DRAM_ADDR_LOW, 0, low, NULL); + amd_pmf_set_dram_addr(dev); /* * Start collecting the metrics data after a small delay @@ -273,6 +278,18 @@ int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev) return 0; } +static int amd_pmf_resume_handler(struct device *dev) +{ + struct amd_pmf_dev *pdev = dev_get_drvdata(dev); + + if (pdev->buf) + amd_pmf_set_dram_addr(pdev); + + return 0; +} + +static DEFINE_SIMPLE_DEV_PM_OPS(amd_pmf_pm, NULL, amd_pmf_resume_handler); + static void amd_pmf_init_features(struct amd_pmf_dev *dev) { int ret; @@ -413,6 +430,7 @@ static struct platform_driver amd_pmf_driver = { .name = "amd-pmf", .acpi_match_table = amd_pmf_acpi_ids, .dev_groups = amd_pmf_driver_groups, + .pm = pm_sleep_ptr(&amd_pmf_pm), }, .probe = amd_pmf_probe, .remove_new = amd_pmf_remove, diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index e2c9a68d12df9c..fdf7da06af3067 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -555,6 +555,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x71, { KEY_F13 } }, /* General-purpose button */ { KE_IGNORE, 0x79, }, /* Charger type dectection notification */ { KE_KEY, 0x7a, { KEY_ALS_TOGGLE } }, /* Ambient Light Sensor Toggle */ + { KE_IGNORE, 0x7B, }, /* Charger connect/disconnect notification */ { KE_KEY, 0x7c, { KEY_MICMUTE } }, { KE_KEY, 0x7D, { KEY_BLUETOOTH } }, /* Bluetooth Enable */ { KE_KEY, 0x7E, { KEY_BLUETOOTH } }, /* Bluetooth Disable */ @@ -584,6 +585,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0xAE, { KEY_FN_F5 } }, /* Fn+F5 fan mode on 2020+ */ { KE_KEY, 0xB3, { KEY_PROG4 } }, /* AURA */ { KE_KEY, 0xB5, { KEY_CALC } }, + { KE_IGNORE, 0xC0, }, /* External display connect/disconnect notification */ { KE_KEY, 0xC4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ diff --git a/drivers/platform/x86/intel/ifs/load.c b/drivers/platform/x86/intel/ifs/load.c index 61dffb4c8a1dcd..e6ae8265f3a37e 100644 --- a/drivers/platform/x86/intel/ifs/load.c +++ b/drivers/platform/x86/intel/ifs/load.c @@ -208,7 +208,7 @@ static int scan_chunks_sanity_check(struct device *dev) continue; reinit_completion(&ifs_done); local_work.dev = dev; - INIT_WORK(&local_work.w, copy_hashes_authenticate_chunks); + INIT_WORK_ONSTACK(&local_work.w, copy_hashes_authenticate_chunks); schedule_work_on(cpu, &local_work.w); wait_for_completion(&ifs_done); if (ifsd->loading_error) { diff --git a/drivers/platform/x86/intel/int3472/clk_and_regulator.c b/drivers/platform/x86/intel/int3472/clk_and_regulator.c index 1086c3d8349454..399f0623ca1b5c 100644 --- a/drivers/platform/x86/intel/int3472/clk_and_regulator.c +++ b/drivers/platform/x86/intel/int3472/clk_and_regulator.c @@ -101,9 +101,11 @@ int skl_int3472_register_clock(struct int3472_discrete_device *int3472, int3472->clock.ena_gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0], "int3472,clk-enable"); - if (IS_ERR(int3472->clock.ena_gpio)) - return dev_err_probe(int3472->dev, PTR_ERR(int3472->clock.ena_gpio), - "getting clk-enable GPIO\n"); + if (IS_ERR(int3472->clock.ena_gpio)) { + ret = PTR_ERR(int3472->clock.ena_gpio); + int3472->clock.ena_gpio = NULL; + return dev_err_probe(int3472->dev, ret, "getting clk-enable GPIO\n"); + } if (polarity == GPIO_ACTIVE_LOW) gpiod_toggle_active_low(int3472->clock.ena_gpio); @@ -199,8 +201,9 @@ int skl_int3472_register_regulator(struct int3472_discrete_device *int3472, int3472->regulator.gpio = acpi_get_and_request_gpiod(path, agpio->pin_table[0], "int3472,regulator"); if (IS_ERR(int3472->regulator.gpio)) { - dev_err(int3472->dev, "Failed to get regulator GPIO line\n"); - return PTR_ERR(int3472->regulator.gpio); + ret = PTR_ERR(int3472->regulator.gpio); + int3472->regulator.gpio = NULL; + return dev_err_probe(int3472->dev, ret, "getting regulator GPIO\n"); } /* Ensure the pin is in output mode and non-active state */ diff --git a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c index e0572a29212e85..02fe360a59c7cf 100644 --- a/drivers/platform/x86/intel/speed_select_if/isst_if_common.c +++ b/drivers/platform/x86/intel/speed_select_if/isst_if_common.c @@ -304,14 +304,13 @@ struct isst_if_pkg_info { static struct isst_if_cpu_info *isst_cpu_info; static struct isst_if_pkg_info *isst_pkg_info; -#define ISST_MAX_PCI_DOMAINS 8 - static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn) { struct pci_dev *matched_pci_dev = NULL; struct pci_dev *pci_dev = NULL; + struct pci_dev *_pci_dev = NULL; int no_matches = 0, pkg_id; - int i, bus_number; + int bus_number; if (bus_no < 0 || bus_no >= ISST_MAX_BUS_NUMBER || cpu < 0 || cpu >= nr_cpu_ids || cpu >= num_possible_cpus()) @@ -323,12 +322,11 @@ static struct pci_dev *_isst_if_get_pci_dev(int cpu, int bus_no, int dev, int fn if (bus_number < 0) return NULL; - for (i = 0; i < ISST_MAX_PCI_DOMAINS; ++i) { - struct pci_dev *_pci_dev; + for_each_pci_dev(_pci_dev) { int node; - _pci_dev = pci_get_domain_bus_and_slot(i, bus_number, PCI_DEVFN(dev, fn)); - if (!_pci_dev) + if (_pci_dev->bus->number != bus_number || + _pci_dev->devfn != PCI_DEVFN(dev, fn)) continue; ++no_matches; diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 307ee6f71042e9..6f83e99d2eb72e 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -624,10 +624,8 @@ static int ab8500_btemp_get_ext_psy_data(struct device *dev, void *data) */ static void ab8500_btemp_external_power_changed(struct power_supply *psy) { - struct ab8500_btemp *di = power_supply_get_drvdata(psy); - - class_for_each_device(power_supply_class, NULL, - di->btemp_psy, ab8500_btemp_get_ext_psy_data); + class_for_each_device(power_supply_class, NULL, psy, + ab8500_btemp_get_ext_psy_data); } /* ab8500 btemp driver interrupts and their respective isr */ diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 41a7bff9ac3765..53560fbb6dcd34 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -2407,10 +2407,8 @@ static int ab8500_fg_init_hw_registers(struct ab8500_fg *di) */ static void ab8500_fg_external_power_changed(struct power_supply *psy) { - struct ab8500_fg *di = power_supply_get_drvdata(psy); - - class_for_each_device(power_supply_class, NULL, - di->fg_psy, ab8500_fg_get_ext_psy_data); + class_for_each_device(power_supply_class, NULL, psy, + ab8500_fg_get_ext_psy_data); } /** diff --git a/drivers/power/supply/axp288_fuel_gauge.c b/drivers/power/supply/axp288_fuel_gauge.c index 05f41317846296..3be6f3b10ea428 100644 --- a/drivers/power/supply/axp288_fuel_gauge.c +++ b/drivers/power/supply/axp288_fuel_gauge.c @@ -507,7 +507,7 @@ static void fuel_gauge_external_power_changed(struct power_supply *psy) mutex_lock(&info->lock); info->valid = 0; /* Force updating of the cached registers */ mutex_unlock(&info->lock); - power_supply_changed(info->bat); + power_supply_changed(psy); } static struct power_supply_desc fuel_gauge_desc = { diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c index de67b985f0a913..dc33f00fcc0682 100644 --- a/drivers/power/supply/bq24190_charger.c +++ b/drivers/power/supply/bq24190_charger.c @@ -1262,6 +1262,7 @@ static void bq24190_input_current_limit_work(struct work_struct *work) bq24190_charger_set_property(bdi->charger, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); + power_supply_changed(bdi->charger); } /* Sync the input-current-limit with our parent supply (if we have one) */ diff --git a/drivers/power/supply/bq25890_charger.c b/drivers/power/supply/bq25890_charger.c index 22cde35eb144c6..f8636cf86505a7 100644 --- a/drivers/power/supply/bq25890_charger.c +++ b/drivers/power/supply/bq25890_charger.c @@ -750,7 +750,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy) if (bq->chip_version != BQ25892) return; - ret = power_supply_get_property_from_supplier(bq->charger, + ret = power_supply_get_property_from_supplier(psy, POWER_SUPPLY_PROP_USB_TYPE, &val); if (ret) @@ -775,6 +775,7 @@ static void bq25890_charger_external_power_changed(struct power_supply *psy) } bq25890_field_write(bq, F_IINLIM, input_current_limit); + power_supply_changed(psy); } static int bq25890_get_chip_state(struct bq25890_device *bq, @@ -1106,6 +1107,8 @@ static void bq25890_pump_express_work(struct work_struct *data) dev_info(bq->dev, "Hi-voltage charging requested, input voltage is %d mV\n", voltage); + power_supply_changed(bq->charger); + return; error_print: bq25890_field_write(bq, F_PUMPX_EN, 0); diff --git a/drivers/power/supply/bq27xxx_battery.c b/drivers/power/supply/bq27xxx_battery.c index 5ff6f44fd47b22..4296600e8912a3 100644 --- a/drivers/power/supply/bq27xxx_battery.c +++ b/drivers/power/supply/bq27xxx_battery.c @@ -1083,10 +1083,8 @@ static int poll_interval_param_set(const char *val, const struct kernel_param *k return ret; mutex_lock(&bq27xxx_list_lock); - list_for_each_entry(di, &bq27xxx_battery_devices, list) { - cancel_delayed_work_sync(&di->work); - schedule_delayed_work(&di->work, 0); - } + list_for_each_entry(di, &bq27xxx_battery_devices, list) + mod_delayed_work(system_wq, &di->work, 0); mutex_unlock(&bq27xxx_list_lock); return ret; @@ -1761,60 +1759,6 @@ static int bq27xxx_battery_read_health(struct bq27xxx_device_info *di) return POWER_SUPPLY_HEALTH_GOOD; } -void bq27xxx_battery_update(struct bq27xxx_device_info *di) -{ - struct bq27xxx_reg_cache cache = {0, }; - bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; - - cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); - if ((cache.flags & 0xff) == 0xff) - cache.flags = -1; /* read error */ - if (cache.flags >= 0) { - cache.temperature = bq27xxx_battery_read_temperature(di); - if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) - cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); - if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) - cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); - if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) - cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); - - cache.charge_full = bq27xxx_battery_read_fcc(di); - cache.capacity = bq27xxx_battery_read_soc(di); - if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) - cache.energy = bq27xxx_battery_read_energy(di); - di->cache.flags = cache.flags; - cache.health = bq27xxx_battery_read_health(di); - if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) - cache.cycle_count = bq27xxx_battery_read_cyct(di); - - /* We only have to read charge design full once */ - if (di->charge_design_full <= 0) - di->charge_design_full = bq27xxx_battery_read_dcap(di); - } - - if ((di->cache.capacity != cache.capacity) || - (di->cache.flags != cache.flags)) - power_supply_changed(di->bat); - - if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) - di->cache = cache; - - di->last_update = jiffies; -} -EXPORT_SYMBOL_GPL(bq27xxx_battery_update); - -static void bq27xxx_battery_poll(struct work_struct *work) -{ - struct bq27xxx_device_info *di = - container_of(work, struct bq27xxx_device_info, - work.work); - - bq27xxx_battery_update(di); - - if (poll_interval > 0) - schedule_delayed_work(&di->work, poll_interval * HZ); -} - static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags) { if (di->opts & BQ27XXX_O_ZERO) @@ -1833,7 +1777,8 @@ static bool bq27xxx_battery_is_full(struct bq27xxx_device_info *di, int flags) static int bq27xxx_battery_current_and_status( struct bq27xxx_device_info *di, union power_supply_propval *val_curr, - union power_supply_propval *val_status) + union power_supply_propval *val_status, + struct bq27xxx_reg_cache *cache) { bool single_flags = (di->opts & BQ27XXX_O_ZERO); int curr; @@ -1845,10 +1790,14 @@ static int bq27xxx_battery_current_and_status( return curr; } - flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags); - if (flags < 0) { - dev_err(di->dev, "error reading flags\n"); - return flags; + if (cache) { + flags = cache->flags; + } else { + flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, single_flags); + if (flags < 0) { + dev_err(di->dev, "error reading flags\n"); + return flags; + } } if (di->opts & BQ27XXX_O_ZERO) { @@ -1883,6 +1832,78 @@ static int bq27xxx_battery_current_and_status( return 0; } +static void bq27xxx_battery_update_unlocked(struct bq27xxx_device_info *di) +{ + union power_supply_propval status = di->last_status; + struct bq27xxx_reg_cache cache = {0, }; + bool has_singe_flag = di->opts & BQ27XXX_O_ZERO; + + cache.flags = bq27xxx_read(di, BQ27XXX_REG_FLAGS, has_singe_flag); + if ((cache.flags & 0xff) == 0xff) + cache.flags = -1; /* read error */ + if (cache.flags >= 0) { + cache.temperature = bq27xxx_battery_read_temperature(di); + if (di->regs[BQ27XXX_REG_TTE] != INVALID_REG_ADDR) + cache.time_to_empty = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTE); + if (di->regs[BQ27XXX_REG_TTECP] != INVALID_REG_ADDR) + cache.time_to_empty_avg = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTECP); + if (di->regs[BQ27XXX_REG_TTF] != INVALID_REG_ADDR) + cache.time_to_full = bq27xxx_battery_read_time(di, BQ27XXX_REG_TTF); + + cache.charge_full = bq27xxx_battery_read_fcc(di); + cache.capacity = bq27xxx_battery_read_soc(di); + if (di->regs[BQ27XXX_REG_AE] != INVALID_REG_ADDR) + cache.energy = bq27xxx_battery_read_energy(di); + di->cache.flags = cache.flags; + cache.health = bq27xxx_battery_read_health(di); + if (di->regs[BQ27XXX_REG_CYCT] != INVALID_REG_ADDR) + cache.cycle_count = bq27xxx_battery_read_cyct(di); + + /* + * On gauges with signed current reporting the current must be + * checked to detect charging <-> discharging status changes. + */ + if (!(di->opts & BQ27XXX_O_ZERO)) + bq27xxx_battery_current_and_status(di, NULL, &status, &cache); + + /* We only have to read charge design full once */ + if (di->charge_design_full <= 0) + di->charge_design_full = bq27xxx_battery_read_dcap(di); + } + + if ((di->cache.capacity != cache.capacity) || + (di->cache.flags != cache.flags) || + (di->last_status.intval != status.intval)) { + di->last_status.intval = status.intval; + power_supply_changed(di->bat); + } + + if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) + di->cache = cache; + + di->last_update = jiffies; + + if (!di->removed && poll_interval > 0) + mod_delayed_work(system_wq, &di->work, poll_interval * HZ); +} + +void bq27xxx_battery_update(struct bq27xxx_device_info *di) +{ + mutex_lock(&di->lock); + bq27xxx_battery_update_unlocked(di); + mutex_unlock(&di->lock); +} +EXPORT_SYMBOL_GPL(bq27xxx_battery_update); + +static void bq27xxx_battery_poll(struct work_struct *work) +{ + struct bq27xxx_device_info *di = + container_of(work, struct bq27xxx_device_info, + work.work); + + bq27xxx_battery_update(di); +} + /* * Get the average power in µW * Return < 0 if something fails. @@ -1985,10 +2006,8 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); mutex_lock(&di->lock); - if (time_is_before_jiffies(di->last_update + 5 * HZ)) { - cancel_delayed_work_sync(&di->work); - bq27xxx_battery_poll(&di->work.work); - } + if (time_is_before_jiffies(di->last_update + 5 * HZ)) + bq27xxx_battery_update_unlocked(di); mutex_unlock(&di->lock); if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0) @@ -1996,7 +2015,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_STATUS: - ret = bq27xxx_battery_current_and_status(di, NULL, val); + ret = bq27xxx_battery_current_and_status(di, NULL, val, NULL); break; case POWER_SUPPLY_PROP_VOLTAGE_NOW: ret = bq27xxx_battery_voltage(di, val); @@ -2005,7 +2024,7 @@ static int bq27xxx_battery_get_property(struct power_supply *psy, val->intval = di->cache.flags < 0 ? 0 : 1; break; case POWER_SUPPLY_PROP_CURRENT_NOW: - ret = bq27xxx_battery_current_and_status(di, val, NULL); + ret = bq27xxx_battery_current_and_status(di, val, NULL, NULL); break; case POWER_SUPPLY_PROP_CAPACITY: ret = bq27xxx_simple_value(di->cache.capacity, val); @@ -2078,8 +2097,8 @@ static void bq27xxx_external_power_changed(struct power_supply *psy) { struct bq27xxx_device_info *di = power_supply_get_drvdata(psy); - cancel_delayed_work_sync(&di->work); - schedule_delayed_work(&di->work, 0); + /* After charger plug in/out wait 0.5s for things to stabilize */ + mod_delayed_work(system_wq, &di->work, HZ / 2); } int bq27xxx_battery_setup(struct bq27xxx_device_info *di) @@ -2127,22 +2146,18 @@ EXPORT_SYMBOL_GPL(bq27xxx_battery_setup); void bq27xxx_battery_teardown(struct bq27xxx_device_info *di) { - /* - * power_supply_unregister call bq27xxx_battery_get_property which - * call bq27xxx_battery_poll. - * Make sure that bq27xxx_battery_poll will not call - * schedule_delayed_work again after unregister (which cause OOPS). - */ - poll_interval = 0; - - cancel_delayed_work_sync(&di->work); - - power_supply_unregister(di->bat); - mutex_lock(&bq27xxx_list_lock); list_del(&di->list); mutex_unlock(&bq27xxx_list_lock); + /* Set removed to avoid bq27xxx_battery_update() re-queuing the work */ + mutex_lock(&di->lock); + di->removed = true; + mutex_unlock(&di->lock); + + cancel_delayed_work_sync(&di->work); + + power_supply_unregister(di->bat); mutex_destroy(&di->lock); } EXPORT_SYMBOL_GPL(bq27xxx_battery_teardown); diff --git a/drivers/power/supply/bq27xxx_battery_i2c.c b/drivers/power/supply/bq27xxx_battery_i2c.c index f8768997333bc5..6d3c7487633906 100644 --- a/drivers/power/supply/bq27xxx_battery_i2c.c +++ b/drivers/power/supply/bq27xxx_battery_i2c.c @@ -179,7 +179,7 @@ static int bq27xxx_battery_i2c_probe(struct i2c_client *client) i2c_set_clientdata(client, di); if (client->irq) { - ret = devm_request_threaded_irq(&client->dev, client->irq, + ret = request_threaded_irq(client->irq, NULL, bq27xxx_battery_irq_handler_thread, IRQF_ONESHOT, di->name, di); @@ -209,6 +209,7 @@ static void bq27xxx_battery_i2c_remove(struct i2c_client *client) { struct bq27xxx_device_info *di = i2c_get_clientdata(client); + free_irq(client->irq, di); bq27xxx_battery_teardown(di); mutex_lock(&battery_mutex); diff --git a/drivers/power/supply/mt6360_charger.c b/drivers/power/supply/mt6360_charger.c index 92e48e3a485364..1305cba61edd4b 100644 --- a/drivers/power/supply/mt6360_charger.c +++ b/drivers/power/supply/mt6360_charger.c @@ -796,7 +796,9 @@ static int mt6360_charger_probe(struct platform_device *pdev) mci->vinovp = 6500000; mutex_init(&mci->chgdet_lock); platform_set_drvdata(pdev, mci); - devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work); + ret = devm_work_autocancel(&pdev->dev, &mci->chrdet_work, mt6360_chrdet_work); + if (ret) + return dev_err_probe(&pdev->dev, ret, "Failed to set delayed work\n"); ret = device_property_read_u32(&pdev->dev, "richtek,vinovp-microvolt", &mci->vinovp); if (ret) diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index ab986dbace16a3..3791aec69ddc67 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -348,6 +348,10 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data) struct power_supply *psy = dev_get_drvdata(dev); unsigned int *count = data; + if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_SCOPE, &ret)) + if (ret.intval == POWER_SUPPLY_SCOPE_DEVICE) + return 0; + (*count)++; if (psy->desc->type != POWER_SUPPLY_TYPE_BATTERY) if (!psy->desc->get_property(psy, POWER_SUPPLY_PROP_ONLINE, @@ -366,8 +370,8 @@ int power_supply_is_system_supplied(void) __power_supply_is_system_supplied); /* - * If no power class device was found at all, most probably we are - * running on a desktop system, so assume we are on mains power. + * If no system scope power class device was found at all, most probably we + * are running on a desktop system, so assume we are on mains power. */ if (count == 0) return 1; @@ -573,7 +577,7 @@ int power_supply_get_battery_info(struct power_supply *psy, struct power_supply_battery_info *info; struct device_node *battery_np = NULL; struct fwnode_reference_args args; - struct fwnode_handle *fwnode; + struct fwnode_handle *fwnode = NULL; const char *value; int err, len, index; const __be32 *list; @@ -585,7 +589,7 @@ int power_supply_get_battery_info(struct power_supply *psy, return -ENODEV; fwnode = fwnode_handle_get(of_fwnode_handle(battery_np)); - } else { + } else if (psy->dev.parent) { err = fwnode_property_get_reference_args( dev_fwnode(psy->dev.parent), "monitored-battery", NULL, 0, 0, &args); @@ -595,6 +599,9 @@ int power_supply_get_battery_info(struct power_supply *psy, fwnode = args.fwnode; } + if (!fwnode) + return -ENOENT; + err = fwnode_property_read_string(fwnode, "compatible", &value); if (err) goto out_put_node; diff --git a/drivers/power/supply/power_supply_leds.c b/drivers/power/supply/power_supply_leds.c index 702bf83f6e6d25..0674483279d77c 100644 --- a/drivers/power/supply/power_supply_leds.c +++ b/drivers/power/supply/power_supply_leds.c @@ -35,8 +35,9 @@ static void power_supply_update_bat_leds(struct power_supply *psy) led_trigger_event(psy->charging_full_trig, LED_FULL); led_trigger_event(psy->charging_trig, LED_OFF); led_trigger_event(psy->full_trig, LED_FULL); - led_trigger_event(psy->charging_blink_full_solid_trig, - LED_FULL); + /* Going from blink to LED on requires a LED_OFF event to stop blink */ + led_trigger_event(psy->charging_blink_full_solid_trig, LED_OFF); + led_trigger_event(psy->charging_blink_full_solid_trig, LED_FULL); break; case POWER_SUPPLY_STATUS_CHARGING: led_trigger_event(psy->charging_full_trig, LED_FULL); diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c index ba3b125cd66e43..06e5b6b0e255ce 100644 --- a/drivers/power/supply/power_supply_sysfs.c +++ b/drivers/power/supply/power_supply_sysfs.c @@ -286,7 +286,8 @@ static ssize_t power_supply_show_property(struct device *dev, if (ret < 0) { if (ret == -ENODATA) - dev_dbg(dev, "driver has no data for `%s' property\n", + dev_dbg_ratelimited(dev, + "driver has no data for `%s' property\n", attr->attr.name); else if (ret != -ENODEV && ret != -EAGAIN) dev_err_ratelimited(dev, diff --git a/drivers/power/supply/rt9467-charger.c b/drivers/power/supply/rt9467-charger.c index 73f744a3155d4c..ea33693b69779a 100644 --- a/drivers/power/supply/rt9467-charger.c +++ b/drivers/power/supply/rt9467-charger.c @@ -1023,7 +1023,7 @@ static int rt9467_request_interrupt(struct rt9467_chg_data *data) for (i = 0; i < num_chg_irqs; i++) { virq = regmap_irq_get_virq(data->irq_chip_data, chg_irqs[i].hwirq); if (virq <= 0) - return dev_err_probe(dev, virq, "Failed to get (%s) irq\n", + return dev_err_probe(dev, -EINVAL, "Failed to get (%s) irq\n", chg_irqs[i].name); ret = devm_request_threaded_irq(dev, virq, NULL, chg_irqs[i].handler, diff --git a/drivers/power/supply/sbs-charger.c b/drivers/power/supply/sbs-charger.c index 75ebcbf0a78837..a14e89ac0369ca 100644 --- a/drivers/power/supply/sbs-charger.c +++ b/drivers/power/supply/sbs-charger.c @@ -24,7 +24,7 @@ #define SBS_CHARGER_REG_STATUS 0x13 #define SBS_CHARGER_REG_ALARM_WARNING 0x16 -#define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(1) +#define SBS_CHARGER_STATUS_CHARGE_INHIBITED BIT(0) #define SBS_CHARGER_STATUS_RES_COLD BIT(9) #define SBS_CHARGER_STATUS_RES_HOT BIT(10) #define SBS_CHARGER_STATUS_BATTERY_PRESENT BIT(14) diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index 632977f84b954e..bd23c4d9fed434 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -733,13 +733,6 @@ static int sc27xx_fgu_set_property(struct power_supply *psy, return ret; } -static void sc27xx_fgu_external_power_changed(struct power_supply *psy) -{ - struct sc27xx_fgu_data *data = power_supply_get_drvdata(psy); - - power_supply_changed(data->battery); -} - static int sc27xx_fgu_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) { @@ -774,7 +767,7 @@ static const struct power_supply_desc sc27xx_fgu_desc = { .num_properties = ARRAY_SIZE(sc27xx_fgu_props), .get_property = sc27xx_fgu_get_property, .set_property = sc27xx_fgu_set_property, - .external_power_changed = sc27xx_fgu_external_power_changed, + .external_power_changed = power_supply_changed, .property_is_writeable = sc27xx_fgu_property_is_writeable, .no_thermal = true, }; diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index b00201d8131370..32dff1b4f891b0 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -102,7 +102,7 @@ config PTP_1588_CLOCK_INES config PTP_1588_CLOCK_PCH tristate "Intel PCH EG20T as PTP clock" - depends on X86_32 || COMPILE_TEST + depends on MIPS_GENERIC || X86_32 || COMPILE_TEST depends on HAS_IOMEM && PCI depends on NET depends on PTP_1588_CLOCK diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index dc741ac156c32c..698ab7f5004bf6 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -5256,7 +5256,7 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) } rdev->debugfs = debugfs_create_dir(rname, debugfs_root); - if (!rdev->debugfs) { + if (IS_ERR(rdev->debugfs)) { rdev_warn(rdev, "Failed to create debugfs directory\n"); return; } @@ -6178,7 +6178,7 @@ static int __init regulator_init(void) ret = class_register(®ulator_class); debugfs_root = debugfs_create_dir("regulator", NULL); - if (!debugfs_root) + if (IS_ERR(debugfs_root)) pr_warn("regulator: Failed to create debugfs directory\n"); #ifdef CONFIG_DEBUG_FS diff --git a/drivers/regulator/mt6359-regulator.c b/drivers/regulator/mt6359-regulator.c index 1849566784ab5e..3eb86ec21d0880 100644 --- a/drivers/regulator/mt6359-regulator.c +++ b/drivers/regulator/mt6359-regulator.c @@ -951,9 +951,12 @@ static int mt6359_regulator_probe(struct platform_device *pdev) struct regulator_config config = {}; struct regulator_dev *rdev; struct mt6359_regulator_info *mt6359_info; - int i, hw_ver; + int i, hw_ver, ret; + + ret = regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver); + if (ret) + return ret; - regmap_read(mt6397->regmap, MT6359P_HWCID, &hw_ver); if (hw_ver >= MT6359P_CHIP_VER) mt6359_info = mt6359p_regulators; else diff --git a/drivers/regulator/pca9450-regulator.c b/drivers/regulator/pca9450-regulator.c index 87a746dcb51697..e75dd92f86ca72 100644 --- a/drivers/regulator/pca9450-regulator.c +++ b/drivers/regulator/pca9450-regulator.c @@ -264,7 +264,7 @@ static const struct pca9450_regulator_desc pca9450a_regulators[] = { .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0, .vsel_mask = BUCK2OUT_DVS0_MASK, .enable_reg = PCA9450_REG_BUCK2CTRL, - .enable_mask = BUCK1_ENMODE_MASK, + .enable_mask = BUCK2_ENMODE_MASK, .ramp_reg = PCA9450_REG_BUCK2CTRL, .ramp_mask = BUCK2_RAMP_MASK, .ramp_delay_table = pca9450_dvs_buck_ramp_table, @@ -502,7 +502,7 @@ static const struct pca9450_regulator_desc pca9450bc_regulators[] = { .vsel_reg = PCA9450_REG_BUCK2OUT_DVS0, .vsel_mask = BUCK2OUT_DVS0_MASK, .enable_reg = PCA9450_REG_BUCK2CTRL, - .enable_mask = BUCK1_ENMODE_MASK, + .enable_mask = BUCK2_ENMODE_MASK, .ramp_reg = PCA9450_REG_BUCK2CTRL, .ramp_mask = BUCK2_RAMP_MASK, .ramp_delay_table = pca9450_dvs_buck_ramp_table, diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index ade1369fe5ed30..113c509bf6d052 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -127,6 +127,8 @@ static int prepare_itcw(struct itcw *, unsigned int, unsigned int, int, struct dasd_device *, struct dasd_device *, unsigned int, int, unsigned int, unsigned int, unsigned int, unsigned int); +static int dasd_eckd_query_pprc_status(struct dasd_device *, + struct dasd_pprc_data_sc4 *); /* initial attempt at a probe function. this can be simplified once * the other detection code is gone */ @@ -3733,6 +3735,26 @@ static int count_exts(unsigned int from, unsigned int to, int trks_per_ext) return count; } +static int dasd_in_copy_relation(struct dasd_device *device) +{ + struct dasd_pprc_data_sc4 *temp; + int rc; + + if (!dasd_eckd_pprc_enabled(device)) + return 0; + + temp = kzalloc(sizeof(*temp), GFP_KERNEL); + if (!temp) + return -ENOMEM; + + rc = dasd_eckd_query_pprc_status(device, temp); + if (!rc) + rc = temp->dev_info[0].state; + + kfree(temp); + return rc; +} + /* * Release allocated space for a given range or an entire volume. */ @@ -3749,6 +3771,7 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block, int cur_to_trk, cur_from_trk; struct dasd_ccw_req *cqr; u32 beg_cyl, end_cyl; + int copy_relation; struct ccw1 *ccw; int trks_per_ext; size_t ras_size; @@ -3760,6 +3783,10 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block, if (dasd_eckd_ras_sanity_checks(device, first_trk, last_trk)) return ERR_PTR(-EINVAL); + copy_relation = dasd_in_copy_relation(device); + if (copy_relation < 0) + return ERR_PTR(copy_relation); + rq = req ? blk_mq_rq_to_pdu(req) : NULL; features = &private->features; @@ -3788,9 +3815,11 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block, /* * This bit guarantees initialisation of tracks within an extent that is * not fully specified, but is only supported with a certain feature - * subset. + * subset and for devices not in a copy relation. */ - ras_data->op_flags.guarantee_init = !!(features->feature[56] & 0x01); + if (features->feature[56] & 0x01 && !copy_relation) + ras_data->op_flags.guarantee_init = 1; + ras_data->lss = private->conf.ned->ID; ras_data->dev_addr = private->conf.ned->unit_addr; ras_data->nr_exts = nr_exts; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 8eb089b99cde92..d5c43e9b512894 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -1111,6 +1111,8 @@ static void io_subchannel_verify(struct subchannel *sch) cdev = sch_get_cdev(sch); if (cdev) dev_fsm_event(cdev, DEV_EVENT_VERIFY); + else + css_schedule_eval(sch->schid); } static void io_subchannel_terminate_path(struct subchannel *sch, u8 mask) diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 5ea6249d81803a..641f0dbb65a90b 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h @@ -95,7 +95,7 @@ static inline int do_sqbs(u64 token, unsigned char state, int queue, " lgr 1,%[token]\n" " .insn rsy,0xeb000000008a,%[qs],%[ccq],0(%[state])" : [ccq] "+&d" (_ccq), [qs] "+&d" (_queuestart) - : [state] "d" ((unsigned long)state), [token] "d" (token) + : [state] "a" ((unsigned long)state), [token] "d" (token) : "memory", "cc", "1"); *count = _ccq & 0xff; *start = _queuestart & 0xff; diff --git a/drivers/s390/crypto/pkey_api.c b/drivers/s390/crypto/pkey_api.c index 5a05d1cdfec20a..a8def50c149bd4 100644 --- a/drivers/s390/crypto/pkey_api.c +++ b/drivers/s390/crypto/pkey_api.c @@ -1293,6 +1293,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, return PTR_ERR(kkey); rc = pkey_keyblob2pkey(kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey()=%d\n", __func__, rc); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) break; @@ -1426,6 +1427,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, kkey, ktp.keylen, &ktp.protkey); DEBUG_DBG("%s pkey_keyblob2pkey2()=%d\n", __func__, rc); kfree(apqns); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) break; @@ -1552,6 +1554,7 @@ static long pkey_unlocked_ioctl(struct file *filp, unsigned int cmd, protkey, &protkeylen); DEBUG_DBG("%s pkey_keyblob2pkey3()=%d\n", __func__, rc); kfree(apqns); + memzero_explicit(kkey, ktp.keylen); kfree(kkey); if (rc) { kfree(protkey); diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index 8acb9eba691b5e..1399b5dc646c7b 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -660,7 +660,7 @@ static int ism_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto err_disable; - ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); if (ret) goto err_resource; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index df5e5b7fdcfe73..84aa3571be6d4d 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -3796,6 +3796,7 @@ struct qla_qpair { uint64_t retry_term_jiff; struct qla_tgt_counters tgt_counters; uint16_t cpuid; + bool cpu_mapped; struct qla_fw_resources fwres ____cacheline_aligned; struct qla_buf_pool buf_pool; u32 cmd_cnt; diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index ec0423ec66817c..1a955c3ff3d6ce 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -9426,6 +9426,9 @@ struct qla_qpair *qla2xxx_create_qpair(struct scsi_qla_host *vha, int qos, qpair->rsp->req = qpair->req; qpair->rsp->qpair = qpair; + if (!qpair->cpu_mapped) + qla_cpu_update(qpair, raw_smp_processor_id()); + if (IS_T10_PI_CAPABLE(ha) && ql2xenabledif) { if (ha->fw_attributes & BIT_4) qpair->difdix_supported = 1; diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h index cce6e425c1214a..7b42558a8839ad 100644 --- a/drivers/scsi/qla2xxx/qla_inline.h +++ b/drivers/scsi/qla2xxx/qla_inline.h @@ -539,11 +539,14 @@ qla_mapq_init_qp_cpu_map(struct qla_hw_data *ha, if (!ha->qp_cpu_map) return; mask = pci_irq_get_affinity(ha->pdev, msix->vector_base0); + if (!mask) + return; qpair->cpuid = cpumask_first(mask); for_each_cpu(cpu, mask) { ha->qp_cpu_map[cpu] = qpair; } msix->cpuid = qpair->cpuid; + qpair->cpu_mapped = true; } static inline void diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 71feda2cdb6304..245e3a5d81fd33 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3770,6 +3770,9 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) { rsp->qpair->rcv_intr = 1; + + if (!rsp->qpair->cpu_mapped) + qla_cpu_update(rsp->qpair, raw_smp_processor_id()); } #define __update_rsp_in(_is_shadow_hba, _rsp, _rsp_in) \ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index b7c569a42aa477..0226c9279cef60 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1463,6 +1463,8 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) struct Scsi_Host *host = cmd->device->host; int rtn = 0; + atomic_inc(&cmd->device->iorequest_cnt); + /* check if the device is still usable */ if (unlikely(cmd->device->sdev_state == SDEV_DEL)) { /* in SDEV_DEL we error all commands. DID_NO_CONNECT @@ -1483,6 +1485,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) */ SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, "queuecommand : device blocked\n")); + atomic_dec(&cmd->device->iorequest_cnt); return SCSI_MLQUEUE_DEVICE_BUSY; } @@ -1515,6 +1518,7 @@ static int scsi_dispatch_cmd(struct scsi_cmnd *cmd) trace_scsi_dispatch_cmd_start(cmd); rtn = host->hostt->queuecommand(host, cmd); if (rtn) { + atomic_dec(&cmd->device->iorequest_cnt); trace_scsi_dispatch_cmd_error(cmd, rtn); if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && rtn != SCSI_MLQUEUE_TARGET_BUSY) @@ -1761,7 +1765,6 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, goto out_dec_host_busy; } - atomic_inc(&cmd->device->iorequest_cnt); return BLK_STS_OK; out_dec_host_busy: diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c index 5b230e149c3dfe..8ffb75be99bc8f 100644 --- a/drivers/scsi/stex.c +++ b/drivers/scsi/stex.c @@ -109,7 +109,9 @@ enum { TASK_ATTRIBUTE_HEADOFQUEUE = 0x1, TASK_ATTRIBUTE_ORDERED = 0x2, TASK_ATTRIBUTE_ACA = 0x4, +}; +enum { SS_STS_NORMAL = 0x80000000, SS_STS_DONE = 0x40000000, SS_STS_HANDSHAKE = 0x20000000, @@ -121,7 +123,9 @@ enum { SS_I2H_REQUEST_RESET = 0x2000, SS_MU_OPERATIONAL = 0x80000000, +}; +enum { STEX_CDB_LENGTH = 16, STATUS_VAR_LEN = 128, diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index d9ce379c4d2e83..e6bc622954cfab 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1780,7 +1780,7 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) length = scsi_bufflen(scmnd); payload = (struct vmbus_packet_mpb_array *)&cmd_request->mpb; - payload_sz = sizeof(cmd_request->mpb); + payload_sz = 0; if (scsi_sg_count(scmnd)) { unsigned long offset_in_hvpg = offset_in_hvpage(sgl->offset); @@ -1789,10 +1789,10 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) unsigned long hvpfn, hvpfns_to_add; int j, i = 0, sg_count; - if (hvpg_count > MAX_PAGE_BUFFER_COUNT) { + payload_sz = (hvpg_count * sizeof(u64) + + sizeof(struct vmbus_packet_mpb_array)); - payload_sz = (hvpg_count * sizeof(u64) + - sizeof(struct vmbus_packet_mpb_array)); + if (hvpg_count > MAX_PAGE_BUFFER_COUNT) { payload = kzalloc(payload_sz, GFP_ATOMIC); if (!payload) return SCSI_MLQUEUE_DEVICE_BUSY; diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig index 7268c2fbcbc1d8..e0d096607fefba 100644 --- a/drivers/soc/fsl/qe/Kconfig +++ b/drivers/soc/fsl/qe/Kconfig @@ -36,7 +36,7 @@ config UCC config CPM_TSA tristate "CPM TSA support" depends on OF && HAS_IOMEM - depends on CPM1 || COMPILE_TEST + depends on CPM1 || (CPM && COMPILE_TEST) help Freescale CPM Time Slot Assigner (TSA) controller. @@ -47,7 +47,7 @@ config CPM_TSA config CPM_QMC tristate "CPM QMC support" depends on OF && HAS_IOMEM - depends on CPM1 || (FSL_SOC && COMPILE_TEST) + depends on CPM1 || (FSL_SOC && CPM && COMPILE_TEST) depends on CPM_TSA help Freescale CPM QUICC Multichannel Controller diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index ac85d556221270..26e6633693196e 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -301,49 +302,43 @@ static int cdns_spi_setup_transfer(struct spi_device *spi, } /** - * cdns_spi_fill_tx_fifo - Fills the TX FIFO with as many bytes as possible + * cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO * @xspi: Pointer to the cdns_spi structure + * @ntx: Number of bytes to pack into the TX FIFO + * @nrx: Number of bytes to drain from the RX FIFO */ -static void cdns_spi_fill_tx_fifo(struct cdns_spi *xspi) +static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx) { - unsigned long trans_cnt = 0; + ntx = clamp(ntx, 0, xspi->tx_bytes); + nrx = clamp(nrx, 0, xspi->rx_bytes); - while ((trans_cnt < xspi->tx_fifo_depth) && - (xspi->tx_bytes > 0)) { + xspi->tx_bytes -= ntx; + xspi->rx_bytes -= nrx; + while (ntx || nrx) { /* When xspi in busy condition, bytes may send failed, * then spi control did't work thoroughly, add one byte delay */ - if (cdns_spi_read(xspi, CDNS_SPI_ISR) & - CDNS_SPI_IXR_TXFULL) + if (cdns_spi_read(xspi, CDNS_SPI_ISR) & CDNS_SPI_IXR_TXFULL) udelay(10); - if (xspi->txbuf) - cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); - else - cdns_spi_write(xspi, CDNS_SPI_TXD, 0); + if (ntx) { + if (xspi->txbuf) + cdns_spi_write(xspi, CDNS_SPI_TXD, *xspi->txbuf++); + else + cdns_spi_write(xspi, CDNS_SPI_TXD, 0); - xspi->tx_bytes--; - trans_cnt++; - } -} + ntx--; + } -/** - * cdns_spi_read_rx_fifo - Reads the RX FIFO with as many bytes as possible - * @xspi: Pointer to the cdns_spi structure - * @count: Read byte count - */ -static void cdns_spi_read_rx_fifo(struct cdns_spi *xspi, unsigned long count) -{ - u8 data; - - /* Read out the data from the RX FIFO */ - while (count > 0) { - data = cdns_spi_read(xspi, CDNS_SPI_RXD); - if (xspi->rxbuf) - *xspi->rxbuf++ = data; - xspi->rx_bytes--; - count--; + if (nrx) { + u8 data = cdns_spi_read(xspi, CDNS_SPI_RXD); + + if (xspi->rxbuf) + *xspi->rxbuf++ = data; + + nrx--; + } } } @@ -381,33 +376,22 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id) spi_finalize_current_transfer(ctlr); status = IRQ_HANDLED; } else if (intr_status & CDNS_SPI_IXR_TXOW) { - int trans_cnt = cdns_spi_read(xspi, CDNS_SPI_THLD); + int threshold = cdns_spi_read(xspi, CDNS_SPI_THLD); + int trans_cnt = xspi->rx_bytes - xspi->tx_bytes; + + if (threshold > 1) + trans_cnt -= threshold; + /* Set threshold to one if number of pending are * less than half fifo */ if (xspi->tx_bytes < xspi->tx_fifo_depth >> 1) cdns_spi_write(xspi, CDNS_SPI_THLD, 1); - while (trans_cnt) { - cdns_spi_read_rx_fifo(xspi, 1); - - if (xspi->tx_bytes) { - if (xspi->txbuf) - cdns_spi_write(xspi, CDNS_SPI_TXD, - *xspi->txbuf++); - else - cdns_spi_write(xspi, CDNS_SPI_TXD, 0); - xspi->tx_bytes--; - } - trans_cnt--; - } - if (!xspi->tx_bytes) { - /* Fixed delay due to controller limitation with - * RX_NEMPTY incorrect status - * Xilinx AR:65885 contains more details - */ - udelay(10); - cdns_spi_read_rx_fifo(xspi, xspi->rx_bytes); + if (xspi->tx_bytes) { + cdns_spi_process_fifo(xspi, trans_cnt, trans_cnt); + } else { + cdns_spi_process_fifo(xspi, 0, trans_cnt); cdns_spi_write(xspi, CDNS_SPI_IDR, CDNS_SPI_IXR_DEFAULT); spi_finalize_current_transfer(ctlr); @@ -450,16 +434,17 @@ static int cdns_transfer_one(struct spi_controller *ctlr, xspi->tx_bytes = transfer->len; xspi->rx_bytes = transfer->len; - if (!spi_controller_is_slave(ctlr)) + if (!spi_controller_is_slave(ctlr)) { cdns_spi_setup_transfer(spi, transfer); + } else { + /* Set TX empty threshold to half of FIFO depth + * only if TX bytes are more than half FIFO depth. + */ + if (xspi->tx_bytes > xspi->tx_fifo_depth) + cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1); + } - /* Set TX empty threshold to half of FIFO depth - * only if TX bytes are more than half FIFO depth. - */ - if (xspi->tx_bytes > (xspi->tx_fifo_depth >> 1)) - cdns_spi_write(xspi, CDNS_SPI_THLD, xspi->tx_fifo_depth >> 1); - - cdns_spi_fill_tx_fifo(xspi); + cdns_spi_process_fifo(xspi, xspi->tx_fifo_depth, 0); spi_transfer_delay_exec(transfer); cdns_spi_write(xspi, CDNS_SPI_IER, CDNS_SPI_IXR_DEFAULT); diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c index 5e6faa98aa8523..5f2aee69c1c131 100644 --- a/drivers/spi/spi-dw-mmio.c +++ b/drivers/spi/spi-dw-mmio.c @@ -264,17 +264,17 @@ static void dw_spi_elba_set_cs(struct spi_device *spi, bool enable) struct regmap *syscon = dwsmmio->priv; u8 cs; - cs = spi->chip_select; + cs = spi_get_chipselect(spi, 0); if (cs < 2) - dw_spi_elba_override_cs(syscon, spi->chip_select, enable); + dw_spi_elba_override_cs(syscon, spi_get_chipselect(spi, 0), enable); /* * The DW SPI controller needs a native CS bit selected to start * the serial engine. */ - spi->chip_select = 0; + spi_set_chipselect(spi, 0, 0); dw_spi_set_cs(spi, enable); - spi->chip_select = cs; + spi_get_chipselect(spi, cs); } static int dw_spi_elba_init(struct platform_device *pdev, diff --git a/drivers/spi/spi-fsl-lpspi.c b/drivers/spi/spi-fsl-lpspi.c index f2341ab9955664..4b70038ceb6b28 100644 --- a/drivers/spi/spi-fsl-lpspi.c +++ b/drivers/spi/spi-fsl-lpspi.c @@ -910,9 +910,14 @@ static int fsl_lpspi_probe(struct platform_device *pdev) ret = fsl_lpspi_dma_init(&pdev->dev, fsl_lpspi, controller); if (ret == -EPROBE_DEFER) goto out_pm_get; - if (ret < 0) dev_err(&pdev->dev, "dma setup error %d, use pio\n", ret); + else + /* + * disable LPSPI module IRQ when enable DMA mode successfully, + * to prevent the unexpected LPSPI module IRQ events. + */ + disable_irq(irq); ret = devm_spi_register_controller(&pdev->dev, controller); if (ret < 0) { diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c index ba7be505ec4ef5..a98b781b103ab3 100644 --- a/drivers/spi/spi-geni-qcom.c +++ b/drivers/spi/spi-geni-qcom.c @@ -294,6 +294,8 @@ static void spi_geni_set_cs(struct spi_device *slv, bool set_flag) mas->cs_flag = set_flag; /* set xfer_mode to FIFO to complete cs_done in isr */ mas->cur_xfer_mode = GENI_SE_FIFO; + geni_se_select_mode(se, mas->cur_xfer_mode); + reinit_completion(&mas->cs_done); if (set_flag) geni_se_setup_m_cmd(se, SPI_CS_ASSERT, 0); diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 21c321f4376674..d7432e2219d850 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1275,6 +1275,9 @@ static int mtk_spi_remove(struct platform_device *pdev) struct mtk_spi *mdata = spi_master_get_devdata(master); int ret; + if (mdata->use_spimem && !completion_done(&mdata->spimem_done)) + complete(&mdata->spimem_done); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) return ret; diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 944ef6b42bce6f..00e5e88e72c49d 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1028,23 +1028,8 @@ static int spi_qup_probe(struct platform_device *pdev) return -ENXIO; } - ret = clk_prepare_enable(cclk); - if (ret) { - dev_err(dev, "cannot enable core clock\n"); - return ret; - } - - ret = clk_prepare_enable(iclk); - if (ret) { - clk_disable_unprepare(cclk); - dev_err(dev, "cannot enable iface clock\n"); - return ret; - } - master = spi_alloc_master(dev, sizeof(struct spi_qup)); if (!master) { - clk_disable_unprepare(cclk); - clk_disable_unprepare(iclk); dev_err(dev, "cannot allocate master\n"); return -ENOMEM; } @@ -1092,6 +1077,19 @@ static int spi_qup_probe(struct platform_device *pdev) spin_lock_init(&controller->lock); init_completion(&controller->done); + ret = clk_prepare_enable(cclk); + if (ret) { + dev_err(dev, "cannot enable core clock\n"); + goto error_dma; + } + + ret = clk_prepare_enable(iclk); + if (ret) { + clk_disable_unprepare(cclk); + dev_err(dev, "cannot enable iface clock\n"); + goto error_dma; + } + iomode = readl_relaxed(base + QUP_IO_M_MODES); size = QUP_IO_M_OUTPUT_BLOCK_SIZE(iomode); @@ -1121,7 +1119,7 @@ static int spi_qup_probe(struct platform_device *pdev) ret = spi_qup_set_state(controller, QUP_STATE_RESET); if (ret) { dev_err(dev, "cannot set RESET state\n"); - goto error_dma; + goto error_clk; } writel_relaxed(0, base + QUP_OPERATIONAL); @@ -1145,7 +1143,7 @@ static int spi_qup_probe(struct platform_device *pdev) ret = devm_request_irq(dev, irq, spi_qup_qup_irq, IRQF_TRIGGER_HIGH, pdev->name, controller); if (ret) - goto error_dma; + goto error_clk; pm_runtime_set_autosuspend_delay(dev, MSEC_PER_SEC); pm_runtime_use_autosuspend(dev); @@ -1160,11 +1158,12 @@ static int spi_qup_probe(struct platform_device *pdev) disable_pm: pm_runtime_disable(&pdev->dev); +error_clk: + clk_disable_unprepare(cclk); + clk_disable_unprepare(iclk); error_dma: spi_qup_release_dma(master); error: - clk_disable_unprepare(cclk); - clk_disable_unprepare(iclk); spi_master_put(master); return ret; } diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 63de214916f59a..c079368019e87f 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -373,7 +373,7 @@ static int ov2680_get_fmt(struct v4l2_subdev *sd, static int ov2680_detect(struct i2c_client *client) { struct i2c_adapter *adapter = client->adapter; - u32 high, low; + u32 high = 0, low = 0; int ret; u16 id; u8 revision; @@ -383,7 +383,7 @@ static int ov2680_detect(struct i2c_client *client) ret = ov_read_reg8(client, OV2680_SC_CMMN_CHIP_ID_H, &high); if (ret) { - dev_err(&client->dev, "sensor_id_high = 0x%x\n", high); + dev_err(&client->dev, "sensor_id_high read failed (%d)\n", ret); return -ENODEV; } ret = ov_read_reg8(client, OV2680_SC_CMMN_CHIP_ID_L, &low); diff --git a/drivers/staging/media/imx/imx8mq-mipi-csi2.c b/drivers/staging/media/imx/imx8mq-mipi-csi2.c index 32700cb8bc4d55..ca2efcc21efe30 100644 --- a/drivers/staging/media/imx/imx8mq-mipi-csi2.c +++ b/drivers/staging/media/imx/imx8mq-mipi-csi2.c @@ -354,7 +354,7 @@ static int imx8mq_mipi_csi_start_stream(struct csi_state *state, struct v4l2_subdev_state *sd_state) { int ret; - u32 hs_settle; + u32 hs_settle = 0; ret = imx8mq_mipi_csi_sw_reset(state); if (ret) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 834cce50f9b00a..b516c2893420bc 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -364,8 +364,6 @@ struct iscsi_np *iscsit_add_np( init_completion(&np->np_restart_comp); INIT_LIST_HEAD(&np->np_list); - timer_setup(&np->np_login_timer, iscsi_handle_login_thread_timeout, 0); - ret = iscsi_target_setup_login_socket(np, sockaddr); if (ret != 0) { kfree(np); diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index 274bdd7845ca93..90b870f234f03c 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -811,59 +811,6 @@ void iscsi_post_login_handler( iscsit_dec_conn_usage_count(conn); } -void iscsi_handle_login_thread_timeout(struct timer_list *t) -{ - struct iscsi_np *np = from_timer(np, t, np_login_timer); - - spin_lock_bh(&np->np_thread_lock); - pr_err("iSCSI Login timeout on Network Portal %pISpc\n", - &np->np_sockaddr); - - if (np->np_login_timer_flags & ISCSI_TF_STOP) { - spin_unlock_bh(&np->np_thread_lock); - return; - } - - if (np->np_thread) - send_sig(SIGINT, np->np_thread, 1); - - np->np_login_timer_flags &= ~ISCSI_TF_RUNNING; - spin_unlock_bh(&np->np_thread_lock); -} - -static void iscsi_start_login_thread_timer(struct iscsi_np *np) -{ - /* - * This used the TA_LOGIN_TIMEOUT constant because at this - * point we do not have access to ISCSI_TPG_ATTRIB(tpg)->login_timeout - */ - spin_lock_bh(&np->np_thread_lock); - np->np_login_timer_flags &= ~ISCSI_TF_STOP; - np->np_login_timer_flags |= ISCSI_TF_RUNNING; - mod_timer(&np->np_login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ); - - pr_debug("Added timeout timer to iSCSI login request for" - " %u seconds.\n", TA_LOGIN_TIMEOUT); - spin_unlock_bh(&np->np_thread_lock); -} - -static void iscsi_stop_login_thread_timer(struct iscsi_np *np) -{ - spin_lock_bh(&np->np_thread_lock); - if (!(np->np_login_timer_flags & ISCSI_TF_RUNNING)) { - spin_unlock_bh(&np->np_thread_lock); - return; - } - np->np_login_timer_flags |= ISCSI_TF_STOP; - spin_unlock_bh(&np->np_thread_lock); - - del_timer_sync(&np->np_login_timer); - - spin_lock_bh(&np->np_thread_lock); - np->np_login_timer_flags &= ~ISCSI_TF_RUNNING; - spin_unlock_bh(&np->np_thread_lock); -} - int iscsit_setup_np( struct iscsi_np *np, struct sockaddr_storage *sockaddr) @@ -1123,10 +1070,13 @@ static struct iscsit_conn *iscsit_alloc_conn(struct iscsi_np *np) spin_lock_init(&conn->nopin_timer_lock); spin_lock_init(&conn->response_queue_lock); spin_lock_init(&conn->state_lock); + spin_lock_init(&conn->login_worker_lock); + spin_lock_init(&conn->login_timer_lock); timer_setup(&conn->nopin_response_timer, iscsit_handle_nopin_response_timeout, 0); timer_setup(&conn->nopin_timer, iscsit_handle_nopin_timeout, 0); + timer_setup(&conn->login_timer, iscsit_login_timeout, 0); if (iscsit_conn_set_transport(conn, np->np_transport) < 0) goto free_conn; @@ -1304,7 +1254,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) goto new_sess_out; } - iscsi_start_login_thread_timer(np); + iscsit_start_login_timer(conn, current); pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n"); conn->conn_state = TARG_CONN_STATE_XPT_UP; @@ -1417,8 +1367,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) if (ret < 0) goto new_sess_out; - iscsi_stop_login_thread_timer(np); - if (ret == 1) { tpg_np = conn->tpg_np; @@ -1434,7 +1382,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) new_sess_out: new_sess = true; old_sess_out: - iscsi_stop_login_thread_timer(np); + iscsit_stop_login_timer(conn); tpg_np = conn->tpg_np; iscsi_target_login_sess_out(conn, zero_tsih, new_sess); new_sess = false; @@ -1448,7 +1396,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) return 1; exit: - iscsi_stop_login_thread_timer(np); spin_lock_bh(&np->np_thread_lock); np->np_thread_state = ISCSI_NP_THREAD_EXIT; spin_unlock_bh(&np->np_thread_lock); diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 24040c118e49d2..fa3fb5f4e6bc44 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -535,25 +535,6 @@ static void iscsi_target_login_drop(struct iscsit_conn *conn, struct iscsi_login iscsi_target_login_sess_out(conn, zero_tsih, true); } -struct conn_timeout { - struct timer_list timer; - struct iscsit_conn *conn; -}; - -static void iscsi_target_login_timeout(struct timer_list *t) -{ - struct conn_timeout *timeout = from_timer(timeout, t, timer); - struct iscsit_conn *conn = timeout->conn; - - pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); - - if (conn->login_kworker) { - pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n", - conn->login_kworker->comm, conn->login_kworker->pid); - send_sig(SIGINT, conn->login_kworker, 1); - } -} - static void iscsi_target_do_login_rx(struct work_struct *work) { struct iscsit_conn *conn = container_of(work, @@ -562,12 +543,15 @@ static void iscsi_target_do_login_rx(struct work_struct *work) struct iscsi_np *np = login->np; struct iscsi_portal_group *tpg = conn->tpg; struct iscsi_tpg_np *tpg_np = conn->tpg_np; - struct conn_timeout timeout; int rc, zero_tsih = login->zero_tsih; bool state; pr_debug("entering iscsi_target_do_login_rx, conn: %p, %s:%d\n", conn, current->comm, current->pid); + + spin_lock(&conn->login_worker_lock); + set_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags); + spin_unlock(&conn->login_worker_lock); /* * If iscsi_target_do_login_rx() has been invoked by ->sk_data_ready() * before initial PDU processing in iscsi_target_start_negotiation() @@ -597,19 +581,16 @@ static void iscsi_target_do_login_rx(struct work_struct *work) goto err; } - conn->login_kworker = current; allow_signal(SIGINT); - - timeout.conn = conn; - timer_setup_on_stack(&timeout.timer, iscsi_target_login_timeout, 0); - mod_timer(&timeout.timer, jiffies + TA_LOGIN_TIMEOUT * HZ); - pr_debug("Starting login timer for %s/%d\n", current->comm, current->pid); + rc = iscsit_set_login_timer_kworker(conn, current); + if (rc < 0) { + /* The login timer has already expired */ + pr_debug("iscsi_target_do_login_rx, login failed\n"); + goto err; + } rc = conn->conn_transport->iscsit_get_login_rx(conn, login); - del_timer_sync(&timeout.timer); - destroy_timer_on_stack(&timeout.timer); flush_signals(current); - conn->login_kworker = NULL; if (rc < 0) goto err; @@ -646,7 +627,17 @@ static void iscsi_target_do_login_rx(struct work_struct *work) if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_WRITE_ACTIVE)) goto err; + + /* + * Set the login timer thread pointer to NULL to prevent the + * login process from getting stuck if the initiator + * stops sending data. + */ + rc = iscsit_set_login_timer_kworker(conn, NULL); + if (rc < 0) + goto err; } else if (rc == 1) { + iscsit_stop_login_timer(conn); cancel_delayed_work(&conn->login_work); iscsi_target_nego_release(conn); iscsi_post_login_handler(np, conn, zero_tsih); @@ -656,6 +647,7 @@ static void iscsi_target_do_login_rx(struct work_struct *work) err: iscsi_target_restore_sock_callbacks(conn); + iscsit_stop_login_timer(conn); cancel_delayed_work(&conn->login_work); iscsi_target_login_drop(conn, login); iscsit_deaccess_np(np, tpg, tpg_np); @@ -1130,6 +1122,7 @@ int iscsi_target_locate_portal( iscsi_target_set_sock_callbacks(conn); login->np = np; + conn->tpg = NULL; login_req = (struct iscsi_login_req *) login->req; payload_length = ntoh24(login_req->dlength); @@ -1197,7 +1190,6 @@ int iscsi_target_locate_portal( */ sessiontype = strncmp(s_buf, DISCOVERY, 9); if (!sessiontype) { - conn->tpg = iscsit_global->discovery_tpg; if (!login->leading_connection) goto get_target; @@ -1214,9 +1206,11 @@ int iscsi_target_locate_portal( * Serialize access across the discovery struct iscsi_portal_group to * process login attempt. */ + conn->tpg = iscsit_global->discovery_tpg; if (iscsit_access_np(np, conn->tpg) < 0) { iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR, ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE); + conn->tpg = NULL; ret = -1; goto out; } @@ -1368,14 +1362,30 @@ int iscsi_target_start_negotiation( * and perform connection cleanup now. */ ret = iscsi_target_do_login(conn, login); - if (!ret && iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU)) - ret = -1; + if (!ret) { + spin_lock(&conn->login_worker_lock); + + if (iscsi_target_sk_check_and_clear(conn, LOGIN_FLAGS_INITIAL_PDU)) + ret = -1; + else if (!test_bit(LOGIN_FLAGS_WORKER_RUNNING, &conn->login_flags)) { + if (iscsit_set_login_timer_kworker(conn, NULL) < 0) { + /* + * The timeout has expired already. + * Schedule login_work to perform the cleanup. + */ + schedule_delayed_work(&conn->login_work, 0); + } + } + + spin_unlock(&conn->login_worker_lock); + } if (ret < 0) { iscsi_target_restore_sock_callbacks(conn); iscsi_remove_failed_auth_entry(conn); } if (ret != 0) { + iscsit_stop_login_timer(conn); cancel_delayed_work_sync(&conn->login_work); iscsi_target_nego_release(conn); } diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 26dc8ed3045b6a..b14835fcb03344 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -1040,6 +1040,57 @@ void iscsit_stop_nopin_timer(struct iscsit_conn *conn) spin_unlock_bh(&conn->nopin_timer_lock); } +void iscsit_login_timeout(struct timer_list *t) +{ + struct iscsit_conn *conn = from_timer(conn, t, login_timer); + struct iscsi_login *login = conn->login; + + pr_debug("Entering iscsi_target_login_timeout >>>>>>>>>>>>>>>>>>>\n"); + + spin_lock_bh(&conn->login_timer_lock); + login->login_failed = 1; + + if (conn->login_kworker) { + pr_debug("Sending SIGINT to conn->login_kworker %s/%d\n", + conn->login_kworker->comm, conn->login_kworker->pid); + send_sig(SIGINT, conn->login_kworker, 1); + } else { + schedule_delayed_work(&conn->login_work, 0); + } + spin_unlock_bh(&conn->login_timer_lock); +} + +void iscsit_start_login_timer(struct iscsit_conn *conn, struct task_struct *kthr) +{ + pr_debug("Login timer started\n"); + + conn->login_kworker = kthr; + mod_timer(&conn->login_timer, jiffies + TA_LOGIN_TIMEOUT * HZ); +} + +int iscsit_set_login_timer_kworker(struct iscsit_conn *conn, struct task_struct *kthr) +{ + struct iscsi_login *login = conn->login; + int ret = 0; + + spin_lock_bh(&conn->login_timer_lock); + if (login->login_failed) { + /* The timer has already expired */ + ret = -1; + } else { + conn->login_kworker = kthr; + } + spin_unlock_bh(&conn->login_timer_lock); + + return ret; +} + +void iscsit_stop_login_timer(struct iscsit_conn *conn) +{ + pr_debug("Login timer stopped\n"); + timer_delete_sync(&conn->login_timer); +} + int iscsit_send_tx_data( struct iscsit_cmd *cmd, struct iscsit_conn *conn, diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 33ea799a08508f..24b8e577575a6b 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -56,6 +56,10 @@ extern void iscsit_handle_nopin_timeout(struct timer_list *t); extern void __iscsit_start_nopin_timer(struct iscsit_conn *); extern void iscsit_start_nopin_timer(struct iscsit_conn *); extern void iscsit_stop_nopin_timer(struct iscsit_conn *); +extern void iscsit_login_timeout(struct timer_list *t); +extern void iscsit_start_login_timer(struct iscsit_conn *, struct task_struct *kthr); +extern void iscsit_stop_login_timer(struct iscsit_conn *); +extern int iscsit_set_login_timer_kworker(struct iscsit_conn *, struct task_struct *kthr); extern int iscsit_send_tx_data(struct iscsit_cmd *, struct iscsit_conn *, int); extern int iscsit_fe_sendpage_sg(struct iscsit_cmd *, struct iscsit_conn *); extern int iscsit_tx_login_rsp(struct iscsit_conn *, u8, u8); diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c index 49702cb08f4fb3..3861ae06d902f0 100644 --- a/drivers/tee/optee/smc_abi.c +++ b/drivers/tee/optee/smc_abi.c @@ -1004,8 +1004,10 @@ static u32 get_async_notif_value(optee_invoke_fn *invoke_fn, bool *value_valid, invoke_fn(OPTEE_SMC_GET_ASYNC_NOTIF_VALUE, 0, 0, 0, 0, 0, 0, 0, &res); - if (res.a0) + if (res.a0) { + *value_valid = false; return 0; + } *value_valid = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_VALID); *value_pending = (res.a2 & OPTEE_SMC_ASYNC_NOTIF_VALUE_PENDING); return res.a1; diff --git a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c index 810231b59dcdcc..5e1164226ada21 100644 --- a/drivers/thermal/intel/int340x_thermal/int3400_thermal.c +++ b/drivers/thermal/intel/int340x_thermal/int3400_thermal.c @@ -131,7 +131,7 @@ static ssize_t available_uuids_show(struct device *dev, for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) { if (priv->uuid_bitmap & (1 << i)) - length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]); + length += sysfs_emit_at(buf, length, "%s\n", int3400_thermal_uuids[i]); } return length; @@ -149,7 +149,7 @@ static ssize_t current_uuid_show(struct device *dev, for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) { if (priv->os_uuid_mask & BIT(i)) - length += sysfs_emit_at(buf, length, int3400_thermal_uuids[i]); + length += sysfs_emit_at(buf, length, "%s\n", int3400_thermal_uuids[i]); } if (length) diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c index d76e923fbc6a01..c0aee5dc5237f7 100644 --- a/drivers/thunderbolt/nhi.c +++ b/drivers/thunderbolt/nhi.c @@ -54,6 +54,21 @@ static int ring_interrupt_index(const struct tb_ring *ring) return bit; } +static void nhi_mask_interrupt(struct tb_nhi *nhi, int mask, int ring) +{ + if (nhi->quirks & QUIRK_AUTO_CLEAR_INT) + return; + iowrite32(mask, nhi->iobase + REG_RING_INTERRUPT_MASK_CLEAR_BASE + ring); +} + +static void nhi_clear_interrupt(struct tb_nhi *nhi, int ring) +{ + if (nhi->quirks & QUIRK_AUTO_CLEAR_INT) + ioread32(nhi->iobase + REG_RING_NOTIFY_BASE + ring); + else + iowrite32(~0, nhi->iobase + REG_RING_INT_CLEAR + ring); +} + /* * ring_interrupt_active() - activate/deactivate interrupts for a single ring * @@ -61,8 +76,8 @@ static int ring_interrupt_index(const struct tb_ring *ring) */ static void ring_interrupt_active(struct tb_ring *ring, bool active) { - int reg = REG_RING_INTERRUPT_BASE + - ring_interrupt_index(ring) / 32 * 4; + int index = ring_interrupt_index(ring) / 32 * 4; + int reg = REG_RING_INTERRUPT_BASE + index; int interrupt_bit = ring_interrupt_index(ring) & 31; int mask = 1 << interrupt_bit; u32 old, new; @@ -123,7 +138,11 @@ static void ring_interrupt_active(struct tb_ring *ring, bool active) "interrupt for %s %d is already %s\n", RING_TYPE(ring), ring->hop, active ? "enabled" : "disabled"); - iowrite32(new, ring->nhi->iobase + reg); + + if (active) + iowrite32(new, ring->nhi->iobase + reg); + else + nhi_mask_interrupt(ring->nhi, mask, index); } /* @@ -136,11 +155,11 @@ static void nhi_disable_interrupts(struct tb_nhi *nhi) int i = 0; /* disable interrupts */ for (i = 0; i < RING_INTERRUPT_REG_COUNT(nhi); i++) - iowrite32(0, nhi->iobase + REG_RING_INTERRUPT_BASE + 4 * i); + nhi_mask_interrupt(nhi, ~0, 4 * i); /* clear interrupt status bits */ for (i = 0; i < RING_NOTIFY_REG_COUNT(nhi); i++) - ioread32(nhi->iobase + REG_RING_NOTIFY_BASE + 4 * i); + nhi_clear_interrupt(nhi, 4 * i); } /* ring helper methods */ diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index faef165a919ccd..6ba2958154770f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -93,6 +93,8 @@ struct ring_desc { #define REG_RING_INTERRUPT_BASE 0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INTERRUPT_MASK_CLEAR_BASE 0x38208 + #define REG_INT_THROTTLING_RATE 0x38c00 /* Interrupt Vector Allocation */ diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c index f801b1f5b46c0c..af0e1c07018795 100644 --- a/drivers/tty/serial/8250/8250_bcm7271.c +++ b/drivers/tty/serial/8250/8250_bcm7271.c @@ -1012,7 +1012,7 @@ static int brcmuart_probe(struct platform_device *pdev) of_property_read_u32(np, "clock-frequency", &clk_rate); /* See if a Baud clock has been specified */ - baud_mux_clk = of_clk_get_by_name(np, "sw_baud"); + baud_mux_clk = devm_clk_get(dev, "sw_baud"); if (IS_ERR(baud_mux_clk)) { if (PTR_ERR(baud_mux_clk) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; @@ -1032,7 +1032,7 @@ static int brcmuart_probe(struct platform_device *pdev) if (clk_rate == 0) { dev_err(dev, "clock-frequency or clk not defined\n"); ret = -EINVAL; - goto release_dma; + goto err_clk_disable; } dev_dbg(dev, "DMA is %senabled\n", priv->dma_enabled ? "" : "not "); @@ -1119,6 +1119,8 @@ static int brcmuart_probe(struct platform_device *pdev) serial8250_unregister_port(priv->line); err: brcmuart_free_bufs(dev, priv); +err_clk_disable: + clk_disable_unprepare(baud_mux_clk); release_dma: if (priv->dma_enabled) brcmuart_arbitration(priv, 0); @@ -1133,6 +1135,7 @@ static int brcmuart_remove(struct platform_device *pdev) hrtimer_cancel(&priv->hrt); serial8250_unregister_port(priv->line); brcmuart_free_bufs(&pdev->dev, priv); + clk_disable_unprepare(priv->baud_mux_clk); if (priv->dma_enabled) brcmuart_arbitration(priv, 0); return 0; diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index 64770c62bbec54..b406cba10b0eb4 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -40,9 +40,13 @@ #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 + #define PCI_DEVICE_ID_EXAR_XR17V4358 0x4358 #define PCI_DEVICE_ID_EXAR_XR17V8358 0x8358 +#define PCI_SUBDEVICE_ID_USR_2980 0x0128 +#define PCI_SUBDEVICE_ID_USR_2981 0x0129 + #define PCI_DEVICE_ID_SEALEVEL_710xC 0x1001 #define PCI_DEVICE_ID_SEALEVEL_720xC 0x1002 #define PCI_DEVICE_ID_SEALEVEL_740xC 0x1004 @@ -829,6 +833,15 @@ static const struct exar8250_board pbn_exar_XR17V8358 = { (kernel_ulong_t)&bd \ } +#define USR_DEVICE(devid, sdevid, bd) { \ + PCI_DEVICE_SUB( \ + PCI_VENDOR_ID_USR, \ + PCI_DEVICE_ID_EXAR_##devid, \ + PCI_VENDOR_ID_EXAR, \ + PCI_SUBDEVICE_ID_USR_##sdevid), 0, 0, \ + (kernel_ulong_t)&bd \ + } + static const struct pci_device_id exar_pci_tbl[] = { EXAR_DEVICE(ACCESSIO, COM_2S, pbn_exar_XR17C15x), EXAR_DEVICE(ACCESSIO, COM_4S, pbn_exar_XR17C15x), @@ -853,6 +866,10 @@ static const struct pci_device_id exar_pci_tbl[] = { IBM_DEVICE(XR17C152, SATURN_SERIAL_ONE_PORT, pbn_exar_ibm_saturn), + /* USRobotics USR298x-OEM PCI Modems */ + USR_DEVICE(XR17C152, 2980, pbn_exar_XR17C15x), + USR_DEVICE(XR17C152, 2981, pbn_exar_XR17C15x), + /* Exar Corp. XR17C15[248] Dual/Quad/Octal UART */ EXAR_DEVICE(EXAR, XR17C152, pbn_exar_XR17C15x), EXAR_DEVICE(EXAR, XR17C154, pbn_exar_XR17C15x), diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index c55be6fda0cab1..e80c4f6551a1c2 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1920,6 +1920,8 @@ pci_moxa_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 +#define PCI_DEVICE_ID_ADVANTECH_PCI1600 0x1600 +#define PCI_DEVICE_ID_ADVANTECH_PCI1600_1611 0x1611 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 #define PCI_DEVICE_ID_ADVANTECH_PCI3618 0x3618 #define PCI_DEVICE_ID_ADVANTECH_PCIf618 0xf618 @@ -4085,6 +4087,9 @@ static SIMPLE_DEV_PM_OPS(pciserial_pm_ops, pciserial_suspend_one, pciserial_resume_one); static const struct pci_device_id serial_pci_tbl[] = { + { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI1600, + PCI_DEVICE_ID_ADVANTECH_PCI1600_1611, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */ { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620, PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index fe8d79c4ae95e5..c153ba3a018a25 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -669,6 +669,7 @@ EXPORT_SYMBOL_GPL(serial8250_em485_supported); /** * serial8250_em485_config() - generic ->rs485_config() callback * @port: uart port + * @termios: termios structure * @rs485: rs485 settings * * Generic callback usable by 8250 uart drivers to activate rs485 settings diff --git a/drivers/tty/serial/8250/8250_tegra.c b/drivers/tty/serial/8250/8250_tegra.c index 2509e7f74ccf2b..89956bbf34d9e4 100644 --- a/drivers/tty/serial/8250/8250_tegra.c +++ b/drivers/tty/serial/8250/8250_tegra.c @@ -113,13 +113,15 @@ static int tegra_uart_probe(struct platform_device *pdev) ret = serial8250_register_8250_port(&port8250); if (ret < 0) - goto err_clkdisable; + goto err_ctrl_assert; platform_set_drvdata(pdev, uart); uart->line = ret; return 0; +err_ctrl_assert: + reset_control_assert(uart->rst); err_clkdisable: clk_disable_unprepare(uart->clk); diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 398e5aac2e77a3..3e3fb377d90d4c 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -762,7 +762,7 @@ config SERIAL_PMACZILOG_CONSOLE config SERIAL_CPM tristate "CPM SCC/SMC serial port support" - depends on CPM2 || CPM1 || (PPC32 && COMPILE_TEST) + depends on CPM2 || CPM1 select SERIAL_CORE help This driver supports the SCC and SMC serial ports on Motorola diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c index 59e25f2b663221..4b2512eef577b4 100644 --- a/drivers/tty/serial/arc_uart.c +++ b/drivers/tty/serial/arc_uart.c @@ -606,10 +606,11 @@ static int arc_serial_probe(struct platform_device *pdev) } uart->baud = val; - port->membase = of_iomap(np, 0); - if (!port->membase) + port->membase = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(port->membase)) { /* No point of dev_err since UART itself is hosed here */ - return -ENXIO; + return PTR_ERR(port->membase); + } port->irq = irq_of_parse_and_map(np, 0); diff --git a/drivers/tty/serial/cpm_uart/cpm_uart.h b/drivers/tty/serial/cpm_uart/cpm_uart.h index 0577618e78c041..46c03ed71c31bb 100644 --- a/drivers/tty/serial/cpm_uart/cpm_uart.h +++ b/drivers/tty/serial/cpm_uart/cpm_uart.h @@ -19,8 +19,6 @@ struct gpio_desc; #include "cpm_uart_cpm2.h" #elif defined(CONFIG_CPM1) #include "cpm_uart_cpm1.h" -#elif defined(CONFIG_COMPILE_TEST) -#include "cpm_uart_cpm2.h" #endif #define SERIAL_CPM_MAJOR 204 diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index c91916e1364830..7486a2b8556c80 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1495,34 +1495,36 @@ static void lpuart_break_ctl(struct uart_port *port, int break_state) static void lpuart32_break_ctl(struct uart_port *port, int break_state) { - unsigned long temp, modem; - struct tty_struct *tty; - unsigned int cflag = 0; - - tty = tty_port_tty_get(&port->state->port); - if (tty) { - cflag = tty->termios.c_cflag; - tty_kref_put(tty); - } + unsigned long temp; - temp = lpuart32_read(port, UARTCTRL) & ~UARTCTRL_SBK; - modem = lpuart32_read(port, UARTMODIR); + temp = lpuart32_read(port, UARTCTRL); + /* + * LPUART IP now has two known bugs, one is CTS has higher priority than the + * break signal, which causes the break signal sending through UARTCTRL_SBK + * may impacted by the CTS input if the HW flow control is enabled. It + * exists on all platforms we support in this driver. + * Another bug is i.MX8QM LPUART may have an additional break character + * being sent after SBK was cleared. + * To avoid above two bugs, we use Transmit Data Inversion function to send + * the break signal instead of UARTCTRL_SBK. + */ if (break_state != 0) { - temp |= UARTCTRL_SBK; /* - * LPUART CTS has higher priority than SBK, need to disable CTS before - * asserting SBK to avoid any interference if flow control is enabled. + * Disable the transmitter to prevent any data from being sent out + * during break, then invert the TX line to send break. */ - if (cflag & CRTSCTS && modem & UARTMODIR_TXCTSE) - lpuart32_write(port, modem & ~UARTMODIR_TXCTSE, UARTMODIR); + temp &= ~UARTCTRL_TE; + lpuart32_write(port, temp, UARTCTRL); + temp |= UARTCTRL_TXINV; + lpuart32_write(port, temp, UARTCTRL); } else { - /* Re-enable the CTS when break off. */ - if (cflag & CRTSCTS && !(modem & UARTMODIR_TXCTSE)) - lpuart32_write(port, modem | UARTMODIR_TXCTSE, UARTMODIR); + /* Disable the TXINV to turn off break and re-enable transmitter. */ + temp &= ~UARTCTRL_TXINV; + lpuart32_write(port, temp, UARTCTRL); + temp |= UARTCTRL_TE; + lpuart32_write(port, temp, UARTCTRL); } - - lpuart32_write(port, temp, UARTCTRL); } static void lpuart_setup_watermark(struct lpuart_port *sport) diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 08dc3e2a729c76..8582479f0211a0 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1664,19 +1664,18 @@ static int qcom_geni_serial_probe(struct platform_device *pdev) uport->private_data = &port->private_data; platform_set_drvdata(pdev, port); - ret = uart_add_one_port(drv, uport); - if (ret) - return ret; - irq_set_status_flags(uport->irq, IRQ_NOAUTOEN); ret = devm_request_irq(uport->dev, uport->irq, qcom_geni_serial_isr, IRQF_TRIGGER_HIGH, port->name, uport); if (ret) { dev_err(uport->dev, "Failed to get IRQ ret %d\n", ret); - uart_remove_one_port(drv, uport); return ret; } + ret = uart_add_one_port(drv, uport); + if (ret) + return ret; + /* * Set pm_runtime status as ACTIVE so that wakeup_irq gets * enabled/disabled from dev_pm_arm_wake_irq during system diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index 498ba9c0ee9374..829c4be66f3b03 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -656,10 +656,17 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) } } - /* The vcs_size might have changed while we slept to grab - * the user buffer, so recheck. + /* The vc might have been freed or vcs_size might have changed + * while we slept to grab the user buffer, so recheck. * Return data written up to now on failure. */ + vc = vcs_vc(inode, &viewed); + if (!vc) { + if (written) + break; + ret = -ENXIO; + goto unlock_out; + } size = vcs_size(vc, attr, false); if (size < 0) { if (written) diff --git a/drivers/ufs/core/ufs-mcq.c b/drivers/ufs/core/ufs-mcq.c index 202ff71e1b5821..51b3c6ae781df4 100644 --- a/drivers/ufs/core/ufs-mcq.c +++ b/drivers/ufs/core/ufs-mcq.c @@ -150,7 +150,8 @@ static int ufshcd_mcq_config_nr_queues(struct ufs_hba *hba) u32 hba_maxq, rem, tot_queues; struct Scsi_Host *host = hba->host; - hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities); + /* maxq is 0 based value */ + hba_maxq = FIELD_GET(MAX_QUEUE_SUP, hba->mcq_capabilities) + 1; tot_queues = UFS_MCQ_NUM_DEV_CMD_QUEUES + read_queues + poll_queues + rw_queues; @@ -265,7 +266,7 @@ static int ufshcd_mcq_get_tag(struct ufs_hba *hba, addr = (le64_to_cpu(cqe->command_desc_base_addr) & CQE_UCD_BA) - hba->ucdl_dma_addr; - return div_u64(addr, sizeof(struct utp_transfer_cmd_desc)); + return div_u64(addr, ufshcd_get_ucd_size(hba)); } static void ufshcd_mcq_process_cqe(struct ufs_hba *hba, diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c index 45fd374fe56c13..e7e79f515e1418 100644 --- a/drivers/ufs/core/ufshcd.c +++ b/drivers/ufs/core/ufshcd.c @@ -2849,10 +2849,10 @@ static void ufshcd_map_queues(struct Scsi_Host *shost) static void ufshcd_init_lrb(struct ufs_hba *hba, struct ufshcd_lrb *lrb, int i) { struct utp_transfer_cmd_desc *cmd_descp = (void *)hba->ucdl_base_addr + - i * sizeof_utp_transfer_cmd_desc(hba); + i * ufshcd_get_ucd_size(hba); struct utp_transfer_req_desc *utrdlp = hba->utrdl_base_addr; dma_addr_t cmd_desc_element_addr = hba->ucdl_dma_addr + - i * sizeof_utp_transfer_cmd_desc(hba); + i * ufshcd_get_ucd_size(hba); u16 response_offset = offsetof(struct utp_transfer_cmd_desc, response_upiu); u16 prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table); @@ -3761,7 +3761,7 @@ static int ufshcd_memory_alloc(struct ufs_hba *hba) size_t utmrdl_size, utrdl_size, ucdl_size; /* Allocate memory for UTP command descriptors */ - ucdl_size = sizeof_utp_transfer_cmd_desc(hba) * hba->nutrs; + ucdl_size = ufshcd_get_ucd_size(hba) * hba->nutrs; hba->ucdl_base_addr = dmam_alloc_coherent(hba->dev, ucdl_size, &hba->ucdl_dma_addr, @@ -3861,7 +3861,7 @@ static void ufshcd_host_memory_configure(struct ufs_hba *hba) prdt_offset = offsetof(struct utp_transfer_cmd_desc, prd_table); - cmd_desc_size = sizeof_utp_transfer_cmd_desc(hba); + cmd_desc_size = ufshcd_get_ucd_size(hba); cmd_desc_dma_addr = hba->ucdl_dma_addr; for (i = 0; i < hba->nutrs; i++) { @@ -8452,7 +8452,7 @@ static void ufshcd_release_sdb_queue(struct ufs_hba *hba, int nutrs) { size_t ucdl_size, utrdl_size; - ucdl_size = sizeof(struct utp_transfer_cmd_desc) * nutrs; + ucdl_size = ufshcd_get_ucd_size(hba) * nutrs; dmam_free_coherent(hba->dev, ucdl_size, hba->ucdl_base_addr, hba->ucdl_dma_addr); diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c index ccfaebca6faa75..1dcadef933e3a6 100644 --- a/drivers/usb/cdns3/cdns3-gadget.c +++ b/drivers/usb/cdns3/cdns3-gadget.c @@ -2097,6 +2097,19 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) else priv_ep->trb_burst_size = 16; + /* + * In versions preceding DEV_VER_V2, for example, iMX8QM, there exit the bugs + * in the DMA. These bugs occur when the trb_burst_size exceeds 16 and the + * address is not aligned to 128 Bytes (which is a product of the 64-bit AXI + * and AXI maximum burst length of 16 or 0xF+1, dma_axi_ctrl0[3:0]). This + * results in data corruption when it crosses the 4K border. The corruption + * specifically occurs from the position (4K - (address & 0x7F)) to 4K. + * + * So force trb_burst_size to 16 at such platform. + */ + if (priv_dev->dev_ver < DEV_VER_V2) + priv_ep->trb_burst_size = 16; + mult = min_t(u8, mult, EP_CFG_MULT_MAX); buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX); maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX); diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 4bb6d304eb4b21..311007b1d90465 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -1928,6 +1928,8 @@ static int usbtmc_ioctl_request(struct usbtmc_device_data *data, if (request.req.wLength > USBTMC_BUFSIZE) return -EMSGSIZE; + if (request.req.wLength == 0) /* Length-0 requests are never IN */ + request.req.bRequestType &= ~USB_DIR_IN; is_in = request.req.bRequestType & USB_DIR_IN; diff --git a/drivers/usb/core/buffer.c b/drivers/usb/core/buffer.c index fbb087b728dc98..268ccbec88f951 100644 --- a/drivers/usb/core/buffer.c +++ b/drivers/usb/core/buffer.c @@ -172,3 +172,44 @@ void hcd_buffer_free( } dma_free_coherent(hcd->self.sysdev, size, addr, dma); } + +void *hcd_buffer_alloc_pages(struct usb_hcd *hcd, + size_t size, gfp_t mem_flags, dma_addr_t *dma) +{ + if (size == 0) + return NULL; + + if (hcd->localmem_pool) + return gen_pool_dma_alloc_align(hcd->localmem_pool, + size, dma, PAGE_SIZE); + + /* some USB hosts just use PIO */ + if (!hcd_uses_dma(hcd)) { + *dma = DMA_MAPPING_ERROR; + return (void *)__get_free_pages(mem_flags, + get_order(size)); + } + + return dma_alloc_coherent(hcd->self.sysdev, + size, dma, mem_flags); +} + +void hcd_buffer_free_pages(struct usb_hcd *hcd, + size_t size, void *addr, dma_addr_t dma) +{ + if (!addr) + return; + + if (hcd->localmem_pool) { + gen_pool_free(hcd->localmem_pool, + (unsigned long)addr, size); + return; + } + + if (!hcd_uses_dma(hcd)) { + free_pages((unsigned long)addr, get_order(size)); + return; + } + + dma_free_coherent(hcd->self.sysdev, size, addr, dma); +} diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index e501a03d6c700b..fcf68818e99928 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -186,6 +186,7 @@ static int connected(struct usb_dev_state *ps) static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count) { struct usb_dev_state *ps = usbm->ps; + struct usb_hcd *hcd = bus_to_hcd(ps->dev->bus); unsigned long flags; spin_lock_irqsave(&ps->lock, flags); @@ -194,8 +195,8 @@ static void dec_usb_memory_use_count(struct usb_memory *usbm, int *count) list_del(&usbm->memlist); spin_unlock_irqrestore(&ps->lock, flags); - usb_free_coherent(ps->dev, usbm->size, usbm->mem, - usbm->dma_handle); + hcd_buffer_free_pages(hcd, usbm->size, + usbm->mem, usbm->dma_handle); usbfs_decrease_memory_usage( usbm->size + sizeof(struct usb_memory)); kfree(usbm); @@ -234,7 +235,7 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) size_t size = vma->vm_end - vma->vm_start; void *mem; unsigned long flags; - dma_addr_t dma_handle; + dma_addr_t dma_handle = DMA_MAPPING_ERROR; int ret; ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory)); @@ -247,8 +248,8 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) goto error_decrease_mem; } - mem = usb_alloc_coherent(ps->dev, size, GFP_USER | __GFP_NOWARN, - &dma_handle); + mem = hcd_buffer_alloc_pages(hcd, + size, GFP_USER | __GFP_NOWARN, &dma_handle); if (!mem) { ret = -ENOMEM; goto error_free_usbm; @@ -264,7 +265,14 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma) usbm->vma_use_count = 1; INIT_LIST_HEAD(&usbm->memlist); - if (hcd->localmem_pool || !hcd_uses_dma(hcd)) { + /* + * In DMA-unavailable cases, hcd_buffer_alloc_pages allocates + * normal pages and assigns DMA_MAPPING_ERROR to dma_handle. Check + * whether we are in such cases, and then use remap_pfn_range (or + * dma_mmap_coherent) to map normal (or DMA) pages into the user + * space, respectively. + */ + if (dma_handle == DMA_MAPPING_ERROR) { if (remap_pfn_range(vma, vma->vm_start, virt_to_phys(usbm->mem) >> PAGE_SHIFT, size, vma->vm_page_prot) < 0) { diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 0beaab932e7db2..7b2ce013cc5bab 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1137,7 +1137,7 @@ static int dwc3_core_init(struct dwc3 *dwc) dwc3_set_incr_burst_type(dwc); - dwc3_phy_power_on(dwc); + ret = dwc3_phy_power_on(dwc); if (ret) goto err_exit_phy; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index d56457c02996b6..1f043c31a0969f 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1116,6 +1116,7 @@ struct dwc3_scratchpad_array { * @dis_metastability_quirk: set to disable metastability quirk. * @dis_split_quirk: set to disable split boundary. * @wakeup_configured: set if the device is configured for remote wakeup. + * @suspended: set to track suspend event due to U3/L2. * @imod_interval: set the interrupt moderation interval in 250ns * increments or 0 to disable. * @max_cfg_eps: current max number of IN eps used across all USB configs. @@ -1332,6 +1333,7 @@ struct dwc3 { unsigned dis_split_quirk:1; unsigned async_callbacks:1; unsigned wakeup_configured:1; + unsigned suspended:1; u16 imod_interval; diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index e4a2560b9dc0c6..ebf03468fac4a9 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -332,6 +332,11 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused) unsigned int current_mode; unsigned long flags; u32 reg; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_GSTS); @@ -350,6 +355,8 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused) } spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -395,6 +402,11 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) struct dwc3 *dwc = s->private; unsigned long flags; u32 reg; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_GCTL); @@ -414,6 +426,8 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg)); } + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -463,6 +477,11 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused) struct dwc3 *dwc = s->private; unsigned long flags; u32 reg; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_DCTL); @@ -493,6 +512,8 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused) seq_printf(s, "UNKNOWN %d\n", reg); } + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -509,6 +530,7 @@ static ssize_t dwc3_testmode_write(struct file *file, unsigned long flags; u32 testmode = 0; char buf[32]; + int ret; if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) return -EFAULT; @@ -526,10 +548,16 @@ static ssize_t dwc3_testmode_write(struct file *file, else testmode = 0; + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; + spin_lock_irqsave(&dwc->lock, flags); dwc3_gadget_set_test_mode(dwc, testmode); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return count; } @@ -548,12 +576,18 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) enum dwc3_link_state state; u32 reg; u8 speed; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_GSTS); if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { seq_puts(s, "Not available\n"); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); return 0; } @@ -566,6 +600,8 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) dwc3_gadget_hs_link_string(state)); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -584,6 +620,7 @@ static ssize_t dwc3_link_state_write(struct file *file, char buf[32]; u32 reg; u8 speed; + int ret; if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) return -EFAULT; @@ -603,10 +640,15 @@ static ssize_t dwc3_link_state_write(struct file *file, else return -EINVAL; + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; + spin_lock_irqsave(&dwc->lock, flags); reg = dwc3_readl(dwc->regs, DWC3_GSTS); if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); return -EINVAL; } @@ -616,12 +658,15 @@ static ssize_t dwc3_link_state_write(struct file *file, if (speed < DWC3_DSTS_SUPERSPEED && state != DWC3_LINK_STATE_RECOV) { spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); return -EINVAL; } dwc3_gadget_set_link_state(dwc, state); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return count; } @@ -645,6 +690,11 @@ static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused) unsigned long flags; u32 mdwidth; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_TXFIFO); @@ -657,6 +707,8 @@ static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused) seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -667,6 +719,11 @@ static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused) unsigned long flags; u32 mdwidth; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_RXFIFO); @@ -679,6 +736,8 @@ static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused) seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -688,12 +747,19 @@ static int dwc3_tx_request_queue_show(struct seq_file *s, void *unused) struct dwc3 *dwc = dep->dwc; unsigned long flags; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_TXREQQ); seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -703,12 +769,19 @@ static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused) struct dwc3 *dwc = dep->dwc; unsigned long flags; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_RXREQQ); seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -718,12 +791,19 @@ static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused) struct dwc3 *dwc = dep->dwc; unsigned long flags; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ); seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -733,12 +813,19 @@ static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused) struct dwc3 *dwc = dep->dwc; unsigned long flags; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ); seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -748,12 +835,19 @@ static int dwc3_event_queue_show(struct seq_file *s, void *unused) struct dwc3 *dwc = dep->dwc; unsigned long flags; u32 val; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); val = dwc3_core_fifo_space(dep, DWC3_EVENTQ); seq_printf(s, "%u\n", val); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -798,6 +892,11 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused) struct dwc3 *dwc = dep->dwc; unsigned long flags; int i; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); if (dep->number <= 1) { @@ -827,6 +926,8 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused) out: spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -839,6 +940,11 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused) u32 lower_32_bits; u32 upper_32_bits; u32 reg; + int ret; + + ret = pm_runtime_resume_and_get(dwc->dev); + if (ret < 0) + return ret; spin_lock_irqsave(&dwc->lock, flags); reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number); @@ -851,6 +957,8 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused) seq_printf(s, "0x%016llx\n", ep_info); spin_unlock_irqrestore(&dwc->lock, flags); + pm_runtime_put_sync(dwc->dev); + return 0; } @@ -910,6 +1018,7 @@ void dwc3_debugfs_init(struct dwc3 *dwc) dwc->regset->regs = dwc3_regs; dwc->regset->nregs = ARRAY_SIZE(dwc3_regs); dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START; + dwc->regset->dev = dwc->dev; root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root); dwc->debug_root = root; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c0ca4d12f95d96..d831f5acf7b56b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2440,6 +2440,7 @@ static int dwc3_gadget_func_wakeup(struct usb_gadget *g, int intf_id) return -EINVAL; } dwc3_resume_gadget(dwc); + dwc->suspended = false; dwc->link_state = DWC3_LINK_STATE_U0; } @@ -2699,6 +2700,21 @@ static int dwc3_gadget_soft_disconnect(struct dwc3 *dwc) return ret; } +static int dwc3_gadget_soft_connect(struct dwc3 *dwc) +{ + /* + * In the Synopsys DWC_usb31 1.90a programming guide section + * 4.1.9, it specifies that for a reconnect after a + * device-initiated disconnect requires a core soft reset + * (DCTL.CSftRst) before enabling the run/stop bit. + */ + dwc3_core_soft_reset(dwc); + + dwc3_event_buffers_setup(dwc); + __dwc3_gadget_start(dwc); + return dwc3_gadget_run_stop(dwc, true); +} + static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) { struct dwc3 *dwc = gadget_to_dwc(g); @@ -2737,21 +2753,10 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on) synchronize_irq(dwc->irq_gadget); - if (!is_on) { + if (!is_on) ret = dwc3_gadget_soft_disconnect(dwc); - } else { - /* - * In the Synopsys DWC_usb31 1.90a programming guide section - * 4.1.9, it specifies that for a reconnect after a - * device-initiated disconnect requires a core soft reset - * (DCTL.CSftRst) before enabling the run/stop bit. - */ - dwc3_core_soft_reset(dwc); - - dwc3_event_buffers_setup(dwc); - __dwc3_gadget_start(dwc); - ret = dwc3_gadget_run_stop(dwc, true); - } + else + ret = dwc3_gadget_soft_connect(dwc); pm_runtime_put(dwc->dev); @@ -3938,6 +3943,8 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) { int reg; + dwc->suspended = false; + dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET); reg = dwc3_readl(dwc->regs, DWC3_DCTL); @@ -3962,6 +3969,8 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) { u32 reg; + dwc->suspended = false; + /* * Ideally, dwc3_reset_gadget() would trigger the function * drivers to stop any active transfers through ep disable. @@ -4180,6 +4189,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc, unsigned int evtinfo) { + dwc->suspended = false; + /* * TODO take core out of low power mode when that's * implemented. @@ -4277,6 +4288,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, if (dwc->gadget->wakeup_armed) { dwc3_gadget_enable_linksts_evts(dwc, false); dwc3_resume_gadget(dwc); + dwc->suspended = false; } break; case DWC3_LINK_STATE_U1: @@ -4303,8 +4315,10 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc, { enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK; - if (dwc->link_state != next && next == DWC3_LINK_STATE_U3) + if (!dwc->suspended && next == DWC3_LINK_STATE_U3) { + dwc->suspended = true; dwc3_suspend_gadget(dwc); + } dwc->link_state = next; } @@ -4655,42 +4669,39 @@ void dwc3_gadget_exit(struct dwc3 *dwc) int dwc3_gadget_suspend(struct dwc3 *dwc) { unsigned long flags; + int ret; if (!dwc->gadget_driver) return 0; - dwc3_gadget_run_stop(dwc, false); + ret = dwc3_gadget_soft_disconnect(dwc); + if (ret) + goto err; spin_lock_irqsave(&dwc->lock, flags); dwc3_disconnect_gadget(dwc); - __dwc3_gadget_stop(dwc); spin_unlock_irqrestore(&dwc->lock, flags); return 0; + +err: + /* + * Attempt to reset the controller's state. Likely no + * communication can be established until the host + * performs a port reset. + */ + if (dwc->softconnect) + dwc3_gadget_soft_connect(dwc); + + return ret; } int dwc3_gadget_resume(struct dwc3 *dwc) { - int ret; - if (!dwc->gadget_driver || !dwc->softconnect) return 0; - ret = __dwc3_gadget_start(dwc); - if (ret < 0) - goto err0; - - ret = dwc3_gadget_run_stop(dwc, true); - if (ret < 0) - goto err1; - - return 0; - -err1: - __dwc3_gadget_stop(dwc); - -err0: - return ret; + return dwc3_gadget_soft_connect(dwc); } void dwc3_gadget_process_pending_events(struct dwc3 *dwc) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index a13c946e0663c2..f41a385a5c421a 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -3535,6 +3535,7 @@ static void ffs_func_unbind(struct usb_configuration *c, /* Drain any pending AIO completions */ drain_workqueue(ffs->io_completion_wq); + ffs_event_add(ffs, FUNCTIONFS_UNBIND); if (!--opts->refcnt) functionfs_unbind(ffs); @@ -3559,7 +3560,6 @@ static void ffs_func_unbind(struct usb_configuration *c, func->function.ssp_descriptors = NULL; func->interfaces_nums = NULL; - ffs_event_add(ffs, FUNCTIONFS_UNBIND); } static struct usb_function *ffs_alloc(struct usb_function_instance *fi) diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 6956ad8ba8dd86..a366abb456236c 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "u_ether.h" @@ -965,6 +966,8 @@ int gether_get_host_addr_cdc(struct net_device *net, char *host_addr, int len) dev = netdev_priv(net); snprintf(host_addr, len, "%pm", dev->host_mac); + string_upper(host_addr, host_addr); + return strlen(host_addr); } EXPORT_SYMBOL_GPL(gether_get_host_addr_cdc); diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c index c80f9bd51b7501..a36913ae31f9ef 100644 --- a/drivers/usb/gadget/udc/amd5536udc_pci.c +++ b/drivers/usb/gadget/udc/amd5536udc_pci.c @@ -170,6 +170,9 @@ static int udc_pci_probe( retval = -ENODEV; goto err_probe; } + + udc = dev; + return 0; err_probe: diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 4641153e9706b1..52e6d2e84e3528 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -37,10 +37,6 @@ static const struct bus_type gadget_bus_type; * @vbus: for udcs who care about vbus status, this value is real vbus status; * for udcs who do not care about vbus status, this value is always true * @started: the UDC's started state. True if the UDC had started. - * @connect_lock: protects udc->vbus, udc->started, gadget->connect, gadget->deactivate related - * functions. usb_gadget_connect_locked, usb_gadget_disconnect_locked, - * usb_udc_connect_control_locked, usb_gadget_udc_start_locked, usb_gadget_udc_stop_locked are - * called with this lock held. * * This represents the internal data structure which is used by the UDC-class * to hold information about udc driver and gadget together. @@ -52,7 +48,6 @@ struct usb_udc { struct list_head list; bool vbus; bool started; - struct mutex connect_lock; }; static struct class *udc_class; @@ -692,9 +687,17 @@ int usb_gadget_vbus_disconnect(struct usb_gadget *gadget) } EXPORT_SYMBOL_GPL(usb_gadget_vbus_disconnect); -/* Internal version of usb_gadget_connect needs to be called with connect_lock held. */ -static int usb_gadget_connect_locked(struct usb_gadget *gadget) - __must_hold(&gadget->udc->connect_lock) +/** + * usb_gadget_connect - software-controlled connect to USB host + * @gadget:the peripheral being connected + * + * Enables the D+ (or potentially D-) pullup. The host will start + * enumerating this gadget when the pullup is active and a VBUS session + * is active (the link is powered). + * + * Returns zero on success, else negative errno. + */ +int usb_gadget_connect(struct usb_gadget *gadget) { int ret = 0; @@ -703,15 +706,10 @@ static int usb_gadget_connect_locked(struct usb_gadget *gadget) goto out; } - if (gadget->connected) - goto out; - - if (gadget->deactivated || !gadget->udc->started) { + if (gadget->deactivated) { /* * If gadget is deactivated we only save new state. * Gadget will be connected automatically after activation. - * - * udc first needs to be started before gadget can be pulled up. */ gadget->connected = true; goto out; @@ -726,32 +724,22 @@ static int usb_gadget_connect_locked(struct usb_gadget *gadget) return ret; } +EXPORT_SYMBOL_GPL(usb_gadget_connect); /** - * usb_gadget_connect - software-controlled connect to USB host - * @gadget:the peripheral being connected + * usb_gadget_disconnect - software-controlled disconnect from USB host + * @gadget:the peripheral being disconnected * - * Enables the D+ (or potentially D-) pullup. The host will start - * enumerating this gadget when the pullup is active and a VBUS session - * is active (the link is powered). + * Disables the D+ (or potentially D-) pullup, which the host may see + * as a disconnect (when a VBUS session is active). Not all systems + * support software pullup controls. + * + * Following a successful disconnect, invoke the ->disconnect() callback + * for the current gadget driver so that UDC drivers don't need to. * * Returns zero on success, else negative errno. */ -int usb_gadget_connect(struct usb_gadget *gadget) -{ - int ret; - - mutex_lock(&gadget->udc->connect_lock); - ret = usb_gadget_connect_locked(gadget); - mutex_unlock(&gadget->udc->connect_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(usb_gadget_connect); - -/* Internal version of usb_gadget_disconnect needs to be called with connect_lock held. */ -static int usb_gadget_disconnect_locked(struct usb_gadget *gadget) - __must_hold(&gadget->udc->connect_lock) +int usb_gadget_disconnect(struct usb_gadget *gadget) { int ret = 0; @@ -763,12 +751,10 @@ static int usb_gadget_disconnect_locked(struct usb_gadget *gadget) if (!gadget->connected) goto out; - if (gadget->deactivated || !gadget->udc->started) { + if (gadget->deactivated) { /* * If gadget is deactivated we only save new state. * Gadget will stay disconnected after activation. - * - * udc should have been started before gadget being pulled down. */ gadget->connected = false; goto out; @@ -788,30 +774,6 @@ static int usb_gadget_disconnect_locked(struct usb_gadget *gadget) return ret; } - -/** - * usb_gadget_disconnect - software-controlled disconnect from USB host - * @gadget:the peripheral being disconnected - * - * Disables the D+ (or potentially D-) pullup, which the host may see - * as a disconnect (when a VBUS session is active). Not all systems - * support software pullup controls. - * - * Following a successful disconnect, invoke the ->disconnect() callback - * for the current gadget driver so that UDC drivers don't need to. - * - * Returns zero on success, else negative errno. - */ -int usb_gadget_disconnect(struct usb_gadget *gadget) -{ - int ret; - - mutex_lock(&gadget->udc->connect_lock); - ret = usb_gadget_disconnect_locked(gadget); - mutex_unlock(&gadget->udc->connect_lock); - - return ret; -} EXPORT_SYMBOL_GPL(usb_gadget_disconnect); /** @@ -832,11 +794,10 @@ int usb_gadget_deactivate(struct usb_gadget *gadget) if (gadget->deactivated) goto out; - mutex_lock(&gadget->udc->connect_lock); if (gadget->connected) { - ret = usb_gadget_disconnect_locked(gadget); + ret = usb_gadget_disconnect(gadget); if (ret) - goto unlock; + goto out; /* * If gadget was being connected before deactivation, we want @@ -846,8 +807,6 @@ int usb_gadget_deactivate(struct usb_gadget *gadget) } gadget->deactivated = true; -unlock: - mutex_unlock(&gadget->udc->connect_lock); out: trace_usb_gadget_deactivate(gadget, ret); @@ -871,7 +830,6 @@ int usb_gadget_activate(struct usb_gadget *gadget) if (!gadget->deactivated) goto out; - mutex_lock(&gadget->udc->connect_lock); gadget->deactivated = false; /* @@ -879,8 +837,7 @@ int usb_gadget_activate(struct usb_gadget *gadget) * while it was being deactivated, we call usb_gadget_connect(). */ if (gadget->connected) - ret = usb_gadget_connect_locked(gadget); - mutex_unlock(&gadget->udc->connect_lock); + ret = usb_gadget_connect(gadget); out: trace_usb_gadget_activate(gadget, ret); @@ -1121,13 +1078,12 @@ EXPORT_SYMBOL_GPL(usb_gadget_set_state); /* ------------------------------------------------------------------------- */ -/* Acquire connect_lock before calling this function. */ -static void usb_udc_connect_control_locked(struct usb_udc *udc) __must_hold(&udc->connect_lock) +static void usb_udc_connect_control(struct usb_udc *udc) { - if (udc->vbus && udc->started) - usb_gadget_connect_locked(udc->gadget); + if (udc->vbus) + usb_gadget_connect(udc->gadget); else - usb_gadget_disconnect_locked(udc->gadget); + usb_gadget_disconnect(udc->gadget); } /** @@ -1143,12 +1099,10 @@ void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status) { struct usb_udc *udc = gadget->udc; - mutex_lock(&udc->connect_lock); if (udc) { udc->vbus = status; - usb_udc_connect_control_locked(udc); + usb_udc_connect_control(udc); } - mutex_unlock(&udc->connect_lock); } EXPORT_SYMBOL_GPL(usb_udc_vbus_handler); @@ -1170,7 +1124,7 @@ void usb_gadget_udc_reset(struct usb_gadget *gadget, EXPORT_SYMBOL_GPL(usb_gadget_udc_reset); /** - * usb_gadget_udc_start_locked - tells usb device controller to start up + * usb_gadget_udc_start - tells usb device controller to start up * @udc: The UDC to be started * * This call is issued by the UDC Class driver when it's about @@ -1181,11 +1135,8 @@ EXPORT_SYMBOL_GPL(usb_gadget_udc_reset); * necessary to have it powered on. * * Returns zero on success, else negative errno. - * - * Caller should acquire connect_lock before invoking this function. */ -static inline int usb_gadget_udc_start_locked(struct usb_udc *udc) - __must_hold(&udc->connect_lock) +static inline int usb_gadget_udc_start(struct usb_udc *udc) { int ret; @@ -1202,7 +1153,7 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc) } /** - * usb_gadget_udc_stop_locked - tells usb device controller we don't need it anymore + * usb_gadget_udc_stop - tells usb device controller we don't need it anymore * @udc: The UDC to be stopped * * This call is issued by the UDC Class driver after calling @@ -1211,11 +1162,8 @@ static inline int usb_gadget_udc_start_locked(struct usb_udc *udc) * The details are implementation specific, but it can go as * far as powering off UDC completely and disable its data * line pullups. - * - * Caller should acquire connect lock before invoking this function. */ -static inline void usb_gadget_udc_stop_locked(struct usb_udc *udc) - __must_hold(&udc->connect_lock) +static inline void usb_gadget_udc_stop(struct usb_udc *udc) { if (!udc->started) { dev_err(&udc->dev, "UDC had already stopped\n"); @@ -1374,7 +1322,6 @@ int usb_add_gadget(struct usb_gadget *gadget) udc->gadget = gadget; gadget->udc = udc; - mutex_init(&udc->connect_lock); udc->started = false; @@ -1576,15 +1523,11 @@ static int gadget_bind_driver(struct device *dev) if (ret) goto err_bind; - mutex_lock(&udc->connect_lock); - ret = usb_gadget_udc_start_locked(udc); - if (ret) { - mutex_unlock(&udc->connect_lock); + ret = usb_gadget_udc_start(udc); + if (ret) goto err_start; - } usb_gadget_enable_async_callbacks(udc); - usb_udc_connect_control_locked(udc); - mutex_unlock(&udc->connect_lock); + usb_udc_connect_control(udc); kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); return 0; @@ -1615,14 +1558,12 @@ static void gadget_unbind_driver(struct device *dev) kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); - mutex_lock(&udc->connect_lock); - usb_gadget_disconnect_locked(gadget); + usb_gadget_disconnect(gadget); usb_gadget_disable_async_callbacks(udc); if (gadget->irq) synchronize_irq(gadget->irq); udc->driver->unbind(gadget); - usb_gadget_udc_stop_locked(udc); - mutex_unlock(&udc->connect_lock); + usb_gadget_udc_stop(udc); mutex_lock(&udc_lock); driver->is_bound = false; @@ -1708,15 +1649,11 @@ static ssize_t soft_connect_store(struct device *dev, } if (sysfs_streq(buf, "connect")) { - mutex_lock(&udc->connect_lock); - usb_gadget_udc_start_locked(udc); - usb_gadget_connect_locked(udc->gadget); - mutex_unlock(&udc->connect_lock); + usb_gadget_udc_start(udc); + usb_gadget_connect(udc->gadget); } else if (sysfs_streq(buf, "disconnect")) { - mutex_lock(&udc->connect_lock); - usb_gadget_disconnect_locked(udc->gadget); - usb_gadget_udc_stop_locked(udc); - mutex_unlock(&udc->connect_lock); + usb_gadget_disconnect(udc->gadget); + usb_gadget_udc_stop(udc); } else { dev_err(dev, "unsupported command '%s'\n", buf); ret = -EINVAL; diff --git a/drivers/usb/host/uhci-pci.c b/drivers/usb/host/uhci-pci.c index 3592f757fe05dd..7bd2fddde770ae 100644 --- a/drivers/usb/host/uhci-pci.c +++ b/drivers/usb/host/uhci-pci.c @@ -119,11 +119,13 @@ static int uhci_pci_init(struct usb_hcd *hcd) uhci->rh_numports = uhci_count_ports(hcd); - /* Intel controllers report the OverCurrent bit active on. - * VIA controllers report it active off, so we'll adjust the - * bit value. (It's not standardized in the UHCI spec.) + /* + * Intel controllers report the OverCurrent bit active on. VIA + * and ZHAOXIN controllers report it active off, so we'll adjust + * the bit value. (It's not standardized in the UHCI spec.) */ - if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_VIA) + if (to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_VIA || + to_pci_dev(uhci_dev(uhci))->vendor == PCI_VENDOR_ID_ZHAOXIN) uhci->oc_low = 1; /* HP's server management chip requires a longer port reset delay. */ diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index ddb79f23fb3b7c..79b3691f373f34 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "xhci.h" #include "xhci-trace.h" @@ -387,7 +388,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_AMD && pdev->device == PCI_DEVICE_ID_AMD_RENOIR_XHCI) - xhci->quirks |= XHCI_BROKEN_D3COLD; + xhci->quirks |= XHCI_BROKEN_D3COLD_S2I; if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; @@ -801,9 +802,16 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) * Systems with the TI redriver that loses port status change events * need to have the registers polled during D3, so avoid D3cold. */ - if (xhci->quirks & (XHCI_COMP_MODE_QUIRK | XHCI_BROKEN_D3COLD)) + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) pci_d3cold_disable(pdev); +#ifdef CONFIG_SUSPEND + /* d3cold is broken, but only when s2idle is used */ + if (pm_suspend_target_state == PM_SUSPEND_TO_IDLE && + xhci->quirks & (XHCI_BROKEN_D3COLD_S2I)) + pci_d3cold_disable(pdev); +#endif + if (xhci->quirks & XHCI_PME_STUCK_QUIRK) xhci_pme_quirk(hcd); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 1ad12d5a48572b..2bc82b3a2f984c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -276,6 +276,26 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, trace_xhci_inc_enq(ring); } +static int xhci_num_trbs_to(struct xhci_segment *start_seg, union xhci_trb *start, + struct xhci_segment *end_seg, union xhci_trb *end, + unsigned int num_segs) +{ + union xhci_trb *last_on_seg; + int num = 0; + int i = 0; + + do { + if (start_seg == end_seg && end >= start) + return num + (end - start); + last_on_seg = &start_seg->trbs[TRBS_PER_SEGMENT - 1]; + num += last_on_seg - start; + start_seg = start_seg->next; + start = start_seg->trbs; + } while (i++ <= num_segs); + + return -EINVAL; +} + /* * Check to see if there's room to enqueue num_trbs on the ring and make sure * enqueue pointer will not advance into dequeue segment. See rules above. @@ -2140,6 +2160,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, u32 trb_comp_code) { struct xhci_ep_ctx *ep_ctx; + int trbs_freed; ep_ctx = xhci_get_ep_ctx(xhci, ep->vdev->out_ctx, ep->ep_index); @@ -2209,9 +2230,15 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, } /* Update ring dequeue pointer */ + trbs_freed = xhci_num_trbs_to(ep_ring->deq_seg, ep_ring->dequeue, + td->last_trb_seg, td->last_trb, + ep_ring->num_segs); + if (trbs_freed < 0) + xhci_dbg(xhci, "Failed to count freed trbs at TD finish\n"); + else + ep_ring->num_trbs_free += trbs_freed; ep_ring->dequeue = td->last_trb; ep_ring->deq_seg = td->last_trb_seg; - ep_ring->num_trbs_free += td->num_trbs - 1; inc_deq(xhci, ep_ring); return xhci_td_cleanup(xhci, td, ep_ring, td->status); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 08d721921b7bb2..6b690ec91ff3ae 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1901,7 +1901,7 @@ struct xhci_hcd { #define XHCI_DISABLE_SPARSE BIT_ULL(38) #define XHCI_SG_TRB_CACHE_SIZE_QUIRK BIT_ULL(39) #define XHCI_NO_SOFT_RETRY BIT_ULL(40) -#define XHCI_BROKEN_D3COLD BIT_ULL(41) +#define XHCI_BROKEN_D3COLD_S2I BIT_ULL(41) #define XHCI_EP_CTX_BROKEN_DCS BIT_ULL(42) #define XHCI_SUSPEND_RESUME_CLKS BIT_ULL(43) #define XHCI_RESET_TO_DEFAULT BIT_ULL(44) diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 8931df5a85fd9e..c54e9805da536a 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -406,22 +406,25 @@ static DEF_SCSI_QCMD(queuecommand) ***********************************************************************/ /* Command timeout and abort */ -static int command_abort(struct scsi_cmnd *srb) +static int command_abort_matching(struct us_data *us, struct scsi_cmnd *srb_match) { - struct us_data *us = host_to_us(srb->device->host); - - usb_stor_dbg(us, "%s called\n", __func__); - /* * us->srb together with the TIMED_OUT, RESETTING, and ABORTING * bits are protected by the host lock. */ scsi_lock(us_to_host(us)); - /* Is this command still active? */ - if (us->srb != srb) { + /* is there any active pending command to abort ? */ + if (!us->srb) { scsi_unlock(us_to_host(us)); usb_stor_dbg(us, "-- nothing to abort\n"); + return SUCCESS; + } + + /* Does the command match the passed srb if any ? */ + if (srb_match && us->srb != srb_match) { + scsi_unlock(us_to_host(us)); + usb_stor_dbg(us, "-- pending command mismatch\n"); return FAILED; } @@ -444,6 +447,14 @@ static int command_abort(struct scsi_cmnd *srb) return SUCCESS; } +static int command_abort(struct scsi_cmnd *srb) +{ + struct us_data *us = host_to_us(srb->device->host); + + usb_stor_dbg(us, "%s called\n", __func__); + return command_abort_matching(us, srb); +} + /* * This invokes the transport reset mechanism to reset the state of the * device @@ -455,6 +466,9 @@ static int device_reset(struct scsi_cmnd *srb) usb_stor_dbg(us, "%s called\n", __func__); + /* abort any pending command before reset */ + command_abort_matching(us, NULL); + /* lock the device pointers and do the reset */ mutex_lock(&(us->dev_mutex)); result = us->transport_reset(us); diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c index 8f3e884222adef..66de880b28d01a 100644 --- a/drivers/usb/typec/altmodes/displayport.c +++ b/drivers/usb/typec/altmodes/displayport.c @@ -516,6 +516,10 @@ static ssize_t pin_assignment_show(struct device *dev, mutex_unlock(&dp->lock); + /* get_current_pin_assignments can return 0 when no matching pin assignments are found */ + if (len == 0) + len++; + buf[len - 1] = '\n'; return len; } diff --git a/drivers/usb/typec/tipd/core.c b/drivers/usb/typec/tipd/core.c index 8b075ca82ef6de..603dbd44deba9a 100644 --- a/drivers/usb/typec/tipd/core.c +++ b/drivers/usb/typec/tipd/core.c @@ -886,6 +886,9 @@ static void tps6598x_remove(struct i2c_client *client) { struct tps6598x *tps = i2c_get_clientdata(client); + if (!client->irq) + cancel_delayed_work_sync(&tps->wq_poll); + tps6598x_disconnect(tps, 0); typec_unregister_port(tps->port); usb_role_switch_put(tps->role_sw); @@ -917,7 +920,7 @@ static int __maybe_unused tps6598x_resume(struct device *dev) enable_irq(client->irq); } - if (client->irq) + if (!client->irq) queue_delayed_work(system_power_efficient_wq, &tps->wq_poll, msecs_to_jiffies(POLL_INTERVAL)); diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index 3d4dd9420c3070..0d2f805468e190 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -860,6 +860,11 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, if (ret) goto pin_unwind; + if (!pfn_valid(phys_pfn)) { + ret = -EINVAL; + goto pin_unwind; + } + ret = vfio_add_to_pfn_list(dma, iova, phys_pfn); if (ret) { if (put_pfn(phys_pfn, dma->prot) && do_accounting) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index a92af08e786450..07427302084955 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -256,7 +256,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work) * test_and_set_bit() implies a memory barrier. */ llist_add(&work->node, &dev->worker->work_list); - wake_up_process(dev->worker->vtsk->task); + vhost_task_wake(dev->worker->vtsk); } } EXPORT_SYMBOL_GPL(vhost_work_queue); @@ -333,31 +333,19 @@ static void vhost_vq_reset(struct vhost_dev *dev, __vhost_vq_meta_reset(vq); } -static int vhost_worker(void *data) +static bool vhost_worker(void *data) { struct vhost_worker *worker = data; struct vhost_work *work, *work_next; struct llist_node *node; - for (;;) { - /* mb paired w/ kthread_stop */ - set_current_state(TASK_INTERRUPTIBLE); - - if (vhost_task_should_stop(worker->vtsk)) { - __set_current_state(TASK_RUNNING); - break; - } - - node = llist_del_all(&worker->work_list); - if (!node) - schedule(); - + node = llist_del_all(&worker->work_list); + if (node) { node = llist_reverse_order(node); /* make sure flag is seen after deletion */ smp_wmb(); llist_for_each_entry_safe(work, work_next, node, node) { clear_bit(VHOST_WORK_QUEUED, &work->flags); - __set_current_state(TASK_RUNNING); kcov_remote_start_common(worker->kcov_handle); work->fn(work); kcov_remote_stop(); @@ -365,7 +353,7 @@ static int vhost_worker(void *data) } } - return 0; + return !!node; } static void vhost_vq_free_iovecs(struct vhost_virtqueue *vq) diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 96e91570cdd329..0fdf5f46802c7f 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -124,7 +124,7 @@ config FB_PROVIDE_GET_FB_UNMAPPED_AREA depends on FB help Allow generic frame-buffer to provide get_fb_unmapped_area - function. + function to provide shareable character device support on nommu. menuconfig FB_FOREIGN_ENDIAN bool "Framebuffer foreign endianness support" diff --git a/drivers/video/fbdev/arcfb.c b/drivers/video/fbdev/arcfb.c index 024d0ee4f04f93..08d15e4084130e 100644 --- a/drivers/video/fbdev/arcfb.c +++ b/drivers/video/fbdev/arcfb.c @@ -590,7 +590,7 @@ static int arcfb_probe(struct platform_device *dev) return retval; } -static int arcfb_remove(struct platform_device *dev) +static void arcfb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); @@ -601,12 +601,11 @@ static int arcfb_remove(struct platform_device *dev) vfree((void __force *)info->screen_base); framebuffer_release(info); } - return 0; } static struct platform_driver arcfb_driver = { .probe = arcfb_probe, - .remove = arcfb_remove, + .remove_new = arcfb_remove, .driver = { .name = "arcfb", }, diff --git a/drivers/video/fbdev/aty/atyfb_base.c b/drivers/video/fbdev/aty/atyfb_base.c index b02e4e645035c4..cba2b113b28b05 100644 --- a/drivers/video/fbdev/aty/atyfb_base.c +++ b/drivers/video/fbdev/aty/atyfb_base.c @@ -3498,11 +3498,6 @@ static int atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, if (ret) goto atyfb_setup_generic_fail; #endif - if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN)) - par->clk_wr_offset = (inb(R_GENMO) & 0x0CU) >> 2; - else - par->clk_wr_offset = aty_ld_8(CLOCK_CNTL, par) & 0x03U; - /* according to ATI, we should use clock 3 for acelerated mode */ par->clk_wr_offset = 3; diff --git a/drivers/video/fbdev/au1100fb.c b/drivers/video/fbdev/au1100fb.c index 519313b8bb004f..648d6cac86e8fb 100644 --- a/drivers/video/fbdev/au1100fb.c +++ b/drivers/video/fbdev/au1100fb.c @@ -520,13 +520,10 @@ static int au1100fb_drv_probe(struct platform_device *dev) return -ENODEV; } -int au1100fb_drv_remove(struct platform_device *dev) +void au1100fb_drv_remove(struct platform_device *dev) { struct au1100fb_device *fbdev = NULL; - if (!dev) - return -ENODEV; - fbdev = platform_get_drvdata(dev); #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) @@ -543,8 +540,6 @@ int au1100fb_drv_remove(struct platform_device *dev) clk_disable_unprepare(fbdev->lcdclk); clk_put(fbdev->lcdclk); } - - return 0; } #ifdef CONFIG_PM @@ -593,9 +588,9 @@ static struct platform_driver au1100fb_driver = { .name = "au1100-lcd", }, .probe = au1100fb_drv_probe, - .remove = au1100fb_drv_remove, + .remove_new = au1100fb_drv_remove, .suspend = au1100fb_drv_suspend, - .resume = au1100fb_drv_resume, + .resume = au1100fb_drv_resume, }; module_platform_driver(au1100fb_driver); diff --git a/drivers/video/fbdev/au1200fb.c b/drivers/video/fbdev/au1200fb.c index b6b22fa4a8a013..aed88ce45bf091 100644 --- a/drivers/video/fbdev/au1200fb.c +++ b/drivers/video/fbdev/au1200fb.c @@ -1765,7 +1765,7 @@ static int au1200fb_drv_probe(struct platform_device *dev) return ret; } -static int au1200fb_drv_remove(struct platform_device *dev) +static void au1200fb_drv_remove(struct platform_device *dev) { struct au1200fb_platdata *pd = platform_get_drvdata(dev); struct fb_info *fbi; @@ -1788,8 +1788,6 @@ static int au1200fb_drv_remove(struct platform_device *dev) } free_irq(platform_get_irq(dev, 0), (void *)dev); - - return 0; } #ifdef CONFIG_PM @@ -1840,7 +1838,7 @@ static struct platform_driver au1200fb_driver = { .pm = AU1200FB_PMOPS, }, .probe = au1200fb_drv_probe, - .remove = au1200fb_drv_remove, + .remove_new = au1200fb_drv_remove, }; module_platform_driver(au1200fb_driver); diff --git a/drivers/video/fbdev/broadsheetfb.c b/drivers/video/fbdev/broadsheetfb.c index 55e62dd96f9bef..b518cacbf7cd9e 100644 --- a/drivers/video/fbdev/broadsheetfb.c +++ b/drivers/video/fbdev/broadsheetfb.c @@ -1193,7 +1193,7 @@ static int broadsheetfb_probe(struct platform_device *dev) } -static int broadsheetfb_remove(struct platform_device *dev) +static void broadsheetfb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); @@ -1209,12 +1209,11 @@ static int broadsheetfb_remove(struct platform_device *dev) module_put(par->board->owner); framebuffer_release(info); } - return 0; } static struct platform_driver broadsheetfb_driver = { .probe = broadsheetfb_probe, - .remove = broadsheetfb_remove, + .remove_new = broadsheetfb_remove, .driver = { .name = "broadsheetfb", }, diff --git a/drivers/video/fbdev/bw2.c b/drivers/video/fbdev/bw2.c index 9cbadcd18b256c..025d663dc6fdca 100644 --- a/drivers/video/fbdev/bw2.c +++ b/drivers/video/fbdev/bw2.c @@ -352,7 +352,7 @@ static int bw2_probe(struct platform_device *op) return err; } -static int bw2_remove(struct platform_device *op) +static void bw2_remove(struct platform_device *op) { struct fb_info *info = dev_get_drvdata(&op->dev); struct bw2_par *par = info->par; @@ -363,8 +363,6 @@ static int bw2_remove(struct platform_device *op) of_iounmap(&op->resource[0], info->screen_base, info->fix.smem_len); framebuffer_release(info); - - return 0; } static const struct of_device_id bw2_match[] = { @@ -381,7 +379,7 @@ static struct platform_driver bw2_driver = { .of_match_table = bw2_match, }, .probe = bw2_probe, - .remove = bw2_remove, + .remove_new = bw2_remove, }; static int __init bw2_init(void) diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index f98e8f298bc19a..8587c9da067003 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -247,6 +247,9 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, cursor.set = 0; + if (!vc->vc_font.data) + return; + c = scr_readw((u16 *) vc->vc_pos); attribute = get_attribute(info, c); src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index e808dc86001cc9..28739f1cb5e7a1 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1468,7 +1468,7 @@ __releases(&info->lock) } #if defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA) && !defined(CONFIG_MMU) -unsigned long get_fb_unmapped_area(struct file *filp, +static unsigned long get_fb_unmapped_area(struct file *filp, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags) { diff --git a/drivers/video/fbdev/i810/i810_dvt.c b/drivers/video/fbdev/i810/i810_dvt.c index b4b3670667ab8c..2082b5c92e8f3b 100644 --- a/drivers/video/fbdev/i810/i810_dvt.c +++ b/drivers/video/fbdev/i810/i810_dvt.c @@ -14,6 +14,7 @@ #include "i810_regs.h" #include "i810.h" +#include "i810_main.h" struct mode_registers std_modes[] = { /* 640x480 @ 60Hz */ @@ -276,7 +277,7 @@ void i810fb_fill_var_timings(struct fb_var_screeninfo *var) var->upper_margin = total - (yres + var->lower_margin + var->vsync_len); } -u32 i810_get_watermark(struct fb_var_screeninfo *var, +u32 i810_get_watermark(const struct fb_var_screeninfo *var, struct i810fb_par *par) { struct mode_registers *params = &par->regs; diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index 975dd682fae4bb..ee7d01ad140686 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -1452,9 +1452,13 @@ static int init_imstt(struct fb_info *info) FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_YPAN; - fb_alloc_cmap(&info->cmap, 0, 0); + if (fb_alloc_cmap(&info->cmap, 0, 0)) { + framebuffer_release(info); + return -ENODEV; + } if (register_framebuffer(info) < 0) { + fb_dealloc_cmap(&info->cmap); framebuffer_release(info); return -ENODEV; } @@ -1531,8 +1535,10 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto error; info->pseudo_palette = par->palette; ret = init_imstt(info); - if (!ret) - pci_set_drvdata(pdev, info); + if (ret) + goto error; + + pci_set_drvdata(pdev, info); return ret; error: diff --git a/drivers/video/fbdev/matrox/matroxfb_maven.c b/drivers/video/fbdev/matrox/matroxfb_maven.c index 727a10a59811b3..b15a8ad92ba704 100644 --- a/drivers/video/fbdev/matrox/matroxfb_maven.c +++ b/drivers/video/fbdev/matrox/matroxfb_maven.c @@ -1291,7 +1291,7 @@ static struct i2c_driver maven_driver={ .driver = { .name = "maven", }, - .probe_new = maven_probe, + .probe = maven_probe, .remove = maven_remove, .id_table = maven_id, }; diff --git a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c index 1eaa35c2783598..477789cff8e08d 100644 --- a/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/fbdev/omap2/omapfb/displays/panel-tpo-td043mtea1.c @@ -491,7 +491,8 @@ static int tpo_td043_probe(struct spi_device *spi) ddata->vcc_reg = devm_regulator_get(&spi->dev, "vcc"); if (IS_ERR(ddata->vcc_reg)) { - r = dev_err_probe(&spi->dev, r, "failed to get LCD VCC regulator\n"); + r = dev_err_probe(&spi->dev, PTR_ERR(ddata->vcc_reg), + "failed to get LCD VCC regulator\n"); goto err_regulator; } diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 046b9990d27cd9..132d1a20501183 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -844,7 +844,7 @@ static const struct i2c_device_id ssd1307fb_i2c_id[] = { MODULE_DEVICE_TABLE(i2c, ssd1307fb_i2c_id); static struct i2c_driver ssd1307fb_driver = { - .probe_new = ssd1307fb_probe, + .probe = ssd1307fb_probe, .remove = ssd1307fb_remove, .id_table = ssd1307fb_i2c_id, .driver = { diff --git a/drivers/video/fbdev/stifb.c b/drivers/video/fbdev/stifb.c index 14c9215284c504..686a234f3899e5 100644 --- a/drivers/video/fbdev/stifb.c +++ b/drivers/video/fbdev/stifb.c @@ -741,7 +741,7 @@ ngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data) packed_len = (fb->info.var.xres << 16) | fb->info.var.yres; NGLE_SET_DSTXY(fb, packed_dst); - /* Write zeroes to overlay planes */ + /* Write zeroes to overlay planes */ NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, IBOvals(RopSrc, MaskAddrOffset(0), BitmapExtent08, StaticReg(0), @@ -1297,14 +1297,14 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) break; default: #ifdef FALLBACK_TO_1BPP - printk(KERN_WARNING + printk(KERN_WARNING "stifb: Unsupported graphics card (id=0x%08x) " "- now trying 1bpp mode instead\n", fb->id); bpp = 1; /* default to 1 bpp */ break; #else - printk(KERN_WARNING + printk(KERN_WARNING "stifb: Unsupported graphics card (id=0x%08x) " "- skipping.\n", fb->id); diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c index 216d49c9d47e5c..dabc30a09f9698 100644 --- a/drivers/video/fbdev/udlfb.c +++ b/drivers/video/fbdev/udlfb.c @@ -27,6 +27,8 @@ #include