Merge remote-tracking branch 'wireless/main' into wireless-next
authorJohannes Berg <johannes.berg@intel.com>
Tue, 6 Sep 2022 08:05:29 +0000 (10:05 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 6 Sep 2022 08:05:39 +0000 (10:05 +0200)
Merge wireless/main to get the rx.link fix, which is needed
for further work in this area.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
1195 files changed:
.mailmap
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/admin-guide/README.rst
Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/mm/damon/usage.rst
Documentation/admin-guide/sysctl/net.rst
Documentation/arm64/elf_hwcaps.rst
Documentation/arm64/silicon-errata.rst
Documentation/atomic_bitops.txt
Documentation/bpf/kfuncs.rst
Documentation/conf.py
Documentation/devicetree/bindings/net/cortina,gemini-ethernet.yaml
Documentation/devicetree/bindings/net/dsa/arrow,xrs700x.yaml
Documentation/devicetree/bindings/net/dsa/brcm,b53.yaml
Documentation/devicetree/bindings/net/dsa/dsa-port.yaml
Documentation/devicetree/bindings/net/dsa/hirschmann,hellcreek.yaml
Documentation/devicetree/bindings/net/dsa/mediatek,mt7530.yaml
Documentation/devicetree/bindings/net/dsa/microchip,ksz.yaml
Documentation/devicetree/bindings/net/dsa/renesas,rzn1-a5psw.yaml
Documentation/devicetree/bindings/net/ethernet-controller.yaml
Documentation/devicetree/bindings/net/fsl,fman-dtsec.yaml [new file with mode: 0644]
Documentation/devicetree/bindings/net/fsl-fman.txt
Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
Documentation/devicetree/bindings/net/nxp,tja11xx.yaml
Documentation/devicetree/bindings/net/qca,ar803x.yaml
Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
Documentation/devicetree/bindings/net/snps,dwmac.yaml
Documentation/devicetree/bindings/net/sunplus,sp7021-emac.yaml
Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml
Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
Documentation/devicetree/bindings/net/vertexcom-mse102x.yaml
Documentation/devicetree/bindings/net/wireless/microchip,wilc1000.yaml
Documentation/devicetree/bindings/net/wireless/silabs,wfx.yaml
Documentation/devicetree/bindings/net/wireless/ti,wlcore.yaml
Documentation/devicetree/bindings/thermal/thermal-zones.yaml
Documentation/networking/bonding.rst
Documentation/networking/decnet.rst [deleted file]
Documentation/networking/device_drivers/ethernet/index.rst
Documentation/networking/device_drivers/ethernet/wangxun/ngbe.rst [new file with mode: 0644]
Documentation/networking/devlink/ice.rst
Documentation/networking/devlink/index.rst
Documentation/networking/devlink/netdevsim.rst
Documentation/networking/driver.rst
Documentation/networking/index.rst
Documentation/networking/ip-sysctl.rst
Documentation/networking/ipvlan.rst
Documentation/networking/l2tp.rst
Documentation/networking/phy.rst
Documentation/networking/switchdev.rst
Documentation/sphinx/kerneldoc-preamble.sty
Documentation/translations/ja_JP/SubmittingPatches
Documentation/userspace-api/index.rst
Documentation/userspace-api/ioctl/ioctl-number.rst
Documentation/userspace-api/netlink/index.rst [new file with mode: 0644]
Documentation/userspace-api/netlink/intro.rst [new file with mode: 0644]
MAINTAINERS
Makefile
arch/alpha/include/asm/bitops.h
arch/arm64/Kconfig
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/setup.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/cacheinfo.c
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/pi/kaslr_early.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kernel/topology.c
arch/arm64/mm/mmu.c
arch/arm64/tools/cpucaps
arch/hexagon/include/asm/bitops.h
arch/ia64/include/asm/bitops.h
arch/loongarch/Kconfig
arch/loongarch/include/asm/addrspace.h
arch/loongarch/include/asm/cmpxchg.h
arch/loongarch/include/asm/io.h
arch/loongarch/include/asm/page.h
arch/loongarch/include/asm/percpu.h
arch/loongarch/include/asm/pgtable.h
arch/loongarch/include/asm/reboot.h [deleted file]
arch/loongarch/kernel/reset.c
arch/loongarch/mm/fault.c
arch/loongarch/mm/mmap.c
arch/loongarch/vdso/vgetcpu.c
arch/loongarch/vdso/vgettimeofday.c
arch/m68k/include/asm/bitops.h
arch/mips/configs/decstation_64_defconfig
arch/mips/configs/decstation_defconfig
arch/mips/configs/decstation_r4k_defconfig
arch/mips/configs/gpr_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/configs/rm200_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
arch/riscv/boot/dts/microchip/mpfs-polarberry.dts
arch/riscv/boot/dts/microchip/mpfs.dtsi
arch/riscv/include/asm/signal.h [new file with mode: 0644]
arch/riscv/include/asm/thread_info.h
arch/riscv/kernel/signal.c
arch/riscv/kernel/traps.c
arch/s390/include/asm/bitops.h
arch/s390/kernel/process.c
arch/s390/mm/fault.c
arch/sh/include/asm/bitops-op32.h
arch/x86/boot/compressed/misc.h
arch/x86/boot/compressed/sev.c
arch/x86/configs/xen.config
arch/x86/entry/entry_64_compat.S
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/lbr.c
arch/x86/events/intel/uncore_snb.c
arch/x86/include/asm/bitops.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/sev.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/sev.c
arch/x86/kernel/unwind_orc.c
arch/x86/mm/pat/memtype.c
block/blk-mq.c
drivers/acpi/processor_thermal.c
drivers/acpi/property.c
drivers/android/binder_alloc.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/char/mem.c
drivers/cpufreq/cpufreq.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_7_0_offset.h
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_7_0_sh_mask.h
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/vc4/Kconfig
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/hid-asus.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-nintendo.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/hid-thrustmaster.c
drivers/hid/hidraw.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/intel-ish-hid/ishtp-hid.h
drivers/hid/intel-ish-hid/ishtp/client.c
drivers/isdn/capi/kcapi.c
drivers/md/md.c
drivers/md/raid10.c
drivers/net/Space.c
drivers/net/amt.c
drivers/net/bonding/bond_main.c
drivers/net/can/sja1000/peak_pcmcia.c
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/bcm_sf2_cfp.c
drivers/net/dsa/hirschmann/hellcreek.c
drivers/net/dsa/microchip/ksz8.h
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/microchip/ksz9477.h
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/microchip/ksz_spi.c
drivers/net/dsa/microchip/lan937x.h
drivers/net/dsa/microchip/lan937x_main.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/global2.h
drivers/net/dsa/mv88e6xxx/port.c
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/xrs700x/xrs700x.c
drivers/net/dummy.c
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/3com/3c515.c
drivers/net/ethernet/3com/3c589_cs.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/3com/typhoon.c
drivers/net/ethernet/8390/ax88796.c
drivers/net/ethernet/8390/etherh.c
drivers/net/ethernet/adaptec/starfire.c
drivers/net/ethernet/aeroflex/greth.c
drivers/net/ethernet/agere/et131x.c
drivers/net/ethernet/alacritech/slicoss.c
drivers/net/ethernet/allwinner/sun4i-emac.c
drivers/net/ethernet/alteon/acenic.c
drivers/net/ethernet/altera/altera_tse_ethtool.c
drivers/net/ethernet/amazon/ena/ena_ethtool.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amd/amd8111e.c
drivers/net/ethernet/amd/au1000_eth.c
drivers/net/ethernet/amd/nmclan_cs.c
drivers/net/ethernet/amd/pcnet32.c
drivers/net/ethernet/amd/sunlance.c
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c
drivers/net/ethernet/arc/emac_main.c
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/atheros/atl1c/atl1c_ethtool.c
drivers/net/ethernet/atheros/atl1e/atl1e_ethtool.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/atheros/atlx/atl2.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcm4908_enet.c
drivers/net/ethernet/broadcom/bcm63xx_enet.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/brocade/bna/bnad_ethtool.c
drivers/net/ethernet/cavium/octeon/octeon_mgmt.c
drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
drivers/net/ethernet/chelsio/cxgb/cxgb2.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
drivers/net/ethernet/cirrus/ep93xx_eth.c
drivers/net/ethernet/cisco/enic/enic_ethtool.c
drivers/net/ethernet/cortina/gemini.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/dec/tulip/de2104x.c
drivers/net/ethernet/dec/tulip/dmfe.c
drivers/net/ethernet/dec/tulip/tulip_core.c
drivers/net/ethernet/dec/tulip/uli526x.c
drivers/net/ethernet/dec/tulip/winbond-840.c
drivers/net/ethernet/dlink/dl2k.c
drivers/net/ethernet/dlink/sundance.c
drivers/net/ethernet/dnet.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/engleder/tsnep.h
drivers/net/ethernet/engleder/tsnep_hw.h
drivers/net/ethernet/engleder/tsnep_main.c
drivers/net/ethernet/faraday/ftgmac100.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/fealnx.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa/dpaa_ethtool.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
drivers/net/ethernet/freescale/enetc/enetc_ethtool.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/freescale/fman/fman.c
drivers/net/ethernet/freescale/fman/fman.h
drivers/net/ethernet/freescale/fman/fman_dtsec.c
drivers/net/ethernet/freescale/fman/fman_dtsec.h
drivers/net/ethernet/freescale/fman/fman_keygen.c
drivers/net/ethernet/freescale/fman/fman_keygen.h
drivers/net/ethernet/freescale/fman/fman_mac.h
drivers/net/ethernet/freescale/fman/fman_memac.c
drivers/net/ethernet/freescale/fman/fman_memac.h
drivers/net/ethernet/freescale/fman/fman_muram.c
drivers/net/ethernet/freescale/fman/fman_muram.h
drivers/net/ethernet/freescale/fman/fman_port.c
drivers/net/ethernet/freescale/fman/fman_port.h
drivers/net/ethernet/freescale/fman/fman_sp.c
drivers/net/ethernet/freescale/fman/fman_sp.h
drivers/net/ethernet/freescale/fman/fman_tgec.c
drivers/net/ethernet/freescale/fman/fman_tgec.h
drivers/net/ethernet/freescale/fman/mac.c
drivers/net/ethernet/freescale/fman/mac.h
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/ethernet/freescale/ucc_geth_ethtool.c
drivers/net/ethernet/freescale/xgmac_mdio.c
drivers/net/ethernet/fujitsu/fmvj18x_cs.c
drivers/net/ethernet/fungible/funeth/funeth_main.c
drivers/net/ethernet/fungible/funeth/funeth_txrx.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/huawei/hinic/hinic_rx.c
drivers/net/ethernet/huawei/hinic/hinic_tx.c
drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
drivers/net/ethernet/ibm/emac/core.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/e100.c
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_ptp.c
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
drivers/net/ethernet/intel/ice/ice_base.c
drivers/net/ethernet/intel/ice/ice_common.c
drivers/net/ethernet/intel/ice/ice_common.h
drivers/net/ethernet/intel/ice/ice_devlink.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lag.c
drivers/net/ethernet/intel/ice/ice_lag.h
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_lib.h
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_nvm.c
drivers/net/ethernet/intel/ice/ice_nvm.h
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_ptp.h
drivers/net/ethernet/intel/ice/ice_switch.c
drivers/net/ethernet/intel/ice/ice_tc_lib.c
drivers/net/ethernet/intel/ice/ice_tc_lib.h
drivers/net/ethernet/intel/ice/ice_txrx.c
drivers/net/ethernet/intel/ice/ice_txrx.h
drivers/net/ethernet/intel/ice/ice_type.h
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/ethtool.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_fcoe.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
drivers/net/ethernet/intel/ixgbevf/ethtool.c
drivers/net/ethernet/jme.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/octeontx2/nic/cn10k.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/prestera/Makefile
drivers/net/ethernet/marvell/prestera/prestera.h
drivers/net/ethernet/marvell/prestera/prestera_acl.c
drivers/net/ethernet/marvell/prestera/prestera_acl.h
drivers/net/ethernet/marvell/prestera/prestera_ethtool.c
drivers/net/ethernet/marvell/prestera/prestera_flow.c
drivers/net/ethernet/marvell/prestera/prestera_flow.h
drivers/net/ethernet/marvell/prestera/prestera_flower.c
drivers/net/ethernet/marvell/prestera/prestera_flower.h
drivers/net/ethernet/marvell/prestera/prestera_hw.c
drivers/net/ethernet/marvell/prestera/prestera_hw.h
drivers/net/ethernet/marvell/prestera/prestera_main.c
drivers/net/ethernet/marvell/prestera/prestera_matchall.c [new file with mode: 0644]
drivers/net/ethernet/marvell/prestera/prestera_matchall.h [new file with mode: 0644]
drivers/net/ethernet/marvell/prestera/prestera_span.c
drivers/net/ethernet/marvell/prestera/prestera_span.h
drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
drivers/net/ethernet/marvell/pxa168_eth.c
drivers/net/ethernet/marvell/skge.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_star_emac.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/icm.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
drivers/net/ethernet/mellanox/mlx5/core/en/fs_ethtool.h [new file with mode: 0644]
drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.h
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/goto.c
drivers/net/ethernet/mellanox/mlx5/core/en/trap.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.h
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.h
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.h
drivers/net/ethernet/mellanox/mlx5/core/esw/indir_table.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_mdio.c
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h
drivers/net/ethernet/mellanox/mlxsw/cmd.h
drivers/net/ethernet/mellanox/mlxsw/core.c
drivers/net/ethernet/mellanox/mlxsw/core.h
drivers/net/ethernet/mellanox/mlxsw/core_linecards.c
drivers/net/ethernet/mellanox/mlxsw/i2c.c
drivers/net/ethernet/mellanox/mlxsw/minimal.c
drivers/net/ethernet/mellanox/mlxsw/pci.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
drivers/net/ethernet/micrel/ks8851_common.c
drivers/net/ethernet/micrel/ks8851_spi.c
drivers/net/ethernet/micrel/ksz884x.c
drivers/net/ethernet/microchip/enc28j60.c
drivers/net/ethernet/microchip/encx24j600.c
drivers/net/ethernet/microchip/lan743x_ethtool.c
drivers/net/ethernet/microchip/lan966x/Kconfig
drivers/net/ethernet/microchip/lan966x/Makefile
drivers/net/ethernet/microchip/lan966x/lan966x_fdb.c
drivers/net/ethernet/microchip/lan966x/lan966x_fdma.c
drivers/net/ethernet/microchip/lan966x/lan966x_lag.c [new file with mode: 0644]
drivers/net/ethernet/microchip/lan966x/lan966x_mac.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_main.h
drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
drivers/net/ethernet/microchip/lan966x/lan966x_port.c
drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
drivers/net/ethernet/microchip/lan966x/lan966x_switchdev.c
drivers/net/ethernet/microchip/sparx5/sparx5_main.c
drivers/net/ethernet/microchip/sparx5/sparx5_main.h
drivers/net/ethernet/microchip/sparx5/sparx5_packet.c
drivers/net/ethernet/microchip/sparx5/sparx5_switchdev.c
drivers/net/ethernet/microchip/sparx5/sparx5_vlan.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/myricom/myri10ge/myri10ge.c
drivers/net/ethernet/natsemi/natsemi.c
drivers/net/ethernet/natsemi/ns83820.c
drivers/net/ethernet/neterion/s2io.c
drivers/net/ethernet/netronome/nfp/flower/offload.c
drivers/net/ethernet/netronome/nfp/flower/qos_conf.c
drivers/net/ethernet/netronome/nfp/nfp_main.h
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.c
drivers/net/ethernet/netronome/nfp/nfp_net_ctrl.h
drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
drivers/net/ethernet/netronome/nfp/nfp_net_main.c
drivers/net/ethernet/netronome/nfp/nfp_port.h
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c
drivers/net/ethernet/ni/nixge.c
drivers/net/ethernet/nvidia/forcedeth.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
drivers/net/ethernet/packetengines/hamachi.c
drivers/net/ethernet/packetengines/yellowfin.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_ethtool.c
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qede/qede_ethtool.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qualcomm/qca_debug.c
drivers/net/ethernet/rdc/r6040.c
drivers/net/ethernet/realtek/8139cp.c
drivers/net/ethernet/realtek/8139too.c
drivers/net/ethernet/realtek/r8169.h
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/realtek/r8169_phy_config.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/efx_common.c
drivers/net/ethernet/sfc/ethtool_common.c
drivers/net/ethernet/sfc/falcon/efx.c
drivers/net/ethernet/sfc/falcon/ethtool.c
drivers/net/ethernet/sfc/falcon/falcon.c
drivers/net/ethernet/sfc/falcon/nic.c
drivers/net/ethernet/sfc/mcdi_mon.c
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/siena/efx.c
drivers/net/ethernet/sfc/siena/efx_common.c
drivers/net/ethernet/sfc/siena/ethtool_common.c
drivers/net/ethernet/sfc/siena/mcdi_mon.c
drivers/net/ethernet/sfc/siena/nic.c
drivers/net/ethernet/sgi/ioc3-eth.c
drivers/net/ethernet/sis/sis190.c
drivers/net/ethernet/sis/sis900.c
drivers/net/ethernet/smsc/epic100.c
drivers/net/ethernet/smsc/smc911x.c
drivers/net/ethernet/smsc/smc91c92_cs.c
drivers/net/ethernet/smsc/smc91x.c
drivers/net/ethernet/smsc/smsc911x.c
drivers/net/ethernet/smsc/smsc9420.c
drivers/net/ethernet/socionext/netsec.c
drivers/net/ethernet/socionext/sni_ave.c
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/sun/cassini.c
drivers/net/ethernet/sun/ldmvsw.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/sun/sunbmac.c
drivers/net/ethernet/sun/sungem.c
drivers/net/ethernet/sun/sunhme.c
drivers/net/ethernet/sun/sunqe.c
drivers/net/ethernet/sun/sunvnet.c
drivers/net/ethernet/sunplus/spl2sw_driver.c
drivers/net/ethernet/synopsys/dwc-xlgmac-common.c
drivers/net/ethernet/synopsys/dwc-xlgmac-ethtool.c
drivers/net/ethernet/tehuti/tehuti.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/am65-cpsw-ethtool.c
drivers/net/ethernet/ti/am65-cpsw-nuss.c
drivers/net/ethernet/ti/am65-cpsw-nuss.h
drivers/net/ethernet/ti/cpmac.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/ethernet/ti/tlan.c
drivers/net/ethernet/toshiba/ps3_gelic_net.c
drivers/net/ethernet/toshiba/spider_net_ethtool.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/ethernet/vertexcom/mse102x.c
drivers/net/ethernet/via/via-rhine.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/ethernet/wangxun/Kconfig
drivers/net/ethernet/wangxun/Makefile
drivers/net/ethernet/wangxun/ngbe/Makefile [new file with mode: 0644]
drivers/net/ethernet/wangxun/ngbe/ngbe.h [new file with mode: 0644]
drivers/net/ethernet/wangxun/ngbe/ngbe_main.c [new file with mode: 0644]
drivers/net/ethernet/wangxun/ngbe/ngbe_type.h [new file with mode: 0644]
drivers/net/ethernet/wiznet/w5100.c
drivers/net/ethernet/wiznet/w5300.c
drivers/net/ethernet/xilinx/xilinx_axienet.h
drivers/net/ethernet/xilinx/xilinx_axienet_main.c
drivers/net/ethernet/xilinx/xilinx_emaclite.c
drivers/net/ethernet/xircom/xirc2ps_cs.c
drivers/net/ethernet/xscale/ixp4xx_eth.c
drivers/net/fjes/fjes_ethtool.c
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/hamradio/hdlcdrv.c
drivers/net/hyperv/netvsc_drv.c
drivers/net/ieee802154/adf7242.c
drivers/net/ieee802154/ca8210.c
drivers/net/ieee802154/cc2520.c
drivers/net/ieee802154/mac802154_hwsim.c
drivers/net/ipa/gsi.h
drivers/net/ipa/gsi_trans.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/macsec.c
drivers/net/macvlan.c
drivers/net/net_failover.c
drivers/net/netconsole.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/netdev.c
drivers/net/ntb_netdev.c
drivers/net/phy/adin.c
drivers/net/phy/at803x.c
drivers/net/phy/bcm-phy-lib.c
drivers/net/phy/broadcom.c
drivers/net/phy/marvell.c
drivers/net/phy/micrel.c
drivers/net/phy/mscc/mscc_main.c
drivers/net/phy/nxp-tja11xx.c
drivers/net/phy/phy-core.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/phy/realtek.c
drivers/net/phy/sfp.c
drivers/net/phy/smsc.c
drivers/net/rionet.c
drivers/net/team/team.c
drivers/net/thunderbolt.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/aqc111.c
drivers/net/usb/asix.h
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/catc.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/pegasus.c
drivers/net/usb/r8152.c
drivers/net/usb/rtl8150.c
drivers/net/usb/sierra_net.c
drivers/net/usb/usbnet.c
drivers/net/veth.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/vrf.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wireguard/netlink.c
drivers/net/wireless/ath/ath10k/core.c
drivers/net/wireless/ath/ath10k/htc.c
drivers/net/wireless/ath/ath10k/hw.h
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/init.c
drivers/net/wireless/ath/ath9k/htc_hst.c
drivers/net/wireless/ath/carl9170/fw.c
drivers/net/wireless/ath/wil6210/cfg80211.c
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/netdev.c
drivers/net/wireless/ath/wil6210/wmi.c
drivers/net/wireless/atmel/atmel.c
drivers/net/wireless/broadcom/b43/leds.c
drivers/net/wireless/broadcom/b43legacy/leds.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcdc.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/firmware.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pno.c
drivers/net/wireless/broadcom/brcm80211/brcmsmac/types.h
drivers/net/wireless/intel/ipw2x00/ipw2100.c
drivers/net/wireless/intel/ipw2x00/ipw2200.c
drivers/net/wireless/intel/iwlegacy/3945-mac.c
drivers/net/wireless/intersil/hostap/hostap_ioctl.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/marvell/libertas/cfg.c
drivers/net/wireless/marvell/libertas/ethtool.c
drivers/net/wireless/marvell/mwifiex/cfg80211.c
drivers/net/wireless/microchip/wilc1000/cfg80211.c
drivers/net/wireless/microchip/wilc1000/mon.c
drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
drivers/net/wireless/quantenna/qtnfmac/commands.c
drivers/net/wireless/realtek/rtl818x/rtl8187/leds.c
drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_core.c
drivers/net/wireless/realtek/rtlwifi/rtl8192de/phy.c
drivers/net/wireless/realtek/rtw88/bf.c
drivers/net/wireless/realtek/rtw88/coex.c
drivers/net/wireless/realtek/rtw88/coex.h
drivers/net/wireless/realtek/rtw88/debug.c
drivers/net/wireless/realtek/rtw88/efuse.c
drivers/net/wireless/realtek/rtw88/fw.c
drivers/net/wireless/realtek/rtw88/fw.h
drivers/net/wireless/realtek/rtw88/mac.c
drivers/net/wireless/realtek/rtw88/mac80211.c
drivers/net/wireless/realtek/rtw88/main.c
drivers/net/wireless/realtek/rtw88/main.h
drivers/net/wireless/realtek/rtw88/pci.c
drivers/net/wireless/realtek/rtw88/phy.c
drivers/net/wireless/realtek/rtw88/phy.h
drivers/net/wireless/realtek/rtw88/ps.c
drivers/net/wireless/realtek/rtw88/regd.c
drivers/net/wireless/realtek/rtw88/rtw8723d.c
drivers/net/wireless/realtek/rtw88/rtw8821c.c
drivers/net/wireless/realtek/rtw88/rtw8822b.c
drivers/net/wireless/realtek/rtw88/rtw8822c.c
drivers/net/wireless/realtek/rtw88/tx.c
drivers/net/wireless/realtek/rtw88/util.c
drivers/net/wireless/realtek/rtw89/Makefile
drivers/net/wireless/realtek/rtw89/chan.c [new file with mode: 0644]
drivers/net/wireless/realtek/rtw89/chan.h [new file with mode: 0644]
drivers/net/wireless/realtek/rtw89/coex.c
drivers/net/wireless/realtek/rtw89/coex.h
drivers/net/wireless/realtek/rtw89/core.c
drivers/net/wireless/realtek/rtw89/core.h
drivers/net/wireless/realtek/rtw89/debug.c
drivers/net/wireless/realtek/rtw89/fw.c
drivers/net/wireless/realtek/rtw89/fw.h
drivers/net/wireless/realtek/rtw89/mac.c
drivers/net/wireless/realtek/rtw89/mac.h
drivers/net/wireless/realtek/rtw89/mac80211.c
drivers/net/wireless/realtek/rtw89/pci.c
drivers/net/wireless/realtek/rtw89/pci.h
drivers/net/wireless/realtek/rtw89/phy.c
drivers/net/wireless/realtek/rtw89/phy.h
drivers/net/wireless/realtek/rtw89/ps.c
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/regd.c
drivers/net/wireless/realtek/rtw89/rtw8852a.c
drivers/net/wireless/realtek/rtw89/rtw8852a_rfk.c
drivers/net/wireless/realtek/rtw89/rtw8852c.c
drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.h
drivers/net/wireless/realtek/rtw89/rtw8852c_table.c
drivers/net/wireless/realtek/rtw89/sar.c
drivers/net/wireless/realtek/rtw89/ser.c
drivers/net/wireless/rndis_wlan.c
drivers/net/wireless/silabs/wfx/main.c
drivers/net/wireless/wl3501_cs.c
drivers/of/base.c
drivers/phy/microchip/lan966x_serdes.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/storvsc_drv.c
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
drivers/staging/wlan-ng/cfg80211.c
drivers/target/target_core_user.c
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_netlink.c
drivers/thunderbolt/nhi.c
drivers/thunderbolt/tb.c
drivers/thunderbolt/tb.h
drivers/thunderbolt/usb4.c
drivers/thunderbolt/usb4_port.c
drivers/ufs/core/ufshcd.c
drivers/ufs/host/ufs-exynos.c
drivers/vdpa/vdpa.c
drivers/video/console/sticore.c
drivers/video/fbdev/aty/atyfb_base.c
drivers/video/fbdev/aty/radeon_base.c
drivers/video/fbdev/bw2.c
drivers/video/fbdev/chipsfb.c
drivers/video/fbdev/cirrusfb.c
drivers/video/fbdev/clps711x-fb.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbsysfs.c
drivers/video/fbdev/cyber2000fb.c
drivers/video/fbdev/ffb.c
drivers/video/fbdev/geode/gx1fb_core.c
drivers/video/fbdev/gxt4500.c
drivers/video/fbdev/i740fb.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/matrox/matroxfb_base.c
drivers/video/fbdev/omap/omapfb_main.c
drivers/video/fbdev/omap2/omapfb/omapfb-main.c
drivers/video/fbdev/pm2fb.c
drivers/video/fbdev/pxa168fb.c
drivers/video/fbdev/pxafb.c
drivers/video/fbdev/s3fb.c
drivers/video/fbdev/simplefb.c
drivers/video/fbdev/sis/sis_main.c
drivers/video/fbdev/sm501fb.c
drivers/video/fbdev/ssd1307fb.c
drivers/video/fbdev/sstfb.c
drivers/video/fbdev/sunxvr1000.c
drivers/video/fbdev/sunxvr2500.c
drivers/video/fbdev/sunxvr500.c
drivers/video/fbdev/tcx.c
drivers/video/fbdev/tdfxfb.c
drivers/video/fbdev/tgafb.c
drivers/video/fbdev/tridentfb.c
drivers/xen/privcmd.c
drivers/xen/xen-scsiback.c
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/ctree.h
fs/btrfs/dev-replace.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/root-tree.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/cachefiles/internal.h
fs/cachefiles/ondemand.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/netlink.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/transport.c
fs/dlm/netlink.c
fs/fs-writeback.c
fs/ksmbd/transport_ipc.c
fs/ocfs2/dlmglue.c
fs/ocfs2/super.c
fs/squashfs/file.c
fs/squashfs/file_direct.c
fs/squashfs/page_actor.c
fs/squashfs/page_actor.h
include/asm-generic/bitops/generic-non-atomic.h
include/asm-generic/bitops/instrumented-non-atomic.h
include/asm-generic/bitops/non-atomic.h
include/asm-generic/bitops/non-instrumented-non-atomic.h
include/asm-generic/sections.h
include/linux/bitops.h
include/linux/bpf.h
include/linux/brcmphy.h
include/linux/btf.h
include/linux/buffer_head.h
include/linux/compiler.h
include/linux/compiler_attributes.h
include/linux/etherdevice.h
include/linux/fscache.h
include/linux/genl_magic_func.h
include/linux/ieee80211.h
include/linux/lsm_hook_defs.h
include/linux/lsm_hooks.h
include/linux/memcontrol.h
include/linux/mm.h
include/linux/netdevice.h
include/linux/netfilter.h
include/linux/netfilter_defs.h
include/linux/netlink.h
include/linux/overflow.h
include/linux/phy.h
include/linux/rmap.h
include/linux/security.h
include/linux/skbuff.h
include/linux/stmmac.h
include/linux/thunderbolt.h
include/linux/trace_events.h
include/linux/wait_bit.h
include/net/af_vsock.h
include/net/cfg80211.h
include/net/devlink.h
include/net/dn.h [deleted file]
include/net/dn_dev.h [deleted file]
include/net/dn_fib.h [deleted file]
include/net/dn_neigh.h [deleted file]
include/net/dn_nsp.h [deleted file]
include/net/dn_route.h [deleted file]
include/net/dsa.h
include/net/genetlink.h
include/net/gro.h
include/net/inet_connection_sock.h
include/net/inet_hashtables.h
include/net/ip_tunnels.h
include/net/mac80211.h
include/net/macsec.h
include/net/netfilter/nf_conntrack_core.h
include/net/netlink.h
include/net/netns/ipv4.h
include/net/netns/netfilter.h
include/net/nl802154.h
include/net/pkt_sched.h
include/net/red.h
include/net/sch_generic.h
include/net/sock.h
include/soc/mscc/ocelot.h
include/uapi/linux/bpf.h
include/uapi/linux/dn.h [deleted file]
include/uapi/linux/if_macsec.h
include/uapi/linux/in.h
include/uapi/linux/io_uring.h
include/uapi/linux/netfilter_decnet.h [deleted file]
include/uapi/linux/netlink.h
include/uapi/linux/nl80211.h
include/uapi/linux/openvswitch.h
include/uapi/linux/virtio_net.h
include/ufs/ufshci.h
init/main.c
io_uring/cancel.c
io_uring/io_uring.c
io_uring/net.c
io_uring/net.h
io_uring/notif.c
io_uring/opdef.c
io_uring/opdef.h
io_uring/uring_cmd.c
kernel/auditsc.c
kernel/bpf/bpf_iter.c
kernel/bpf/bpf_local_storage.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/core.c
kernel/bpf/cpumap.c
kernel/bpf/devmap.c
kernel/bpf/hashtab.c
kernel/bpf/helpers.c
kernel/bpf/local_storage.c
kernel/bpf/lpm_trie.c
kernel/bpf/offload.c
kernel/bpf/queue_stack_maps.c
kernel/bpf/ringbuf.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/crash_core.c
kernel/sched/wait_bit.c
kernel/taskstats.c
lib/Kconfig.debug
lib/Makefile
lib/cpumask_kunit.c [new file with mode: 0644]
lib/crypto/Kconfig
lib/test_cpumask.c [deleted file]
mm/backing-dev.c
mm/bootmem_info.c
mm/damon/dbgfs.c
mm/hugetlb.c
mm/mprotect.c
mm/page-writeback.c
mm/rmap.c
mm/shmem.c
mm/slab_common.c
mm/zsmalloc.c
net/8021q/vlan_core.c
net/8021q/vlan_dev.c
net/Kconfig
net/Makefile
net/ax25/af_ax25.c
net/batman-adv/netlink.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/hidp/core.c
net/bluetooth/iso.c
net/bluetooth/l2cap_core.c
net/bluetooth/mgmt.c
net/bpf/test_run.c
net/bridge/br_device.c
net/bridge/br_if.c
net/bridge/br_sysfs_if.c
net/bridge/netfilter/ebtables.c
net/caif/caif_dev.c
net/caif/caif_usb.c
net/caif/cfcnfg.c
net/caif/cfctrl.c
net/core/dev.c
net/core/devlink.c
net/core/drop_monitor.c
net/core/neighbour.c
net/core/netclassid_cgroup.c
net/core/netpoll.c
net/core/rtnetlink.c
net/core/skbuff.c
net/core/skmsg.c
net/core/sock_map.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/dccp/proto.c
net/decnet/Kconfig [deleted file]
net/decnet/Makefile [deleted file]
net/decnet/README [deleted file]
net/decnet/af_decnet.c [deleted file]
net/decnet/dn_dev.c [deleted file]
net/decnet/dn_fib.c [deleted file]
net/decnet/dn_neigh.c [deleted file]
net/decnet/dn_nsp_in.c [deleted file]
net/decnet/dn_nsp_out.c [deleted file]
net/decnet/dn_route.c [deleted file]
net/decnet/dn_rules.c [deleted file]
net/decnet/dn_table.c [deleted file]
net/decnet/dn_timer.c [deleted file]
net/decnet/netfilter/Kconfig [deleted file]
net/decnet/netfilter/Makefile [deleted file]
net/decnet/netfilter/dn_rtmsg.c [deleted file]
net/decnet/sysctl_net_decnet.c [deleted file]
net/dsa/dsa2.c
net/dsa/dsa_priv.h
net/dsa/master.c
net/dsa/port.c
net/dsa/slave.c
net/dsa/tag_8021q.c
net/dsa/tag_hellcreek.c
net/ethernet/eth.c
net/ethtool/ioctl.c
net/ethtool/netlink.c
net/ethtool/strset.c
net/hsr/hsr_netlink.c
net/ieee802154/netlink.c
net/ieee802154/nl802154.c
net/ipv4/af_inet.c
net/ipv4/arp.c
net/ipv4/datagram.c
net/ipv4/fib_frontend.c
net/ipv4/fou.c
net/ipv4/gre_offload.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_tunnel.c
net/ipv4/tcp.c
net/ipv4/tcp_fastopen.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_offload.c
net/ipv4/tcp_timer.c
net/ipv6/ila/ila_main.c
net/ipv6/ioam6.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/seg6.c
net/ipv6/sit.c
net/ipv6/tcp_ipv6.c
net/kcm/kcmsock.c
net/l2tp/l2tp_eth.c
net/l2tp/l2tp_netlink.c
net/mac80211/Makefile
net/mac80211/cfg.c
net/mac80211/eht.c
net/mac80211/ethtool.c
net/mac80211/ibss.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/link.c [new file with mode: 0644]
net/mac80211/main.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/scan.c
net/mac80211/sta_info.c
net/mac80211/tx.c
net/mac80211/util.c
net/mac802154/rx.c
net/mpls/af_mpls.c
net/mptcp/pm_netlink.c
net/ncsi/ncsi-netlink.c
net/netfilter/core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nfnetlink_hook.c
net/netlabel/netlabel_calipso.c
net/netlabel/netlabel_cipso_v4.c
net/netlabel/netlabel_mgmt.c
net/netlabel/netlabel_unlabeled.c
net/netlink/af_netlink.c
net/netlink/genetlink.c
net/nfc/netlink.c
net/openvswitch/conntrack.c
net/openvswitch/datapath.c
net/openvswitch/meter.c
net/openvswitch/vport-internal_dev.c
net/openvswitch/vport.h
net/packet/af_packet.c
net/psample/psample.c
net/rds/message.c
net/sched/cls_api.c
net/sched/cls_route.c
net/sched/sch_api.c
net/sched/sch_atm.c
net/sched/sch_cake.c
net/sched/sch_cbq.c
net/sched/sch_choke.c
net/sched/sch_codel.c
net/sched/sch_drr.c
net/sched/sch_dsmark.c
net/sched/sch_etf.c
net/sched/sch_ets.c
net/sched/sch_fq.c
net/sched/sch_fq_codel.c
net/sched/sch_fq_pie.c
net/sched/sch_generic.c
net/sched/sch_gred.c
net/sched/sch_hfsc.c
net/sched/sch_hhf.c
net/sched/sch_htb.c
net/sched/sch_multiq.c
net/sched/sch_netem.c
net/sched/sch_pie.c
net/sched/sch_plug.c
net/sched/sch_prio.c
net/sched/sch_qfq.c
net/sched/sch_red.c
net/sched/sch_sfb.c
net/sched/sch_skbprio.c
net/sched/sch_taprio.c
net/sched/sch_tbf.c
net/sched/sch_teql.c
net/smc/af_smc.c
net/smc/smc_netlink.c
net/smc/smc_pnet.c
net/tipc/netlink.c
net/tipc/netlink_compat.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/hyperv_transport.c
net/vmw_vsock/virtio_transport_common.c
net/vmw_vsock/vmci_transport_notify.c
net/vmw_vsock/vmci_transport_notify_qstate.c
net/wireless/core.c
net/wireless/ibss.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/reg.c
net/wireless/scan.c
net/wireless/sme.c
net/wireless/trace.h
net/wireless/util.c
net/wireless/wext-compat.c
net/xdp/xsk_buff_pool.c
security/security.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/smack/smack_lsm.c
sound/core/control.c
sound/core/memalloc.c
sound/core/seq/oss/seq_oss_midi.c
sound/core/seq/seq_clientmgr.c
sound/hda/intel-nhlt.c
sound/pci/hda/patch_realtek.c
sound/usb/quirks.c
tools/arch/arm64/include/uapi/asm/kvm.h
tools/bpf/bpftool/common.c
tools/bpf/bpftool/feature.c
tools/bpf/bpftool/main.c
tools/include/uapi/linux/bpf.h
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf_tracing.h
tools/lib/bpf/btf.c
tools/lib/bpf/btf.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf.h
tools/lib/bpf/libbpf.map
tools/lib/bpf/libbpf_internal.h
tools/lib/bpf/libbpf_legacy.h
tools/lib/bpf/libbpf_probes.c
tools/lib/bpf/netlink.c
tools/lib/bpf/skel_internal.h
tools/lib/bpf/usdt.bpf.h
tools/objtool/check.c
tools/perf/Documentation/intel-hybrid.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Makefile.config
tools/perf/builtin-sched.c
tools/perf/builtin-stat.c
tools/perf/tests/shell/stat.sh
tools/perf/util/stat-shadow.c
tools/testing/selftests/bpf/DENYLIST.s390x
tools/testing/selftests/bpf/config
tools/testing/selftests/bpf/prog_tests/attach_probe.c
tools/testing/selftests/bpf/prog_tests/autoattach.c [new file with mode: 0644]
tools/testing/selftests/bpf/prog_tests/bpf_cookie.c
tools/testing/selftests/bpf/prog_tests/bpf_nf.c
tools/testing/selftests/bpf/prog_tests/dynptr.c
tools/testing/selftests/bpf/prog_tests/kfunc_call.c
tools/testing/selftests/bpf/prog_tests/task_pt_regs.c
tools/testing/selftests/bpf/prog_tests/time_tai.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/dynptr_fail.c
tools/testing/selftests/bpf/progs/kfunc_call_destructive.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/lsm.c
tools/testing/selftests/bpf/progs/test_autoattach.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_bpf_cookie.c
tools/testing/selftests/bpf/progs/test_bpf_nf.c
tools/testing/selftests/bpf/progs/test_helper_restricted.c
tools/testing/selftests/bpf/progs/test_time_tai.c [new file with mode: 0644]
tools/testing/selftests/bpf/verifier/precise.c
tools/testing/selftests/bpf/vmtest.sh
tools/testing/selftests/bpf/xskxceiver.c
tools/testing/selftests/bpf/xskxceiver.h
tools/testing/selftests/drivers/net/dsa/Makefile
tools/testing/selftests/drivers/net/dsa/tc_actions.sh [new symlink]
tools/testing/selftests/drivers/net/dsa/tc_common.sh [new symlink]
tools/testing/selftests/drivers/net/mlxsw/egress_vid_classification.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_1d.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_1q.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_vxlan.sh [new file with mode: 0755]
tools/testing/selftests/net/.gitignore
tools/testing/selftests/net/Makefile
tools/testing/selftests/net/bind_bhash.c [new file with mode: 0644]
tools/testing/selftests/net/bind_bhash.sh [new file with mode: 0755]
tools/testing/selftests/net/fcnal-test.sh
tools/testing/selftests/net/l2_tos_ttl_inherit.sh [new file with mode: 0755]
tools/testing/selftests/net/nettest.c
tools/testing/selftests/net/sk_bind_sendto_listen.c [new file with mode: 0644]
tools/testing/selftests/net/sk_connect_zero_addr.c [new file with mode: 0644]
tools/testing/vsock/vsock_test.c

index 38255d4..8ded2e7 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -98,8 +98,7 @@ Christian Brauner <brauner@kernel.org> <christian.brauner@ubuntu.com>
 Christian Marangi <ansuelsmth@gmail.com>
 Christophe Ricard <christophe.ricard@gmail.com>
 Christoph Hellwig <hch@lst.de>
-Colin Ian King <colin.king@intel.com> <colin.king@canonical.com>
-Colin Ian King <colin.king@intel.com> <colin.i.king@gmail.com>
+Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
 Corey Minyard <minyard@acm.org>
 Damian Hobson-Garcia <dhobsong@igel.co.jp>
 Daniel Borkmann <daniel@iogearbox.net> <danborkmann@googlemail.com>
@@ -150,6 +149,8 @@ Greg Kroah-Hartman <gregkh@suse.de>
 Greg Kroah-Hartman <greg@kroah.com>
 Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
 Gregory CLEMENT <gregory.clement@bootlin.com> <gregory.clement@free-electrons.com>
+Guilherme G. Piccoli <kernel@gpiccoli.net> <gpiccoli@linux.vnet.ibm.com>
+Guilherme G. Piccoli <kernel@gpiccoli.net> <gpiccoli@canonical.com>
 Guo Ren <guoren@kernel.org> <guoren@linux.alibaba.com>
 Guo Ren <guoren@kernel.org> <ren_guo@c-sky.com>
 Gustavo Padovan <gustavo@las.ic.unicamp.br>
@@ -253,6 +254,7 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
 Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
 Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
 Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com>
+Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
 Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
 Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
 Maciej W. Rozycki <macro@orcam.me.uk> <macro@linux-mips.org>
index 5bf6188..760c889 100644 (file)
@@ -523,6 +523,7 @@ What:               /sys/devices/system/cpu/vulnerabilities
                /sys/devices/system/cpu/vulnerabilities/tsx_async_abort
                /sys/devices/system/cpu/vulnerabilities/itlb_multihit
                /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
+               /sys/devices/system/cpu/vulnerabilities/retbleed
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:   Information about CPU vulnerabilities
index caa3c09..9eb6b90 100644 (file)
@@ -1,9 +1,9 @@
 .. _readme:
 
-Linux kernel release 5.x <http://kernel.org/>
+Linux kernel release 6.x <http://kernel.org/>
 =============================================
 
-These are the release notes for Linux version 5.  Read them carefully,
+These are the release notes for Linux version 6.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong.
 
@@ -63,7 +63,7 @@ Installing the kernel source
    directory where you have permissions (e.g. your home directory) and
    unpack it::
 
-     xz -cd linux-5.x.tar.xz | tar xvf -
+     xz -cd linux-6.x.tar.xz | tar xvf -
 
    Replace "X" with the version number of the latest kernel.
 
@@ -72,12 +72,12 @@ Installing the kernel source
    files.  They should match the library, and not get messed up by
    whatever the kernel-du-jour happens to be.
 
- - You can also upgrade between 5.x releases by patching.  Patches are
+ - You can also upgrade between 6.x releases by patching.  Patches are
    distributed in the xz format.  To install by patching, get all the
    newer patch files, enter the top level directory of the kernel source
-   (linux-5.x) and execute::
+   (linux-6.x) and execute::
 
-     xz -cd ../patch-5.x.xz | patch -p1
+     xz -cd ../patch-6.x.xz | patch -p1
 
    Replace "x" for all versions bigger than the version "x" of your current
    source tree, **in_order**, and you should be ok.  You may want to remove
@@ -85,13 +85,13 @@ Installing the kernel source
    that there are no failed patches (some-file-name# or some-file-name.rej).
    If there are, either you or I have made a mistake.
 
-   Unlike patches for the 5.x kernels, patches for the 5.x.y kernels
+   Unlike patches for the 6.x kernels, patches for the 6.x.y kernels
    (also known as the -stable kernels) are not incremental but instead apply
-   directly to the base 5.x kernel.  For example, if your base kernel is 5.0
-   and you want to apply the 5.0.3 patch, you must not first apply the 5.0.1
-   and 5.0.2 patches. Similarly, if you are running kernel version 5.0.2 and
-   want to jump to 5.0.3, you must first reverse the 5.0.2 patch (that is,
-   patch -R) **before** applying the 5.0.3 patch. You can read more on this in
+   directly to the base 6.x kernel.  For example, if your base kernel is 6.0
+   and you want to apply the 6.0.3 patch, you must not first apply the 6.0.1
+   and 6.0.2 patches. Similarly, if you are running kernel version 6.0.2 and
+   want to jump to 6.0.3, you must first reverse the 6.0.2 patch (that is,
+   patch -R) **before** applying the 6.0.3 patch. You can read more on this in
    :ref:`Documentation/process/applying-patches.rst <applying_patches>`.
 
    Alternatively, the script patch-kernel can be used to automate this
@@ -114,7 +114,7 @@ Installing the kernel source
 Software requirements
 ---------------------
 
-   Compiling and running the 5.x kernels requires up-to-date
+   Compiling and running the 6.x kernels requires up-to-date
    versions of various software packages.  Consult
    :ref:`Documentation/process/changes.rst <changes>` for the minimum version numbers
    required and how to get updates for these packages.  Beware that using
@@ -132,12 +132,12 @@ Build directory for the kernel
    place for the output files (including .config).
    Example::
 
-     kernel source code: /usr/src/linux-5.x
+     kernel source code: /usr/src/linux-6.x
      build directory:    /home/name/build/kernel
 
    To configure and build the kernel, use::
 
-     cd /usr/src/linux-5.x
+     cd /usr/src/linux-6.x
      make O=/home/name/build/kernel menuconfig
      make O=/home/name/build/kernel
      sudo make O=/home/name/build/kernel modules_install install
index 9393c50..c98fd11 100644 (file)
@@ -230,6 +230,20 @@ The possible values in this file are:
      * - 'Mitigation: Clear CPU buffers'
        - The processor is vulnerable and the CPU buffer clearing mitigation is
          enabled.
+     * - 'Unknown: No mitigations'
+       - The processor vulnerability status is unknown because it is
+        out of Servicing period. Mitigation is not attempted.
+
+Definitions:
+------------
+
+Servicing period: The process of providing functional and security updates to
+Intel processors or platforms, utilizing the Intel Platform Update (IPU)
+process or other similar mechanisms.
+
+End of Servicing Updates (ESU): ESU is the date at which Intel will no
+longer provide Servicing, such as through IPU or other similar update
+processes. ESU dates will typically be aligned to end of quarter.
 
 If the processor is vulnerable then the following information is appended to
 the above information:
index d7f3090..a6d3c7b 100644 (file)
 
        debugpat        [X86] Enable PAT debugging
 
-       decnet.addr=    [HW,NET]
-                       Format: <area>[,<node>]
-                       See also Documentation/networking/decnet.rst.
-
        default_hugepagesz=
                        [HW] The size of the default HugeTLB page. This is
                        the size represented by the legacy /proc/ hugepages
        rodata=         [KNL]
                on      Mark read-only kernel memory as read-only (default).
                off     Leave read-only kernel memory writable for debugging.
+               full    Mark read-only kernel memory and aliases as read-only
+                       [arm64]
 
        rockchip.usb_uart
                        Enable the uart passthrough on the designated usb port
index d52f572..ca91ecc 100644 (file)
@@ -50,10 +50,10 @@ For a short example, users can monitor the virtual address space of a given
 workload as below. ::
 
     # cd /sys/kernel/mm/damon/admin/
-    # echo 1 > kdamonds/nr && echo 1 > kdamonds/0/contexts/nr
+    # echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
     # echo vaddr > kdamonds/0/contexts/0/operations
-    # echo 1 > kdamonds/0/contexts/0/targets/nr
-    # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid
+    # echo 1 > kdamonds/0/contexts/0/targets/nr_targets
+    # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
     # echo on > kdamonds/0/state
 
 Files Hierarchy
@@ -366,12 +366,12 @@ memory rate becomes larger than 60%, or lower than 30%". ::
     # echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
     # cd kdamonds/0/contexts/0/schemes/0
     # # set the basic access pattern and the action
-    # echo 4096 > access_patterns/sz/min
-    # echo 8192 > access_patterns/sz/max
-    # echo 0 > access_patterns/nr_accesses/min
-    # echo 5 > access_patterns/nr_accesses/max
-    # echo 10 > access_patterns/age/min
-    # echo 20 > access_patterns/age/max
+    # echo 4096 > access_pattern/sz/min
+    # echo 8192 > access_pattern/sz/max
+    # echo 0 > access_pattern/nr_accesses/min
+    # echo 5 > access_pattern/nr_accesses/max
+    # echo 10 > access_pattern/age/min
+    # echo 20 > access_pattern/age/max
     # echo pageout > action
     # # set quotas
     # echo 10 > quotas/ms
index 60d4416..555681e 100644 (file)
@@ -31,17 +31,18 @@ see only some of them, depending on your kernel's configuration.
 
 Table : Subdirectories in /proc/sys/net
 
- ========= =================== = ========== ==================
+ ========= =================== = ========== ===================
  Directory Content               Directory  Content
- ========= =================== = ========== ==================
- core      General parameter     appletalk  Appletalk protocol
- unix      Unix domain sockets   netrom     NET/ROM
- 802       E802 protocol         ax25       AX25
- ethernet  Ethernet protocol     rose       X.25 PLP layer
+ ========= =================== = ========== ===================
+ 802       E802 protocol         mptcp      Multipath TCP
+ appletalk Appletalk protocol    netfilter  Network Filter
+ ax25      AX25                  netrom     NET/ROM
+ bridge    Bridging              rose       X.25 PLP layer
+ core      General parameter     tipc       TIPC
+ ethernet  Ethernet protocol     unix       Unix domain sockets
  ipv4      IP version 4          x25        X.25 protocol
- bridge    Bridging              decnet     DEC net
- ipv6      IP version 6          tipc       TIPC
- ========= =================== = ========== ==================
+ ipv6      IP version 6
+ ========= =================== = ========== ===================
 
 1. /proc/sys/net/core - Network core options
 ============================================
index 52b75a2..311021f 100644 (file)
@@ -242,44 +242,34 @@ HWCAP2_MTE3
     by Documentation/arm64/memory-tagging-extension.rst.
 
 HWCAP2_SME
-
     Functionality implied by ID_AA64PFR1_EL1.SME == 0b0001, as described
     by Documentation/arm64/sme.rst.
 
 HWCAP2_SME_I16I64
-
     Functionality implied by ID_AA64SMFR0_EL1.I16I64 == 0b1111.
 
 HWCAP2_SME_F64F64
-
     Functionality implied by ID_AA64SMFR0_EL1.F64F64 == 0b1.
 
 HWCAP2_SME_I8I32
-
     Functionality implied by ID_AA64SMFR0_EL1.I8I32 == 0b1111.
 
 HWCAP2_SME_F16F32
-
     Functionality implied by ID_AA64SMFR0_EL1.F16F32 == 0b1.
 
 HWCAP2_SME_B16F32
-
     Functionality implied by ID_AA64SMFR0_EL1.B16F32 == 0b1.
 
 HWCAP2_SME_F32F32
-
     Functionality implied by ID_AA64SMFR0_EL1.F32F32 == 0b1.
 
 HWCAP2_SME_FA64
-
     Functionality implied by ID_AA64SMFR0_EL1.FA64 == 0b1.
 
 HWCAP2_WFXT
-
     Functionality implied by ID_AA64ISAR2_EL1.WFXT == 0b0010.
 
 HWCAP2_EBF16
-
     Functionality implied by ID_AA64ISAR1_EL1.BF16 == 0b0010.
 
 4. Unused AT_HWCAP bits
index 33b04db..fda97b3 100644 (file)
@@ -52,6 +52,8 @@ stable kernels.
 | Allwinner      | A64/R18         | UNKNOWN1        | SUN50I_ERRATUM_UNKNOWN1     |
 +----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A510     | #2457168        | ARM64_ERRATUM_2457168       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A510     | #2064142        | ARM64_ERRATUM_2064142       |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A510     | #2038923        | ARM64_ERRATUM_2038923       |
index d8b101c..edea465 100644 (file)
@@ -58,13 +58,11 @@ Like with atomic_t, the rule of thumb is:
 
  - RMW operations that have a return value are fully ordered.
 
- - RMW operations that are conditional are unordered on FAILURE,
-   otherwise the above rules apply. In the case of test_and_set_bit_lock(),
-   if the bit in memory is unchanged by the operation then it is deemed to have
-   failed.
+ - RMW operations that are conditional are fully ordered.
 
-Except for a successful test_and_set_bit_lock() which has ACQUIRE semantics and
-clear_bit_unlock() which has RELEASE semantics.
+Except for a successful test_and_set_bit_lock() which has ACQUIRE semantics,
+clear_bit_unlock() which has RELEASE semantics and test_bit_acquire which has
+ACQUIRE semantics.
 
 Since a platform only has a single means of achieving atomic operations
 the same barriers as for atomic_t are used, see atomic_t.txt.
index c0b7dae..7817317 100644 (file)
@@ -146,6 +146,21 @@ that operate (change some property, perform some operation) on an object that
 was obtained using an acquire kfunc. Such kfuncs need an unchanged pointer to
 ensure the integrity of the operation being performed on the expected object.
 
+2.4.6 KF_SLEEPABLE flag
+-----------------------
+
+The KF_SLEEPABLE flag is used for kfuncs that may sleep. Such kfuncs can only
+be called by sleepable BPF programs (BPF_F_SLEEPABLE).
+
+2.4.7 KF_DESTRUCTIVE flag
+--------------------------
+
+The KF_DESTRUCTIVE flag is used to indicate functions calling which is
+destructive to the system. For example such a call can result in system
+rebooting or panicking. Due to this additional restrictions apply to these
+calls. At the moment they only require CAP_SYS_BOOT capability, but more can be
+added later.
+
 2.5 Registering the kfuncs
 --------------------------
 
index 934727e..255384d 100644 (file)
@@ -86,6 +86,7 @@ if major >= 3:
             "__used",
             "__weak",
             "noinline",
+            "__fix_address",
 
             # include/linux/memblock.h:
             "__init_memblock",
index cc01b9b..253b5d1 100644 (file)
@@ -37,6 +37,7 @@ properties:
 patternProperties:
   "^ethernet-port@[0-9]+$":
     type: object
+    unevaluatedProperties: false
     description: contains the resources for ethernet port
     allOf:
       - $ref: ethernet-controller.yaml#
index 3f01b65..eb01a8f 100644 (file)
@@ -63,6 +63,8 @@ examples:
                     reg = <3>;
                     label = "cpu";
                     ethernet = <&fec1>;
+                    phy-mode = "rgmii-id";
+
                     fixed-link {
                         speed = <1000>;
                         full-duplex;
index 23114d6..2e01371 100644 (file)
@@ -254,6 +254,8 @@ examples:
                     ethernet = <&amac2>;
                     label = "cpu";
                     reg = <8>;
+                    phy-mode = "internal";
+
                     fixed-link {
                         speed = <1000>;
                         full-duplex;
index 09317e1..10ad7e7 100644 (file)
@@ -76,6 +76,23 @@ properties:
 required:
   - reg
 
+# CPU and DSA ports must have phylink-compatible link descriptions
+if:
+  oneOf:
+    - required: [ ethernet ]
+    - required: [ link ]
+then:
+  allOf:
+    - required:
+        - phy-mode
+    - oneOf:
+        - required:
+            - fixed-link
+        - required:
+            - phy-handle
+        - required:
+            - managed
+
 additionalProperties: true
 
 ...
index 2286837..1ff44dd 100644 (file)
@@ -93,6 +93,12 @@ examples:
                     reg = <0>;
                     label = "cpu";
                     ethernet = <&gmac0>;
+                    phy-mode = "mii";
+
+                    fixed-link {
+                        speed = <100>;
+                        full-duplex;
+                    };
                 };
 
                 port@2 {
index 17ab6c6..f9e7b6e 100644 (file)
@@ -4,67 +4,92 @@
 $id: http://devicetree.org/schemas/net/dsa/mediatek,mt7530.yaml#
 $schema: http://devicetree.org/meta-schemas/core.yaml#
 
-title: Mediatek MT7530 Ethernet switch
+title: Mediatek MT7530 and MT7531 Ethernet Switches
 
 maintainers:
-  - Sean Wang <sean.wang@mediatek.com>
+  - Arınç ÜNAL <arinc.unal@arinc9.com>
   - Landen Chao <Landen.Chao@mediatek.com>
   - DENG Qingfang <dqfext@gmail.com>
+  - Sean Wang <sean.wang@mediatek.com>
 
 description: |
-  Port 5 of mt7530 and mt7621 switch is muxed between:
-  1. GMAC5: GMAC5 can interface with another external MAC or PHY.
-  2. PHY of port 0 or port 4: PHY interfaces with an external MAC like 2nd GMAC
-     of the SOC. Used in many setups where port 0/4 becomes the WAN port.
-     Note: On a MT7621 SOC with integrated switch: 2nd GMAC can only connected to
-       GMAC5 when the gpios for RGMII2 (GPIO 22-33) are not used and not
-       connected to external component!
-
-  Port 5 modes/configurations:
-  1. Port 5 is disabled and isolated: An external phy can interface to the 2nd
-     GMAC of the SOC.
-     In the case of a build-in MT7530 switch, port 5 shares the RGMII bus with 2nd
-     GMAC and an optional external phy. Mind the GPIO/pinctl settings of the SOC!
-  2. Port 5 is muxed to PHY of port 0/4: Port 0/4 interfaces with 2nd GMAC.
-     It is a simple MAC to PHY interface, port 5 needs to be setup for xMII mode
-     and RGMII delay.
-  3. Port 5 is muxed to GMAC5 and can interface to an external phy.
-     Port 5 becomes an extra switch port.
-     Only works on platform where external phy TX<->RX lines are swapped.
-     Like in the Ubiquiti ER-X-SFP.
-  4. Port 5 is muxed to GMAC5 and interfaces with the 2nd GAMC as 2nd CPU port.
-     Currently a 2nd CPU port is not supported by DSA code.
-
-  Depending on how the external PHY is wired:
-  1. normal: The PHY can only connect to 2nd GMAC but not to the switch
-  2. swapped: RGMII TX, RX are swapped; external phy interface with the switch as
-     a ethernet port. But can't interface to the 2nd GMAC.
-
-    Based on the DT the port 5 mode is configured.
-
-  Driver tries to lookup the phy-handle of the 2nd GMAC of the master device.
-  When phy-handle matches PHY of port 0 or 4 then port 5 set-up as mode 2.
-  phy-mode must be set, see also example 2 below!
-  * mt7621: phy-mode = "rgmii-txid";
-  * mt7623: phy-mode = "rgmii";
-
-  CPU-Ports need a phy-mode property:
-    Allowed values on mt7530 and mt7621:
-      - "rgmii"
-      - "trgmii"
-    On mt7531:
-      - "1000base-x"
-      - "2500base-x"
-      - "rgmii"
-      - "sgmii"
+  There are two versions of MT7530, standalone and in a multi-chip module.
+
+  MT7530 is a part of the multi-chip module in MT7620AN, MT7620DA, MT7620DAN,
+  MT7620NN, MT7621AT, MT7621DAT, MT7621ST and MT7623AI SoCs.
+
+  MT7530 in MT7620AN, MT7620DA, MT7620DAN and MT7620NN SoCs has got 10/100 PHYs
+  and the switch registers are directly mapped into SoC's memory map rather than
+  using MDIO. The DSA driver currently doesn't support this.
+
+  There is only the standalone version of MT7531.
+
+  Port 5 on MT7530 has got various ways of configuration.
+
+  For standalone MT7530:
+
+    - Port 5 can be used as a CPU port.
+
+    - PHY 0 or 4 of the switch can be muxed to connect to the gmac of the SoC
+      which port 5 is wired to. Usually used for connecting the wan port
+      directly to the CPU to achieve 2 Gbps routing in total.
+
+      The driver looks up the reg on the ethernet-phy node which the phy-handle
+      property refers to on the gmac node to mux the specified phy.
+
+      The driver requires the gmac of the SoC to have "mediatek,eth-mac" as the
+      compatible string and the reg must be 1. So, for now, only gmac1 of an
+      MediaTek SoC can benefit this. Banana Pi BPI-R2 suits this.
+      Check out example 5 for a similar configuration.
+
+    - Port 5 can be wired to an external phy. Port 5 becomes a DSA slave.
+      Check out example 7 for a similar configuration.
+
+  For multi-chip module MT7530:
+
+    - Port 5 can be used as a CPU port.
+
+    - PHY 0 or 4 of the switch can be muxed to connect to gmac1 of the SoC.
+      Usually used for connecting the wan port directly to the CPU to achieve 2
+      Gbps routing in total.
+
+      The driver looks up the reg on the ethernet-phy node which the phy-handle
+      property refers to on the gmac node to mux the specified phy.
+
+      For the MT7621 SoCs, rgmii2 group must be claimed with rgmii2 function.
+      Check out example 5.
+
+    - In case of an external phy wired to gmac1 of the SoC, port 5 must not be
+      enabled.
+
+      In case of muxing PHY 0 or 4, the external phy must not be enabled.
+
+      For the MT7621 SoCs, rgmii2 group must be claimed with rgmii2 function.
+      Check out example 6.
 
+    - Port 5 can be muxed to an external phy. Port 5 becomes a DSA slave.
+      The external phy must be wired TX to TX to gmac1 of the SoC for this to
+      work. Ubiquiti EdgeRouter X SFP is wired this way.
+
+      Muxing PHY 0 or 4 won't work when the external phy is connected TX to TX.
+
+      For the MT7621 SoCs, rgmii2 group must be claimed with gpio function.
+      Check out example 7.
 
 properties:
   compatible:
-    enum:
-      - mediatek,mt7530
-      - mediatek,mt7531
-      - mediatek,mt7621
+    oneOf:
+      - description:
+          Standalone MT7530 and multi-chip module MT7530 in MT7623AI SoC
+        const: mediatek,mt7530
+
+      - description:
+          Standalone MT7531
+        const: mediatek,mt7531
+
+      - description:
+          Multi-chip module MT7530 in MT7621AT, MT7621DAT and MT7621ST SoCs
+        const: mediatek,mt7621
 
   reg:
     maxItems: 1
@@ -79,7 +104,7 @@ properties:
   gpio-controller:
     type: boolean
     description:
-      if defined, MT7530's LED controller will run on GPIO mode.
+      If defined, MT7530's LED controller will run on GPIO mode.
 
   "#interrupt-cells":
     const: 1
@@ -92,17 +117,21 @@ properties:
   io-supply:
     description:
       Phandle to the regulator node necessary for the I/O power.
-      See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt
-      for details for the regulator setup on these boards.
+      See Documentation/devicetree/bindings/regulator/mt6323-regulator.txt for
+      details for the regulator setup on these boards.
 
   mediatek,mcm:
     type: boolean
     description:
-      if defined, indicates that either MT7530 is the part on multi-chip
-      module belong to MT7623A has or the remotely standalone chip as the
-      function MT7623N reference board provided for.
+      Used for MT7621AT, MT7621DAT, MT7621ST and MT7623AI SoCs which the MT7530
+      switch is a part of the multi-chip module.
 
   reset-gpios:
+    description:
+      GPIO to reset the switch. Use this if mediatek,mcm is not used.
+      This property is optional because some boards share the reset line with
+      other components which makes it impossible to probe the switch if the
+      reset line is used.
     maxItems: 1
 
   reset-names:
@@ -110,8 +139,8 @@ properties:
 
   resets:
     description:
-      Phandle pointing to the system reset controller with line index for
-      the ethsys.
+      Phandle pointing to the system reset controller with line index for the
+      ethsys.
     maxItems: 1
 
 patternProperties:
@@ -128,31 +157,97 @@ patternProperties:
         properties:
           reg:
             description:
-              Port address described must be 5 or 6 for CPU port and from 0
-              to 5 for user ports.
+              Port address described must be 5 or 6 for CPU port and from 0 to 5
+              for user ports.
 
         allOf:
           - $ref: dsa-port.yaml#
           - if:
               properties:
                 label:
-                  items:
-                    - const: cpu
+                  const: cpu
             then:
               required:
-                - reg
                 - phy-mode
 
+              properties:
+                reg:
+                  enum:
+                    - 5
+                    - 6
+
 required:
   - compatible
   - reg
 
+$defs:
+  mt7530-dsa-port:
+    patternProperties:
+      "^(ethernet-)?ports$":
+        patternProperties:
+          "^(ethernet-)?port@[0-9]+$":
+            if:
+              properties:
+                label:
+                  const: cpu
+            then:
+              if:
+                properties:
+                  reg:
+                    const: 5
+              then:
+                properties:
+                  phy-mode:
+                    enum:
+                      - gmii
+                      - mii
+                      - rgmii
+              else:
+                properties:
+                  phy-mode:
+                    enum:
+                      - rgmii
+                      - trgmii
+
+  mt7531-dsa-port:
+    patternProperties:
+      "^(ethernet-)?ports$":
+        patternProperties:
+          "^(ethernet-)?port@[0-9]+$":
+            if:
+              properties:
+                label:
+                  const: cpu
+            then:
+              if:
+                properties:
+                  reg:
+                    const: 5
+              then:
+                properties:
+                  phy-mode:
+                    enum:
+                      - 1000base-x
+                      - 2500base-x
+                      - rgmii
+                      - sgmii
+              else:
+                properties:
+                  phy-mode:
+                    enum:
+                      - 1000base-x
+                      - 2500base-x
+                      - sgmii
+
 allOf:
-  - $ref: "dsa.yaml#"
+  - $ref: dsa.yaml#
   - if:
       required:
         - mediatek,mcm
     then:
+      properties:
+        reset-gpios: false
+
       required:
         - resets
         - reset-names
@@ -163,52 +258,139 @@ allOf:
   - if:
       properties:
         compatible:
-          items:
-            - const: mediatek,mt7530
+          const: mediatek,mt7530
     then:
+      $ref: "#/$defs/mt7530-dsa-port"
       required:
         - core-supply
         - io-supply
 
+  - if:
+      properties:
+        compatible:
+          const: mediatek,mt7531
+    then:
+      $ref: "#/$defs/mt7531-dsa-port"
+      properties:
+        mediatek,mcm: false
+
+  - if:
+      properties:
+        compatible:
+          const: mediatek,mt7621
+    then:
+      $ref: "#/$defs/mt7530-dsa-port"
+      required:
+        - mediatek,mcm
+
 unevaluatedProperties: false
 
 examples:
+  # Example 1: Standalone MT7530
   - |
     #include <dt-bindings/gpio/gpio.h>
+
     mdio {
         #address-cells = <1>;
         #size-cells = <0>;
+
         switch@0 {
             compatible = "mediatek,mt7530";
             reg = <0>;
 
+            reset-gpios = <&pio 33 0>;
+
             core-supply = <&mt6323_vpa_reg>;
             io-supply = <&mt6323_vemc3v3_reg>;
-            reset-gpios = <&pio 33 GPIO_ACTIVE_HIGH>;
 
             ethernet-ports {
                 #address-cells = <1>;
                 #size-cells = <0>;
+
                 port@0 {
                     reg = <0>;
-                    label = "lan0";
+                    label = "lan1";
                 };
 
                 port@1 {
                     reg = <1>;
-                    label = "lan1";
+                    label = "lan2";
                 };
 
                 port@2 {
                     reg = <2>;
-                    label = "lan2";
+                    label = "lan3";
                 };
 
                 port@3 {
                     reg = <3>;
+                    label = "lan4";
+                };
+
+                port@4 {
+                    reg = <4>;
+                    label = "wan";
+                };
+
+                port@6 {
+                    reg = <6>;
+                    label = "cpu";
+                    ethernet = <&gmac0>;
+                    phy-mode = "rgmii";
+
+                    fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                    };
+                };
+            };
+        };
+    };
+
+  # Example 2: MT7530 in MT7623AI SoC
+  - |
+    #include <dt-bindings/reset/mt2701-resets.h>
+
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        switch@0 {
+            compatible = "mediatek,mt7530";
+            reg = <0>;
+
+            mediatek,mcm;
+            resets = <&ethsys MT2701_ETHSYS_MCM_RST>;
+            reset-names = "mcm";
+
+            core-supply = <&mt6323_vpa_reg>;
+            io-supply = <&mt6323_vemc3v3_reg>;
+
+            ethernet-ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                    reg = <0>;
+                    label = "lan1";
+                };
+
+                port@1 {
+                    reg = <1>;
+                    label = "lan2";
+                };
+
+                port@2 {
+                    reg = <2>;
                     label = "lan3";
                 };
 
+                port@3 {
+                    reg = <3>;
+                    label = "lan4";
+                };
+
                 port@4 {
                     reg = <4>;
                     label = "wan";
@@ -219,85 +401,219 @@ examples:
                     label = "cpu";
                     ethernet = <&gmac0>;
                     phy-mode = "trgmii";
+
                     fixed-link {
                         speed = <1000>;
                         full-duplex;
+                        pause;
                     };
                 };
             };
         };
     };
 
+  # Example 3: Standalone MT7531
   - |
-    //Example 2: MT7621: Port 4 is WAN port: 2nd GMAC -> Port 5 -> PHY port 4.
+    #include <dt-bindings/gpio/gpio.h>
+    #include <dt-bindings/interrupt-controller/irq.h>
 
-    ethernet {
+    mdio {
         #address-cells = <1>;
         #size-cells = <0>;
-        gmac0: mac@0 {
-            compatible = "mediatek,eth-mac";
+
+        switch@0 {
+            compatible = "mediatek,mt7531";
             reg = <0>;
-            phy-mode = "rgmii";
 
-            fixed-link {
-                speed = <1000>;
-                full-duplex;
-                pause;
+            reset-gpios = <&pio 54 0>;
+
+            interrupt-controller;
+            #interrupt-cells = <1>;
+            interrupt-parent = <&pio>;
+            interrupts = <53 IRQ_TYPE_LEVEL_HIGH>;
+
+            ethernet-ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
+
+                port@0 {
+                    reg = <0>;
+                    label = "lan1";
+                };
+
+                port@1 {
+                    reg = <1>;
+                    label = "lan2";
+                };
+
+                port@2 {
+                    reg = <2>;
+                    label = "lan3";
+                };
+
+                port@3 {
+                    reg = <3>;
+                    label = "lan4";
+                };
+
+                port@4 {
+                    reg = <4>;
+                    label = "wan";
+                };
+
+                port@6 {
+                    reg = <6>;
+                    label = "cpu";
+                    ethernet = <&gmac0>;
+                    phy-mode = "2500base-x";
+
+                    fixed-link {
+                        speed = <2500>;
+                        full-duplex;
+                        pause;
+                    };
+                };
             };
         };
+    };
+
+  # Example 4: MT7530 in MT7621AT, MT7621DAT and MT7621ST SoCs
+  - |
+    #include <dt-bindings/interrupt-controller/mips-gic.h>
+    #include <dt-bindings/reset/mt7621-reset.h>
+
+    mdio {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        switch@0 {
+            compatible = "mediatek,mt7621";
+            reg = <0>;
+
+            mediatek,mcm;
+            resets = <&sysc MT7621_RST_MCM>;
+            reset-names = "mcm";
+
+            interrupt-controller;
+            #interrupt-cells = <1>;
+            interrupt-parent = <&gic>;
+            interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>;
+
+            ethernet-ports {
+                #address-cells = <1>;
+                #size-cells = <0>;
 
-        gmac1: mac@1 {
+                port@0 {
+                    reg = <0>;
+                    label = "lan1";
+                };
+
+                port@1 {
+                    reg = <1>;
+                    label = "lan2";
+                };
+
+                port@2 {
+                    reg = <2>;
+                    label = "lan3";
+                };
+
+                port@3 {
+                    reg = <3>;
+                    label = "lan4";
+                };
+
+                port@4 {
+                    reg = <4>;
+                    label = "wan";
+                };
+
+                port@6 {
+                    reg = <6>;
+                    label = "cpu";
+                    ethernet = <&gmac0>;
+                    phy-mode = "trgmii";
+
+                    fixed-link {
+                        speed = <1000>;
+                        full-duplex;
+                        pause;
+                    };
+                };
+            };
+        };
+    };
+
+  # Example 5: MT7621: mux MT7530's phy4 to SoC's gmac1
+  - |
+    #include <dt-bindings/interrupt-controller/mips-gic.h>
+    #include <dt-bindings/reset/mt7621-reset.h>
+
+    ethernet {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pinctrl-names = "default";
+        pinctrl-0 = <&rgmii2_pins>;
+
+        mac@1 {
             compatible = "mediatek,eth-mac";
             reg = <1>;
-            phy-mode = "rgmii-txid";
-            phy-handle = <&phy4>;
+
+            phy-mode = "rgmii";
+            phy-handle = <&example5_ethphy4>;
         };
 
-        mdio: mdio-bus {
+        mdio {
             #address-cells = <1>;
             #size-cells = <0>;
 
-            /* Internal phy */
-            phy4: ethernet-phy@4 {
+            /* MT7530's phy4 */
+            example5_ethphy4: ethernet-phy@4 {
                 reg = <4>;
             };
 
-            mt7530: switch@1f {
+            switch@0 {
                 compatible = "mediatek,mt7621";
-                reg = <0x1f>;
-                mediatek,mcm;
+                reg = <0>;
 
-                resets = <&rstctrl 2>;
+                mediatek,mcm;
+                resets = <&sysc MT7621_RST_MCM>;
                 reset-names = "mcm";
 
+                interrupt-controller;
+                #interrupt-cells = <1>;
+                interrupt-parent = <&gic>;
+                interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>;
+
                 ethernet-ports {
                     #address-cells = <1>;
                     #size-cells = <0>;
 
                     port@0 {
                         reg = <0>;
-                        label = "lan0";
+                        label = "lan1";
                     };
 
                     port@1 {
                         reg = <1>;
-                        label = "lan1";
+                        label = "lan2";
                     };
 
                     port@2 {
                         reg = <2>;
-                        label = "lan2";
+                        label = "lan3";
                     };
 
                     port@3 {
                         reg = <3>;
-                        label = "lan3";
+                        label = "lan4";
                     };
 
-                    /* Commented out. Port 4 is handled by 2nd GMAC.
+                    /* Commented out, phy4 is muxed to gmac1.
                     port@4 {
                         reg = <4>;
-                        label = "lan4";
+                        label = "wan";
                     };
                     */
 
@@ -305,7 +621,7 @@ examples:
                         reg = <6>;
                         label = "cpu";
                         ethernet = <&gmac0>;
-                        phy-mode = "rgmii";
+                        phy-mode = "trgmii";
 
                         fixed-link {
                             speed = <1000>;
@@ -318,82 +634,171 @@ examples:
         };
     };
 
+  # Example 6: MT7621: mux external phy to SoC's gmac1
   - |
-    //Example 3: MT7621: Port 5 is connected to external PHY: Port 5 -> external PHY.
+    #include <dt-bindings/interrupt-controller/mips-gic.h>
+    #include <dt-bindings/reset/mt7621-reset.h>
 
     ethernet {
         #address-cells = <1>;
         #size-cells = <0>;
-        gmac_0: mac@0 {
+
+        pinctrl-names = "default";
+        pinctrl-0 = <&rgmii2_pins>;
+
+        mac@1 {
             compatible = "mediatek,eth-mac";
-            reg = <0>;
+            reg = <1>;
+
             phy-mode = "rgmii";
+            phy-handle = <&example6_ethphy7>;
+        };
 
-            fixed-link {
-                speed = <1000>;
-                full-duplex;
-                pause;
+        mdio {
+            #address-cells = <1>;
+            #size-cells = <0>;
+
+            /* External PHY */
+            example6_ethphy7: ethernet-phy@7 {
+                reg = <7>;
+                phy-mode = "rgmii";
+            };
+
+            switch@0 {
+                compatible = "mediatek,mt7621";
+                reg = <0>;
+
+                mediatek,mcm;
+                resets = <&sysc MT7621_RST_MCM>;
+                reset-names = "mcm";
+
+                interrupt-controller;
+                #interrupt-cells = <1>;
+                interrupt-parent = <&gic>;
+                interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>;
+
+                ethernet-ports {
+                    #address-cells = <1>;
+                    #size-cells = <0>;
+
+                    port@0 {
+                        reg = <0>;
+                        label = "lan1";
+                    };
+
+                    port@1 {
+                        reg = <1>;
+                        label = "lan2";
+                    };
+
+                    port@2 {
+                        reg = <2>;
+                        label = "lan3";
+                    };
+
+                    port@3 {
+                        reg = <3>;
+                        label = "lan4";
+                    };
+
+                    port@4 {
+                        reg = <4>;
+                        label = "wan";
+                    };
+
+                    port@6 {
+                        reg = <6>;
+                        label = "cpu";
+                        ethernet = <&gmac0>;
+                        phy-mode = "trgmii";
+
+                        fixed-link {
+                            speed = <1000>;
+                            full-duplex;
+                            pause;
+                        };
+                    };
+                };
             };
         };
+    };
 
-        mdio0: mdio-bus {
+  # Example 7: MT7621: mux external phy to MT7530's port 5
+  - |
+    #include <dt-bindings/interrupt-controller/mips-gic.h>
+    #include <dt-bindings/reset/mt7621-reset.h>
+
+    ethernet {
+        #address-cells = <1>;
+        #size-cells = <0>;
+
+        pinctrl-names = "default";
+        pinctrl-0 = <&rgmii2_pins>;
+
+        mdio {
             #address-cells = <1>;
             #size-cells = <0>;
 
-            /* External phy */
-            ephy5: ethernet-phy@7 {
+            /* External PHY */
+            example7_ethphy7: ethernet-phy@7 {
                 reg = <7>;
+                phy-mode = "rgmii";
             };
 
-            switch@1f {
+            switch@0 {
                 compatible = "mediatek,mt7621";
-                reg = <0x1f>;
-                mediatek,mcm;
+                reg = <0>;
 
-                resets = <&rstctrl 2>;
+                mediatek,mcm;
+                resets = <&sysc MT7621_RST_MCM>;
                 reset-names = "mcm";
 
+                interrupt-controller;
+                #interrupt-cells = <1>;
+                interrupt-parent = <&gic>;
+                interrupts = <GIC_SHARED 23 IRQ_TYPE_LEVEL_HIGH>;
+
                 ethernet-ports {
                     #address-cells = <1>;
                     #size-cells = <0>;
 
                     port@0 {
                         reg = <0>;
-                        label = "lan0";
+                        label = "lan1";
                     };
 
                     port@1 {
                         reg = <1>;
-                        label = "lan1";
+                        label = "lan2";
                     };
 
                     port@2 {
                         reg = <2>;
-                        label = "lan2";
+                        label = "lan3";
                     };
 
                     port@3 {
                         reg = <3>;
-                        label = "lan3";
+                        label = "lan4";
                     };
 
                     port@4 {
                         reg = <4>;
-                        label = "lan4";
+                        label = "wan";
                     };
 
                     port@5 {
                         reg = <5>;
-                        label = "lan5";
-                        phy-mode = "rgmii";
-                        phy-handle = <&ephy5>;
+                        label = "extphy";
+                        phy-mode = "rgmii-txid";
+                        phy-handle = <&example7_ethphy7>;
                     };
 
-                    cpu_port0: port@6 {
+                    port@6 {
                         reg = <6>;
                         label = "cpu";
-                        ethernet = <&gmac_0>;
-                        phy-mode = "rgmii";
+                        ethernet = <&gmac0>;
+                        phy-mode = "trgmii";
 
                         fixed-link {
                             speed = <1000>;
index 6bbd814..456802a 100644 (file)
@@ -109,6 +109,8 @@ examples:
                     reg = <5>;
                     label = "cpu";
                     ethernet = <&eth0>;
+                    phy-mode = "rgmii";
+
                     fixed-link {
                         speed = <1000>;
                         full-duplex;
@@ -146,6 +148,8 @@ examples:
                     reg = <6>;
                     label = "cpu";
                     ethernet = <&eth0>;
+                    phy-mode = "rgmii";
+
                     fixed-link {
                         speed = <1000>;
                         full-duplex;
index 4d428f5..14a1f0b 100644 (file)
@@ -131,6 +131,8 @@ examples:
                 reg = <4>;
                 ethernet = <&gmac2>;
                 label = "cpu";
+                phy-mode = "internal";
+
                 fixed-link {
                   speed = <1000>;
                   full-duplex;
index c138a10..4b3c590 100644 (file)
@@ -67,6 +67,7 @@ properties:
       - gmii
       - sgmii
       - qsgmii
+      - qusgmii
       - tbi
       - rev-mii
       - rmii
diff --git a/Documentation/devicetree/bindings/net/fsl,fman-dtsec.yaml b/Documentation/devicetree/bindings/net/fsl,fman-dtsec.yaml
new file mode 100644 (file)
index 0000000..3a35ac1
--- /dev/null
@@ -0,0 +1,145 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/fsl,fman-dtsec.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP FMan MAC
+
+maintainers:
+  - Madalin Bucur <madalin.bucur@nxp.com>
+
+description: |
+  Each FMan has several MACs, each implementing an Ethernet interface. Earlier
+  versions of FMan used the Datapath Three Speed Ethernet Controller (dTSEC) for
+  10/100/1000 MBit/s speeds, and the 10-Gigabit Ethernet Media Access Controller
+  (10GEC) for 10 Gbit/s speeds. Later versions of FMan use the Multirate
+  Ethernet Media Access Controller (mEMAC) to handle all speeds.
+
+properties:
+  compatible:
+    enum:
+      - fsl,fman-dtsec
+      - fsl,fman-xgec
+      - fsl,fman-memac
+
+  cell-index:
+    maximum: 64
+    description: |
+      FManV2:
+      register[bit]           MAC             cell-index
+      ============================================================
+      FM_EPI[16]              XGEC            8
+      FM_EPI[16+n]            dTSECn          n-1
+      FM_NPI[11+n]            dTSECn          n-1
+              n = 1,..,5
+
+      FManV3:
+      register[bit]           MAC             cell-index
+      ============================================================
+      FM_EPI[16+n]            mEMACn          n-1
+      FM_EPI[25]              mEMAC10         9
+
+      FM_NPI[11+n]            mEMACn          n-1
+      FM_NPI[10]              mEMAC10         9
+      FM_NPI[11]              mEMAC9          8
+              n = 1,..8
+
+      FM_EPI and FM_NPI are located in the FMan memory map.
+
+      2. SoC registers:
+
+      - P2041, P3041, P4080 P5020, P5040:
+      register[bit]           FMan            MAC             cell
+                              Unit                            index
+      ============================================================
+      DCFG_DEVDISR2[7]        1               XGEC            8
+      DCFG_DEVDISR2[7+n]      1               dTSECn          n-1
+      DCFG_DEVDISR2[15]       2               XGEC            8
+      DCFG_DEVDISR2[15+n]     2               dTSECn          n-1
+              n = 1,..5
+
+      - T1040, T2080, T4240, B4860:
+      register[bit]                   FMan    MAC             cell
+                                      Unit                    index
+      ============================================================
+      DCFG_CCSR_DEVDISR2[n-1]         1       mEMACn          n-1
+      DCFG_CCSR_DEVDISR2[11+n]        2       mEMACn          n-1
+              n = 1,..6,9,10
+
+      EVDISR, DCFG_DEVDISR2 and DCFG_CCSR_DEVDISR2 are located in
+      the specific SoC "Device Configuration/Pin Control" Memory
+      Map.
+
+  reg:
+    maxItems: 1
+
+  fsl,fman-ports:
+    $ref: /schemas/types.yaml#/definitions/phandle-array
+    maxItems: 2
+    description: |
+      An array of two references: the first is the FMan RX port and the second
+      is the TX port used by this MAC.
+
+  ptp-timer:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: A reference to the IEEE1588 timer
+
+  pcsphy-handle:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: A reference to the PCS (typically found on the SerDes)
+
+  tbi-handle:
+    $ref: /schemas/types.yaml#/definitions/phandle
+    description: A reference to the (TBI-based) PCS
+
+required:
+  - compatible
+  - cell-index
+  - reg
+  - fsl,fman-ports
+  - ptp-timer
+
+allOf:
+  - $ref: ethernet-controller.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,fman-dtsec
+    then:
+      required:
+        - tbi-handle
+  - if:
+      properties:
+        compatible:
+          contains:
+            const: fsl,fman-memac
+    then:
+      required:
+        - pcsphy-handle
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    ethernet@e0000 {
+            compatible = "fsl,fman-dtsec";
+            cell-index = <0>;
+            reg = <0xe0000 0x1000>;
+            fsl,fman-ports = <&fman1_rx8 &fman1_tx28>;
+            ptp-timer = <&ptp_timer>;
+            tbi-handle = <&tbi0>;
+    };
+  - |
+    ethernet@e8000 {
+            cell-index = <4>;
+            compatible = "fsl,fman-memac";
+            reg = <0xe8000 0x1000>;
+            fsl,fman-ports = <&fman0_rx_0x0c &fman0_tx_0x2c>;
+            ptp-timer = <&ptp_timer0>;
+            pcsphy-handle = <&pcsphy4>;
+            phy-handle = <&sgmii_phy1>;
+            phy-connection-type = "sgmii";
+    };
+...
index 801efc7..b905533 100644 (file)
@@ -232,133 +232,7 @@ port@81000 {
 =============================================================================
 FMan dTSEC/XGEC/mEMAC Node
 
-DESCRIPTION
-
-mEMAC/dTSEC/XGEC are the Ethernet network interfaces
-
-PROPERTIES
-
-- compatible
-               Usage: required
-               Value type: <stringlist>
-               Definition: A standard property.
-               Must include one of the following:
-               - "fsl,fman-dtsec" for dTSEC MAC
-               - "fsl,fman-xgec" for XGEC MAC
-               - "fsl,fman-memac" for mEMAC MAC
-
-- cell-index
-               Usage: required
-               Value type: <u32>
-               Definition: Specifies the MAC id.
-
-               The cell-index value may be used by the FMan or the SoC, to
-               identify the MAC unit in the FMan (or SoC) memory map.
-               In the tables below there's a description of the cell-index
-               use, there are two tables, one describes the use of cell-index
-               by the FMan, the second describes the use by the SoC:
-
-               1. FMan Registers
-
-               FManV2:
-               register[bit]           MAC             cell-index
-               ============================================================
-               FM_EPI[16]              XGEC            8
-               FM_EPI[16+n]            dTSECn          n-1
-               FM_NPI[11+n]            dTSECn          n-1
-                       n = 1,..,5
-
-               FManV3:
-               register[bit]           MAC             cell-index
-               ============================================================
-               FM_EPI[16+n]            mEMACn          n-1
-               FM_EPI[25]              mEMAC10         9
-
-               FM_NPI[11+n]            mEMACn          n-1
-               FM_NPI[10]              mEMAC10         9
-               FM_NPI[11]              mEMAC9          8
-                       n = 1,..8
-
-               FM_EPI and FM_NPI are located in the FMan memory map.
-
-               2. SoC registers:
-
-               - P2041, P3041, P4080 P5020, P5040:
-               register[bit]           FMan            MAC             cell
-                                       Unit                            index
-               ============================================================
-               DCFG_DEVDISR2[7]        1               XGEC            8
-               DCFG_DEVDISR2[7+n]      1               dTSECn          n-1
-               DCFG_DEVDISR2[15]       2               XGEC            8
-               DCFG_DEVDISR2[15+n]     2               dTSECn          n-1
-                       n = 1,..5
-
-               - T1040, T2080, T4240, B4860:
-               register[bit]                   FMan    MAC             cell
-                                               Unit                    index
-               ============================================================
-               DCFG_CCSR_DEVDISR2[n-1]         1       mEMACn          n-1
-               DCFG_CCSR_DEVDISR2[11+n]        2       mEMACn          n-1
-                       n = 1,..6,9,10
-
-               EVDISR, DCFG_DEVDISR2 and DCFG_CCSR_DEVDISR2 are located in
-               the specific SoC "Device Configuration/Pin Control" Memory
-               Map.
-
-- reg
-               Usage: required
-               Value type: <prop-encoded-array>
-               Definition: A standard property.
-
-- fsl,fman-ports
-               Usage: required
-               Value type: <prop-encoded-array>
-               Definition: An array of two phandles - the first references is
-               the FMan RX port and the second is the TX port used by this
-               MAC.
-
-- ptp-timer
-               Usage required
-               Value type: <phandle>
-               Definition: A phandle for 1EEE1588 timer.
-
-- pcsphy-handle
-               Usage required for "fsl,fman-memac" MACs
-               Value type: <phandle>
-               Definition: A phandle for pcsphy.
-
-- tbi-handle
-               Usage required for "fsl,fman-dtsec" MACs
-               Value type: <phandle>
-               Definition: A phandle for tbiphy.
-
-EXAMPLE
-
-fman1_tx28: port@a8000 {
-       cell-index = <0x28>;
-       compatible = "fsl,fman-v2-port-tx";
-       reg = <0xa8000 0x1000>;
-};
-
-fman1_rx8: port@88000 {
-       cell-index = <0x8>;
-       compatible = "fsl,fman-v2-port-rx";
-       reg = <0x88000 0x1000>;
-};
-
-ptp-timer: ptp_timer@fe000 {
-       compatible = "fsl,fman-ptp-timer";
-       reg = <0xfe000 0x1000>;
-};
-
-ethernet@e0000 {
-       compatible = "fsl,fman-dtsec";
-       cell-index = <0>;
-       reg = <0xe0000 0x1000>;
-       fsl,fman-ports = <&fman1_rx8 &fman1_tx28>;
-       ptp-timer = <&ptp-timer>;
-       tbi-handle = <&tbi0>;
-};
+Refer to Documentation/devicetree/bindings/net/fsl,fman-dtsec.yaml
 
 ============================================================================
 FMan IEEE 1588 Node
index 6c86d3d..57ffeb8 100644 (file)
@@ -74,16 +74,20 @@ properties:
 
   ethernet-ports:
     type: object
+    additionalProperties: false
+
+    properties:
+      '#address-cells':
+        const: 1
+      '#size-cells':
+        const: 0
+
     patternProperties:
       "^port@[0-9a-f]+$":
-        type: object
+        $ref: /schemas/net/ethernet-controller.yaml#
+        unevaluatedProperties: false
 
         properties:
-          '#address-cells':
-            const: 1
-          '#size-cells':
-            const: 0
-
           reg:
             description: Switch port number
 
@@ -93,29 +97,11 @@ properties:
               phandle of a Ethernet SerDes PHY.  This defines which SerDes
               instance will handle the Ethernet traffic.
 
-          phy-mode:
-            description:
-              This specifies the interface used by the Ethernet SerDes towards
-              the PHY or SFP.
-
           microchip,bandwidth:
             description: Specifies bandwidth in Mbit/s allocated to the port.
             $ref: "/schemas/types.yaml#/definitions/uint32"
             maximum: 25000
 
-          phy-handle:
-            description:
-              phandle of a Ethernet PHY.  This is optional and if provided it
-              points to the cuPHY used by the Ethernet SerDes.
-
-          sfp:
-            description:
-              phandle of an SFP.  This is optional and used when not specifying
-              a cuPHY.  It points to the SFP node that describes the SFP used by
-              the Ethernet SerDes.
-
-          managed: true
-
           microchip,sd-sgpio:
             description:
               Index of the ports Signal Detect SGPIO in the set of 384 SGPIOs
@@ -144,8 +130,6 @@ required:
   - reg-names
   - interrupts
   - interrupt-names
-  - resets
-  - reset-names
   - ethernet-ports
 
 additionalProperties: false
index d51da24..ab8867e 100644 (file)
@@ -31,6 +31,22 @@ patternProperties:
         description:
           The ID number for the child PHY. Should be +1 of parent PHY.
 
+      nxp,rmii-refclk-in:
+        type: boolean
+        description: |
+          The REF_CLK is provided for both transmitted and received data
+          in RMII mode. This clock signal is provided by the PHY and is
+          typically derived from an external 25MHz crystal. Alternatively,
+          a 50MHz clock signal generated by an external oscillator can be
+          connected to pin REF_CLK. A third option is to connect a 25MHz
+          clock to pin CLK_IN_OUT. So, the REF_CLK should be configured
+          as input or output according to the actual circuit connection.
+          If present, indicates that the REF_CLK will be configured as
+          interface reference clock input when RMII mode enabled.
+          If not present, the REF_CLK will be configured as interface
+          reference clock output when RMII mode enabled.
+          Only supported on TJA1100 and TJA1101.
+
     required:
       - reg
 
@@ -44,6 +60,7 @@ examples:
 
         tja1101_phy0: ethernet-phy@4 {
             reg = <0x4>;
+            nxp,rmii-refclk-in;
         };
     };
   - |
index b3d4013..161d289 100644 (file)
@@ -40,6 +40,14 @@ properties:
       Only supported on the AR8031.
     type: boolean
 
+  qca,disable-hibernation-mode:
+    description: |
+      Disable Atheros AR803X PHYs hibernation mode. If present, indicates
+      that the hardware of PHY will not enter power saving mode when the
+      cable is disconnected. And the RX_CLK always keeps outputting a
+      valid clock.
+    type: boolean
+
   qca,smarteee-tw-us-100m:
     description: EEE Tw parameter for 100M links.
     $ref: /schemas/types.yaml#/definitions/uint32
index 083623c..3c8c3a9 100644 (file)
@@ -25,6 +25,7 @@ select:
           - rockchip,rk3368-gmac
           - rockchip,rk3399-gmac
           - rockchip,rk3568-gmac
+          - rockchip,rk3588-gmac
           - rockchip,rv1108-gmac
   required:
     - compatible
@@ -50,6 +51,7 @@ properties:
       - items:
           - enum:
               - rockchip,rk3568-gmac
+              - rockchip,rk3588-gmac
           - const: snps,dwmac-4.20a
 
   clocks:
@@ -81,6 +83,11 @@ properties:
     description: The phandle of the syscon node for the general register file.
     $ref: /schemas/types.yaml#/definitions/phandle
 
+  rockchip,php-grf:
+    description:
+      The phandle of the syscon node for the peripheral general register file.
+    $ref: /schemas/types.yaml#/definitions/phandle
+
   tx_delay:
     description: Delay value for TXD timing. Range value is 0~0x7F, 0x30 as default.
     $ref: /schemas/types.yaml#/definitions/uint32
index 491597c..2f909ff 100644 (file)
@@ -74,6 +74,7 @@ properties:
         - rockchip,rk3328-gmac
         - rockchip,rk3366-gmac
         - rockchip,rk3368-gmac
+        - rockchip,rk3588-gmac
         - rockchip,rk3399-gmac
         - rockchip,rv1108-gmac
         - snps,dwmac
index 62dffee..8e51dcd 100644 (file)
@@ -32,6 +32,7 @@ properties:
 
   ethernet-ports:
     type: object
+    additionalProperties: false
     description: Ethernet ports to PHY
 
     properties:
@@ -44,6 +45,7 @@ properties:
     patternProperties:
       "^port@[0-1]$":
         type: object
+        additionalProperties: false
         description: Port to PHY
 
         properties:
index 31bf825..46e330f 100644 (file)
@@ -77,6 +77,8 @@ properties:
 
   ethernet-ports:
     type: object
+    additionalProperties: false
+
     properties:
       '#address-cells':
         const: 1
@@ -89,6 +91,7 @@ properties:
         description: CPSW external ports
 
         $ref: ethernet-controller.yaml#
+        unevaluatedProperties: false
 
         properties:
           reg:
@@ -117,6 +120,7 @@ properties:
 
   cpts:
     type: object
+    unevaluatedProperties: false
     description:
       The Common Platform Time Sync (CPTS) module
 
index b8281d8..7d90bea 100644 (file)
@@ -55,6 +55,7 @@ properties:
   compatible:
     enum:
       - ti,am654-cpsw-nuss
+      - ti,j7200-cpswxg-nuss
       - ti,j721e-cpsw-nuss
       - ti,am642-cpsw-nuss
 
@@ -110,16 +111,17 @@ properties:
         const: 0
 
     patternProperties:
-      port@[1-2]:
+      "^port@[1-4]$":
         type: object
         description: CPSWxG NUSS external ports
 
         $ref: ethernet-controller.yaml#
+        unevaluatedProperties: false
 
         properties:
           reg:
             minimum: 1
-            maximum: 2
+            maximum: 4
             description: CPSW port number
 
           phys:
@@ -178,6 +180,19 @@ required:
   - '#address-cells'
   - '#size-cells'
 
+allOf:
+  - if:
+      not:
+        properties:
+          compatible:
+            contains:
+              const: ti,j7200-cpswxg-nuss
+    then:
+      properties:
+        ethernet-ports:
+          patternProperties:
+            "^port@[3-4]$": false
+
 additionalProperties: false
 
 examples:
index b783ad0..e9f78ce 100644 (file)
@@ -95,6 +95,7 @@ properties:
 
   refclk-mux:
     type: object
+    additionalProperties: false
     description: CPTS reference clock multiplexer clock
     properties:
       '#clock-cells':
index 8156a9a..304757b 100644 (file)
@@ -7,7 +7,7 @@ $schema: "http://devicetree.org/meta-schemas/core.yaml#"
 title: The Vertexcom MSE102x (SPI) Device Tree Bindings
 
 maintainers:
-  - Stefan Wahren <stefan.wahren@in-tech.com>
+  - Stefan Wahren <stefan.wahren@chargebyte.com>
 
 description:
   Vertexcom's MSE102x are a family of HomePlug GreenPHY chips.
index 60de78f..b3405f2 100644 (file)
@@ -20,8 +20,6 @@ properties:
 
   reg: true
 
-  spi-max-frequency: true
-
   interrupts:
     maxItems: 1
 
@@ -51,7 +49,10 @@ required:
   - compatible
   - interrupts
 
-additionalProperties: false
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
 
 examples:
   - |
index 76199a6..b35d2f3 100644 (file)
@@ -29,12 +29,6 @@ description: >
     Documentation/devicetree/bindings/mmc/mmc-pwrseq-simple.yaml for more
     information.
 
-  For SPI:
-
-    In add of the properties below, please consult
-    Documentation/devicetree/bindings/spi/spi-controller.yaml for optional SPI
-    related properties.
-
 properties:
   compatible:
     items:
@@ -52,8 +46,6 @@ properties:
       bindings.
     maxItems: 1
 
-  spi-max-frequency: true
-
   interrupts:
     description: The interrupt line. Should be IRQ_TYPE_EDGE_RISING. When SPI is
       used, this property is required. When SDIO is used, the "in-band"
@@ -84,12 +76,15 @@ properties:
 
   mac-address: true
 
-additionalProperties: false
-
 required:
   - compatible
   - reg
 
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
 examples:
   - |
     #include <dt-bindings/gpio/gpio.h>
index d68bb2e..e314567 100644 (file)
@@ -36,8 +36,6 @@ properties:
       This is required when connected via SPI, and optional when connected via
       SDIO.
 
-  spi-max-frequency: true
-
   interrupts:
     minItems: 1
     maxItems: 2
@@ -69,20 +67,22 @@ required:
   - compatible
   - interrupts
 
-if:
-  properties:
-    compatible:
-      contains:
-        enum:
-          - ti,wl1271
-          - ti,wl1273
-          - ti,wl1281
-          - ti,wl1283
-then:
-  required:
-    - ref-clock-frequency
-
-additionalProperties: false
+allOf:
+  - $ref: /schemas/spi/spi-peripheral-props.yaml#
+  - if:
+      properties:
+        compatible:
+          contains:
+            enum:
+              - ti,wl1271
+              - ti,wl1273
+              - ti,wl1281
+              - ti,wl1283
+    then:
+      required:
+        - ref-clock-frequency
+
+unevaluatedProperties: false
 
 examples:
   - |
index 2d34f3c..8d2c6d7 100644 (file)
@@ -214,6 +214,7 @@ patternProperties:
       - polling-delay
       - polling-delay-passive
       - thermal-sensors
+      - trips
 
     additionalProperties: false
 
index 7823a06..96cd7a2 100644 (file)
@@ -846,7 +846,7 @@ primary_reselect
 tlb_dynamic_lb
 
        Specifies if dynamic shuffling of flows is enabled in tlb
-       mode. The value has no effect on any other modes.
+       or alb mode. The value has no effect on any other modes.
 
        The default behavior of tlb mode is to shuffle active flows across
        slaves based on the load in that interval. This gives nice lb
diff --git a/Documentation/networking/decnet.rst b/Documentation/networking/decnet.rst
deleted file mode 100644 (file)
index b8bc11f..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-.. SPDX-License-Identifier: GPL-2.0
-
-=========================================
-Linux DECnet Networking Layer Information
-=========================================
-
-1. Other documentation....
-==========================
-
-   - Project Home Pages
-     - http://www.chygwyn.com/                            - Kernel info
-     - http://linux-decnet.sourceforge.net/                - Userland tools
-     - http://www.sourceforge.net/projects/linux-decnet/   - Status page
-
-2. Configuring the kernel
-=========================
-
-Be sure to turn on the following options:
-
-    - CONFIG_DECNET (obviously)
-    - CONFIG_PROC_FS (to see what's going on)
-    - CONFIG_SYSCTL (for easy configuration)
-
-if you want to try out router support (not properly debugged yet)
-you'll need the following options as well...
-
-    - CONFIG_DECNET_ROUTER (to be able to add/delete routes)
-    - CONFIG_NETFILTER (will be required for the DECnet routing daemon)
-
-Don't turn on SIOCGIFCONF support for DECnet unless you are really sure
-that you need it, in general you won't and it can cause ifconfig to
-malfunction.
-
-Run time configuration has changed slightly from the 2.4 system. If you
-want to configure an endnode, then the simplified procedure is as follows:
-
- - Set the MAC address on your ethernet card before starting _any_ other
-   network protocols.
-
-As soon as your network card is brought into the UP state, DECnet should
-start working. If you need something more complicated or are unsure how
-to set the MAC address, see the next section. Also all configurations which
-worked with 2.4 will work under 2.5 with no change.
-
-3. Command line options
-=======================
-
-You can set a DECnet address on the kernel command line for compatibility
-with the 2.4 configuration procedure, but in general it's not needed any more.
-If you do st a DECnet address on the command line, it has only one purpose
-which is that its added to the addresses on the loopback device.
-
-With 2.4 kernels, DECnet would only recognise addresses as local if they
-were added to the loopback device. In 2.5, any local interface address
-can be used to loop back to the local machine. Of course this does not
-prevent you adding further addresses to the loopback device if you
-want to.
-
-N.B. Since the address list of an interface determines the addresses for
-which "hello" messages are sent, if you don't set an address on the loopback
-interface then you won't see any entries in /proc/net/neigh for the local
-host until such time as you start a connection. This doesn't affect the
-operation of the local communications in any other way though.
-
-The kernel command line takes options looking like the following::
-
-    decnet.addr=1,2
-
-the two numbers are the node address 1,2 = 1.2 For 2.2.xx kernels
-and early 2.3.xx kernels, you must use a comma when specifying the
-DECnet address like this. For more recent 2.3.xx kernels, you may
-use almost any character except space, although a `.` would be the most
-obvious choice :-)
-
-There used to be a third number specifying the node type. This option
-has gone away in favour of a per interface node type. This is now set
-using /proc/sys/net/decnet/conf/<dev>/forwarding. This file can be
-set with a single digit, 0=EndNode, 1=L1 Router and  2=L2 Router.
-
-There are also equivalent options for modules. The node address can
-also be set through the /proc/sys/net/decnet/ files, as can other system
-parameters.
-
-Currently the only supported devices are ethernet and ip_gre. The
-ethernet address of your ethernet card has to be set according to the DECnet
-address of the node in order for it to be autoconfigured (and then appear in
-/proc/net/decnet_dev). There is a utility available at the above
-FTP sites called dn2ethaddr which can compute the correct ethernet
-address to use. The address can be set by ifconfig either before or
-at the time the device is brought up. If you are using RedHat you can
-add the line::
-
-    MACADDR=AA:00:04:00:03:04
-
-or something similar, to /etc/sysconfig/network-scripts/ifcfg-eth0 or
-wherever your network card's configuration lives. Setting the MAC address
-of your ethernet card to an address starting with "hi-ord" will cause a
-DECnet address which matches to be added to the interface (which you can
-verify with iproute2).
-
-The default device for routing can be set through the /proc filesystem
-by setting /proc/sys/net/decnet/default_device to the
-device you want DECnet to route packets out of when no specific route
-is available. Usually this will be eth0, for example::
-
-    echo -n "eth0" >/proc/sys/net/decnet/default_device
-
-If you don't set the default device, then it will default to the first
-ethernet card which has been autoconfigured as described above. You can
-confirm that by looking in the default_device file of course.
-
-There is a list of what the other files under /proc/sys/net/decnet/ do
-on the kernel patch web site (shown above).
-
-4. Run time kernel configuration
-================================
-
-
-This is either done through the sysctl/proc interface (see the kernel web
-pages for details on what the various options do) or through the iproute2
-package in the same way as IPv4/6 configuration is performed.
-
-Documentation for iproute2 is included with the package, although there is
-as yet no specific section on DECnet, most of the features apply to both
-IP and DECnet, albeit with DECnet addresses instead of IP addresses and
-a reduced functionality.
-
-If you want to configure a DECnet router you'll need the iproute2 package
-since its the _only_ way to add and delete routes currently. Eventually
-there will be a routing daemon to send and receive routing messages for
-each interface and update the kernel routing tables accordingly. The
-routing daemon will use netfilter to listen to routing packets, and
-rtnetlink to update the kernels routing tables.
-
-The DECnet raw socket layer has been removed since it was there purely
-for use by the routing daemon which will now use netfilter (a much cleaner
-and more generic solution) instead.
-
-5. How can I tell if its working?
-=================================
-
-Here is a quick guide of what to look for in order to know if your DECnet
-kernel subsystem is working.
-
-   - Is the node address set (see /proc/sys/net/decnet/node_address)
-   - Is the node of the correct type
-     (see /proc/sys/net/decnet/conf/<dev>/forwarding)
-   - Is the Ethernet MAC address of each Ethernet card set to match
-     the DECnet address. If in doubt use the dn2ethaddr utility available
-     at the ftp archive.
-   - If the previous two steps are satisfied, and the Ethernet card is up,
-     you should find that it is listed in /proc/net/decnet_dev and also
-     that it appears as a directory in /proc/sys/net/decnet/conf/. The
-     loopback device (lo) should also appear and is required to communicate
-     within a node.
-   - If you have any DECnet routers on your network, they should appear
-     in /proc/net/decnet_neigh, otherwise this file will only contain the
-     entry for the node itself (if it doesn't check to see if lo is up).
-   - If you want to send to any node which is not listed in the
-     /proc/net/decnet_neigh file, you'll need to set the default device
-     to point to an Ethernet card with connection to a router. This is
-     again done with the /proc/sys/net/decnet/default_device file.
-   - Try starting a simple server and client, like the dnping/dnmirror
-     over the loopback interface. With luck they should communicate.
-     For this step and those after, you'll need the DECnet library
-     which can be obtained from the above ftp sites as well as the
-     actual utilities themselves.
-   - If this seems to work, then try talking to a node on your local
-     network, and see if you can obtain the same results.
-   - At this point you are on your own... :-)
-
-6. How to send a bug report
-===========================
-
-If you've found a bug and want to report it, then there are several things
-you can do to help me work out exactly what it is that is wrong. Useful
-information (_most_ of which _is_ _essential_) includes:
-
- - What kernel version are you running ?
- - What version of the patch are you running ?
- - How far though the above set of tests can you get ?
- - What is in the /proc/decnet* files and /proc/sys/net/decnet/* files ?
- - Which services are you running ?
- - Which client caused the problem ?
- - How much data was being transferred ?
- - Was the network congested ?
- - How can the problem be reproduced ?
- - Can you use tcpdump to get a trace ? (N.B. Most (all?) versions of
-   tcpdump don't understand how to dump DECnet properly, so including
-   the hex listing of the packet contents is _essential_, usually the -x flag.
-   You may also need to increase the length grabbed with the -s flag. The
-   -e flag also provides very useful information (ethernet MAC addresses))
-
-7. MAC FAQ
-==========
-
-A quick FAQ on ethernet MAC addresses to explain how Linux and DECnet
-interact and how to get the best performance from your hardware.
-
-Ethernet cards are designed to normally only pass received network frames
-to a host computer when they are addressed to it, or to the broadcast address.
-
-Linux has an interface which allows the setting of extra addresses for
-an ethernet card to listen to. If the ethernet card supports it, the
-filtering operation will be done in hardware, if not the extra unwanted packets
-received will be discarded by the host computer. In the latter case,
-significant processor time and bus bandwidth can be used up on a busy
-network (see the NAPI documentation for a longer explanation of these
-effects).
-
-DECnet makes use of this interface to allow running DECnet on an ethernet
-card which has already been configured using TCP/IP (presumably using the
-built in MAC address of the card, as usual) and/or to allow multiple DECnet
-addresses on each physical interface. If you do this, be aware that if your
-ethernet card doesn't support perfect hashing in its MAC address filter
-then your computer will be doing more work than required. Some cards
-will simply set themselves into promiscuous mode in order to receive
-packets from the DECnet specified addresses. So if you have one of these
-cards its better to set the MAC address of the card as described above
-to gain the best efficiency. Better still is to use a card which supports
-NAPI as well.
-
-
-8. Mailing list
-===============
-
-If you are keen to get involved in development, or want to ask questions
-about configuration, or even just report bugs, then there is a mailing
-list that you can join, details are at:
-
-http://sourceforge.net/mail/?group_id=4993
-
-9. Legal Info
-=============
-
-The Linux DECnet project team have placed their code under the GPL. The
-software is provided "as is" and without warranty express or implied.
-DECnet is a trademark of Compaq. This software is not a product of
-Compaq. We acknowledge the help of people at Compaq in providing extra
-documentation above and beyond what was previously publicly available.
-
-Steve Whitehouse <SteveW@ACM.org>
-
index 7f17771..5196905 100644 (file)
@@ -52,6 +52,7 @@ Contents:
    ti/tlan
    toshiba/spider_net
    wangxun/txgbe
+   wangxun/ngbe
 
 .. only::  subproject and html
 
diff --git a/Documentation/networking/device_drivers/ethernet/wangxun/ngbe.rst b/Documentation/networking/device_drivers/ethernet/wangxun/ngbe.rst
new file mode 100644 (file)
index 0000000..43a02f9
--- /dev/null
@@ -0,0 +1,14 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=============================================================
+Linux Base Driver for WangXun(R) Gigabit PCI Express Adapters
+=============================================================
+
+WangXun Gigabit Linux driver.
+Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd.
+
+Support
+=======
+ If you have problems with the software or hardware, please contact our
+ customer support team via email at nic-support@net-swift.com or check our website
+ at https://www.net-swift.com
index 8c082b1..0c89ceb 100644 (file)
@@ -139,6 +139,42 @@ EMP firmware image.
 The driver does not currently support reloading the driver via
 ``DEVLINK_RELOAD_ACTION_DRIVER_REINIT``.
 
+Port split
+==========
+
+The ``ice`` driver supports port splitting only for port 0, as the FW has
+a predefined set of available port split options for the whole device.
+
+A system reboot is required for port split to be applied.
+
+The following command will select the port split option with 4 ports:
+
+.. code:: shell
+
+    $ devlink port split pci/0000:16:00.0/0 count 4
+
+The list of all available port options will be printed to dynamic debug after
+each ``split`` and ``unsplit`` command. The first option is the default.
+
+.. code:: shell
+
+    ice 0000:16:00.0: Available port split options and max port speeds (Gbps):
+    ice 0000:16:00.0: Status  Split      Quad 0          Quad 1
+    ice 0000:16:00.0:         count  L0  L1  L2  L3  L4  L5  L6  L7
+    ice 0000:16:00.0: Active  2     100   -   -   - 100   -   -   -
+    ice 0000:16:00.0:         2      50   -  50   -   -   -   -   -
+    ice 0000:16:00.0: Pending 4      25  25  25  25   -   -   -   -
+    ice 0000:16:00.0:         4      25  25   -   -  25  25   -   -
+    ice 0000:16:00.0:         8      10  10  10  10  10  10  10  10
+    ice 0000:16:00.0:         1     100   -   -   -   -   -   -   -
+
+There could be multiple FW port options with the same port split count. When
+the same port split count request is issued again, the next FW port option with
+the same port split count will be selected.
+
+``devlink port unsplit`` will select the option with a split count of 1. If
+there is no FW option available with split count 1, you will receive an error.
+
 Regions
 =======
 
index e3a5f98..4b653d0 100644 (file)
@@ -13,10 +13,8 @@ new APIs prefixed by ``devl_*``. The older APIs handle all the locking
 in devlink core, but don't allow registration of most sub-objects once
 the main devlink object is itself registered. The newer ``devl_*`` APIs assume
 the devlink instance lock is already held. Drivers can take the instance
-lock by calling ``devl_lock()``. It is also held in most of the callbacks.
-Eventually all callbacks will be invoked under the devlink instance lock,
-refer to the use of the ``DEVLINK_NL_FLAG_NO_LOCK`` flag in devlink core
-to find out which callbacks are not converted, yet.
+lock by calling ``devl_lock()``. It is also held all callbacks of devlink
+netlink commands.
 
 Drivers are encouraged to use the devlink instance lock for their own needs.
 
index 8a292fb..ec5e6d7 100644 (file)
@@ -67,7 +67,7 @@ The ``netdevsim`` driver supports rate objects management, which includes:
 - setting tx_share and tx_max rate values for any rate object type;
 - setting parent node for any rate object type.
 
-Rate nodes and it's parameters are exposed in ``netdevsim`` debugfs in RO mode.
+Rate nodes and their parameters are exposed in ``netdevsim`` debugfs in RO mode.
 For example created rate node with name ``some_group``:
 
 .. code:: shell
index c8f59db..64f7236 100644 (file)
@@ -8,7 +8,7 @@ Transmit path guidelines:
 
 1) The ndo_start_xmit method must not return NETDEV_TX_BUSY under
    any normal circumstances.  It is considered a hard error unless
-   there is no way your device can tell ahead of time when it's
+   there is no way your device can tell ahead of time when its
    transmit function will become busy.
 
    Instead it must maintain the queue properly.  For example,
index 03b215b..bacadd0 100644 (file)
@@ -47,7 +47,6 @@ Contents:
    cdc_mbim
    dccp
    dctcp
-   decnet
    dns_resolver
    driver
    eql
index 56cd4ea..a759872 100644 (file)
@@ -1035,7 +1035,10 @@ tcp_limit_output_bytes - INTEGER
 tcp_challenge_ack_limit - INTEGER
        Limits number of Challenge ACK sent per second, as recommended
        in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks)
-       Default: 1000
+       Note that this per netns rate limit can allow some side channel
+       attacks and probably should not be enabled.
+       TCP stack implements per TCP socket limits anyway.
+       Default: INT_MAX (unlimited)
 
 UDP variables
 =============
index 694adcb..0000c1d 100644 (file)
@@ -11,7 +11,7 @@ Initial Release:
 ================
 This is conceptually very similar to the macvlan driver with one major
 exception of using L3 for mux-ing /demux-ing among slaves. This property makes
-the master device share the L2 with it's slave devices. I have developed this
+the master device share the L2 with its slave devices. I have developed this
 driver in conjunction with network namespaces and not sure if there is use case
 outside of it.
 
index 498b382..7f383e9 100644 (file)
@@ -530,7 +530,7 @@ its tunnel close actions. For L2TPIP sockets, the socket's close
 handler initiates the same tunnel close actions. All sessions are
 first closed. Each session drops its tunnel ref. When the tunnel ref
 reaches zero, the tunnel puts its socket ref. When the socket is
-eventually destroyed, it's sk_destruct finally frees the L2TP tunnel
+eventually destroyed, its sk_destruct finally frees the L2TP tunnel
 context.
 
 Sessions
index 704f31d..712e44c 100644 (file)
@@ -308,6 +308,15 @@ Some of the interface modes are described below:
     rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying
     data rate of 100Mpbs.
 
+``PHY_INTERFACE_MODE_QUSGMII``
+    This defines the Cisco the Quad USGMII mode, which is the Quad variant of
+    the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses
+    a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not
+    only the port id, but also so-called "extensions". The only documented
+    extension so-far in the specification is the inclusion of timestamps, for
+    PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the
+    same capabilities in terms of link speed and negociation.
+
 Pause frames / flow control
 ===========================
 
index f1f4e6a..bbf272e 100644 (file)
@@ -159,7 +159,7 @@ tools such as iproute2.
 
 The switchdev driver can know a particular port's position in the topology by
 monitoring NETDEV_CHANGEUPPER notifications.  For example, a port moved into a
-bond will see it's upper master change.  If that bond is moved into a bridge,
+bond will see its upper master change.  If that bond is moved into a bridge,
 the bond's upper master will change.  And so on.  The driver will track such
 movements to know what position a port is in in the overall topology by
 registering for netdevice events and acting on NETDEV_CHANGEUPPER.
index 2a29cbe..9707e03 100644 (file)
 
 % Translations have Asian (CJK) characters which are only displayed if
 % xeCJK is used
+\usepackage{ifthen}
+\newboolean{enablecjk}
+\setboolean{enablecjk}{false}
 \IfFontExistsTF{Noto Sans CJK SC}{
-    % Load xeCJK when CJK font is available
+    \IfFileExists{xeCJK.sty}{
+       \setboolean{enablecjk}{true}
+    }{}
+}{}
+\ifthenelse{\boolean{enablecjk}}{
+    % Load xeCJK when both the Noto Sans CJK font and xeCJK.sty are available.
     \usepackage{xeCJK}
     % Noto CJK fonts don't provide slant shape. [AutoFakeSlant] permits
     % its emulation.
     % Inactivate CJK after tableofcontents
     \apptocmd{\sphinxtableofcontents}{\kerneldocCJKoff}{}{}
     \xeCJKsetup{CJKspace = true}% For inter-phrase space of Korean TOC
-}{ % No CJK font found
+}{ % Don't enable CJK
     % Custom macros to on/off CJK and switch CJK fonts (Dummy)
     \newcommand{\kerneldocCJKon}{}
     \newcommand{\kerneldocCJKoff}{}
     %% and ignore the argument (#1) in their definitions, whole contents of
     %% CJK chapters can be ignored.
     \newcommand{\kerneldocBeginSC}[1]{%
-       %% Put a note on missing CJK fonts in place of zh_CN translation.
-       \begin{sphinxadmonition}{note}{Note on missing fonts:}
+       %% Put a note on missing CJK fonts or the xecjk package in place of
+       %% zh_CN translation.
+       \begin{sphinxadmonition}{note}{Note on missing fonts and a package:}
            Translations of Simplified Chinese (zh\_CN), Traditional Chinese
            (zh\_TW), Korean (ko\_KR), and Japanese (ja\_JP) were skipped
-           due to the lack of suitable font families.
+           due to the lack of suitable font families and/or the texlive-xecjk
+           package.
 
            If you want them, please install ``Noto Sans CJK'' font families
-           by following instructions from
+           along with the texlive-xecjk package by following instructions from
            \sphinxcode{./scripts/sphinx-pre-install}.
            Having optional ``Noto Serif CJK'' font families will improve
            the looks of those translations.
index 66ce0d8..04deb77 100644 (file)
@@ -35,8 +35,7 @@ Linux カーネルに変更を加えたいと思っている個人又は会社
 てもらえやすくする提案を集めたものです。
 
 コードを投稿する前に、Documentation/process/submit-checklist.rst の項目リストに目
-を通してチェックしてください。もしあなたがドライバーを投稿しようとし
-ているなら、Documentation/process/submitting-drivers.rst にも目を通してください。
+を通してチェックしてください。
 
 --------------------------------------------
 セクション1 パッチの作り方と送り方
index a61eac0..c78da9c 100644 (file)
@@ -26,6 +26,7 @@ place where this information is gathered.
    ioctl/index
    iommu
    media/index
+   netlink/index
    sysfs-platform_profile
    vduse
    futex2
index 3b985b1..5f81e2a 100644 (file)
@@ -308,7 +308,6 @@ Code  Seq#    Include File                                           Comments
 0x89  00-06  arch/x86/include/asm/sockios.h
 0x89  0B-DF  linux/sockios.h
 0x89  E0-EF  linux/sockios.h                                         SIOCPROTOPRIVATE range
-0x89  E0-EF  linux/dn.h                                              PROTOPRIVATE range
 0x89  F0-FF  linux/sockios.h                                         SIOCDEVPRIVATE range
 0x8B  all    linux/wireless.h
 0x8C  00-3F                                                          WiNRADiO driver
diff --git a/Documentation/userspace-api/netlink/index.rst b/Documentation/userspace-api/netlink/index.rst
new file mode 100644 (file)
index 0000000..b0c2153
--- /dev/null
@@ -0,0 +1,12 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+================
+Netlink Handbook
+================
+
+Netlink documentation for users.
+
+.. toctree::
+   :maxdepth: 2
+
+   intro
diff --git a/Documentation/userspace-api/netlink/intro.rst b/Documentation/userspace-api/netlink/intro.rst
new file mode 100644 (file)
index 0000000..8f12207
--- /dev/null
@@ -0,0 +1,646 @@
+.. SPDX-License-Identifier: BSD-3-Clause
+
+=======================
+Introduction to Netlink
+=======================
+
+Netlink is often described as an ioctl() replacement.
+It aims to replace fixed-format C structures as supplied
+to ioctl() with a format which allows an easy way to add
+or extended the arguments.
+
+To achieve this Netlink uses a minimal fixed-format metadata header
+followed by multiple attributes in the TLV (type, length, value) format.
+
+Unfortunately the protocol has evolved over the years, in an organic
+and undocumented fashion, making it hard to coherently explain.
+To make the most practical sense this document starts by describing
+netlink as it is used today and dives into more "historical" uses
+in later sections.
+
+Opening a socket
+================
+
+Netlink communication happens over sockets, a socket needs to be
+opened first:
+
+.. code-block:: c
+
+  fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+
+The use of sockets allows for a natural way of exchanging information
+in both directions (to and from the kernel). The operations are still
+performed synchronously when applications send() the request but
+a separate recv() system call is needed to read the reply.
+
+A very simplified flow of a Netlink "call" will therefore look
+something like:
+
+.. code-block:: c
+
+  fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+
+  /* format the request */
+  send(fd, &request, sizeof(request));
+  n = recv(fd, &response, RSP_BUFFER_SIZE);
+  /* interpret the response */
+
+Netlink also provides natural support for "dumping", i.e. communicating
+to user space all objects of a certain type (e.g. dumping all network
+interfaces).
+
+.. code-block:: c
+
+  fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
+
+  /* format the dump request */
+  send(fd, &request, sizeof(request));
+  while (1) {
+    n = recv(fd, &buffer, RSP_BUFFER_SIZE);
+    /* one recv() call can read multiple messages, hence the loop below */
+    for (nl_msg in buffer) {
+      if (nl_msg.nlmsg_type == NLMSG_DONE)
+        goto dump_finished;
+      /* process the object */
+    }
+  }
+  dump_finished:
+
+The first two arguments of the socket() call require little explanation -
+it is opening a Netlink socket, with all headers provided by the user
+(hence NETLINK, RAW). The last argument is the protocol within Netlink.
+This field used to identify the subsystem with which the socket will
+communicate.
+
+Classic vs Generic Netlink
+--------------------------
+
+Initial implementation of Netlink depended on a static allocation
+of IDs to subsystems and provided little supporting infrastructure.
+Let us refer to those protocols collectively as **Classic Netlink**.
+The list of them is defined on top of the ``include/uapi/linux/netlink.h``
+file, they include among others - general networking (NETLINK_ROUTE),
+iSCSI (NETLINK_ISCSI), and audit (NETLINK_AUDIT).
+
+**Generic Netlink** (introduced in 2005) allows for dynamic registration of
+subsystems (and subsystem ID allocation), introspection and simplifies
+implementing the kernel side of the interface.
+
+The following section describes how to use Generic Netlink, as the
+number of subsystems using Generic Netlink outnumbers the older
+protocols by an order of magnitude. There are also no plans for adding
+more Classic Netlink protocols to the kernel.
+Basic information on how communicating with core networking parts of
+the Linux kernel (or another of the 20 subsystems using Classic
+Netlink) differs from Generic Netlink is provided later in this document.
+
+Generic Netlink
+===============
+
+In addition to the Netlink fixed metadata header each Netlink protocol
+defines its own fixed metadata header. (Similarly to how network
+headers stack - Ethernet > IP > TCP we have Netlink > Generic N. > Family.)
+
+A Netlink message always starts with struct nlmsghdr, which is followed
+by a protocol-specific header. In case of Generic Netlink the protocol
+header is struct genlmsghdr.
+
+The practical meaning of the fields in case of Generic Netlink is as follows:
+
+.. code-block:: c
+
+  struct nlmsghdr {
+       __u32   nlmsg_len;      /* Length of message including headers */
+       __u16   nlmsg_type;     /* Generic Netlink Family (subsystem) ID */
+       __u16   nlmsg_flags;    /* Flags - request or dump */
+       __u32   nlmsg_seq;      /* Sequence number */
+       __u32   nlmsg_pid;      /* Port ID, set to 0 */
+  };
+  struct genlmsghdr {
+       __u8    cmd;            /* Command, as defined by the Family */
+       __u8    version;        /* Irrelevant, set to 1 */
+       __u16   reserved;       /* Reserved, set to 0 */
+  };
+  /* TLV attributes follow... */
+
+In Classic Netlink :c:member:`nlmsghdr.nlmsg_type` used to identify
+which operation within the subsystem the message was referring to
+(e.g. get information about a netdev). Generic Netlink needs to mux
+multiple subsystems in a single protocol so it uses this field to
+identify the subsystem, and :c:member:`genlmsghdr.cmd` identifies
+the operation instead. (See :ref:`res_fam` for
+information on how to find the Family ID of the subsystem of interest.)
+Note that the first 16 values (0 - 15) of this field are reserved for
+control messages both in Classic Netlink and Generic Netlink.
+See :ref:`nl_msg_type` for more details.
+
+There are 3 usual types of message exchanges on a Netlink socket:
+
+ - performing a single action (``do``);
+ - dumping information (``dump``);
+ - getting asynchronous notifications (``multicast``).
+
+Classic Netlink is very flexible and presumably allows other types
+of exchanges to happen, but in practice those are the three that get
+used.
+
+Asynchronous notifications are sent by the kernel and received by
+the user sockets which subscribed to them. ``do`` and ``dump`` requests
+are initiated by the user. :c:member:`nlmsghdr.nlmsg_flags` should
+be set as follows:
+
+ - for ``do``: ``NLM_F_REQUEST | NLM_F_ACK``
+ - for ``dump``: ``NLM_F_REQUEST | NLM_F_ACK | NLM_F_DUMP``
+
+:c:member:`nlmsghdr.nlmsg_seq` should be a set to a monotonically
+increasing value. The value gets echoed back in responses and doesn't
+matter in practice, but setting it to an increasing value for each
+message sent is considered good hygiene. The purpose of the field is
+matching responses to requests. Asynchronous notifications will have
+:c:member:`nlmsghdr.nlmsg_seq` of ``0``.
+
+:c:member:`nlmsghdr.nlmsg_pid` is the Netlink equivalent of an address.
+This field can be set to ``0`` when talking to the kernel.
+See :ref:`nlmsg_pid` for the (uncommon) uses of the field.
+
+The expected use for :c:member:`genlmsghdr.version` was to allow
+versioning of the APIs provided by the subsystems. No subsystem to
+date made significant use of this field, so setting it to ``1`` seems
+like a safe bet.
+
+.. _nl_msg_type:
+
+Netlink message types
+---------------------
+
+As previously mentioned :c:member:`nlmsghdr.nlmsg_type` carries
+protocol specific values but the first 16 identifiers are reserved
+(first subsystem specific message type should be equal to
+``NLMSG_MIN_TYPE`` which is ``0x10``).
+
+There are only 4 Netlink control messages defined:
+
+ - ``NLMSG_NOOP`` - ignore the message, not used in practice;
+ - ``NLMSG_ERROR`` - carries the return code of an operation;
+ - ``NLMSG_DONE`` - marks the end of a dump;
+ - ``NLMSG_OVERRUN`` - socket buffer has overflown, not used to date.
+
+``NLMSG_ERROR`` and ``NLMSG_DONE`` are of practical importance.
+They carry return codes for operations. Note that unless
+the ``NLM_F_ACK`` flag is set on the request Netlink will not respond
+with ``NLMSG_ERROR`` if there is no error. To avoid having to special-case
+this quirk it is recommended to always set ``NLM_F_ACK``.
+
+The format of ``NLMSG_ERROR`` is described by struct nlmsgerr::
+
+  ----------------------------------------------
+  | struct nlmsghdr - response header          |
+  ----------------------------------------------
+  |    int error                               |
+  ----------------------------------------------
+  | struct nlmsghdr - original request header |
+  ----------------------------------------------
+  | ** optionally (1) payload of the request   |
+  ----------------------------------------------
+  | ** optionally (2) extended ACK             |
+  ----------------------------------------------
+
+There are two instances of struct nlmsghdr here, first of the response
+and second of the request. ``NLMSG_ERROR`` carries the information about
+the request which led to the error. This could be useful when trying
+to match requests to responses or re-parse the request to dump it into
+logs.
+
+The payload of the request is not echoed in messages reporting success
+(``error == 0``) or if ``NETLINK_CAP_ACK`` setsockopt() was set.
+The latter is common
+and perhaps recommended as having to read a copy of every request back
+from the kernel is rather wasteful. The absence of request payload
+is indicated by ``NLM_F_CAPPED`` in :c:member:`nlmsghdr.nlmsg_flags`.
+
+The second optional element of ``NLMSG_ERROR`` are the extended ACK
+attributes. See :ref:`ext_ack` for more details. The presence
+of extended ACK is indicated by ``NLM_F_ACK_TLVS`` in
+:c:member:`nlmsghdr.nlmsg_flags`.
+
+``NLMSG_DONE`` is simpler, the request is never echoed but the extended
+ACK attributes may be present::
+
+  ----------------------------------------------
+  | struct nlmsghdr - response header          |
+  ----------------------------------------------
+  |    int error                               |
+  ----------------------------------------------
+  | ** optionally extended ACK                 |
+  ----------------------------------------------
+
+.. _res_fam:
+
+Resolving the Family ID
+-----------------------
+
+This section explains how to find the Family ID of a subsystem.
+It also serves as an example of Generic Netlink communication.
+
+Generic Netlink is itself a subsystem exposed via the Generic Netlink API.
+To avoid a circular dependency Generic Netlink has a statically allocated
+Family ID (``GENL_ID_CTRL`` which is equal to ``NLMSG_MIN_TYPE``).
+The Generic Netlink family implements a command used to find out information
+about other families (``CTRL_CMD_GETFAMILY``).
+
+To get information about the Generic Netlink family named for example
+``"test1"`` we need to send a message on the previously opened Generic Netlink
+socket. The message should target the Generic Netlink Family (1), be a
+``do`` (2) call to ``CTRL_CMD_GETFAMILY`` (3). A ``dump`` version of this
+call would make the kernel respond with information about *all* the families
+it knows about. Last but not least the name of the family in question has
+to be specified (4) as an attribute with the appropriate type::
+
+  struct nlmsghdr:
+    __u32 nlmsg_len:   32
+    __u16 nlmsg_type:  GENL_ID_CTRL               // (1)
+    __u16 nlmsg_flags: NLM_F_REQUEST | NLM_F_ACK  // (2)
+    __u32 nlmsg_seq:   1
+    __u32 nlmsg_pid:   0
+
+  struct genlmsghdr:
+    __u8 cmd:          CTRL_CMD_GETFAMILY         // (3)
+    __u8 version:      2 /* or 1, doesn't matter */
+    __u16 reserved:    0
+
+  struct nlattr:                                   // (4)
+    __u16 nla_len:     10
+    __u16 nla_type:    CTRL_ATTR_FAMILY_NAME
+    char data:                 test1\0
+
+  (padding:)
+    char data:         \0\0
+
+The length fields in Netlink (:c:member:`nlmsghdr.nlmsg_len`
+and :c:member:`nlattr.nla_len`) always *include* the header.
+Attribute headers in netlink must be aligned to 4 bytes from the start
+of the message, hence the extra ``\0\0`` after ``CTRL_ATTR_FAMILY_NAME``.
+The attribute lengths *exclude* the padding.
+
+If the family is found kernel will reply with two messages, the response
+with all the information about the family::
+
+  /* Message #1 - reply */
+  struct nlmsghdr:
+    __u32 nlmsg_len:   136
+    __u16 nlmsg_type:  GENL_ID_CTRL
+    __u16 nlmsg_flags: 0
+    __u32 nlmsg_seq:   1    /* echoed from our request */
+    __u32 nlmsg_pid:   5831 /* The PID of our user space process */
+
+  struct genlmsghdr:
+    __u8 cmd:          CTRL_CMD_GETFAMILY
+    __u8 version:      2
+    __u16 reserved:    0
+
+  struct nlattr:
+    __u16 nla_len:     10
+    __u16 nla_type:    CTRL_ATTR_FAMILY_NAME
+    char data:                 test1\0
+
+  (padding:)
+    data:              \0\0
+
+  struct nlattr:
+    __u16 nla_len:     6
+    __u16 nla_type:    CTRL_ATTR_FAMILY_ID
+    __u16:             123  /* The Family ID we are after */
+
+  (padding:)
+    char data:         \0\0
+
+  struct nlattr:
+    __u16 nla_len:     9
+    __u16 nla_type:    CTRL_ATTR_FAMILY_VERSION
+    __u16:             1
+
+  /* ... etc, more attributes will follow. */
+
+And the error code (success) since ``NLM_F_ACK`` had been set on the request::
+
+  /* Message #2 - the ACK */
+  struct nlmsghdr:
+    __u32 nlmsg_len:   36
+    __u16 nlmsg_type:  NLMSG_ERROR
+    __u16 nlmsg_flags: NLM_F_CAPPED /* There won't be a payload */
+    __u32 nlmsg_seq:   1    /* echoed from our request */
+    __u32 nlmsg_pid:   5831 /* The PID of our user space process */
+
+  int error:           0
+
+  struct nlmsghdr: /* Copy of the request header as we sent it */
+    __u32 nlmsg_len:   32
+    __u16 nlmsg_type:  GENL_ID_CTRL
+    __u16 nlmsg_flags: NLM_F_REQUEST | NLM_F_ACK
+    __u32 nlmsg_seq:   1
+    __u32 nlmsg_pid:   0
+
+The order of attributes (struct nlattr) is not guaranteed so the user
+has to walk the attributes and parse them.
+
+Note that Generic Netlink sockets are not associated or bound to a single
+family. A socket can be used to exchange messages with many different
+families, selecting the recipient family on message-by-message basis using
+the :c:member:`nlmsghdr.nlmsg_type` field.
+
+.. _ext_ack:
+
+Extended ACK
+------------
+
+Extended ACK controls reporting of additional error/warning TLVs
+in ``NLMSG_ERROR`` and ``NLMSG_DONE`` messages. To maintain backward
+compatibility this feature has to be explicitly enabled by setting
+the ``NETLINK_EXT_ACK`` setsockopt() to ``1``.
+
+Types of extended ack attributes are defined in enum nlmsgerr_attrs.
+The most commonly used attributes are ``NLMSGERR_ATTR_MSG``,
+``NLMSGERR_ATTR_OFFS`` and ``NLMSGERR_ATTR_MISS_*``.
+
+``NLMSGERR_ATTR_MSG`` carries a message in English describing
+the encountered problem. These messages are far more detailed
+than what can be expressed thru standard UNIX error codes.
+
+``NLMSGERR_ATTR_OFFS`` points to the attribute which caused the problem.
+
+``NLMSGERR_ATTR_MISS_TYPE`` and ``NLMSGERR_ATTR_MISS_NEST``
+inform about a missing attribute.
+
+Extended ACKs can be reported on errors as well as in case of success.
+The latter should be treated as a warning.
+
+Extended ACKs greatly improve the usability of Netlink and should
+always be enabled, appropriately parsed and reported to the user.
+
+Advanced topics
+===============
+
+Dump consistency
+----------------
+
+Some of the data structures kernel uses for storing objects make
+it hard to provide an atomic snapshot of all the objects in a dump
+(without impacting the fast-paths updating them).
+
+Kernel may set the ``NLM_F_DUMP_INTR`` flag on any message in a dump
+(including the ``NLMSG_DONE`` message) if the dump was interrupted and
+may be inconsistent (e.g. missing objects). User space should retry
+the dump if it sees the flag set.
+
+Introspection
+-------------
+
+The basic introspection abilities are enabled by access to the Family
+object as reported in :ref:`res_fam`. User can query information about
+the Generic Netlink family, including which operations are supported
+by the kernel and what attributes the kernel understands.
+Family information includes the highest ID of an attribute kernel can parse,
+a separate command (``CTRL_CMD_GETPOLICY``) provides detailed information
+about supported attributes, including ranges of values the kernel accepts.
+
+Querying family information is useful in cases when user space needs
+to make sure that the kernel has support for a feature before issuing
+a request.
+
+.. _nlmsg_pid:
+
+nlmsg_pid
+---------
+
+:c:member:`nlmsghdr.nlmsg_pid` is the Netlink equivalent of an address.
+It is referred to as Port ID, sometimes Process ID because for historical
+reasons if the application does not select (bind() to) an explicit Port ID
+kernel will automatically assign it the ID equal to its Process ID
+(as reported by the getpid() system call).
+
+Similarly to the bind() semantics of the TCP/IP network protocols the value
+of zero means "assign automatically", hence it is common for applications
+to leave the :c:member:`nlmsghdr.nlmsg_pid` field initialized to ``0``.
+
+The field is still used today in rare cases when kernel needs to send
+a unicast notification. User space application can use bind() to associate
+its socket with a specific PID, it then communicates its PID to the kernel.
+This way the kernel can reach the specific user space process.
+
+This sort of communication is utilized in UMH (User Mode Helper)-like
+scenarios when kernel needs to trigger user space processing or ask user
+space for a policy decision.
+
+Multicast notifications
+-----------------------
+
+One of the strengths of Netlink is the ability to send event notifications
+to user space. This is a unidirectional form of communication (kernel ->
+user) and does not involve any control messages like ``NLMSG_ERROR`` or
+``NLMSG_DONE``.
+
+For example the Generic Netlink family itself defines a set of multicast
+notifications about registered families. When a new family is added the
+sockets subscribed to the notifications will get the following message::
+
+  struct nlmsghdr:
+    __u32 nlmsg_len:   136
+    __u16 nlmsg_type:  GENL_ID_CTRL
+    __u16 nlmsg_flags: 0
+    __u32 nlmsg_seq:   0
+    __u32 nlmsg_pid:   0
+
+  struct genlmsghdr:
+    __u8 cmd:          CTRL_CMD_NEWFAMILY
+    __u8 version:      2
+    __u16 reserved:    0
+
+  struct nlattr:
+    __u16 nla_len:     10
+    __u16 nla_type:    CTRL_ATTR_FAMILY_NAME
+    char data:                 test1\0
+
+  (padding:)
+    data:              \0\0
+
+  struct nlattr:
+    __u16 nla_len:     6
+    __u16 nla_type:    CTRL_ATTR_FAMILY_ID
+    __u16:             123  /* The Family ID we are after */
+
+  (padding:)
+    char data:         \0\0
+
+  struct nlattr:
+    __u16 nla_len:     9
+    __u16 nla_type:    CTRL_ATTR_FAMILY_VERSION
+    __u16:             1
+
+  /* ... etc, more attributes will follow. */
+
+The notification contains the same information as the response
+to the ``CTRL_CMD_GETFAMILY`` request.
+
+The Netlink headers of the notification are mostly 0 and irrelevant.
+The :c:member:`nlmsghdr.nlmsg_seq` may be either zero or a monotonically
+increasing notification sequence number maintained by the family.
+
+To receive notifications the user socket must subscribe to the relevant
+notification group. Much like the Family ID, the Group ID for a given
+multicast group is dynamic and can be found inside the Family information.
+The ``CTRL_ATTR_MCAST_GROUPS`` attribute contains nests with names
+(``CTRL_ATTR_MCAST_GRP_NAME``) and IDs (``CTRL_ATTR_MCAST_GRP_ID``) of
+the groups family.
+
+Once the Group ID is known a setsockopt() call adds the socket to the group:
+
+.. code-block:: c
+
+  unsigned int group_id;
+
+  /* .. find the group ID... */
+
+  setsockopt(fd, SOL_NETLINK, NETLINK_ADD_MEMBERSHIP,
+             &group_id, sizeof(group_id));
+
+The socket will now receive notifications.
+
+It is recommended to use separate sockets for receiving notifications
+and sending requests to the kernel. The asynchronous nature of notifications
+means that they may get mixed in with the responses making the message
+handling much harder.
+
+Buffer sizing
+-------------
+
+Netlink sockets are datagram sockets rather than stream sockets,
+meaning that each message must be received in its entirety by a single
+recv()/recvmsg() system call. If the buffer provided by the user is too
+short, the message will be truncated and the ``MSG_TRUNC`` flag set
+in struct msghdr (struct msghdr is the second argument
+of the recvmsg() system call, *not* a Netlink header).
+
+Upon truncation the remaining part of the message is discarded.
+
+Netlink expects that the user buffer will be at least 8kB or a page
+size of the CPU architecture, whichever is bigger. Particular Netlink
+families may, however, require a larger buffer. 32kB buffer is recommended
+for most efficient handling of dumps (larger buffer fits more dumped
+objects and therefore fewer recvmsg() calls are needed).
+
+Classic Netlink
+===============
+
+The main differences between Classic and Generic Netlink are the dynamic
+allocation of subsystem identifiers and availability of introspection.
+In theory the protocol does not differ significantly, however, in practice
+Classic Netlink experimented with concepts which were abandoned in Generic
+Netlink (really, they usually only found use in a small corner of a single
+subsystem). This section is meant as an explainer of a few of such concepts,
+with the explicit goal of giving the Generic Netlink
+users the confidence to ignore them when reading the uAPI headers.
+
+Most of the concepts and examples here refer to the ``NETLINK_ROUTE`` family,
+which covers much of the configuration of the Linux networking stack.
+Real documentation of that family, deserves a chapter (or a book) of its own.
+
+Families
+--------
+
+Netlink refers to subsystems as families. This is a remnant of using
+sockets and the concept of protocol families, which are part of message
+demultiplexing in ``NETLINK_ROUTE``.
+
+Sadly every layer of encapsulation likes to refer to whatever it's carrying
+as "families" making the term very confusing:
+
+ 1. AF_NETLINK is a bona fide socket protocol family
+ 2. AF_NETLINK's documentation refers to what comes after its own
+    header (struct nlmsghdr) in a message as a "Family Header"
+ 3. Generic Netlink is a family for AF_NETLINK (struct genlmsghdr follows
+    struct nlmsghdr), yet it also calls its users "Families".
+
+Note that the Generic Netlink Family IDs are in a different "ID space"
+and overlap with Classic Netlink protocol numbers (e.g. ``NETLINK_CRYPTO``
+has the Classic Netlink protocol ID of 21 which Generic Netlink will
+happily allocate to one of its families as well).
+
+Strict checking
+---------------
+
+The ``NETLINK_GET_STRICT_CHK`` socket option enables strict input checking
+in ``NETLINK_ROUTE``. It was needed because historically kernel did not
+validate the fields of structures it didn't process. This made it impossible
+to start using those fields later without risking regressions in applications
+which initialized them incorrectly or not at all.
+
+``NETLINK_GET_STRICT_CHK`` declares that the application is initializing
+all fields correctly. It also opts into validating that message does not
+contain trailing data and requests that kernel rejects attributes with
+type higher than largest attribute type known to the kernel.
+
+``NETLINK_GET_STRICT_CHK`` is not used outside of ``NETLINK_ROUTE``.
+
+Unknown attributes
+------------------
+
+Historically Netlink ignored all unknown attributes. The thinking was that
+it would free the application from having to probe what kernel supports.
+The application could make a request to change the state and check which
+parts of the request "stuck".
+
+This is no longer the case for new Generic Netlink families and those opting
+in to strict checking. See enum netlink_validation for validation types
+performed.
+
+Fixed metadata and structures
+-----------------------------
+
+Classic Netlink made liberal use of fixed-format structures within
+the messages. Messages would commonly have a structure with
+a considerable number of fields after struct nlmsghdr. It was also
+common to put structures with multiple members inside attributes,
+without breaking each member into an attribute of its own.
+
+This has caused problems with validation and extensibility and
+therefore using binary structures is actively discouraged for new
+attributes.
+
+Request types
+-------------
+
+``NETLINK_ROUTE`` categorized requests into 4 types ``NEW``, ``DEL``, ``GET``,
+and ``SET``. Each object can handle all or some of those requests
+(objects being netdevs, routes, addresses, qdiscs etc.) Request type
+is defined by the 2 lowest bits of the message type, so commands for
+new objects would always be allocated with a stride of 4.
+
+Each object would also have it's own fixed metadata shared by all request
+types (e.g. struct ifinfomsg for netdev requests, struct ifaddrmsg for address
+requests, struct tcmsg for qdisc requests).
+
+Even though other protocols and Generic Netlink commands often use
+the same verbs in their message names (``GET``, ``SET``) the concept
+of request types did not find wider adoption.
+
+Message flags
+-------------
+
+The earlier section has already covered the basic request flags
+(``NLM_F_REQUEST``, ``NLM_F_ACK``, ``NLM_F_DUMP``) and the ``NLMSG_ERROR`` /
+``NLMSG_DONE`` flags (``NLM_F_CAPPED``, ``NLM_F_ACK_TLVS``).
+Dump flags were also mentioned (``NLM_F_MULTI``, ``NLM_F_DUMP_INTR``).
+
+Those are the main flags of note, with a small exception (of ``ieee802154``)
+Generic Netlink does not make use of other flags. If the protocol needs
+to communicate special constraints for a request it should use
+an attribute, not the flags in struct nlmsghdr.
+
+Classic Netlink, however, defined various flags for its ``GET``, ``NEW``
+and ``DEL`` requests. Since request types have not been generalized
+the request type specific flags should not be used either.
+
+uAPI reference
+==============
+
+.. kernel-doc:: include/uapi/linux/netlink.h
index af48484..9479f77 100644 (file)
@@ -3612,6 +3612,7 @@ F:        include/linux/find.h
 F:     include/linux/nodemask.h
 F:     lib/bitmap.c
 F:     lib/cpumask.c
+F:     lib/cpumask_kunit.c
 F:     lib/find_bit.c
 F:     lib/find_bit_benchmark.c
 F:     lib/test_bitmap.c
@@ -5721,13 +5722,6 @@ F:       include/linux/tfrc.h
 F:     include/uapi/linux/dccp.h
 F:     net/dccp/
 
-DECnet NETWORK LAYER
-L:     linux-decnet-user@lists.sourceforge.net
-S:     Orphan
-W:     http://linux-decnet.sourceforge.net
-F:     Documentation/networking/decnet.rst
-F:     net/decnet/
-
 DECSTATION PLATFORM SUPPORT
 M:     "Maciej W. Rozycki" <macro@orcam.me.uk>
 L:     linux-mips@vger.kernel.org
@@ -10659,6 +10653,7 @@ T:      git git://git.kernel.dk/linux-block
 T:     git git://git.kernel.dk/liburing
 F:     io_uring/
 F:     include/linux/io_uring.h
+F:     include/linux/io_uring_types.h
 F:     include/uapi/linux/io_uring.h
 F:     tools/io_uring/
 
@@ -21845,9 +21840,11 @@ F:     drivers/input/tablet/wacom_serial4.c
 
 WANGXUN ETHERNET DRIVER
 M:     Jiawen Wu <jiawenwu@trustnetic.com>
+M:     Mengyuan Lou <mengyuanlou@net-swift.com>
+W:     https://www.net-swift.com
 L:     netdev@vger.kernel.org
 S:     Maintained
-F:     Documentation/networking/device_drivers/ethernet/wangxun/txgbe.rst
+F:     Documentation/networking/device_drivers/ethernet/wangxun/*
 F:     drivers/net/ethernet/wangxun/
 
 WATCHDOG DEVICE DRIVERS
index c7705f7..952d354 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 492c771..bafb1c1 100644 (file)
@@ -283,11 +283,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return (old & mask) != 0;
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 /*
  * ffz = Find First Zero in word. Undefined if no zero exists,
index 571cc23..9fb9fff 100644 (file)
@@ -917,6 +917,23 @@ config ARM64_ERRATUM_1902691
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_2457168
+       bool "Cortex-A510: 2457168: workaround for AMEVCNTR01 incrementing incorrectly"
+       depends on ARM64_AMU_EXTN
+       default y
+       help
+         This option adds the workaround for ARM Cortex-A510 erratum 2457168.
+
+         The AMU counter AMEVCNTR01 (constant counter) should increment at the same rate
+         as the system counter. On affected Cortex-A510 cores AMEVCNTR01 increments
+         incorrectly giving a significantly higher output value.
+
+         Work around this problem by returning 0 when reading the affected counter in
+         key locations that results in disabling all users of this counter. This effect
+         is the same to firmware disabling affected counters.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
index ca9b487..34256bd 100644 (file)
@@ -71,7 +71,7 @@ static __always_inline int icache_is_vpipt(void)
 
 static inline u32 cache_type_cwg(void)
 {
-       return (read_cpuid_cachetype() >> CTR_EL0_CWG_SHIFT) & CTR_EL0_CWG_MASK;
+       return SYS_FIELD_GET(CTR_EL0, CWG, read_cpuid_cachetype());
 }
 
 #define __read_mostly __section(".data..read_mostly")
index 9bb1873..6f86b7a 100644 (file)
@@ -153,7 +153,7 @@ struct vl_info {
 
 #ifdef CONFIG_ARM64_SVE
 
-extern void sve_alloc(struct task_struct *task);
+extern void sve_alloc(struct task_struct *task, bool flush);
 extern void fpsimd_release_task(struct task_struct *task);
 extern void fpsimd_sync_to_sve(struct task_struct *task);
 extern void fpsimd_force_sync_to_sve(struct task_struct *task);
@@ -256,7 +256,7 @@ size_t sve_state_size(struct task_struct const *task);
 
 #else /* ! CONFIG_ARM64_SVE */
 
-static inline void sve_alloc(struct task_struct *task) { }
+static inline void sve_alloc(struct task_struct *task, bool flush) { }
 static inline void fpsimd_release_task(struct task_struct *task) { }
 static inline void sve_sync_to_fpsimd(struct task_struct *task) { }
 static inline void sve_sync_from_fpsimd_zeropad(struct task_struct *task) { }
index 6437df6..f4af547 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef __ARM64_ASM_SETUP_H
 #define __ARM64_ASM_SETUP_H
 
+#include <linux/string.h>
+
 #include <uapi/asm/setup.h>
 
 void *get_early_fdt_ptr(void);
@@ -14,4 +16,19 @@ void early_fdt_map(u64 dt_phys);
 extern phys_addr_t __fdt_pointer __initdata;
 extern u64 __cacheline_aligned boot_args[4];
 
+static inline bool arch_parse_debug_rodata(char *arg)
+{
+       extern bool rodata_enabled;
+       extern bool rodata_full;
+
+       if (arg && !strcmp(arg, "full")) {
+               rodata_enabled = true;
+               rodata_full = true;
+               return true;
+       }
+
+       return false;
+}
+#define arch_parse_debug_rodata arch_parse_debug_rodata
+
 #endif
index 7c71358..818df93 100644 (file)
 
 #else
 
+#include <linux/bitfield.h>
 #include <linux/build_bug.h>
 #include <linux/types.h>
 #include <asm/alternative.h>
        par;                                                            \
 })
 
-#endif
-
 #define SYS_FIELD_GET(reg, field, val)         \
                 FIELD_GET(reg##_##field##_MASK, val)
 
 #define SYS_FIELD_PREP_ENUM(reg, field, val)           \
                 FIELD_PREP(reg##_##field##_MASK, reg##_##field##_##val)
 
+#endif
+
 #endif /* __ASM_SYSREG_H */
index 587543c..97c42be 100644 (file)
@@ -45,7 +45,8 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
 
 int init_cache_level(unsigned int cpu)
 {
-       unsigned int ctype, level, leaves, fw_level;
+       unsigned int ctype, level, leaves;
+       int fw_level;
        struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 
        for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
@@ -63,6 +64,9 @@ int init_cache_level(unsigned int cpu)
        else
                fw_level = acpi_find_last_cache_level(cpu);
 
+       if (fw_level < 0)
+               return fw_level;
+
        if (level < fw_level) {
                /*
                 * some external caches not specified in CLIDR_EL1
index 7e6289e..53b973b 100644 (file)
@@ -208,6 +208,8 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
 #ifdef CONFIG_ARM64_ERRATUM_1286807
        {
                ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
+       },
+       {
                /* Kryo4xx Gold (rcpe to rfpe) => (r0p0 to r3p0) */
                ERRATA_MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xe),
        },
@@ -654,6 +656,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2)
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_2457168
+       {
+               .desc = "ARM erratum 2457168",
+               .capability = ARM64_WORKAROUND_2457168,
+               .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
+
+               /* Cortex-A510 r0p0-r1p1 */
+               CAP_MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1)
+       },
+#endif
 #ifdef CONFIG_ARM64_ERRATUM_2038923
        {
                .desc = "ARM erratum 2038923",
index 907401e..af4de81 100644 (file)
@@ -1870,7 +1870,10 @@ static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)
                pr_info("detected CPU%d: Activity Monitors Unit (AMU)\n",
                        smp_processor_id());
                cpumask_set_cpu(smp_processor_id(), &amu_cpus);
-               update_freq_counters_refs();
+
+               /* 0 reference values signal broken/disabled counters */
+               if (!this_cpu_has_cap(ARM64_WORKAROUND_2457168))
+                       update_freq_counters_refs();
        }
 }
 
index 254fe31..2d73b3e 100644 (file)
@@ -502,7 +502,7 @@ tsk .req    x28             // current thread_info
 SYM_CODE_START(vectors)
        kernel_ventry   1, t, 64, sync          // Synchronous EL1t
        kernel_ventry   1, t, 64, irq           // IRQ EL1t
-       kernel_ventry   1, t, 64, fiq           // FIQ EL1h
+       kernel_ventry   1, t, 64, fiq           // FIQ EL1t
        kernel_ventry   1, t, 64, error         // Error EL1t
 
        kernel_ventry   1, h, 64, sync          // Synchronous EL1h
index dd63ffc..23834d9 100644 (file)
@@ -715,10 +715,12 @@ size_t sve_state_size(struct task_struct const *task)
  * do_sve_acc() case, there is no ABI requirement to hide stale data
  * written previously be task.
  */
-void sve_alloc(struct task_struct *task)
+void sve_alloc(struct task_struct *task, bool flush)
 {
        if (task->thread.sve_state) {
-               memset(task->thread.sve_state, 0, sve_state_size(task));
+               if (flush)
+                       memset(task->thread.sve_state, 0,
+                              sve_state_size(task));
                return;
        }
 
@@ -1388,7 +1390,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
                return;
        }
 
-       sve_alloc(current);
+       sve_alloc(current, true);
        if (!current->thread.sve_state) {
                force_sig(SIGKILL);
                return;
@@ -1439,7 +1441,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
                return;
        }
 
-       sve_alloc(current);
+       sve_alloc(current, false);
        sme_alloc(current);
        if (!current->thread.sve_state || !current->thread.za_state) {
                force_sig(SIGKILL);
@@ -1460,17 +1462,6 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
                fpsimd_bind_task_to_cpu();
        }
 
-       /*
-        * If SVE was not already active initialise the SVE registers,
-        * any non-shared state between the streaming and regular SVE
-        * registers is architecturally guaranteed to be zeroed when
-        * we enter streaming mode.  We do not need to initialize ZA
-        * since ZA must be disabled at this point and enabling ZA is
-        * architecturally defined to zero ZA.
-        */
-       if (system_supports_sve() && !test_thread_flag(TIF_SVE))
-               sve_init_regs();
-
        put_cpu_fpsimd_context();
 }
 
index 6c3855e..17bff6e 100644 (file)
@@ -94,11 +94,9 @@ asmlinkage u64 kaslr_early_init(void *fdt)
 
        seed = get_kaslr_seed(fdt);
        if (!seed) {
-#ifdef CONFIG_ARCH_RANDOM
-                if (!__early_cpu_has_rndr() ||
-                    !__arm64_rndr((unsigned long *)&seed))
-#endif
-               return 0;
+               if (!__early_cpu_has_rndr() ||
+                   !__arm64_rndr((unsigned long *)&seed))
+                       return 0;
        }
 
        /*
index 21da831..eb7c08d 100644 (file)
@@ -882,7 +882,7 @@ static int sve_set_common(struct task_struct *target,
                 * state and ensure there's storage.
                 */
                if (target->thread.svcr != old_svcr)
-                       sve_alloc(target);
+                       sve_alloc(target, true);
        }
 
        /* Registers: FPSIMD-only case */
@@ -912,7 +912,7 @@ static int sve_set_common(struct task_struct *target,
                goto out;
        }
 
-       sve_alloc(target);
+       sve_alloc(target, true);
        if (!target->thread.sve_state) {
                ret = -ENOMEM;
                clear_tsk_thread_flag(target, TIF_SVE);
@@ -1082,7 +1082,7 @@ static int za_set(struct task_struct *target,
 
        /* Ensure there is some SVE storage for streaming mode */
        if (!target->thread.sve_state) {
-               sve_alloc(target);
+               sve_alloc(target, false);
                if (!target->thread.sve_state) {
                        clear_thread_flag(TIF_SME);
                        ret = -ENOMEM;
index 3e6d035..9ad911f 100644 (file)
@@ -91,7 +91,7 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
  * not taken into account.  This limit is not a guarantee and is
  * NOT ABI.
  */
-#define SIGFRAME_MAXSZ SZ_64K
+#define SIGFRAME_MAXSZ SZ_256K
 
 static int __sigframe_alloc(struct rt_sigframe_user_layout *user,
                            unsigned long *offset, size_t size, bool extend)
@@ -310,7 +310,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
        fpsimd_flush_task_state(current);
        /* From now, fpsimd_thread_switch() won't touch thread.sve_state */
 
-       sve_alloc(current);
+       sve_alloc(current, true);
        if (!current->thread.sve_state) {
                clear_thread_flag(TIF_SVE);
                return -ENOMEM;
@@ -926,6 +926,16 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 
        /* Signal handlers are invoked with ZA and streaming mode disabled */
        if (system_supports_sme()) {
+               /*
+                * If we were in streaming mode the saved register
+                * state was SVE but we will exit SM and use the
+                * FPSIMD register state - flush the saved FPSIMD
+                * register state in case it gets loaded.
+                */
+               if (current->thread.svcr & SVCR_SM_MASK)
+                       memset(&current->thread.uw.fpsimd_state, 0,
+                              sizeof(current->thread.uw.fpsimd_state));
+
                current->thread.svcr &= ~(SVCR_ZA_MASK |
                                          SVCR_SM_MASK);
                sme_smstop();
index 869ffc4..ad2bfc7 100644 (file)
@@ -296,12 +296,25 @@ core_initcall(init_amu_fie);
 
 static void cpu_read_corecnt(void *val)
 {
+       /*
+        * A value of 0 can be returned if the current CPU does not support AMUs
+        * or if the counter is disabled for this CPU. A return value of 0 at
+        * counter read is properly handled as an error case by the users of the
+        * counter.
+        */
        *(u64 *)val = read_corecnt();
 }
 
 static void cpu_read_constcnt(void *val)
 {
-       *(u64 *)val = read_constcnt();
+       /*
+        * Return 0 if the current CPU is affected by erratum 2457168. A value
+        * of 0 is also returned if the current CPU does not support AMUs or if
+        * the counter is disabled. A return value of 0 at counter read is
+        * properly handled as an error case by the users of the counter.
+        */
+       *(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_2457168) ?
+                     0UL : read_constcnt();
 }
 
 static inline
@@ -328,7 +341,22 @@ int counters_read_on_cpu(int cpu, smp_call_func_t func, u64 *val)
  */
 bool cpc_ffh_supported(void)
 {
-       return freq_counters_valid(get_cpu_with_amu_feat());
+       int cpu = get_cpu_with_amu_feat();
+
+       /*
+        * FFH is considered supported if there is at least one present CPU that
+        * supports AMUs. Using FFH to read core and reference counters for CPUs
+        * that do not support AMUs, have counters disabled or that are affected
+        * by errata, will result in a return value of 0.
+        *
+        * This is done to allow any enabled and valid counters to be read
+        * through FFH, knowing that potentially returning 0 as counter value is
+        * properly handled by the users of these counters.
+        */
+       if ((cpu >= nr_cpu_ids) || !cpumask_test_cpu(cpu, cpu_present_mask))
+               return false;
+
+       return true;
 }
 
 int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
index db7c4e6..e7ad445 100644 (file)
@@ -642,24 +642,6 @@ static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end,
        vm_area_add_early(vma);
 }
 
-static int __init parse_rodata(char *arg)
-{
-       int ret = strtobool(arg, &rodata_enabled);
-       if (!ret) {
-               rodata_full = false;
-               return 0;
-       }
-
-       /* permit 'full' in addition to boolean options */
-       if (strcmp(arg, "full"))
-               return -EINVAL;
-
-       rodata_enabled = true;
-       rodata_full = true;
-       return 0;
-}
-early_param("rodata", parse_rodata);
-
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 static int __init map_entry_trampoline(void)
 {
index 7796537..63b2484 100644 (file)
@@ -67,6 +67,7 @@ WORKAROUND_1902691
 WORKAROUND_2038923
 WORKAROUND_2064142
 WORKAROUND_2077057
+WORKAROUND_2457168
 WORKAROUND_TRBE_OVERWRITE_FILL_MODE
 WORKAROUND_TSB_FLUSH_FAILURE
 WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
index da50047..160d8f3 100644 (file)
@@ -179,6 +179,21 @@ arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
        return retval;
 }
 
+static __always_inline bool
+arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       int retval;
+
+       asm volatile(
+       "{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
+       : "=&r" (retval)
+       : "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
+       : "p0", "memory"
+       );
+
+       return retval;
+}
+
 /*
  * ffz - find first zero in word.
  * @word: The word to search
index 9f62af7..1accb78 100644 (file)
@@ -331,11 +331,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return (old & bit) != 0;
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return 1 & (((const volatile __u32 *) addr)[nr >> 5] >> (nr & 31));
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 /**
  * ffz - find the first zero bit in a long word
index 4abc9a2..26aeb14 100644 (file)
@@ -111,6 +111,7 @@ config LOONGARCH
        select PCI_ECAM if ACPI
        select PCI_LOONGSON
        select PCI_MSI_ARCH_FALLBACKS
+       select PCI_QUIRKS
        select PERF_USE_VMALLOC
        select RTC_LIB
        select SMP
index b91e073..d342935 100644 (file)
@@ -109,4 +109,20 @@ extern unsigned long vm_map_base;
  */
 #define PHYSADDR(a)            ((_ACAST64_(a)) & TO_PHYS_MASK)
 
+/*
+ * On LoongArch, I/O ports mappring is following:
+ *
+ *              |         ....          |
+ *              |-----------------------|
+ *              | pci io ports(16K~32M) |
+ *              |-----------------------|
+ *              | isa io ports(0  ~16K) |
+ * PCI_IOBASE ->|-----------------------|
+ *              |         ....          |
+ */
+#define PCI_IOBASE     ((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
+#define PCI_IOSIZE     SZ_32M
+#define ISA_IOSIZE     SZ_16K
+#define IO_SPACE_LIMIT (PCI_IOSIZE - 1)
+
 #endif /* _ASM_ADDRSPACE_H */
index 0a9b0fa..ae19e33 100644 (file)
@@ -5,8 +5,9 @@
 #ifndef __ASM_CMPXCHG_H
 #define __ASM_CMPXCHG_H
 
-#include <asm/barrier.h>
+#include <linux/bits.h>
 #include <linux/build_bug.h>
+#include <asm/barrier.h>
 
 #define __xchg_asm(amswap_db, m, val)          \
 ({                                             \
                __ret;                          \
 })
 
+static inline unsigned int __xchg_small(volatile void *ptr, unsigned int val,
+                                       unsigned int size)
+{
+       unsigned int shift;
+       u32 old32, mask, temp;
+       volatile u32 *ptr32;
+
+       /* Mask value to the correct size. */
+       mask = GENMASK((size * BITS_PER_BYTE) - 1, 0);
+       val &= mask;
+
+       /*
+        * Calculate a shift & mask that correspond to the value we wish to
+        * exchange within the naturally aligned 4 byte integerthat includes
+        * it.
+        */
+       shift = (unsigned long)ptr & 0x3;
+       shift *= BITS_PER_BYTE;
+       mask <<= shift;
+
+       /*
+        * Calculate a pointer to the naturally aligned 4 byte integer that
+        * includes our byte of interest, and load its value.
+        */
+       ptr32 = (volatile u32 *)((unsigned long)ptr & ~0x3);
+
+       asm volatile (
+       "1:     ll.w            %0, %3          \n"
+       "       andn            %1, %0, %z4     \n"
+       "       or              %1, %1, %z5     \n"
+       "       sc.w            %1, %2          \n"
+       "       beqz            %1, 1b          \n"
+       : "=&r" (old32), "=&r" (temp), "=ZC" (*ptr32)
+       : "ZC" (*ptr32), "Jr" (mask), "Jr" (val << shift)
+       : "memory");
+
+       return (old32 & mask) >> shift;
+}
+
 static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
                                   int size)
 {
        switch (size) {
+       case 1:
+       case 2:
+               return __xchg_small(ptr, x, size);
+
        case 4:
                return __xchg_asm("amswap_db.w", (volatile u32 *)ptr, (u32)x);
 
@@ -67,10 +111,62 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
        __ret;                                                          \
 })
 
+static inline unsigned int __cmpxchg_small(volatile void *ptr, unsigned int old,
+                                          unsigned int new, unsigned int size)
+{
+       unsigned int shift;
+       u32 old32, mask, temp;
+       volatile u32 *ptr32;
+
+       /* Mask inputs to the correct size. */
+       mask = GENMASK((size * BITS_PER_BYTE) - 1, 0);
+       old &= mask;
+       new &= mask;
+
+       /*
+        * Calculate a shift & mask that correspond to the value we wish to
+        * compare & exchange within the naturally aligned 4 byte integer
+        * that includes it.
+        */
+       shift = (unsigned long)ptr & 0x3;
+       shift *= BITS_PER_BYTE;
+       old <<= shift;
+       new <<= shift;
+       mask <<= shift;
+
+       /*
+        * Calculate a pointer to the naturally aligned 4 byte integer that
+        * includes our byte of interest, and load its value.
+        */
+       ptr32 = (volatile u32 *)((unsigned long)ptr & ~0x3);
+
+       asm volatile (
+       "1:     ll.w            %0, %3          \n"
+       "       and             %1, %0, %z4     \n"
+       "       bne             %1, %z5, 2f     \n"
+       "       andn            %1, %0, %z4     \n"
+       "       or              %1, %1, %z6     \n"
+       "       sc.w            %1, %2          \n"
+       "       beqz            %1, 1b          \n"
+       "       b               3f              \n"
+       "2:                                     \n"
+       __WEAK_LLSC_MB
+       "3:                                     \n"
+       : "=&r" (old32), "=&r" (temp), "=ZC" (*ptr32)
+       : "ZC" (*ptr32), "Jr" (mask), "Jr" (old), "Jr" (new)
+       : "memory");
+
+       return (old32 & mask) >> shift;
+}
+
 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
                                      unsigned long new, unsigned int size)
 {
        switch (size) {
+       case 1:
+       case 2:
+               return __cmpxchg_small(ptr, old, new, size);
+
        case 4:
                return __cmpxchg_asm("ll.w", "sc.w", (volatile u32 *)ptr,
                                     (u32)old, new);
index 8845997..999944e 100644 (file)
@@ -7,34 +7,15 @@
 
 #define ARCH_HAS_IOREMAP_WC
 
-#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/bug.h>
-#include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/string.h>
 
-/*
- * On LoongArch, I/O ports mappring is following:
- *
- *              |         ....          |
- *              |-----------------------|
- *              | pci io ports(64K~32M) |
- *              |-----------------------|
- *              | isa io ports(0  ~16K) |
- * PCI_IOBASE ->|-----------------------|
- *              |         ....          |
- */
-#define PCI_IOBASE     ((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
-#define PCI_IOSIZE     SZ_32M
-#define ISA_IOSIZE     SZ_16K
-#define IO_SPACE_LIMIT (PCI_IOSIZE - 1)
-
 /*
  * Change "struct page" to physical address.
  */
index a37324a..53f284a 100644 (file)
@@ -95,7 +95,7 @@ static inline int pfn_valid(unsigned long pfn)
 
 #endif
 
-#define virt_to_pfn(kaddr)     PFN_DOWN(virt_to_phys((void *)(kaddr)))
+#define virt_to_pfn(kaddr)     PFN_DOWN(PHYSADDR(kaddr))
 #define virt_to_page(kaddr)    pfn_to_page(virt_to_pfn(kaddr))
 
 extern int __virt_addr_valid(volatile void *kaddr);
index e6569f1..0bd6b01 100644 (file)
@@ -123,6 +123,10 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
                                                int size)
 {
        switch (size) {
+       case 1:
+       case 2:
+               return __xchg_small((volatile void *)ptr, val, size);
+
        case 4:
                return __xchg_asm("amswap.w", (volatile u32 *)ptr, (u32)val);
 
@@ -204,9 +208,13 @@ do {                                                                       \
 #define this_cpu_write_4(pcp, val) _percpu_write(pcp, val)
 #define this_cpu_write_8(pcp, val) _percpu_write(pcp, val)
 
+#define this_cpu_xchg_1(pcp, val) _percpu_xchg(pcp, val)
+#define this_cpu_xchg_2(pcp, val) _percpu_xchg(pcp, val)
 #define this_cpu_xchg_4(pcp, val) _percpu_xchg(pcp, val)
 #define this_cpu_xchg_8(pcp, val) _percpu_xchg(pcp, val)
 
+#define this_cpu_cmpxchg_1(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
+#define this_cpu_cmpxchg_2(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
 #define this_cpu_cmpxchg_4(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
 #define this_cpu_cmpxchg_8(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
 
index e03443a..8ea57e2 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/mm_types.h>
 #include <linux/mmzone.h>
 #include <asm/fixmap.h>
-#include <asm/io.h>
 
 struct mm_struct;
 struct vm_area_struct;
@@ -145,7 +144,7 @@ static inline void set_p4d(p4d_t *p4d, p4d_t p4dval)
        *p4d = p4dval;
 }
 
-#define p4d_phys(p4d)          virt_to_phys((void *)p4d_val(p4d))
+#define p4d_phys(p4d)          PHYSADDR(p4d_val(p4d))
 #define p4d_page(p4d)          (pfn_to_page(p4d_phys(p4d) >> PAGE_SHIFT))
 
 #endif
@@ -188,7 +187,7 @@ static inline pmd_t *pud_pgtable(pud_t pud)
 
 #define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while (0)
 
-#define pud_phys(pud)          virt_to_phys((void *)pud_val(pud))
+#define pud_phys(pud)          PHYSADDR(pud_val(pud))
 #define pud_page(pud)          (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT))
 
 #endif
@@ -221,7 +220,7 @@ static inline void pmd_clear(pmd_t *pmdp)
 
 #define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while (0)
 
-#define pmd_phys(pmd)          virt_to_phys((void *)pmd_val(pmd))
+#define pmd_phys(pmd)          PHYSADDR(pmd_val(pmd))
 
 #ifndef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
diff --git a/arch/loongarch/include/asm/reboot.h b/arch/loongarch/include/asm/reboot.h
deleted file mode 100644 (file)
index 5115174..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
- */
-#ifndef _ASM_REBOOT_H
-#define _ASM_REBOOT_H
-
-extern void (*pm_restart)(void);
-
-#endif /* _ASM_REBOOT_H */
index 800c965..8c82021 100644 (file)
 #include <acpi/reboot.h>
 #include <asm/idle.h>
 #include <asm/loongarch.h>
-#include <asm/reboot.h>
 
-static void default_halt(void)
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+void machine_halt(void)
 {
+#ifdef CONFIG_SMP
+       preempt_disable();
+       smp_send_stop();
+#endif
        local_irq_disable();
        clear_csr_ecfg(ECFG0_IM);
 
@@ -30,18 +36,29 @@ static void default_halt(void)
        }
 }
 
-static void default_poweroff(void)
+void machine_power_off(void)
 {
+#ifdef CONFIG_SMP
+       preempt_disable();
+       smp_send_stop();
+#endif
+       do_kernel_power_off();
 #ifdef CONFIG_EFI
        efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
 #endif
+
        while (true) {
                __arch_cpu_idle();
        }
 }
 
-static void default_restart(void)
+void machine_restart(char *command)
 {
+#ifdef CONFIG_SMP
+       preempt_disable();
+       smp_send_stop();
+#endif
+       do_kernel_restart(command);
 #ifdef CONFIG_EFI
        if (efi_capsule_pending(NULL))
                efi_reboot(REBOOT_WARM, NULL);
@@ -55,47 +72,3 @@ static void default_restart(void)
                __arch_cpu_idle();
        }
 }
-
-void (*pm_restart)(void);
-EXPORT_SYMBOL(pm_restart);
-
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-void machine_halt(void)
-{
-#ifdef CONFIG_SMP
-       preempt_disable();
-       smp_send_stop();
-#endif
-       default_halt();
-}
-
-void machine_power_off(void)
-{
-#ifdef CONFIG_SMP
-       preempt_disable();
-       smp_send_stop();
-#endif
-       pm_power_off();
-}
-
-void machine_restart(char *command)
-{
-#ifdef CONFIG_SMP
-       preempt_disable();
-       smp_send_stop();
-#endif
-       do_kernel_restart(command);
-       pm_restart();
-}
-
-static int __init loongarch_reboot_setup(void)
-{
-       pm_restart = default_restart;
-       pm_power_off = default_poweroff;
-
-       return 0;
-}
-
-arch_initcall(loongarch_reboot_setup);
index 605579b..1ccd536 100644 (file)
@@ -216,6 +216,10 @@ good_area:
                return;
        }
 
+       /* The fault is fully completed (including releasing mmap lock) */
+       if (fault & VM_FAULT_COMPLETED)
+               return;
+
        if (unlikely(fault & VM_FAULT_RETRY)) {
                flags |= FAULT_FLAG_TRIED;
 
index 52e40f0..381a569 100644 (file)
@@ -2,16 +2,9 @@
 /*
  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  */
-#include <linux/compiler.h>
-#include <linux/elf-randomize.h>
-#include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/export.h>
-#include <linux/personality.h>
-#include <linux/random.h>
-#include <linux/sched/signal.h>
-#include <linux/sched/mm.h>
 
 unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
 EXPORT_SYMBOL(shm_align_mask);
@@ -120,6 +113,6 @@ int __virt_addr_valid(volatile void *kaddr)
        if ((vaddr < PAGE_OFFSET) || (vaddr >= vm_map_base))
                return 0;
 
-       return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
+       return pfn_valid(PFN_DOWN(PHYSADDR(kaddr)));
 }
 EXPORT_SYMBOL_GPL(__virt_addr_valid);
index 43a0078..e02e775 100644 (file)
@@ -24,6 +24,8 @@ static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
        return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE);
 }
 
+extern
+int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused);
 int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused)
 {
        int cpu_id;
index b1f4548..8f22863 100644 (file)
@@ -6,20 +6,23 @@
  */
 #include <linux/types.h>
 
-int __vdso_clock_gettime(clockid_t clock,
-                        struct __kernel_timespec *ts)
+extern
+int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts);
+int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
 {
        return __cvdso_clock_gettime(clock, ts);
 }
 
-int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
-                       struct timezone *tz)
+extern
+int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz);
+int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
 {
        return __cvdso_gettimeofday(tv, tz);
 }
 
-int __vdso_clock_getres(clockid_t clock_id,
-                       struct __kernel_timespec *res)
+extern
+int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res);
+int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res)
 {
        return __cvdso_clock_getres(clock_id, res);
 }
index 470aed9..e984af7 100644 (file)
@@ -157,11 +157,8 @@ arch___change_bit(unsigned long nr, volatile unsigned long *addr)
        change_bit(nr, addr);
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return (addr[nr >> 5] & (1UL << (nr & 31))) != 0;
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 static inline int bset_reg_test_and_set_bit(int nr,
                                            volatile unsigned long *vaddr)
index 0021427..4044f28 100644 (file)
@@ -53,8 +53,6 @@ CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 # CONFIG_FW_LOADER is not set
index 7a97a08..157fc57 100644 (file)
@@ -49,8 +49,6 @@ CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 # CONFIG_FW_LOADER is not set
index a064336..f73c26e 100644 (file)
@@ -48,8 +48,6 @@ CONFIG_IPV6_SUBTREES=y
 CONFIG_NETWORK_SECMARK=y
 CONFIG_IP_SCTP=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 # CONFIG_WIRELESS is not set
 # CONFIG_UEVENT_HELPER is not set
 # CONFIG_FW_LOADER is not set
index d82f4eb..ce8a444 100644 (file)
@@ -69,7 +69,6 @@ CONFIG_IP_NF_RAW=m
 CONFIG_IP_NF_ARPTABLES=m
 CONFIG_IP_NF_ARPFILTER=m
 CONFIG_IP_NF_ARP_MANGLE=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -99,7 +98,6 @@ CONFIG_ATM_MPOA=m
 CONFIG_ATM_BR2684=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
 CONFIG_LLC2=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
index 4194e79..1339c06 100644 (file)
@@ -116,7 +116,6 @@ CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -146,7 +145,6 @@ CONFIG_ATM_MPOA=m
 CONFIG_ATM_BR2684=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
 CONFIG_LLC2=m
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
index 7d6f235..04c681b 100644 (file)
@@ -116,7 +116,6 @@ CONFIG_IP6_NF_FILTER=m
 CONFIG_IP6_NF_TARGET_REJECT=m
 CONFIG_IP6_NF_MANGLE=m
 CONFIG_IP6_NF_RAW=m
-CONFIG_DECNET_NF_GRABULATOR=m
 CONFIG_BRIDGE_NF_EBTABLES=m
 CONFIG_BRIDGE_EBT_BROUTE=m
 CONFIG_BRIDGE_EBT_T_FILTER=m
@@ -137,7 +136,6 @@ CONFIG_BRIDGE_EBT_REDIRECT=m
 CONFIG_BRIDGE_EBT_SNAT=m
 CONFIG_BRIDGE_EBT_LOG=m
 CONFIG_BRIDGE=m
-CONFIG_DECNET=m
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_CBQ=m
 CONFIG_NET_SCH_HTB=m
index 9196782..a24f484 100644 (file)
@@ -243,8 +243,6 @@ CONFIG_ATM_LANE=m
 CONFIG_ATM_BR2684=m
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=m
-CONFIG_DECNET=m
-CONFIG_DECNET_ROUTER=y
 CONFIG_ATALK=m
 CONFIG_DEV_APPLETALK=m
 CONFIG_IPDDP=m
index 044982a..f3f87ed 100644 (file)
 
        phy1: ethernet-phy@9 {
                reg = <9>;
-               ti,fifo-depth = <0x1>;
        };
 
        phy0: ethernet-phy@8 {
                reg = <8>;
-               ti,fifo-depth = <0x1>;
        };
 };
 
        disable-wp;
        cap-sd-highspeed;
        cap-mmc-highspeed;
-       card-detect-delay = <200>;
        mmc-ddr-1_8v;
        mmc-hs200-1_8v;
        sd-uhs-sdr12;
index 82c93c8..c87cc2d 100644 (file)
 
        phy1: ethernet-phy@5 {
                reg = <5>;
-               ti,fifo-depth = <0x01>;
        };
 
        phy0: ethernet-phy@4 {
                reg = <4>;
-               ti,fifo-depth = <0x01>;
        };
 };
 
@@ -72,7 +70,6 @@
        disable-wp;
        cap-sd-highspeed;
        cap-mmc-highspeed;
-       card-detect-delay = <200>;
        mmc-ddr-1_8v;
        mmc-hs200-1_8v;
        sd-uhs-sdr12;
index 499c2e6..7449334 100644 (file)
                        cache-size = <2097152>;
                        cache-unified;
                        interrupt-parent = <&plic>;
-                       interrupts = <1>, <2>, <3>;
+                       interrupts = <1>, <3>, <4>, <2>;
                };
 
                clint: clint@2000000 {
                        ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
                        msi-parent = <&pcie>;
                        msi-controller;
-                       microchip,axi-m-atr0 = <0x10 0x0>;
                        status = "disabled";
-                       pcie_intc: legacy-interrupt-controller {
+                       pcie_intc: interrupt-controller {
                                #address-cells = <0>;
                                #interrupt-cells = <1>;
                                interrupt-controller;
diff --git a/arch/riscv/include/asm/signal.h b/arch/riscv/include/asm/signal.h
new file mode 100644 (file)
index 0000000..532c29e
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_SIGNAL_H
+#define __ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+#include <uapi/asm/ptrace.h>
+
+asmlinkage __visible
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
+
+#endif
index 78933ac..67322f8 100644 (file)
@@ -42,6 +42,8 @@
 
 #ifndef __ASSEMBLY__
 
+extern long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE / sizeof(long)];
+
 #include <asm/processor.h>
 #include <asm/csr.h>
 
index 38b05ca..5a2de6b 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <asm/ucontext.h>
 #include <asm/vdso.h>
+#include <asm/signal.h>
 #include <asm/signal32.h>
 #include <asm/switch_to.h>
 #include <asm/csr.h>
index 39d0f8b..635e6ec 100644 (file)
 
 #include <asm/asm-prototypes.h>
 #include <asm/bug.h>
+#include <asm/csr.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/csr.h>
+#include <asm/thread_info.h>
 
 int show_unhandled_signals = 1;
 
index 9a7d15d..2de74fc 100644 (file)
@@ -176,14 +176,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return old & mask;
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       const volatile unsigned long *p = __bitops_word(nr, addr);
-       unsigned long mask = __bitops_mask(nr);
-
-       return *p & mask;
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 static inline bool arch_test_and_set_bit_lock(unsigned long nr,
                                              volatile unsigned long *ptr)
index 89949b9..d5119e0 100644 (file)
@@ -91,6 +91,18 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 
        memcpy(dst, src, arch_task_struct_size);
        dst->thread.fpu.regs = dst->thread.fpu.fprs;
+
+       /*
+        * Don't transfer over the runtime instrumentation or the guarded
+        * storage control block pointers. These fields are cleared here instead
+        * of in copy_thread() to avoid premature freeing of associated memory
+        * on fork() failure. Wait to clear the RI flag because ->stack still
+        * refers to the source thread.
+        */
+       dst->thread.ri_cb = NULL;
+       dst->thread.gs_cb = NULL;
+       dst->thread.gs_bc_cb = NULL;
+
        return 0;
 }
 
@@ -150,13 +162,11 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
        frame->childregs.flags = 0;
        if (new_stackp)
                frame->childregs.gprs[15] = new_stackp;
-
-       /* Don't copy runtime instrumentation info */
-       p->thread.ri_cb = NULL;
+       /*
+        * Clear the runtime instrumentation flag after the above childregs
+        * copy. The CB pointer was already cleared in arch_dup_task_struct().
+        */
        frame->childregs.psw.mask &= ~PSW_MASK_RI;
-       /* Don't copy guarded storage control block */
-       p->thread.gs_cb = NULL;
-       p->thread.gs_bc_cb = NULL;
 
        /* Set a new TLS ?  */
        if (clone_flags & CLONE_SETTLS) {
index 1344994..09b6e75 100644 (file)
@@ -379,7 +379,9 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
        flags = FAULT_FLAG_DEFAULT;
        if (user_mode(regs))
                flags |= FAULT_FLAG_USER;
-       if (access == VM_WRITE || is_write)
+       if (is_write)
+               access = VM_WRITE;
+       if (access == VM_WRITE)
                flags |= FAULT_FLAG_WRITE;
        mmap_read_lock(mm);
 
index 565a85d..5ace89b 100644 (file)
@@ -135,16 +135,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return (old & mask) != 0;
 }
 
-/**
- * arch_test_bit - Determine whether a bit is set
- * @nr: bit number to test
- * @addr: Address to start counting from
- */
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 #include <asm-generic/bitops/non-instrumented-non-atomic.h>
 
index 4910bf2..62208ec 100644 (file)
@@ -132,7 +132,17 @@ void snp_set_page_private(unsigned long paddr);
 void snp_set_page_shared(unsigned long paddr);
 void sev_prep_identity_maps(unsigned long top_level_pgt);
 #else
-static inline void sev_enable(struct boot_params *bp) { }
+static inline void sev_enable(struct boot_params *bp)
+{
+       /*
+        * bp->cc_blob_address should only be set by boot/compressed kernel.
+        * Initialize it to 0 unconditionally (thus here in this stub too) to
+        * ensure that uninitialized values from buggy bootloaders aren't
+        * propagated.
+        */
+       if (bp)
+               bp->cc_blob_address = 0;
+}
 static inline void sev_es_shutdown_ghcb(void) { }
 static inline bool sev_es_check_ghcb_fault(unsigned long address)
 {
index 52f989f..c93930d 100644 (file)
@@ -276,6 +276,14 @@ void sev_enable(struct boot_params *bp)
        struct msr m;
        bool snp;
 
+       /*
+        * bp->cc_blob_address should only be set by boot/compressed kernel.
+        * Initialize it to 0 to ensure that uninitialized values from
+        * buggy bootloaders aren't propagated.
+        */
+       if (bp)
+               bp->cc_blob_address = 0;
+
        /*
         * Setup/preliminary detection of SNP. This will be sanity-checked
         * against CPUID/MSR values later.
index d9fc713..5812962 100644 (file)
@@ -14,7 +14,6 @@ CONFIG_CPU_FREQ=y
 
 # x86 xen specific config options
 CONFIG_XEN_PVH=y
-CONFIG_XEN_MAX_DOMAIN_MEMORY=500
 CONFIG_XEN_SAVE_RESTORE=y
 # CONFIG_XEN_DEBUG_FS is not set
 CONFIG_XEN_MCE_LOG=y
index 682338e..4dd1981 100644 (file)
@@ -311,7 +311,7 @@ SYM_CODE_START(entry_INT80_compat)
         * Interrupts are off on entry.
         */
        ASM_CLAC                        /* Do this early to minimize exposure */
-       SWAPGS
+       ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV
 
        /*
         * User tracing code (ptrace or signal handlers) might assume that
index 2db9349..cb98a05 100644 (file)
@@ -6291,10 +6291,8 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_aliases = NULL;
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.pebs_block = true;
-               x86_pmu.pebs_capable = ~0ULL;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-               x86_pmu.flags |= PMU_FL_PEBS_ALL;
                x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
                x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
 
@@ -6337,10 +6335,8 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_aliases = NULL;
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.pebs_block = true;
-               x86_pmu.pebs_capable = ~0ULL;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-               x86_pmu.flags |= PMU_FL_PEBS_ALL;
                x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
                x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
                x86_pmu.lbr_pt_coexist = true;
index ba60427..de1f55d 100644 (file)
@@ -291,6 +291,7 @@ static u64 load_latency_data(struct perf_event *event, u64 status)
 static u64 store_latency_data(struct perf_event *event, u64 status)
 {
        union intel_x86_pebs_dse dse;
+       union perf_mem_data_src src;
        u64 val;
 
        dse.val = status;
@@ -304,7 +305,14 @@ static u64 store_latency_data(struct perf_event *event, u64 status)
 
        val |= P(BLK, NA);
 
-       return val;
+       /*
+        * the pebs_data_source table is only for loads
+        * so override the mem_op to say STORE instead
+        */
+       src.val = val;
+       src.mem_op = P(OP,STORE);
+
+       return src.val;
 }
 
 struct pebs_record_core {
@@ -822,7 +830,7 @@ struct event_constraint intel_glm_pebs_event_constraints[] = {
 
 struct event_constraint intel_grt_pebs_event_constraints[] = {
        /* Allow all events as PEBS with no flags */
-       INTEL_HYBRID_LAT_CONSTRAINT(0x5d0, 0xf),
+       INTEL_HYBRID_LAT_CONSTRAINT(0x5d0, 0x3),
        INTEL_HYBRID_LAT_CONSTRAINT(0x6d0, 0xf),
        EVENT_CONSTRAINT_END
 };
@@ -2262,6 +2270,7 @@ void __init intel_ds_init(void)
                                        PERF_SAMPLE_BRANCH_STACK |
                                        PERF_SAMPLE_TIME;
                                x86_pmu.flags |= PMU_FL_PEBS_ALL;
+                               x86_pmu.pebs_capable = ~0ULL;
                                pebs_qual = "-baseline";
                                x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_EXTENDED_REGS;
                        } else {
index 4f70fb6..47fca6a 100644 (file)
@@ -1097,6 +1097,14 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
 
        if (static_cpu_has(X86_FEATURE_ARCH_LBR)) {
                reg->config = mask;
+
+               /*
+                * The Arch LBR HW can retrieve the common branch types
+                * from the LBR_INFO. It doesn't require the high overhead
+                * SW disassemble.
+                * Enable the branch type by default for the Arch LBR.
+                */
+               reg->reg |= X86_BR_TYPE_SAVE;
                return 0;
        }
 
index ce44001..1ef4f78 100644 (file)
@@ -841,6 +841,22 @@ int snb_pci2phy_map_init(int devid)
        return 0;
 }
 
+static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       /*
+        * SNB IMC counters are 32-bit and are laid out back to back
+        * in MMIO space. Therefore we must use a 32-bit accessor function
+        * using readq() from uncore_mmio_read_counter() causes problems
+        * because it is reading 64-bit at a time. This is okay for the
+        * uncore_perf_event_update() function because it drops the upper
+        * 32-bits but not okay for plain uncore_read_counter() as invoked
+        * in uncore_pmu_event_start().
+        */
+       return (u64)readl(box->io_addr + hwc->event_base);
+}
+
 static struct pmu snb_uncore_imc_pmu = {
        .task_ctx_nr    = perf_invalid_context,
        .event_init     = snb_uncore_imc_event_init,
@@ -860,7 +876,7 @@ static struct intel_uncore_ops snb_uncore_imc_ops = {
        .disable_event  = snb_uncore_imc_disable_event,
        .enable_event   = snb_uncore_imc_enable_event,
        .hw_config      = snb_uncore_imc_hw_config,
-       .read_counter   = uncore_mmio_read_counter,
+       .read_counter   = snb_uncore_imc_read_counter,
 };
 
 static struct intel_uncore_type snb_uncore_imc = {
index 973c6bd..0fe9de5 100644 (file)
@@ -207,6 +207,20 @@ static __always_inline bool constant_test_bit(long nr, const volatile unsigned l
                (addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
 }
 
+static __always_inline bool constant_test_bit_acquire(long nr, const volatile unsigned long *addr)
+{
+       bool oldbit;
+
+       asm volatile("testb %2,%1"
+                    CC_SET(nz)
+                    : CC_OUT(nz) (oldbit)
+                    : "m" (((unsigned char *)addr)[nr >> 3]),
+                      "i" (1 << (nr & 7))
+                    :"memory");
+
+       return oldbit;
+}
+
 static __always_inline bool variable_test_bit(long nr, volatile const unsigned long *addr)
 {
        bool oldbit;
@@ -226,6 +240,13 @@ arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
                                          variable_test_bit(nr, addr);
 }
 
+static __always_inline bool
+arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       return __builtin_constant_p(nr) ? constant_test_bit_acquire(nr, addr) :
+                                         variable_test_bit(nr, addr);
+}
+
 /**
  * __ffs - find first set bit in word
  * @word: The word to search
index 235dc85..ef4775c 100644 (file)
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 #define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
 #define X86_BUG_MMIO_STALE_DATA                X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
-#define X86_BUG_RETBLEED               X86_BUG(26) /* CPU is affected by RETBleed */
-#define X86_BUG_EIBRS_PBRSB            X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
+#define X86_BUG_MMIO_UNKNOWN           X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
+#define X86_BUG_RETBLEED               X86_BUG(27) /* CPU is affected by RETBleed */
+#define X86_BUG_EIBRS_PBRSB            X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index def6ca1..aeb3802 100644 (file)
@@ -27,6 +27,7 @@
  *             _X      - regular server parts
  *             _D      - micro server parts
  *             _N,_P   - other mobile parts
+ *             _S      - other client parts
  *
  *             Historical OPTDIFFs:
  *
 
 #define INTEL_FAM6_RAPTORLAKE          0xB7
 #define INTEL_FAM6_RAPTORLAKE_P                0xBA
+#define INTEL_FAM6_RAPTORLAKE_S                0xBF
 
 /* "Small Core" Processors (Atom) */
 
index e64fd20..c936ce9 100644 (file)
 #define RSB_CLEAR_LOOPS                32      /* To forcibly overwrite all entries */
 
 /*
+ * Common helper for __FILL_RETURN_BUFFER and __FILL_ONE_RETURN.
+ */
+#define __FILL_RETURN_SLOT                     \
+       ANNOTATE_INTRA_FUNCTION_CALL;           \
+       call    772f;                           \
+       int3;                                   \
+772:
+
+/*
+ * Stuff the entire RSB.
+ *
  * Google experimented with loop-unrolling and this turned out to be
  * the optimal version - two calls, each with their own speculation
  * trap should their return address end up getting used, in a loop.
  */
-#define __FILL_RETURN_BUFFER(reg, nr, sp)      \
-       mov     $(nr/2), reg;                   \
-771:                                           \
-       ANNOTATE_INTRA_FUNCTION_CALL;           \
-       call    772f;                           \
-773:   /* speculation trap */                  \
-       UNWIND_HINT_EMPTY;                      \
-       pause;                                  \
-       lfence;                                 \
-       jmp     773b;                           \
-772:                                           \
-       ANNOTATE_INTRA_FUNCTION_CALL;           \
-       call    774f;                           \
-775:   /* speculation trap */                  \
-       UNWIND_HINT_EMPTY;                      \
-       pause;                                  \
-       lfence;                                 \
-       jmp     775b;                           \
-774:                                           \
-       add     $(BITS_PER_LONG/8) * 2, sp;     \
-       dec     reg;                            \
-       jnz     771b;                           \
-       /* barrier for jnz misprediction */     \
+#ifdef CONFIG_X86_64
+#define __FILL_RETURN_BUFFER(reg, nr)                  \
+       mov     $(nr/2), reg;                           \
+771:                                                   \
+       __FILL_RETURN_SLOT                              \
+       __FILL_RETURN_SLOT                              \
+       add     $(BITS_PER_LONG/8) * 2, %_ASM_SP;       \
+       dec     reg;                                    \
+       jnz     771b;                                   \
+       /* barrier for jnz misprediction */             \
+       lfence;
+#else
+/*
+ * i386 doesn't unconditionally have LFENCE, as such it can't
+ * do a loop.
+ */
+#define __FILL_RETURN_BUFFER(reg, nr)                  \
+       .rept nr;                                       \
+       __FILL_RETURN_SLOT;                             \
+       .endr;                                          \
+       add     $(BITS_PER_LONG/8) * nr, %_ASM_SP;
+#endif
+
+/*
+ * Stuff a single RSB slot.
+ *
+ * To mitigate Post-Barrier RSB speculation, one CALL instruction must be
+ * forced to retire before letting a RET instruction execute.
+ *
+ * On PBRSB-vulnerable CPUs, it is not safe for a RET to be executed
+ * before this point.
+ */
+#define __FILL_ONE_RETURN                              \
+       __FILL_RETURN_SLOT                              \
+       add     $(BITS_PER_LONG/8), %_ASM_SP;           \
        lfence;
 
 #ifdef __ASSEMBLY__
 #endif
 .endm
 
-.macro ISSUE_UNBALANCED_RET_GUARD
-       ANNOTATE_INTRA_FUNCTION_CALL
-       call .Lunbalanced_ret_guard_\@
-       int3
-.Lunbalanced_ret_guard_\@:
-       add $(BITS_PER_LONG/8), %_ASM_SP
-       lfence
-.endm
-
  /*
   * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP
   * monstrosity above, manually.
   */
-.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2
-.ifb \ftr2
-       ALTERNATIVE "jmp .Lskip_rsb_\@", "", \ftr
-.else
-       ALTERNATIVE_2 "jmp .Lskip_rsb_\@", "", \ftr, "jmp .Lunbalanced_\@", \ftr2
-.endif
-       __FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP)
-.Lunbalanced_\@:
-       ISSUE_UNBALANCED_RET_GUARD
+.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2=ALT_NOT(X86_FEATURE_ALWAYS)
+       ALTERNATIVE_2 "jmp .Lskip_rsb_\@", \
+               __stringify(__FILL_RETURN_BUFFER(\reg,\nr)), \ftr, \
+               __stringify(__FILL_ONE_RETURN), \ftr2
+
 .Lskip_rsb_\@:
 .endm
 
index 4a23e52..ebc271b 100644 (file)
@@ -195,7 +195,7 @@ void snp_set_memory_shared(unsigned long vaddr, unsigned int npages);
 void snp_set_memory_private(unsigned long vaddr, unsigned int npages);
 void snp_set_wakeup_secondary_cpu(void);
 bool snp_init(struct boot_params *bp);
-void snp_abort(void);
+void __init __noreturn snp_abort(void);
 int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err);
 #else
 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
index 510d852..da7c361 100644 (file)
@@ -433,7 +433,8 @@ static void __init mmio_select_mitigation(void)
        u64 ia32_cap;
 
        if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
-           cpu_mitigations_off()) {
+            boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
+            cpu_mitigations_off()) {
                mmio_mitigation = MMIO_MITIGATION_OFF;
                return;
        }
@@ -538,6 +539,8 @@ out:
                pr_info("TAA: %s\n", taa_strings[taa_mitigation]);
        if (boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
                pr_info("MMIO Stale Data: %s\n", mmio_strings[mmio_mitigation]);
+       else if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+               pr_info("MMIO Stale Data: Unknown: No mitigations\n");
 }
 
 static void __init md_clear_select_mitigation(void)
@@ -2275,6 +2278,9 @@ static ssize_t tsx_async_abort_show_state(char *buf)
 
 static ssize_t mmio_stale_data_show_state(char *buf)
 {
+       if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+               return sysfs_emit(buf, "Unknown: No mitigations\n");
+
        if (mmio_mitigation == MMIO_MITIGATION_OFF)
                return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
 
@@ -2421,6 +2427,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                return srbds_show_state(buf);
 
        case X86_BUG_MMIO_STALE_DATA:
+       case X86_BUG_MMIO_UNKNOWN:
                return mmio_stale_data_show_state(buf);
 
        case X86_BUG_RETBLEED:
@@ -2480,7 +2487,10 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *
 
 ssize_t cpu_show_mmio_stale_data(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
+       if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+               return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_UNKNOWN);
+       else
+               return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
 }
 
 ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, char *buf)
index 64a73f4..3e508f2 100644 (file)
@@ -1135,7 +1135,8 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
 #define NO_SWAPGS              BIT(6)
 #define NO_ITLB_MULTIHIT       BIT(7)
 #define NO_SPECTRE_V2          BIT(8)
-#define NO_EIBRS_PBRSB         BIT(9)
+#define NO_MMIO                        BIT(9)
+#define NO_EIBRS_PBRSB         BIT(10)
 
 #define VULNWL(vendor, family, model, whitelist)       \
        X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist)
@@ -1158,6 +1159,11 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL(VORTEX,  6, X86_MODEL_ANY,       NO_SPECULATION),
 
        /* Intel Family 6 */
+       VULNWL_INTEL(TIGERLAKE,                 NO_MMIO),
+       VULNWL_INTEL(TIGERLAKE_L,               NO_MMIO),
+       VULNWL_INTEL(ALDERLAKE,                 NO_MMIO),
+       VULNWL_INTEL(ALDERLAKE_L,               NO_MMIO),
+
        VULNWL_INTEL(ATOM_SALTWELL,             NO_SPECULATION | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_SALTWELL_TABLET,      NO_SPECULATION | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_SALTWELL_MID,         NO_SPECULATION | NO_ITLB_MULTIHIT),
@@ -1176,9 +1182,9 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL_INTEL(ATOM_AIRMONT_MID,          NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_AIRMONT_NP,           NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
 
-       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_INTEL(ATOM_GOLDMONT_D,           NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
+       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_INTEL(ATOM_GOLDMONT_D,           NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
 
        /*
         * Technically, swapgs isn't serializing on AMD (despite it previously
@@ -1193,18 +1199,18 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL_INTEL(ATOM_TREMONT_D,            NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
 
        /* AMD Family 0xf - 0x12 */
-       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
+       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
 
        /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
-       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
+       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
 
        /* Zhaoxin Family 7 */
-       VULNWL(CENTAUR, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS),
-       VULNWL(ZHAOXIN, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS),
+       VULNWL(CENTAUR, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
+       VULNWL(ZHAOXIN, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
        {}
 };
 
@@ -1358,10 +1364,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
         * Affected CPU list is generally enough to enumerate the vulnerability,
         * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
         * not want the guest to enumerate the bug.
+        *
+        * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist,
+        * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits.
         */
-       if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
-           !arch_cap_mmio_immune(ia32_cap))
-               setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+       if (!arch_cap_mmio_immune(ia32_cap)) {
+               if (cpu_matches(cpu_vuln_blacklist, MMIO))
+                       setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+               else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
+                       setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
+       }
 
        if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
                if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
index 63dc626..a428c62 100644 (file)
@@ -701,7 +701,13 @@ e_term:
 void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
                                         unsigned int npages)
 {
-       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+       /*
+        * This can be invoked in early boot while running identity mapped, so
+        * use an open coded check for SNP instead of using cc_platform_has().
+        * This eliminates worries about jump tables or checking boot_cpu_data
+        * in the cc_platform_has() function.
+        */
+       if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
                return;
 
         /*
@@ -717,7 +723,13 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
 void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
                                        unsigned int npages)
 {
-       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+       /*
+        * This can be invoked in early boot while running identity mapped, so
+        * use an open coded check for SNP instead of using cc_platform_has().
+        * This eliminates worries about jump tables or checking boot_cpu_data
+        * in the cc_platform_has() function.
+        */
+       if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
                return;
 
        /* Invalidate the memory pages before they are marked shared in the RMP table. */
@@ -2100,7 +2112,7 @@ bool __init snp_init(struct boot_params *bp)
        return true;
 }
 
-void __init snp_abort(void)
+void __init __noreturn snp_abort(void)
 {
        sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
 }
index 38185ae..0ea57da 100644 (file)
@@ -93,22 +93,27 @@ static struct orc_entry *orc_find(unsigned long ip);
 static struct orc_entry *orc_ftrace_find(unsigned long ip)
 {
        struct ftrace_ops *ops;
-       unsigned long caller;
+       unsigned long tramp_addr, offset;
 
        ops = ftrace_ops_trampoline(ip);
        if (!ops)
                return NULL;
 
+       /* Set tramp_addr to the start of the code copied by the trampoline */
        if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
-               caller = (unsigned long)ftrace_regs_call;
+               tramp_addr = (unsigned long)ftrace_regs_caller;
        else
-               caller = (unsigned long)ftrace_call;
+               tramp_addr = (unsigned long)ftrace_caller;
+
+       /* Now place tramp_addr to the location within the trampoline ip is at */
+       offset = ip - ops->trampoline;
+       tramp_addr += offset;
 
        /* Prevent unlikely recursion */
-       if (ip == caller)
+       if (ip == tramp_addr)
                return NULL;
 
-       return orc_find(caller);
+       return orc_find(tramp_addr);
 }
 #else
 static struct orc_entry *orc_ftrace_find(unsigned long ip)
index d5ef64d..66a209f 100644 (file)
@@ -62,6 +62,7 @@
 
 static bool __read_mostly pat_bp_initialized;
 static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT);
+static bool __initdata pat_force_disabled = !IS_ENABLED(CONFIG_X86_PAT);
 static bool __read_mostly pat_bp_enabled;
 static bool __read_mostly pat_cm_initialized;
 
@@ -86,6 +87,7 @@ void pat_disable(const char *msg_reason)
 static int __init nopat(char *str)
 {
        pat_disable("PAT support disabled via boot option.");
+       pat_force_disabled = true;
        return 0;
 }
 early_param("nopat", nopat);
@@ -272,7 +274,7 @@ static void pat_ap_init(u64 pat)
        wrmsrl(MSR_IA32_CR_PAT, pat);
 }
 
-void init_cache_modes(void)
+void __init init_cache_modes(void)
 {
        u64 pat = 0;
 
@@ -313,6 +315,12 @@ void init_cache_modes(void)
                 */
                pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
                      PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
+       } else if (!pat_force_disabled && cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) {
+               /*
+                * Clearly PAT is enabled underneath. Allow pat_enabled() to
+                * reflect this.
+                */
+               pat_bp_enabled = true;
        }
 
        __init_cache_modes(pat);
index 3c1e6b6..c96c8c4 100644 (file)
@@ -1931,7 +1931,8 @@ out:
        /* If we didn't flush the entire list, we could have told the driver
         * there was more coming, but that turned out to be a lie.
         */
-       if ((!list_empty(list) || errors) && q->mq_ops->commit_rqs && queued)
+       if ((!list_empty(list) || errors || needs_resource ||
+            ret == BLK_STS_DEV_RESOURCE) && q->mq_ops->commit_rqs && queued)
                q->mq_ops->commit_rqs(hctx);
        /*
         * Any items that need requeuing? Stuff them into hctx->dispatch,
@@ -2660,6 +2661,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                list_del_init(&rq->queuelist);
                ret = blk_mq_request_issue_directly(rq, list_empty(list));
                if (ret != BLK_STS_OK) {
+                       errors++;
                        if (ret == BLK_STS_RESOURCE ||
                                        ret == BLK_STS_DEV_RESOURCE) {
                                blk_mq_request_bypass_insert(rq, false,
@@ -2667,7 +2669,6 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                                break;
                        }
                        blk_mq_end_request(rq, ret);
-                       errors++;
                } else
                        queued++;
        }
index db6ac54..e534fd4 100644 (file)
@@ -151,7 +151,7 @@ void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
        unsigned int cpu;
 
        for_each_cpu(cpu, policy->related_cpus) {
-               struct acpi_processor *pr = per_cpu(processors, policy->cpu);
+               struct acpi_processor *pr = per_cpu(processors, cpu);
 
                if (pr)
                        freq_qos_remove_request(&pr->thermal_req);
index 7b3ad8e..d4c168c 100644 (file)
@@ -370,7 +370,7 @@ static bool acpi_tie_nondev_subnodes(struct acpi_device_data *data)
                bool ret;
 
                status = acpi_attach_data(dn->handle, acpi_nondev_subnode_tag, dn);
-               if (ACPI_FAILURE(status)) {
+               if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
                        acpi_handle_err(dn->handle, "Can't tag data node\n");
                        return false;
                }
@@ -1043,11 +1043,10 @@ static int acpi_data_prop_read_single(const struct acpi_device_data *data,
                                break;                                  \
                        }                                               \
                        if (__items[i].integer.value > _Generic(__val,  \
-                                                               u8: U8_MAX, \
-                                                               u16: U16_MAX, \
-                                                               u32: U32_MAX, \
-                                                               u64: U64_MAX, \
-                                                               default: 0U)) { \
+                                                               u8 *: U8_MAX, \
+                                                               u16 *: U16_MAX, \
+                                                               u32 *: U32_MAX, \
+                                                               u64 *: U64_MAX)) { \
                                ret = -EOVERFLOW;                       \
                                break;                                  \
                        }                                               \
index 1014beb..51f4e1c 100644 (file)
@@ -402,12 +402,15 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
        size_t size, data_offsets_size;
        int ret;
 
+       mmap_read_lock(alloc->vma_vm_mm);
        if (!binder_alloc_get_vma(alloc)) {
+               mmap_read_unlock(alloc->vma_vm_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->vma_vm_mm);
 
        data_offsets_size = ALIGN(data_size, sizeof(void *)) +
                ALIGN(offsets_size, sizeof(void *));
@@ -929,17 +932,25 @@ void binder_alloc_print_pages(struct seq_file *m,
         * Make sure the binder_alloc is fully initialized, otherwise we might
         * read inconsistent state.
         */
-       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++;
-               }
+
+       mmap_read_lock(alloc->vma_vm_mm);
+       if (binder_alloc_get_vma(alloc) == NULL) {
+               mmap_read_unlock(alloc->vma_vm_mm);
+               goto uninitialized;
        }
+
+       mmap_read_unlock(alloc->vma_vm_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++;
+       }
+
+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);
index e3c0ba9..ad92192 100644 (file)
@@ -979,6 +979,11 @@ loop_set_status_from_info(struct loop_device *lo,
 
        lo->lo_offset = info->lo_offset;
        lo->lo_sizelimit = info->lo_sizelimit;
+
+       /* loff_t vars have been assigned __u64 */
+       if (lo->lo_offset < 0 || lo->lo_sizelimit < 0)
+               return -EOVERFLOW;
+
        memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
        lo->lo_file_name[LO_NAME_SIZE-1] = 0;
        lo->lo_flags = info->lo_flags;
index 2a709da..6cec9ce 100644 (file)
@@ -2322,6 +2322,7 @@ static struct genl_family nbd_genl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = nbd_connect_genl_ops,
        .n_small_ops    = ARRAY_SIZE(nbd_connect_genl_ops),
+       .resv_start_op  = NBD_CMD_STATUS + 1,
        .maxattr        = NBD_ATTR_MAX,
        .policy = nbd_attr_policy,
        .mcgrps         = nbd_mcast_grps,
index 84ca98e..32a932a 100644 (file)
@@ -480,6 +480,11 @@ static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out,
        return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
 }
 
+static int uring_cmd_null(struct io_uring_cmd *ioucmd, unsigned int issue_flags)
+{
+       return 0;
+}
+
 static ssize_t read_iter_zero(struct kiocb *iocb, struct iov_iter *iter)
 {
        size_t written = 0;
@@ -663,6 +668,7 @@ static const struct file_operations null_fops = {
        .read_iter      = read_iter_null,
        .write_iter     = write_iter_null,
        .splice_write   = splice_write_null,
+       .uring_cmd      = uring_cmd_null,
 };
 
 static const struct file_operations __maybe_unused port_fops = {
index 7820c4e..69b3d61 100644 (file)
@@ -532,7 +532,7 @@ static unsigned int __resolve_freq(struct cpufreq_policy *policy,
 
        target_freq = clamp_val(target_freq, policy->min, policy->max);
 
-       if (!cpufreq_driver->target_index)
+       if (!policy->freq_table)
                return target_freq;
 
        idx = cpufreq_frequency_table_target(policy, target_freq, relation);
index e8a0b19..f095a25 100644 (file)
@@ -2456,12 +2456,14 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                        if (!hive->reset_domain ||
                            !amdgpu_reset_get_reset_domain(hive->reset_domain)) {
                                r = -ENOENT;
+                               amdgpu_put_xgmi_hive(hive);
                                goto init_failed;
                        }
 
                        /* Drop the early temporary reset domain we created for device */
                        amdgpu_reset_put_reset_domain(adev->reset_domain);
                        adev->reset_domain = hive->reset_domain;
+                       amdgpu_put_xgmi_hive(hive);
                }
        }
 
@@ -4413,8 +4415,6 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
 retry:
        amdgpu_amdkfd_pre_reset(adev);
 
-       amdgpu_amdkfd_pre_reset(adev);
-
        if (from_hypervisor)
                r = amdgpu_virt_request_full_gpu(adev, true);
        else
index b067ce4..1036446 100644 (file)
@@ -2641,6 +2641,9 @@ static int psp_hw_fini(void *handle)
                psp_rap_terminate(psp);
                psp_dtm_terminate(psp);
                psp_hdcp_terminate(psp);
+
+               if (adev->gmc.xgmi.num_physical_nodes > 1)
+                       psp_xgmi_terminate(psp);
        }
 
        psp_asd_terminate(psp);
index 1b108d0..f2aebbf 100644 (file)
@@ -742,7 +742,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
                amdgpu_put_xgmi_hive(hive);
        }
 
-       return psp_xgmi_terminate(&adev->psp);
+       return 0;
 }
 
 static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)
index 158d87e..f6b1bb4 100644 (file)
@@ -131,6 +131,8 @@ static void gfx_v11_0_ring_invalidate_tlbs(struct amdgpu_ring *ring,
                                           bool all_hub, uint8_t dst_sel);
 static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev);
 static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev);
+static void gfx_v11_0_update_perf_clk(struct amdgpu_device *adev,
+                                     bool enable);
 
 static void gfx11_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue_mask)
 {
@@ -1139,6 +1141,7 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
        .read_wave_vgprs = &gfx_v11_0_read_wave_vgprs,
        .select_me_pipe_q = &gfx_v11_0_select_me_pipe_q,
        .init_spm_golden = &gfx_v11_0_init_spm_golden_registers,
+       .update_perfmon_mgcg = &gfx_v11_0_update_perf_clk,
 };
 
 static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
@@ -5182,9 +5185,12 @@ static void gfx_v11_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
                data = REG_SET_FIELD(data, SDMA0_RLC_CGCG_CTRL, CGCG_INT_ENABLE, 1);
                WREG32_SOC15(GC, 0, regSDMA0_RLC_CGCG_CTRL, data);
 
-               data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
-               data = REG_SET_FIELD(data, SDMA1_RLC_CGCG_CTRL, CGCG_INT_ENABLE, 1);
-               WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               /* Some ASICs only have one SDMA instance, not need to configure SDMA1 */
+               if (adev->sdma.num_instances > 1) {
+                       data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
+                       data = REG_SET_FIELD(data, SDMA1_RLC_CGCG_CTRL, CGCG_INT_ENABLE, 1);
+                       WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               }
        } else {
                /* Program RLC_CGCG_CGLS_CTRL */
                def = data = RREG32_SOC15(GC, 0, regRLC_CGCG_CGLS_CTRL);
@@ -5213,9 +5219,12 @@ static void gfx_v11_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
                data &= ~SDMA0_RLC_CGCG_CTRL__CGCG_INT_ENABLE_MASK;
                WREG32_SOC15(GC, 0, regSDMA0_RLC_CGCG_CTRL, data);
 
-               data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
-               data &= ~SDMA1_RLC_CGCG_CTRL__CGCG_INT_ENABLE_MASK;
-               WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               /* Some ASICs only have one SDMA instance, not need to configure SDMA1 */
+               if (adev->sdma.num_instances > 1) {
+                       data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
+                       data &= ~SDMA1_RLC_CGCG_CTRL__CGCG_INT_ENABLE_MASK;
+                       WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               }
        }
 }
 
@@ -5328,8 +5337,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
                break;
        case IP_VERSION(11, 0, 1):
                gfx_v11_cntl_pg(adev, enable);
-               /* TODO: Enable this when GFXOFF is ready */
-               // amdgpu_gfx_off_ctrl(adev, enable);
+               amdgpu_gfx_off_ctrl(adev, enable);
                break;
        default:
                break;
index c6e0f93..fc9c104 100644 (file)
@@ -2587,7 +2587,8 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
 
        gfx_v9_0_tiling_mode_table_init(adev);
 
-       gfx_v9_0_setup_rb(adev);
+       if (adev->gfx.num_gfx_rings)
+               gfx_v9_0_setup_rb(adev);
        gfx_v9_0_get_cu_info(adev, &adev->gfx.cu_info);
        adev->gfx.config.db_debug2 = RREG32_SOC15(GC, 0, mmDB_DEBUG2);
 
index 3f44a09..3e51e77 100644 (file)
@@ -176,6 +176,7 @@ static void mmhub_v1_0_init_cache_regs(struct amdgpu_device *adev)
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
        WREG32_SOC15(MMHUB, 0, mmVM_L2_CNTL2, tmp);
 
+       tmp = mmVM_L2_CNTL3_DEFAULT;
        if (adev->gmc.translate_further) {
                tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
                tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
index 6e0145b..445cb06 100644 (file)
@@ -295,9 +295,17 @@ static void mmhub_v9_4_disable_identity_aperture(struct amdgpu_device *adev,
 static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
 {
        struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+       unsigned int num_level, block_size;
        uint32_t tmp;
        int i;
 
+       num_level = adev->vm_manager.num_level;
+       block_size = adev->vm_manager.block_size;
+       if (adev->gmc.translate_further)
+               num_level -= 1;
+       else
+               block_size -= 9;
+
        for (i = 0; i <= 14; i++) {
                tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmVML2VC0_VM_CONTEXT1_CNTL,
                                hubid * MMHUB_INSTANCE_REGISTER_OFFSET + i);
@@ -305,7 +313,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
                                    ENABLE_CONTEXT, 1);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    PAGE_TABLE_DEPTH,
-                                   adev->vm_manager.num_level);
+                                   num_level);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
@@ -323,7 +331,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
                                    EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    PAGE_TABLE_BLOCK_SIZE,
-                                   adev->vm_manager.block_size - 9);
+                                   block_size);
                /* Send no-retry XNACK on fault to suppress VM fault storm. */
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
index 01e8288..1dc95ef 100644 (file)
@@ -247,6 +247,81 @@ static void nbio_v7_7_init_registers(struct amdgpu_device *adev)
 
 }
 
+static void nbio_v7_7_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+                                                      bool enable)
+{
+       uint32_t def, data;
+
+       if (enable && !(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG))
+               return;
+
+       def = data = RREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL);
+       if (enable) {
+               data |= (BIF0_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
+       } else {
+               data &= ~(BIF0_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
+       }
+
+       if (def != data)
+               WREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL, data);
+}
+
+static void nbio_v7_7_update_medium_grain_light_sleep(struct amdgpu_device *adev,
+                                                     bool enable)
+{
+       uint32_t def, data;
+
+       if (enable && !(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
+               return;
+
+       def = data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2);
+       if (enable)
+               data |= BIF0_PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
+       else
+               data &= ~BIF0_PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
+
+       if (def != data)
+               WREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2, data);
+
+       def = data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_TX_POWER_CTRL_1);
+       if (enable) {
+               data |= (BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
+                       BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
+       } else {
+               data &= ~(BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
+                       BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
+       }
+
+       if (def != data)
+               WREG32_SOC15(NBIO, 0, regBIF0_PCIE_TX_POWER_CTRL_1, data);
+}
+
+static void nbio_v7_7_get_clockgating_state(struct amdgpu_device *adev,
+                                           u64 *flags)
+{
+       uint32_t data;
+
+       /* AMD_CG_SUPPORT_BIF_MGCG */
+       data = RREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL);
+       if (data & BIF0_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK)
+               *flags |= AMD_CG_SUPPORT_BIF_MGCG;
+
+       /* AMD_CG_SUPPORT_BIF_LS */
+       data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2);
+       if (data & BIF0_PCIE_CNTL2__SLV_MEM_LS_EN_MASK)
+               *flags |= AMD_CG_SUPPORT_BIF_LS;
+}
+
 const struct amdgpu_nbio_funcs nbio_v7_7_funcs = {
        .get_hdp_flush_req_offset = nbio_v7_7_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v7_7_get_hdp_flush_done_offset,
@@ -262,6 +337,9 @@ const struct amdgpu_nbio_funcs nbio_v7_7_funcs = {
        .enable_doorbell_aperture = nbio_v7_7_enable_doorbell_aperture,
        .enable_doorbell_selfring_aperture = nbio_v7_7_enable_doorbell_selfring_aperture,
        .ih_doorbell_range = nbio_v7_7_ih_doorbell_range,
+       .update_medium_grain_clock_gating = nbio_v7_7_update_medium_grain_clock_gating,
+       .update_medium_grain_light_sleep = nbio_v7_7_update_medium_grain_light_sleep,
+       .get_clockgating_state = nbio_v7_7_get_clockgating_state,
        .ih_control = nbio_v7_7_ih_control,
        .init_registers = nbio_v7_7_init_registers,
 };
index 1ff7fc7..55284b2 100644 (file)
@@ -494,6 +494,20 @@ static void soc21_pre_asic_init(struct amdgpu_device *adev)
 {
 }
 
+static int soc21_update_umd_stable_pstate(struct amdgpu_device *adev,
+                                         bool enter)
+{
+       if (enter)
+               amdgpu_gfx_rlc_enter_safe_mode(adev);
+       else
+               amdgpu_gfx_rlc_exit_safe_mode(adev);
+
+       if (adev->gfx.funcs->update_perfmon_mgcg)
+               adev->gfx.funcs->update_perfmon_mgcg(adev, !enter);
+
+       return 0;
+}
+
 static const struct amdgpu_asic_funcs soc21_asic_funcs =
 {
        .read_disabled_bios = &soc21_read_disabled_bios,
@@ -513,6 +527,7 @@ static const struct amdgpu_asic_funcs soc21_asic_funcs =
        .supports_baco = &amdgpu_dpm_is_baco_supported,
        .pre_asic_init = &soc21_pre_asic_init,
        .query_video_codecs = &soc21_query_video_codecs,
+       .update_umd_stable_pstate = &soc21_update_umd_stable_pstate,
 };
 
 static int soc21_common_early_init(void *handle)
@@ -603,6 +618,8 @@ static int soc21_common_early_init(void *handle)
                        AMD_CG_SUPPORT_ATHUB_MGCG |
                        AMD_CG_SUPPORT_ATHUB_LS |
                        AMD_CG_SUPPORT_IH_CG |
+                       AMD_CG_SUPPORT_BIF_MGCG |
+                       AMD_CG_SUPPORT_BIF_LS |
                        AMD_CG_SUPPORT_VCN_MGCG |
                        AMD_CG_SUPPORT_JPEG_MGCG;
                adev->pg_flags =
@@ -702,6 +719,7 @@ static int soc21_common_set_clockgating_state(void *handle,
        switch (adev->ip_versions[NBIO_HWIP][0]) {
        case IP_VERSION(4, 3, 0):
        case IP_VERSION(4, 3, 1):
+       case IP_VERSION(7, 7, 0):
                adev->nbio.funcs->update_medium_grain_clock_gating(adev,
                                state == AMD_CG_STATE_GATE);
                adev->nbio.funcs->update_medium_grain_light_sleep(adev,
@@ -709,10 +727,6 @@ static int soc21_common_set_clockgating_state(void *handle,
                adev->hdp.funcs->update_clock_gating(adev,
                                state == AMD_CG_STATE_GATE);
                break;
-       case IP_VERSION(7, 7, 0):
-               adev->hdp.funcs->update_clock_gating(adev,
-                               state == AMD_CG_STATE_GATE);
-               break;
        default:
                break;
        }
index 357298e..22c0929 100644 (file)
@@ -382,12 +382,8 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
                                f2g = &gfx_v10_3_kfd2kgd;
                        break;
                case IP_VERSION(10, 3, 6):
-                       gfx_target_version = 100306;
-                       if (!vf)
-                               f2g = &gfx_v10_3_kfd2kgd;
-                       break;
                case IP_VERSION(10, 3, 7):
-                       gfx_target_version = 100307;
+                       gfx_target_version = 100306;
                        if (!vf)
                                f2g = &gfx_v10_3_kfd2kgd;
                        break;
index fca7cf9..987bde4 100644 (file)
@@ -34,6 +34,7 @@
 #include "dal_asic_id.h"
 #include "amdgpu_display.h"
 #include "amdgpu_dm_trace.h"
+#include "amdgpu_dm_plane.h"
 #include "gc/gc_11_0_0_offset.h"
 #include "gc/gc_11_0_0_sh_mask.h"
 
@@ -149,12 +150,12 @@ static void add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_
        *size += 1;
 }
 
-bool modifier_has_dcc(uint64_t modifier)
+static bool modifier_has_dcc(uint64_t modifier)
 {
        return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
 }
 
-unsigned modifier_gfx9_swizzle_mode(uint64_t modifier)
+static unsigned modifier_gfx9_swizzle_mode(uint64_t modifier)
 {
        if (modifier == DRM_FORMAT_MOD_LINEAR)
                return 0;
index 95168c2..286981a 100644 (file)
@@ -36,17 +36,9 @@ int fill_dc_scaling_info(struct amdgpu_device *adev,
                         const struct drm_plane_state *state,
                         struct dc_scaling_info *scaling_info);
 
-void get_min_max_dc_plane_scaling(struct drm_device *dev,
-                                 struct drm_framebuffer *fb,
-                                 int *min_downscale, int *max_upscale);
-
 int dm_plane_helper_check_state(struct drm_plane_state *state,
                                struct drm_crtc_state *new_crtc_state);
 
-bool modifier_has_dcc(uint64_t modifier);
-
-unsigned int modifier_gfx9_swizzle_mode(uint64_t modifier);
-
 int fill_plane_buffer_attributes(struct amdgpu_device *adev,
                                 const struct amdgpu_framebuffer *afb,
                                 const enum surface_pixel_format format,
index 85f3220..3a9e387 100644 (file)
@@ -1750,6 +1750,7 @@ static bool dcn314_resource_construct(
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
        dc->caps.dp_hpo = true;
+       dc->caps.dp_hdmi21_pcon_support = true;
        dc->caps.edp_dsc_support = true;
        dc->caps.extended_aux_timeout_support = true;
        dc->caps.dmcub_support = true;
index 2ed9579..cf8d60c 100644 (file)
 #define regBIF0_PCIE_TX_TRACKING_ADDR_HI_BASE_IDX                                                       5
 #define regBIF0_PCIE_TX_TRACKING_CTRL_STATUS                                                            0x420186
 #define regBIF0_PCIE_TX_TRACKING_CTRL_STATUS_BASE_IDX                                                   5
+#define regBIF0_PCIE_TX_POWER_CTRL_1                                                                    0x420187
+#define regBIF0_PCIE_TX_POWER_CTRL_1_BASE_IDX                                                           5
 #define regBIF0_PCIE_TX_CTRL_4                                                                          0x42018b
 #define regBIF0_PCIE_TX_CTRL_4_BASE_IDX                                                                 5
 #define regBIF0_PCIE_TX_STATUS                                                                          0x420194
index eb62a18..3d60c9e 100644 (file)
 #define BIF0_PCIE_TX_TRACKING_CTRL_STATUS__TX_TRACKING_PORT_MASK                                              0x0000000EL
 #define BIF0_PCIE_TX_TRACKING_CTRL_STATUS__TX_TRACKING_UNIT_ID_MASK                                           0x00007F00L
 #define BIF0_PCIE_TX_TRACKING_CTRL_STATUS__TX_TRACKING_STATUS_VALID_MASK                                      0x00008000L
+//BIF0_PCIE_TX_POWER_CTRL_1
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN__SHIFT                                                       0x0
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_DS_EN__SHIFT                                                       0x1
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_SD_EN__SHIFT                                                       0x2
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN__SHIFT                                                    0x3
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_DS_EN__SHIFT                                                    0x4
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_SD_EN__SHIFT                                                    0x5
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK                                                         0x00000001L
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_DS_EN_MASK                                                         0x00000002L
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_SD_EN_MASK                                                         0x00000004L
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK                                                      0x00000008L
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_DS_EN_MASK                                                      0x00000010L
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_SD_EN_MASK                                                      0x00000020L
 //BIF0_PCIE_TX_CTRL_4
 #define BIF0_PCIE_TX_CTRL_4__TX_PORT_ACCESS_TIMER_SKEW__SHIFT                                                 0x0
 #define BIF0_PCIE_TX_CTRL_4__TX_PORT_ACCESS_TIMER_SKEW_MASK                                                   0x0000000FL
index 78620b0..f745cd8 100644 (file)
 #ifndef SMU13_DRIVER_IF_V13_0_0_H
 #define SMU13_DRIVER_IF_V13_0_0_H
 
-// *** IMPORTANT ***
-// PMFW TEAM: Always increment the interface version on any change to this file
-#define SMU13_DRIVER_IF_VERSION  0x23
-
 //Increment this version if SkuTable_t or BoardTable_t change
-#define PPTABLE_VERSION 0x1D
+#define PPTABLE_VERSION 0x22
 
 #define NUM_GFXCLK_DPM_LEVELS    16
 #define NUM_SOCCLK_DPM_LEVELS    8
@@ -1193,8 +1189,17 @@ typedef struct {
   // SECTION: Advanced Options
   uint32_t          DebugOverrides;
 
+  // Section: Total Board Power idle vs active coefficients
+  uint8_t     TotalBoardPowerSupport;
+  uint8_t     TotalBoardPowerPadding[3];
+
+  int16_t     TotalIdleBoardPowerM;
+  int16_t     TotalIdleBoardPowerB;
+  int16_t     TotalBoardPowerM;
+  int16_t     TotalBoardPowerB;
+
   // SECTION: Sku Reserved
-  uint32_t         Spare[64];
+  uint32_t         Spare[61];
 
   // Padding for MMHUB - do not modify this
   uint32_t     MmHubPadding[8];
@@ -1259,7 +1264,8 @@ typedef struct {
   // SECTION: Clock Spread Spectrum
 
   // UCLK Spread Spectrum
-  uint16_t     UclkSpreadPadding;
+  uint8_t      UclkTrainingModeSpreadPercent;
+  uint8_t      UclkSpreadPadding;
   uint16_t     UclkSpreadFreq;      // kHz
 
   // UCLK Spread Spectrum
@@ -1272,11 +1278,7 @@ typedef struct {
 
   // Section: Memory Config
   uint8_t      DramWidth; // Width of interface to the channel for each DRAM module. See DRAM_BIT_WIDTH_TYPE_e
-  uint8_t      PaddingMem1[3];
-
-  // Section: Total Board Power
-  uint16_t     TotalBoardPower;     //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power
-  uint16_t     BoardPowerPadding;
+  uint8_t      PaddingMem1[7];
 
   // SECTION: UMC feature flags
   uint8_t      HsrEnabled;
@@ -1375,8 +1377,11 @@ typedef struct {
   uint16_t Vcn1ActivityPercentage  ;
 
   uint32_t EnergyAccumulator;
-  uint16_t AverageSocketPower    ;
+  uint16_t AverageSocketPower;
+  uint16_t AverageTotalBoardPower;
+
   uint16_t AvgTemperature[TEMP_COUNT];
+  uint16_t TempPadding;
 
   uint8_t  PcieRate               ;
   uint8_t  PcieWidth              ;
index 6fe2fe9..ac308e7 100644 (file)
@@ -30,7 +30,7 @@
 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x05
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x2C
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x2E
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C
 
 #define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500  //500ms
index 86d670c..ad06886 100644 (file)
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-       /*
-        * Note: obj->dma_buf can't disappear as long as we still hold a
-        * handle reference in obj->handle_count.
-        */
-       mutex_lock(&filp->prime.lock);
-       if (obj->dma_buf) {
-               drm_prime_remove_buf_handle_locked(&filp->prime,
-                                                  obj->dma_buf);
-       }
-       mutex_unlock(&filp->prime.lock);
-}
-
 /**
  * drm_gem_object_handle_free - release resources bound to userspace handles
  * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        if (obj->funcs->close)
                obj->funcs->close(obj, file_priv);
 
-       drm_gem_remove_prime_handles(obj, file_priv);
+       drm_prime_remove_buf_handle(&file_priv->prime, id);
        drm_vma_node_revoke(&obj->vma_node, file_priv);
 
        drm_gem_object_handle_put_unlocked(obj);
index 1fbbc19..7bb98e6 100644 (file)
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
-                                       struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+                                uint32_t handle);
 
 /* drm_drv.c */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
index a3f1806..eb09e86 100644 (file)
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
        return -ENOENT;
 }
 
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
-                                       struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+                                uint32_t handle)
 {
        struct rb_node *rb;
 
-       rb = prime_fpriv->dmabufs.rb_node;
+       mutex_lock(&prime_fpriv->lock);
+
+       rb = prime_fpriv->handles.rb_node;
        while (rb) {
                struct drm_prime_member *member;
 
-               member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-               if (member->dma_buf == dma_buf) {
+               member = rb_entry(rb, struct drm_prime_member, handle_rb);
+               if (member->handle == handle) {
                        rb_erase(&member->handle_rb, &prime_fpriv->handles);
                        rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
 
-                       dma_buf_put(dma_buf);
+                       dma_buf_put(member->dma_buf);
                        kfree(member);
-                       return;
-               } else if (member->dma_buf < dma_buf) {
+                       break;
+               } else if (member->handle < handle) {
                        rb = rb->rb_right;
                } else {
                        rb = rb->rb_left;
                }
        }
+
+       mutex_unlock(&prime_fpriv->lock);
 }
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
index 05076e5..e29175e 100644 (file)
@@ -820,6 +820,15 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
                if (ret == 0) {
                        ret = nouveau_fence_new(chan, false, &fence);
                        if (ret == 0) {
+                               /* TODO: figure out a better solution here
+                                *
+                                * wait on the fence here explicitly as going through
+                                * ttm_bo_move_accel_cleanup somehow doesn't seem to do it.
+                                *
+                                * Without this the operation can timeout and we'll fallback to a
+                                * software copy, which might take several minutes to finish.
+                                */
+                               nouveau_fence_wait(fence, false, false);
                                ret = ttm_bo_move_accel_cleanup(bo,
                                                                &fence->base,
                                                                evict, false,
index 2b12389..ee01656 100644 (file)
@@ -1605,6 +1605,9 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend,
                if (r) {
                        /* delay GPU reset to resume */
                        radeon_fence_driver_force_completion(rdev, i);
+               } else {
+                       /* finish executing delayed work */
+                       flush_delayed_work(&rdev->fence_drv[i].lockup_work);
                }
        }
 
index 061be9a..b0f3117 100644 (file)
@@ -8,6 +8,7 @@ config DRM_VC4
        depends on DRM
        depends on SND && SND_SOC
        depends on COMMON_CLK
+       depends on PM
        select DRM_DISPLAY_HDMI_HELPER
        select DRM_DISPLAY_HELPER
        select DRM_KMS_HELPER
index 592c3b5..1e5f687 100644 (file)
@@ -2855,7 +2855,7 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
        return 0;
 }
 
-static int __maybe_unused vc4_hdmi_runtime_suspend(struct device *dev)
+static int vc4_hdmi_runtime_suspend(struct device *dev)
 {
        struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
 
@@ -2972,17 +2972,15 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                        vc4_hdmi->disable_4kp60 = true;
        }
 
+       pm_runtime_enable(dev);
+
        /*
-        * We need to have the device powered up at this point to call
-        * our reset hook and for the CEC init.
+        *  We need to have the device powered up at this point to call
+        *  our reset hook and for the CEC init.
         */
-       ret = vc4_hdmi_runtime_resume(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret)
-               goto err_put_ddc;
-
-       pm_runtime_get_noresume(dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
+               goto err_disable_runtime_pm;
 
        if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") ||
             of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) &&
@@ -3028,6 +3026,7 @@ err_destroy_conn:
 err_destroy_encoder:
        drm_encoder_cleanup(encoder);
        pm_runtime_put_sync(dev);
+err_disable_runtime_pm:
        pm_runtime_disable(dev);
 err_put_ddc:
        put_device(&vc4_hdmi->ddc->dev);
index 4b90c86..47774b9 100644 (file)
@@ -288,11 +288,29 @@ int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
        return 0;
 }
 
+static const struct dmi_system_id dmi_nodevs[] = {
+       {
+               /*
+                * Google Chromebooks use Chrome OS Embedded Controller Sensor
+                * Hub instead of Sensor Hub Fusion and leaves MP2
+                * uninitialized, which disables all functionalities, even
+                * including the registers necessary for feature detections.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+               },
+       },
+       { }
+};
+
 static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct amd_mp2_dev *privdata;
        int rc;
 
+       if (dmi_first_match(dmi_nodevs))
+               return -ENODEV;
+
        privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
        if (!privdata)
                return -ENOMEM;
index 08c9a9a..b59c3da 100644 (file)
@@ -1212,6 +1212,13 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc = new_rdesc;
        }
 
+       if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD &&
+                       *rsize == 331 && rdesc[190] == 0x85 && rdesc[191] == 0x5a &&
+                       rdesc[204] == 0x95 && rdesc[205] == 0x05) {
+               hid_info(hdev, "Fixing up Asus N-KEY keyb report descriptor\n");
+               rdesc[205] = 0x01;
+       }
+
        return rdesc;
 }
 
index 0fb720a..f80d619 100644 (file)
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021   0x029c
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021   0x029a
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021   0x029f
+#define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102
+#define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302
 
 #define USB_VENDOR_ID_ASUS             0x0486
 #define USB_DEVICE_ID_ASUS_T91MT       0x0185
 #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN   0x2706
 #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN   0x261A
 #define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN  0x2A1C
+#define I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN     0x279F
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index 48c1c02..859aeb0 100644 (file)
@@ -383,6 +383,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
          HID_BATTERY_QUIRK_IGNORE },
        { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
@@ -1532,7 +1534,10 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
                         * assume ours
                         */
                        if (!report->tool)
-                               hid_report_set_tool(report, input, usage->code);
+                               report->tool = usage->code;
+
+                       /* drivers may have changed the value behind our back, resend it */
+                       hid_report_set_tool(report, input, report->tool);
                } else {
                        hid_report_release_tool(report, input, usage->code);
                }
index 92ac4f6..6028af3 100644 (file)
@@ -1221,6 +1221,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
 
        spin_lock_irqsave(&ctlr->lock, flags);
        if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
+           ctlr->ctlr_state != JOYCON_CTLR_STATE_REMOVED &&
            (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS &&
            (ctlr->rumble_queue_head != ctlr->rumble_queue_tail ||
             ctlr->rumble_zero_countdown > 0)) {
@@ -1545,12 +1546,13 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
                ctlr->rumble_queue_head = 0;
        memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
               JC_RUMBLE_DATA_SIZE);
-       spin_unlock_irqrestore(&ctlr->lock, flags);
 
        /* don't wait for the periodic send (reduces latency) */
-       if (schedule_now)
+       if (schedule_now && ctlr->ctlr_state != JOYCON_CTLR_STATE_REMOVED)
                queue_work(ctlr->rumble_queue, &ctlr->rumble_worker);
 
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+
        return 0;
 }
 
index dc67717..70f602c 100644 (file)
@@ -314,6 +314,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
 #endif
 #if IS_ENABLED(CONFIG_HID_APPLEIR)
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
index a3b151b..fc616db 100644 (file)
@@ -134,6 +134,11 @@ static int steam_recv_report(struct steam_device *steam,
        int ret;
 
        r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+       if (!r) {
+               hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+               return -EINVAL;
+       }
+
        if (hid_report_len(r) < 64)
                return -EINVAL;
 
@@ -165,6 +170,11 @@ static int steam_send_report(struct steam_device *steam,
        int ret;
 
        r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+       if (!r) {
+               hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+               return -EINVAL;
+       }
+
        if (hid_report_len(r) < 64)
                return -EINVAL;
 
index c3e6d69..cf1679b 100644 (file)
@@ -67,12 +67,13 @@ static const struct tm_wheel_info tm_wheels_infos[] = {
        {0x0200, 0x0005, "Thrustmaster T300RS (Missing Attachment)"},
        {0x0206, 0x0005, "Thrustmaster T300RS"},
        {0x0209, 0x0005, "Thrustmaster T300RS (Open Wheel Attachment)"},
+       {0x020a, 0x0005, "Thrustmaster T300RS (Sparco R383 Mod)"},
        {0x0204, 0x0005, "Thrustmaster T300 Ferrari Alcantara Edition"},
        {0x0002, 0x0002, "Thrustmaster T500RS"}
        //{0x0407, 0x0001, "Thrustmaster TMX"}
 };
 
-static const uint8_t tm_wheels_infos_length = 4;
+static const uint8_t tm_wheels_infos_length = 7;
 
 /*
  * This structs contains (in little endian) the response data
index 681614a..197b1e7 100644 (file)
@@ -350,6 +350,8 @@ static int hidraw_release(struct inode * inode, struct file * file)
        down_write(&minors_rwsem);
 
        spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
+       for (int i = list->tail; i < list->head; i++)
+               kfree(list->buffer[i].value);
        list_del(&list->node);
        spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
        kfree(list);
index e600dbf..fc108f1 100644 (file)
@@ -32,6 +32,7 @@
 #define ADL_P_DEVICE_ID                0x51FC
 #define ADL_N_DEVICE_ID                0x54FC
 #define RPL_S_DEVICE_ID                0x7A78
+#define MTL_P_DEVICE_ID                0x7E45
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index 2c67ec1..7120b30 100644 (file)
@@ -43,6 +43,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_P_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index 6a5cc11..35dddc5 100644 (file)
@@ -105,7 +105,7 @@ struct report_list {
  * @multi_packet_cnt:  Count of fragmented packet count
  *
  * This structure is used to store completion flags and per client data like
- * like report description, number of HID devices etc.
+ * report description, number of HID devices etc.
  */
 struct ishtp_cl_data {
        /* completion flags */
index 405e0d5..df0a825 100644 (file)
@@ -626,13 +626,14 @@ static void ishtp_cl_read_complete(struct ishtp_cl_rb *rb)
 }
 
 /**
- * ipc_tx_callback() - IPC tx callback function
+ * ipc_tx_send() - IPC tx send function
  * @prm: Pointer to client device instance
  *
- * Send message over IPC either first time or on callback on previous message
- * completion
+ * Send message over IPC. Message will be split into fragments
+ * if message size is bigger than IPC FIFO size, and all
+ * fragments will be sent one by one.
  */
-static void ipc_tx_callback(void *prm)
+static void ipc_tx_send(void *prm)
 {
        struct ishtp_cl *cl = prm;
        struct ishtp_cl_tx_ring *cl_msg;
@@ -677,32 +678,41 @@ static void ipc_tx_callback(void *prm)
                            list);
        rem = cl_msg->send_buf.size - cl->tx_offs;
 
-       ishtp_hdr.host_addr = cl->host_client_id;
-       ishtp_hdr.fw_addr = cl->fw_client_id;
-       ishtp_hdr.reserved = 0;
-       pmsg = cl_msg->send_buf.data + cl->tx_offs;
+       while (rem > 0) {
+               ishtp_hdr.host_addr = cl->host_client_id;
+               ishtp_hdr.fw_addr = cl->fw_client_id;
+               ishtp_hdr.reserved = 0;
+               pmsg = cl_msg->send_buf.data + cl->tx_offs;
+
+               if (rem <= dev->mtu) {
+                       /* Last fragment or only one packet */
+                       ishtp_hdr.length = rem;
+                       ishtp_hdr.msg_complete = 1;
+                       /* Submit to IPC queue with no callback */
+                       ishtp_write_message(dev, &ishtp_hdr, pmsg);
+                       cl->tx_offs = 0;
+                       cl->sending = 0;
 
-       if (rem <= dev->mtu) {
-               ishtp_hdr.length = rem;
-               ishtp_hdr.msg_complete = 1;
-               cl->sending = 0;
-               list_del_init(&cl_msg->list);   /* Must be before write */
-               spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-               /* Submit to IPC queue with no callback */
-               ishtp_write_message(dev, &ishtp_hdr, pmsg);
-               spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
-               list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
-               ++cl->tx_ring_free_size;
-               spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
-                       tx_free_flags);
-       } else {
-               /* Send IPC fragment */
-               spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-               cl->tx_offs += dev->mtu;
-               ishtp_hdr.length = dev->mtu;
-               ishtp_hdr.msg_complete = 0;
-               ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl);
+                       break;
+               } else {
+                       /* Send ipc fragment */
+                       ishtp_hdr.length = dev->mtu;
+                       ishtp_hdr.msg_complete = 0;
+                       /* All fregments submitted to IPC queue with no callback */
+                       ishtp_write_message(dev, &ishtp_hdr, pmsg);
+                       cl->tx_offs += dev->mtu;
+                       rem = cl_msg->send_buf.size - cl->tx_offs;
+               }
        }
+
+       list_del_init(&cl_msg->list);
+       spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
+
+       spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
+       list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
+       ++cl->tx_ring_free_size;
+       spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
+               tx_free_flags);
 }
 
 /**
@@ -720,7 +730,7 @@ static void ishtp_cl_send_msg_ipc(struct ishtp_device *dev,
                return;
 
        cl->tx_offs = 0;
-       ipc_tx_callback(cl);
+       ipc_tx_send(cl);
        ++cl->send_msg_cnt_ipc;
 }
 
index e69c4bf..ae24848 100644 (file)
@@ -798,7 +798,7 @@ u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN])
        u16 ret;
 
        if (contr == 0) {
-               strlcpy(serial, driver_serial, CAPI_SERIAL_LEN);
+               strscpy(serial, driver_serial, CAPI_SERIAL_LEN);
                return CAPI_NOERROR;
        }
 
@@ -806,7 +806,7 @@ u16 capi20_get_serial(u32 contr, u8 serial[CAPI_SERIAL_LEN])
 
        ctr = get_capi_ctr_by_nr(contr);
        if (ctr && ctr->state == CAPI_CTR_RUNNING) {
-               strlcpy(serial, ctr->serial, CAPI_SERIAL_LEN);
+               strscpy(serial, ctr->serial, CAPI_SERIAL_LEN);
                ret = CAPI_NOERROR;
        } else
                ret = CAPI_REGNOTINSTALLED;
index afaf36b..729be2c 100644 (file)
@@ -5620,6 +5620,7 @@ struct mddev *md_alloc(dev_t dev, char *name)
         * removed (mddev_delayed_delete).
         */
        flush_workqueue(md_misc_wq);
+       flush_workqueue(md_rdev_misc_wq);
 
        mutex_lock(&disks_mutex);
        mddev = mddev_alloc(dev);
@@ -6238,11 +6239,11 @@ static void mddev_detach(struct mddev *mddev)
 static void __md_stop(struct mddev *mddev)
 {
        struct md_personality *pers = mddev->pers;
+       md_bitmap_destroy(mddev);
        mddev_detach(mddev);
        /* Ensure ->event_work is done */
        if (mddev->event_work.func)
                flush_workqueue(md_misc_wq);
-       md_bitmap_destroy(mddev);
        spin_lock(&mddev->lock);
        mddev->pers = NULL;
        spin_unlock(&mddev->lock);
@@ -6260,6 +6261,7 @@ void md_stop(struct mddev *mddev)
        /* stop the array and free an attached data structures.
         * This is called from dm-raid
         */
+       __md_stop_writes(mddev);
        __md_stop(mddev);
        bioset_exit(&mddev->bio_set);
        bioset_exit(&mddev->sync_set);
index 9117fcd..64d6e4c 100644 (file)
@@ -2639,18 +2639,18 @@ static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev)
 }
 
 static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector,
-                           int sectors, struct page *page, int rw)
+                           int sectors, struct page *page, enum req_op op)
 {
        sector_t first_bad;
        int bad_sectors;
 
        if (is_badblock(rdev, sector, sectors, &first_bad, &bad_sectors)
-           && (rw == READ || test_bit(WriteErrorSeen, &rdev->flags)))
+           && (op == REQ_OP_READ || test_bit(WriteErrorSeen, &rdev->flags)))
                return -1;
-       if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
+       if (sync_page_io(rdev, sector, sectors << 9, page, op, false))
                /* success */
                return 1;
-       if (rw == WRITE) {
+       if (op == REQ_OP_WRITE) {
                set_bit(WriteErrorSeen, &rdev->flags);
                if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED,
@@ -2780,7 +2780,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
                        if (r10_sync_page_io(rdev,
                                             r10_bio->devs[sl].addr +
                                             sect,
-                                            s, conf->tmppage, WRITE)
+                                            s, conf->tmppage, REQ_OP_WRITE)
                            == 0) {
                                /* Well, this device is dead */
                                pr_notice("md/raid10:%s: read correction write failed (%d sectors at %llu on %pg)\n",
@@ -2814,8 +2814,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
                        switch (r10_sync_page_io(rdev,
                                             r10_bio->devs[sl].addr +
                                             sect,
-                                            s, conf->tmppage,
-                                                READ)) {
+                                            s, conf->tmppage, REQ_OP_READ)) {
                        case 0:
                                /* Well, this device is dead */
                                pr_notice("md/raid10:%s: unable to read back corrected sectors (%d sectors at %llu on %pg)\n",
index f475eef..83214e2 100644 (file)
@@ -68,7 +68,7 @@ static int netdev_boot_setup_add(char *name, struct ifmap *map)
        for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++) {
                if (s[i].name[0] == '\0' || s[i].name[0] == ' ') {
                        memset(s[i].name, 0, sizeof(s[i].name));
-                       strlcpy(s[i].name, name, IFNAMSIZ);
+                       strscpy(s[i].name, name, IFNAMSIZ);
                        memcpy(&s[i].map, map, sizeof(s[i].map));
                        break;
                }
index 9a247eb..2d20be6 100644 (file)
@@ -2894,8 +2894,7 @@ static void amt_event_work(struct work_struct *work)
                        amt_event_send_request(amt);
                        break;
                default:
-                       if (skb)
-                               kfree_skb(skb);
+                       kfree_skb(skb);
                        break;
                }
        }
@@ -3033,8 +3032,7 @@ static int amt_dev_stop(struct net_device *dev)
        cancel_work_sync(&amt->event_wq);
        for (i = 0; i < AMT_MAX_EVENTS; i++) {
                skb = amt->events[i].skb;
-               if (skb)
-                       kfree_skb(skb);
+               kfree_skb(skb);
                amt->events[i].event = AMT_EVENT_NONE;
                amt->events[i].skb = NULL;
        }
index 2f4da2c..dc618bf 100644 (file)
@@ -5619,7 +5619,7 @@ static int bond_ethtool_get_link_ksettings(struct net_device *bond_dev,
 static void bond_ethtool_get_drvinfo(struct net_device *bond_dev,
                                     struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d",
                 BOND_ABI_VERSION);
 }
index 131a084..ebd5941 100644 (file)
@@ -478,7 +478,7 @@ static void pcan_free_channels(struct pcan_pccard *card)
                if (!netdev)
                        continue;
 
-               strlcpy(name, netdev->name, IFNAMSIZ);
+               strscpy(name, netdev->name, IFNAMSIZ);
 
                unregister_sja1000dev(netdev);
 
index 8c9d53f..225697d 100644 (file)
@@ -962,7 +962,7 @@ static void peak_usb_disconnect(struct usb_interface *intf)
 
                dev_prev_siblings = dev->prev_siblings;
                dev->state &= ~PCAN_USB_STATE_CONNECTED;
-               strlcpy(name, netdev->name, IFNAMSIZ);
+               strscpy(name, netdev->name, IFNAMSIZ);
 
                unregister_netdev(netdev);
 
index 48cf344..59cdfc5 100644 (file)
@@ -972,7 +972,7 @@ void b53_get_strings(struct dsa_switch *ds, int port, u32 stringset,
 
        if (stringset == ETH_SS_STATS) {
                for (i = 0; i < mib_size; i++)
-                       strlcpy(data + i * ETH_GSTRING_LEN,
+                       strscpy(data + i * ETH_GSTRING_LEN,
                                mibs[i].name, ETH_GSTRING_LEN);
        } else if (stringset == ETH_SS_PHY_STATS) {
                phydev = b53_get_phy_device(ds, port);
index be0edfa..572f745 100644 (file)
@@ -94,6 +94,24 @@ static u16 bcm_sf2_reg_led_base(struct bcm_sf2_priv *priv, int port)
        return REG_SWITCH_STATUS;
 }
 
+static u32 bcm_sf2_port_override_offset(struct bcm_sf2_priv *priv, int port)
+{
+       switch (priv->type) {
+       case BCM4908_DEVICE_ID:
+       case BCM7445_DEVICE_ID:
+               return port == 8 ? CORE_STS_OVERRIDE_IMP :
+                                  CORE_STS_OVERRIDE_GMIIP_PORT(port);
+       case BCM7278_DEVICE_ID:
+               return port == 8 ? CORE_STS_OVERRIDE_IMP2 :
+                                  CORE_STS_OVERRIDE_GMIIP2_PORT(port);
+       default:
+               WARN_ONCE(1, "Unsupported device: %d\n", priv->type);
+       }
+
+       /* RO fallback register */
+       return REG_SWITCH_STATUS;
+}
+
 /* Return the number of active ports, not counting the IMP (CPU) port */
 static unsigned int bcm_sf2_num_active_ports(struct dsa_switch *ds)
 {
@@ -141,7 +159,7 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 {
        struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
        unsigned int i;
-       u32 reg, offset;
+       u32 reg;
 
        /* Enable the port memories */
        reg = core_readl(priv, CORE_MEM_PSM_VDD_CTRL);
@@ -167,21 +185,6 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
        b53_brcm_hdr_setup(ds, port);
 
        if (port == 8) {
-               if (priv->type == BCM4908_DEVICE_ID ||
-                   priv->type == BCM7445_DEVICE_ID)
-                       offset = CORE_STS_OVERRIDE_IMP;
-               else
-                       offset = CORE_STS_OVERRIDE_IMP2;
-
-               /* Force link status for IMP port */
-               reg = core_readl(priv, offset);
-               reg |= (MII_SW_OR | LINK_STS);
-               if (priv->type == BCM4908_DEVICE_ID)
-                       reg |= GMII_SPEED_UP_2G;
-               else
-                       reg &= ~GMII_SPEED_UP_2G;
-               core_writel(priv, reg, offset);
-
                /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
                reg = core_readl(priv, CORE_IMP_CTL);
                reg |= (RX_BCST_EN | RX_MCST_EN | RX_UCST_EN);
@@ -812,17 +815,10 @@ static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port,
        if (priv->wol_ports_mask & BIT(port))
                return;
 
-       if (port != core_readl(priv, CORE_IMP0_PRT_ID)) {
-               if (priv->type == BCM4908_DEVICE_ID ||
-                   priv->type == BCM7445_DEVICE_ID)
-                       offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
-               else
-                       offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port);
-
-               reg = core_readl(priv, offset);
-               reg &= ~LINK_STS;
-               core_writel(priv, reg, offset);
-       }
+       offset = bcm_sf2_port_override_offset(priv, port);
+       reg = core_readl(priv, offset);
+       reg &= ~LINK_STS;
+       core_writel(priv, reg, offset);
 
        bcm_sf2_sw_mac_link_set(ds, port, interface, false);
 }
@@ -836,56 +832,56 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
 {
        struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
        struct ethtool_eee *p = &priv->dev->ports[port].eee;
+       u32 reg_rgmii_ctrl = 0;
+       u32 reg, offset;
 
        bcm_sf2_sw_mac_link_set(ds, port, interface, true);
 
-       if (port != core_readl(priv, CORE_IMP0_PRT_ID)) {
-               u32 reg_rgmii_ctrl = 0;
-               u32 reg, offset;
+       offset = bcm_sf2_port_override_offset(priv, port);
 
-               if (priv->type == BCM4908_DEVICE_ID ||
-                   priv->type == BCM7445_DEVICE_ID)
-                       offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
-               else
-                       offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port);
-
-               if (interface == PHY_INTERFACE_MODE_RGMII ||
-                   interface == PHY_INTERFACE_MODE_RGMII_TXID ||
-                   interface == PHY_INTERFACE_MODE_MII ||
-                   interface == PHY_INTERFACE_MODE_REVMII) {
-                       reg_rgmii_ctrl = bcm_sf2_reg_rgmii_cntrl(priv, port);
-                       reg = reg_readl(priv, reg_rgmii_ctrl);
-                       reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
-
-                       if (tx_pause)
-                               reg |= TX_PAUSE_EN;
-                       if (rx_pause)
-                               reg |= RX_PAUSE_EN;
-
-                       reg_writel(priv, reg, reg_rgmii_ctrl);
-               }
-
-               reg = SW_OVERRIDE | LINK_STS;
-               switch (speed) {
-               case SPEED_1000:
-                       reg |= SPDSTS_1000 << SPEED_SHIFT;
-                       break;
-               case SPEED_100:
-                       reg |= SPDSTS_100 << SPEED_SHIFT;
-                       break;
-               }
-
-               if (duplex == DUPLEX_FULL)
-                       reg |= DUPLX_MODE;
+       if (phy_interface_mode_is_rgmii(interface) ||
+           interface == PHY_INTERFACE_MODE_MII ||
+           interface == PHY_INTERFACE_MODE_REVMII) {
+               reg_rgmii_ctrl = bcm_sf2_reg_rgmii_cntrl(priv, port);
+               reg = reg_readl(priv, reg_rgmii_ctrl);
+               reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
 
                if (tx_pause)
-                       reg |= TXFLOW_CNTL;
+                       reg |= TX_PAUSE_EN;
                if (rx_pause)
-                       reg |= RXFLOW_CNTL;
+                       reg |= RX_PAUSE_EN;
+
+               reg_writel(priv, reg, reg_rgmii_ctrl);
+       }
+
+       reg = LINK_STS;
+       if (port == 8) {
+               if (priv->type == BCM4908_DEVICE_ID)
+                       reg |= GMII_SPEED_UP_2G;
+               reg |= MII_SW_OR;
+       } else {
+               reg |= SW_OVERRIDE;
+       }
 
-               core_writel(priv, reg, offset);
+       switch (speed) {
+       case SPEED_1000:
+               reg |= SPDSTS_1000 << SPEED_SHIFT;
+               break;
+       case SPEED_100:
+               reg |= SPDSTS_100 << SPEED_SHIFT;
+               break;
        }
 
+       if (duplex == DUPLEX_FULL)
+               reg |= DUPLX_MODE;
+
+       if (tx_pause)
+               reg |= TXFLOW_CNTL;
+       if (rx_pause)
+               reg |= RXFLOW_CNTL;
+
+       core_writel(priv, reg, offset);
+
        if (mode == MLO_AN_PHY && phydev)
                p->eee_enabled = b53_eee_init(ds, port, phydev);
 }
index edbe5e7..22bc295 100644 (file)
@@ -1296,7 +1296,7 @@ void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,
                                 "CFP%03d_%sCntr",
                                 i, bcm_sf2_cfp_stats[j].name);
                        iter = (i - 1) * s + j;
-                       strlcpy(data + iter * ETH_GSTRING_LEN,
+                       strscpy(data + iter * ETH_GSTRING_LEN,
                                buf, ETH_GSTRING_LEN);
                }
        }
index 01f9099..ea8bbfc 100644 (file)
@@ -288,7 +288,7 @@ static void hellcreek_get_strings(struct dsa_switch *ds, int port,
        for (i = 0; i < ARRAY_SIZE(hellcreek_counter); ++i) {
                const struct hellcreek_counter *counter = &hellcreek_counter[i];
 
-               strlcpy(data + i * ETH_GSTRING_LEN,
+               strscpy(data + i * ETH_GSTRING_LEN,
                        counter->name, ETH_GSTRING_LEN);
        }
 }
index 42c50cc..8582b4b 100644 (file)
@@ -17,8 +17,8 @@ u32 ksz8_get_port_addr(int port, int offset);
 void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member);
 void ksz8_flush_dyn_mac_table(struct ksz_device *dev, int port);
 void ksz8_port_setup(struct ksz_device *dev, int port, bool cpu_port);
-void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
-void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
+int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
+int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
 int ksz8_r_dyn_mac_table(struct ksz_device *dev, u16 addr, u8 *mac_addr,
                         u8 *fid, u8 *src_port, u8 *timestamp, u16 *entries);
 int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
index c79a512..bd3b133 100644 (file)
@@ -552,7 +552,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
        ksz8_w_table(dev, TABLE_VLAN, addr, buf);
 }
 
-void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
+int ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
 {
        u8 restart, speed, ctrl, link;
        int processed = true;
@@ -560,14 +560,24 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
        u8 val1, val2;
        u16 data = 0;
        u8 p = phy;
+       int ret;
 
        regs = dev->info->regs;
 
        switch (reg) {
        case MII_BMCR:
-               ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
-               ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
-               ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
+               ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
+               if (ret)
+                       return ret;
+
+               ret = ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
+               if (ret)
+                       return ret;
+
+               ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
+               if (ret)
+                       return ret;
+
                if (restart & PORT_PHY_LOOPBACK)
                        data |= BMCR_LOOPBACK;
                if (ctrl & PORT_FORCE_100_MBIT)
@@ -597,7 +607,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
                        data |= KSZ886X_BMCR_DISABLE_LED;
                break;
        case MII_BMSR:
-               ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
+               ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
+               if (ret)
+                       return ret;
+
                data = BMSR_100FULL |
                       BMSR_100HALF |
                       BMSR_10FULL |
@@ -618,7 +631,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
                        data = KSZ8795_ID_LO;
                break;
        case MII_ADVERTISE:
-               ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
+               ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
+               if (ret)
+                       return ret;
+
                data = ADVERTISE_CSMA;
                if (ctrl & PORT_AUTO_NEG_SYM_PAUSE)
                        data |= ADVERTISE_PAUSE_CAP;
@@ -632,7 +648,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
                        data |= ADVERTISE_10HALF;
                break;
        case MII_LPA:
-               ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link);
+               ret = ksz_pread8(dev, p, regs[P_REMOTE_STATUS], &link);
+               if (ret)
+                       return ret;
+
                data = LPA_SLCT;
                if (link & PORT_REMOTE_SYM_PAUSE)
                        data |= LPA_PAUSE_CAP;
@@ -648,8 +667,14 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
                        data |= LPA_LPACK;
                break;
        case PHY_REG_LINK_MD:
-               ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
-               ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
+               ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_CTRL, &val1);
+               if (ret)
+                       return ret;
+
+               ret = ksz_pread8(dev, p, REG_PORT_LINK_MD_RESULT, &val2);
+               if (ret)
+                       return ret;
+
                if (val1 & PORT_START_CABLE_DIAG)
                        data |= PHY_START_CABLE_DIAG;
 
@@ -664,7 +689,10 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
                                FIELD_GET(PORT_CABLE_FAULT_COUNTER_L, val2));
                break;
        case PHY_REG_PHY_CTRL:
-               ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
+               ret = ksz_pread8(dev, p, regs[P_LINK_STATUS], &link);
+               if (ret)
+                       return ret;
+
                if (link & PORT_MDIX_STATUS)
                        data |= KSZ886X_CTRL_MDIX_STAT;
                break;
@@ -674,13 +702,16 @@ void ksz8_r_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 *val)
        }
        if (processed)
                *val = data;
+
+       return 0;
 }
 
-void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
+int ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
 {
        u8 restart, speed, ctrl, data;
        const u16 *regs;
        u8 p = phy;
+       int ret;
 
        regs = dev->info->regs;
 
@@ -690,15 +721,26 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
                /* Do not support PHY reset function. */
                if (val & BMCR_RESET)
                        break;
-               ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
+               ret = ksz_pread8(dev, p, regs[P_SPEED_STATUS], &speed);
+               if (ret)
+                       return ret;
+
                data = speed;
                if (val & KSZ886X_BMCR_HP_MDIX)
                        data |= PORT_HP_MDIX;
                else
                        data &= ~PORT_HP_MDIX;
-               if (data != speed)
-                       ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
-               ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
+
+               if (data != speed) {
+                       ret = ksz_pwrite8(dev, p, regs[P_SPEED_STATUS], data);
+                       if (ret)
+                               return ret;
+               }
+
+               ret = ksz_pread8(dev, p, regs[P_FORCE_CTRL], &ctrl);
+               if (ret)
+                       return ret;
+
                data = ctrl;
                if (ksz_is_ksz88x3(dev)) {
                        if ((val & BMCR_ANENABLE))
@@ -724,9 +766,17 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
                        data |= PORT_FORCE_FULL_DUPLEX;
                else
                        data &= ~PORT_FORCE_FULL_DUPLEX;
-               if (data != ctrl)
-                       ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
-               ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
+
+               if (data != ctrl) {
+                       ret = ksz_pwrite8(dev, p, regs[P_FORCE_CTRL], data);
+                       if (ret)
+                               return ret;
+               }
+
+               ret = ksz_pread8(dev, p, regs[P_NEG_RESTART_CTRL], &restart);
+               if (ret)
+                       return ret;
+
                data = restart;
                if (val & KSZ886X_BMCR_DISABLE_LED)
                        data |= PORT_LED_OFF;
@@ -756,11 +806,19 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
                        data |= PORT_PHY_LOOPBACK;
                else
                        data &= ~PORT_PHY_LOOPBACK;
-               if (data != restart)
-                       ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL], data);
+
+               if (data != restart) {
+                       ret = ksz_pwrite8(dev, p, regs[P_NEG_RESTART_CTRL],
+                                         data);
+                       if (ret)
+                               return ret;
+               }
                break;
        case MII_ADVERTISE:
-               ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
+               ret = ksz_pread8(dev, p, regs[P_LOCAL_CTRL], &ctrl);
+               if (ret)
+                       return ret;
+
                data = ctrl;
                data &= ~(PORT_AUTO_NEG_SYM_PAUSE |
                          PORT_AUTO_NEG_100BTX_FD |
@@ -777,8 +835,12 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
                        data |= PORT_AUTO_NEG_10BT_FD;
                if (val & ADVERTISE_10HALF)
                        data |= PORT_AUTO_NEG_10BT;
-               if (data != ctrl)
-                       ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
+
+               if (data != ctrl) {
+                       ret = ksz_pwrite8(dev, p, regs[P_LOCAL_CTRL], data);
+                       if (ret)
+                               return ret;
+               }
                break;
        case PHY_REG_LINK_MD:
                if (val & PHY_START_CABLE_DIAG)
@@ -787,6 +849,8 @@ void ksz8_w_phy(struct ksz_device *dev, u16 phy, u16 reg, u16 val)
        default:
                break;
        }
+
+       return 0;
 }
 
 void ksz8_cfg_port_member(struct ksz_device *dev, int port, u8 member)
@@ -1187,7 +1251,6 @@ void ksz8_config_cpu_port(struct dsa_switch *ds)
                if (i == dev->phy_port_cnt)
                        break;
                p->on = 1;
-               p->phy = 1;
        }
        for (i = 0; i < dev->phy_port_cnt; i++) {
                p = &dev->ports[i];
index e4f446d..42d7e4c 100644 (file)
@@ -193,6 +193,11 @@ int ksz9477_reset_switch(struct ksz_device *dev)
        ksz_write32(dev, REG_SW_PORT_INT_MASK__4, 0x7F);
        ksz_read32(dev, REG_SW_PORT_INT_STATUS__4, &data32);
 
+       /* KSZ9893 compatible chips do not support refclk configuration */
+       if (dev->chip_id == KSZ9893_CHIP_ID ||
+           dev->chip_id == KSZ8563_CHIP_ID)
+               return 0;
+
        data8 = SW_ENABLE_REFCLKO;
        if (dev->synclko_disable)
                data8 = 0;
@@ -264,9 +269,20 @@ void ksz9477_port_init_cnt(struct ksz_device *dev, int port)
        mutex_unlock(&mib->cnt_mutex);
 }
 
-void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
+static void ksz9477_r_phy_quirks(struct ksz_device *dev, u16 addr, u16 reg,
+                                u16 *data)
+{
+       /* KSZ8563R do not have extended registers but BMSR_ESTATEN and
+        * BMSR_ERCAP bits are set.
+        */
+       if (dev->chip_id == KSZ8563_CHIP_ID && reg == MII_BMSR)
+               *data &= ~(BMSR_ESTATEN | BMSR_ERCAP);
+}
+
+int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
 {
        u16 val = 0xffff;
+       int ret;
 
        /* No real PHY after this. Simulate the PHY.
         * A fixed PHY can be setup in the device tree, but this function is
@@ -274,7 +290,7 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
         * For RGMII PHY there is no way to access it so the fixed PHY should
         * be used.  For SGMII PHY the supporting code will be added later.
         */
-       if (addr >= dev->phy_port_cnt) {
+       if (!dev->info->internal_phy[addr]) {
                struct ksz_port *p = &dev->ports[addr];
 
                switch (reg) {
@@ -307,23 +323,25 @@ void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
                        break;
                }
        } else {
-               ksz_pread16(dev, addr, 0x100 + (reg << 1), &val);
+               ret = ksz_pread16(dev, addr, 0x100 + (reg << 1), &val);
+               if (ret)
+                       return ret;
+
+               ksz9477_r_phy_quirks(dev, addr, reg, &val);
        }
 
        *data = val;
+
+       return 0;
 }
 
-void ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
+int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
 {
        /* No real PHY after this. */
-       if (addr >= dev->phy_port_cnt)
-               return;
-
-       /* No gigabit support.  Do not write to this register. */
-       if (!(dev->features & GBIT_SUPPORT) && reg == MII_CTRL1000)
-               return;
+       if (!dev->info->internal_phy[addr])
+               return 0;
 
-       ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
+       return ksz_pwrite16(dev, addr, 0x100 + (reg << 1), val);
 }
 
 void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member)
@@ -869,7 +887,7 @@ static phy_interface_t ksz9477_get_interface(struct ksz_device *dev, int port)
        phy_interface_t interface;
        bool gbit;
 
-       if (port < dev->phy_port_cnt)
+       if (dev->info->internal_phy[port])
                return PHY_INTERFACE_MODE_NA;
 
        gbit = ksz_get_gbit(dev, port);
@@ -914,7 +932,7 @@ static void ksz9477_phy_errata_setup(struct ksz_device *dev, int port)
        /* Energy Efficient Ethernet (EEE) feature select must
         * be manually disabled (except on KSZ8565 which is 100Mbit)
         */
-       if (dev->features & GBIT_SUPPORT)
+       if (dev->info->gbit_capable[port])
                ksz9477_port_mmd_write(dev, port, 0x07, 0x3c, 0x0000);
 
        /* Register settings are required to meet data sheet
@@ -941,7 +959,7 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
        config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE |
                                   MAC_SYM_PAUSE;
 
-       if (dev->features & GBIT_SUPPORT)
+       if (dev->info->gbit_capable[port])
                config->mac_capabilities |= MAC_1000FD;
 }
 
@@ -976,7 +994,7 @@ 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 (port < dev->phy_port_cnt) {
+       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,
@@ -999,7 +1017,7 @@ void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port)
        ksz9477_cfg_port_member(dev, port, member);
 
        /* clear pending interrupts */
-       if (port < dev->phy_port_cnt)
+       if (dev->info->internal_phy[port])
                ksz_pread16(dev, port, REG_PORT_PHY_INT_ENABLE, &data16);
 }
 
@@ -1051,25 +1069,13 @@ void ksz9477_config_cpu_port(struct dsa_switch *ds)
 
                        /* enable cpu port */
                        ksz9477_port_setup(dev, i, true);
-                       p->on = 1;
                }
        }
 
        for (i = 0; i < dev->info->port_cnt; i++) {
                if (i == dev->cpu_port)
                        continue;
-               p = &dev->ports[i];
-
                ksz_port_stp_state_set(ds, i, BR_STATE_DISABLED);
-               p->on = 1;
-               if (i < dev->phy_port_cnt)
-                       p->phy = 1;
-               if (dev->chip_id == 0x00947700 && i == 6) {
-                       p->sgmii = 1;
-
-                       /* SGMII PHY detection code is not implemented yet. */
-                       p->phy = 0;
-               }
        }
 }
 
@@ -1158,29 +1164,6 @@ int ksz9477_switch_init(struct ksz_device *dev)
        if (ret)
                return ret;
 
-       ret = ksz_read8(dev, REG_GLOBAL_OPTIONS, &data8);
-       if (ret)
-               return ret;
-
-       /* Number of ports can be reduced depending on chip. */
-       dev->phy_port_cnt = 5;
-
-       /* Default capability is gigabit capable. */
-       dev->features = GBIT_SUPPORT;
-
-       if (dev->chip_id == KSZ9893_CHIP_ID) {
-               dev->features |= IS_9893;
-
-               /* Chip does not support gigabit. */
-               if (data8 & SW_QW_ABLE)
-                       dev->features &= ~GBIT_SUPPORT;
-               dev->phy_port_cnt = 2;
-       } else {
-               /* Chip does not support gigabit. */
-               if (!(data8 & SW_GIGABIT_ABLE))
-                       dev->features &= ~GBIT_SUPPORT;
-       }
-
        return 0;
 }
 
index cd278b3..ce87e4e 100644 (file)
@@ -16,8 +16,8 @@ u32 ksz9477_get_port_addr(int port, int offset);
 void ksz9477_cfg_port_member(struct ksz_device *dev, int port, u8 member);
 void ksz9477_flush_dyn_mac_table(struct ksz_device *dev, int port);
 void ksz9477_port_setup(struct ksz_device *dev, int port, bool cpu_port);
-void ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
-void ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
+int ksz9477_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
+int ksz9477_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
 void ksz9477_r_mib_cnt(struct ksz_device *dev, int port, u16 addr, u64 *cnt);
 void ksz9477_r_mib_pkt(struct ksz_device *dev, int port, u16 addr,
                       u64 *dropped, u64 *cnt);
index 6bd69a7..37fb5ba 100644 (file)
@@ -412,7 +412,422 @@ static const u8 lan937x_shifts[] = {
        [ALU_STAT_INDEX]                = 8,
 };
 
+static const struct regmap_range ksz8563_valid_regs[] = {
+       regmap_reg_range(0x0000, 0x0003),
+       regmap_reg_range(0x0006, 0x0006),
+       regmap_reg_range(0x000f, 0x001f),
+       regmap_reg_range(0x0100, 0x0100),
+       regmap_reg_range(0x0104, 0x0107),
+       regmap_reg_range(0x010d, 0x010d),
+       regmap_reg_range(0x0110, 0x0113),
+       regmap_reg_range(0x0120, 0x012b),
+       regmap_reg_range(0x0201, 0x0201),
+       regmap_reg_range(0x0210, 0x0213),
+       regmap_reg_range(0x0300, 0x0300),
+       regmap_reg_range(0x0302, 0x031b),
+       regmap_reg_range(0x0320, 0x032b),
+       regmap_reg_range(0x0330, 0x0336),
+       regmap_reg_range(0x0338, 0x033e),
+       regmap_reg_range(0x0340, 0x035f),
+       regmap_reg_range(0x0370, 0x0370),
+       regmap_reg_range(0x0378, 0x0378),
+       regmap_reg_range(0x037c, 0x037d),
+       regmap_reg_range(0x0390, 0x0393),
+       regmap_reg_range(0x0400, 0x040e),
+       regmap_reg_range(0x0410, 0x042f),
+       regmap_reg_range(0x0500, 0x0519),
+       regmap_reg_range(0x0520, 0x054b),
+       regmap_reg_range(0x0550, 0x05b3),
+
+       /* port 1 */
+       regmap_reg_range(0x1000, 0x1001),
+       regmap_reg_range(0x1004, 0x100b),
+       regmap_reg_range(0x1013, 0x1013),
+       regmap_reg_range(0x1017, 0x1017),
+       regmap_reg_range(0x101b, 0x101b),
+       regmap_reg_range(0x101f, 0x1021),
+       regmap_reg_range(0x1030, 0x1030),
+       regmap_reg_range(0x1100, 0x1111),
+       regmap_reg_range(0x111a, 0x111d),
+       regmap_reg_range(0x1122, 0x1127),
+       regmap_reg_range(0x112a, 0x112b),
+       regmap_reg_range(0x1136, 0x1139),
+       regmap_reg_range(0x113e, 0x113f),
+       regmap_reg_range(0x1400, 0x1401),
+       regmap_reg_range(0x1403, 0x1403),
+       regmap_reg_range(0x1410, 0x1417),
+       regmap_reg_range(0x1420, 0x1423),
+       regmap_reg_range(0x1500, 0x1507),
+       regmap_reg_range(0x1600, 0x1612),
+       regmap_reg_range(0x1800, 0x180f),
+       regmap_reg_range(0x1900, 0x1907),
+       regmap_reg_range(0x1914, 0x191b),
+       regmap_reg_range(0x1a00, 0x1a03),
+       regmap_reg_range(0x1a04, 0x1a08),
+       regmap_reg_range(0x1b00, 0x1b01),
+       regmap_reg_range(0x1b04, 0x1b04),
+       regmap_reg_range(0x1c00, 0x1c05),
+       regmap_reg_range(0x1c08, 0x1c1b),
+
+       /* port 2 */
+       regmap_reg_range(0x2000, 0x2001),
+       regmap_reg_range(0x2004, 0x200b),
+       regmap_reg_range(0x2013, 0x2013),
+       regmap_reg_range(0x2017, 0x2017),
+       regmap_reg_range(0x201b, 0x201b),
+       regmap_reg_range(0x201f, 0x2021),
+       regmap_reg_range(0x2030, 0x2030),
+       regmap_reg_range(0x2100, 0x2111),
+       regmap_reg_range(0x211a, 0x211d),
+       regmap_reg_range(0x2122, 0x2127),
+       regmap_reg_range(0x212a, 0x212b),
+       regmap_reg_range(0x2136, 0x2139),
+       regmap_reg_range(0x213e, 0x213f),
+       regmap_reg_range(0x2400, 0x2401),
+       regmap_reg_range(0x2403, 0x2403),
+       regmap_reg_range(0x2410, 0x2417),
+       regmap_reg_range(0x2420, 0x2423),
+       regmap_reg_range(0x2500, 0x2507),
+       regmap_reg_range(0x2600, 0x2612),
+       regmap_reg_range(0x2800, 0x280f),
+       regmap_reg_range(0x2900, 0x2907),
+       regmap_reg_range(0x2914, 0x291b),
+       regmap_reg_range(0x2a00, 0x2a03),
+       regmap_reg_range(0x2a04, 0x2a08),
+       regmap_reg_range(0x2b00, 0x2b01),
+       regmap_reg_range(0x2b04, 0x2b04),
+       regmap_reg_range(0x2c00, 0x2c05),
+       regmap_reg_range(0x2c08, 0x2c1b),
+
+       /* port 3 */
+       regmap_reg_range(0x3000, 0x3001),
+       regmap_reg_range(0x3004, 0x300b),
+       regmap_reg_range(0x3013, 0x3013),
+       regmap_reg_range(0x3017, 0x3017),
+       regmap_reg_range(0x301b, 0x301b),
+       regmap_reg_range(0x301f, 0x3021),
+       regmap_reg_range(0x3030, 0x3030),
+       regmap_reg_range(0x3300, 0x3301),
+       regmap_reg_range(0x3303, 0x3303),
+       regmap_reg_range(0x3400, 0x3401),
+       regmap_reg_range(0x3403, 0x3403),
+       regmap_reg_range(0x3410, 0x3417),
+       regmap_reg_range(0x3420, 0x3423),
+       regmap_reg_range(0x3500, 0x3507),
+       regmap_reg_range(0x3600, 0x3612),
+       regmap_reg_range(0x3800, 0x380f),
+       regmap_reg_range(0x3900, 0x3907),
+       regmap_reg_range(0x3914, 0x391b),
+       regmap_reg_range(0x3a00, 0x3a03),
+       regmap_reg_range(0x3a04, 0x3a08),
+       regmap_reg_range(0x3b00, 0x3b01),
+       regmap_reg_range(0x3b04, 0x3b04),
+       regmap_reg_range(0x3c00, 0x3c05),
+       regmap_reg_range(0x3c08, 0x3c1b),
+};
+
+static const struct regmap_access_table ksz8563_register_set = {
+       .yes_ranges = ksz8563_valid_regs,
+       .n_yes_ranges = ARRAY_SIZE(ksz8563_valid_regs),
+};
+
+static const struct regmap_range ksz9477_valid_regs[] = {
+       regmap_reg_range(0x0000, 0x0003),
+       regmap_reg_range(0x0006, 0x0006),
+       regmap_reg_range(0x0010, 0x001f),
+       regmap_reg_range(0x0100, 0x0100),
+       regmap_reg_range(0x0103, 0x0107),
+       regmap_reg_range(0x010d, 0x010d),
+       regmap_reg_range(0x0110, 0x0113),
+       regmap_reg_range(0x0120, 0x012b),
+       regmap_reg_range(0x0201, 0x0201),
+       regmap_reg_range(0x0210, 0x0213),
+       regmap_reg_range(0x0300, 0x0300),
+       regmap_reg_range(0x0302, 0x031b),
+       regmap_reg_range(0x0320, 0x032b),
+       regmap_reg_range(0x0330, 0x0336),
+       regmap_reg_range(0x0338, 0x033e),
+       regmap_reg_range(0x0340, 0x035f),
+       regmap_reg_range(0x0370, 0x0370),
+       regmap_reg_range(0x0378, 0x0378),
+       regmap_reg_range(0x037c, 0x037d),
+       regmap_reg_range(0x0390, 0x0393),
+       regmap_reg_range(0x0400, 0x040e),
+       regmap_reg_range(0x0410, 0x042f),
+       regmap_reg_range(0x0444, 0x044b),
+       regmap_reg_range(0x0450, 0x046f),
+       regmap_reg_range(0x0500, 0x0519),
+       regmap_reg_range(0x0520, 0x054b),
+       regmap_reg_range(0x0550, 0x05b3),
+       regmap_reg_range(0x0604, 0x060b),
+       regmap_reg_range(0x0610, 0x0612),
+       regmap_reg_range(0x0614, 0x062c),
+       regmap_reg_range(0x0640, 0x0645),
+       regmap_reg_range(0x0648, 0x064d),
+
+       /* port 1 */
+       regmap_reg_range(0x1000, 0x1001),
+       regmap_reg_range(0x1013, 0x1013),
+       regmap_reg_range(0x1017, 0x1017),
+       regmap_reg_range(0x101b, 0x101b),
+       regmap_reg_range(0x101f, 0x1020),
+       regmap_reg_range(0x1030, 0x1030),
+       regmap_reg_range(0x1100, 0x1115),
+       regmap_reg_range(0x111a, 0x111f),
+       regmap_reg_range(0x1122, 0x1127),
+       regmap_reg_range(0x112a, 0x112b),
+       regmap_reg_range(0x1136, 0x1139),
+       regmap_reg_range(0x113e, 0x113f),
+       regmap_reg_range(0x1400, 0x1401),
+       regmap_reg_range(0x1403, 0x1403),
+       regmap_reg_range(0x1410, 0x1417),
+       regmap_reg_range(0x1420, 0x1423),
+       regmap_reg_range(0x1500, 0x1507),
+       regmap_reg_range(0x1600, 0x1613),
+       regmap_reg_range(0x1800, 0x180f),
+       regmap_reg_range(0x1820, 0x1827),
+       regmap_reg_range(0x1830, 0x1837),
+       regmap_reg_range(0x1840, 0x184b),
+       regmap_reg_range(0x1900, 0x1907),
+       regmap_reg_range(0x1914, 0x191b),
+       regmap_reg_range(0x1920, 0x1920),
+       regmap_reg_range(0x1923, 0x1927),
+       regmap_reg_range(0x1a00, 0x1a03),
+       regmap_reg_range(0x1a04, 0x1a07),
+       regmap_reg_range(0x1b00, 0x1b01),
+       regmap_reg_range(0x1b04, 0x1b04),
+       regmap_reg_range(0x1c00, 0x1c05),
+       regmap_reg_range(0x1c08, 0x1c1b),
+
+       /* port 2 */
+       regmap_reg_range(0x2000, 0x2001),
+       regmap_reg_range(0x2013, 0x2013),
+       regmap_reg_range(0x2017, 0x2017),
+       regmap_reg_range(0x201b, 0x201b),
+       regmap_reg_range(0x201f, 0x2020),
+       regmap_reg_range(0x2030, 0x2030),
+       regmap_reg_range(0x2100, 0x2115),
+       regmap_reg_range(0x211a, 0x211f),
+       regmap_reg_range(0x2122, 0x2127),
+       regmap_reg_range(0x212a, 0x212b),
+       regmap_reg_range(0x2136, 0x2139),
+       regmap_reg_range(0x213e, 0x213f),
+       regmap_reg_range(0x2400, 0x2401),
+       regmap_reg_range(0x2403, 0x2403),
+       regmap_reg_range(0x2410, 0x2417),
+       regmap_reg_range(0x2420, 0x2423),
+       regmap_reg_range(0x2500, 0x2507),
+       regmap_reg_range(0x2600, 0x2613),
+       regmap_reg_range(0x2800, 0x280f),
+       regmap_reg_range(0x2820, 0x2827),
+       regmap_reg_range(0x2830, 0x2837),
+       regmap_reg_range(0x2840, 0x284b),
+       regmap_reg_range(0x2900, 0x2907),
+       regmap_reg_range(0x2914, 0x291b),
+       regmap_reg_range(0x2920, 0x2920),
+       regmap_reg_range(0x2923, 0x2927),
+       regmap_reg_range(0x2a00, 0x2a03),
+       regmap_reg_range(0x2a04, 0x2a07),
+       regmap_reg_range(0x2b00, 0x2b01),
+       regmap_reg_range(0x2b04, 0x2b04),
+       regmap_reg_range(0x2c00, 0x2c05),
+       regmap_reg_range(0x2c08, 0x2c1b),
+
+       /* port 3 */
+       regmap_reg_range(0x3000, 0x3001),
+       regmap_reg_range(0x3013, 0x3013),
+       regmap_reg_range(0x3017, 0x3017),
+       regmap_reg_range(0x301b, 0x301b),
+       regmap_reg_range(0x301f, 0x3020),
+       regmap_reg_range(0x3030, 0x3030),
+       regmap_reg_range(0x3100, 0x3115),
+       regmap_reg_range(0x311a, 0x311f),
+       regmap_reg_range(0x3122, 0x3127),
+       regmap_reg_range(0x312a, 0x312b),
+       regmap_reg_range(0x3136, 0x3139),
+       regmap_reg_range(0x313e, 0x313f),
+       regmap_reg_range(0x3400, 0x3401),
+       regmap_reg_range(0x3403, 0x3403),
+       regmap_reg_range(0x3410, 0x3417),
+       regmap_reg_range(0x3420, 0x3423),
+       regmap_reg_range(0x3500, 0x3507),
+       regmap_reg_range(0x3600, 0x3613),
+       regmap_reg_range(0x3800, 0x380f),
+       regmap_reg_range(0x3820, 0x3827),
+       regmap_reg_range(0x3830, 0x3837),
+       regmap_reg_range(0x3840, 0x384b),
+       regmap_reg_range(0x3900, 0x3907),
+       regmap_reg_range(0x3914, 0x391b),
+       regmap_reg_range(0x3920, 0x3920),
+       regmap_reg_range(0x3923, 0x3927),
+       regmap_reg_range(0x3a00, 0x3a03),
+       regmap_reg_range(0x3a04, 0x3a07),
+       regmap_reg_range(0x3b00, 0x3b01),
+       regmap_reg_range(0x3b04, 0x3b04),
+       regmap_reg_range(0x3c00, 0x3c05),
+       regmap_reg_range(0x3c08, 0x3c1b),
+
+       /* port 4 */
+       regmap_reg_range(0x4000, 0x4001),
+       regmap_reg_range(0x4013, 0x4013),
+       regmap_reg_range(0x4017, 0x4017),
+       regmap_reg_range(0x401b, 0x401b),
+       regmap_reg_range(0x401f, 0x4020),
+       regmap_reg_range(0x4030, 0x4030),
+       regmap_reg_range(0x4100, 0x4115),
+       regmap_reg_range(0x411a, 0x411f),
+       regmap_reg_range(0x4122, 0x4127),
+       regmap_reg_range(0x412a, 0x412b),
+       regmap_reg_range(0x4136, 0x4139),
+       regmap_reg_range(0x413e, 0x413f),
+       regmap_reg_range(0x4400, 0x4401),
+       regmap_reg_range(0x4403, 0x4403),
+       regmap_reg_range(0x4410, 0x4417),
+       regmap_reg_range(0x4420, 0x4423),
+       regmap_reg_range(0x4500, 0x4507),
+       regmap_reg_range(0x4600, 0x4613),
+       regmap_reg_range(0x4800, 0x480f),
+       regmap_reg_range(0x4820, 0x4827),
+       regmap_reg_range(0x4830, 0x4837),
+       regmap_reg_range(0x4840, 0x484b),
+       regmap_reg_range(0x4900, 0x4907),
+       regmap_reg_range(0x4914, 0x491b),
+       regmap_reg_range(0x4920, 0x4920),
+       regmap_reg_range(0x4923, 0x4927),
+       regmap_reg_range(0x4a00, 0x4a03),
+       regmap_reg_range(0x4a04, 0x4a07),
+       regmap_reg_range(0x4b00, 0x4b01),
+       regmap_reg_range(0x4b04, 0x4b04),
+       regmap_reg_range(0x4c00, 0x4c05),
+       regmap_reg_range(0x4c08, 0x4c1b),
+
+       /* port 5 */
+       regmap_reg_range(0x5000, 0x5001),
+       regmap_reg_range(0x5013, 0x5013),
+       regmap_reg_range(0x5017, 0x5017),
+       regmap_reg_range(0x501b, 0x501b),
+       regmap_reg_range(0x501f, 0x5020),
+       regmap_reg_range(0x5030, 0x5030),
+       regmap_reg_range(0x5100, 0x5115),
+       regmap_reg_range(0x511a, 0x511f),
+       regmap_reg_range(0x5122, 0x5127),
+       regmap_reg_range(0x512a, 0x512b),
+       regmap_reg_range(0x5136, 0x5139),
+       regmap_reg_range(0x513e, 0x513f),
+       regmap_reg_range(0x5400, 0x5401),
+       regmap_reg_range(0x5403, 0x5403),
+       regmap_reg_range(0x5410, 0x5417),
+       regmap_reg_range(0x5420, 0x5423),
+       regmap_reg_range(0x5500, 0x5507),
+       regmap_reg_range(0x5600, 0x5613),
+       regmap_reg_range(0x5800, 0x580f),
+       regmap_reg_range(0x5820, 0x5827),
+       regmap_reg_range(0x5830, 0x5837),
+       regmap_reg_range(0x5840, 0x584b),
+       regmap_reg_range(0x5900, 0x5907),
+       regmap_reg_range(0x5914, 0x591b),
+       regmap_reg_range(0x5920, 0x5920),
+       regmap_reg_range(0x5923, 0x5927),
+       regmap_reg_range(0x5a00, 0x5a03),
+       regmap_reg_range(0x5a04, 0x5a07),
+       regmap_reg_range(0x5b00, 0x5b01),
+       regmap_reg_range(0x5b04, 0x5b04),
+       regmap_reg_range(0x5c00, 0x5c05),
+       regmap_reg_range(0x5c08, 0x5c1b),
+
+       /* port 6 */
+       regmap_reg_range(0x6000, 0x6001),
+       regmap_reg_range(0x6013, 0x6013),
+       regmap_reg_range(0x6017, 0x6017),
+       regmap_reg_range(0x601b, 0x601b),
+       regmap_reg_range(0x601f, 0x6020),
+       regmap_reg_range(0x6030, 0x6030),
+       regmap_reg_range(0x6300, 0x6301),
+       regmap_reg_range(0x6400, 0x6401),
+       regmap_reg_range(0x6403, 0x6403),
+       regmap_reg_range(0x6410, 0x6417),
+       regmap_reg_range(0x6420, 0x6423),
+       regmap_reg_range(0x6500, 0x6507),
+       regmap_reg_range(0x6600, 0x6613),
+       regmap_reg_range(0x6800, 0x680f),
+       regmap_reg_range(0x6820, 0x6827),
+       regmap_reg_range(0x6830, 0x6837),
+       regmap_reg_range(0x6840, 0x684b),
+       regmap_reg_range(0x6900, 0x6907),
+       regmap_reg_range(0x6914, 0x691b),
+       regmap_reg_range(0x6920, 0x6920),
+       regmap_reg_range(0x6923, 0x6927),
+       regmap_reg_range(0x6a00, 0x6a03),
+       regmap_reg_range(0x6a04, 0x6a07),
+       regmap_reg_range(0x6b00, 0x6b01),
+       regmap_reg_range(0x6b04, 0x6b04),
+       regmap_reg_range(0x6c00, 0x6c05),
+       regmap_reg_range(0x6c08, 0x6c1b),
+
+       /* port 7 */
+       regmap_reg_range(0x7000, 0x7001),
+       regmap_reg_range(0x7013, 0x7013),
+       regmap_reg_range(0x7017, 0x7017),
+       regmap_reg_range(0x701b, 0x701b),
+       regmap_reg_range(0x701f, 0x7020),
+       regmap_reg_range(0x7030, 0x7030),
+       regmap_reg_range(0x7200, 0x7203),
+       regmap_reg_range(0x7206, 0x7207),
+       regmap_reg_range(0x7300, 0x7301),
+       regmap_reg_range(0x7400, 0x7401),
+       regmap_reg_range(0x7403, 0x7403),
+       regmap_reg_range(0x7410, 0x7417),
+       regmap_reg_range(0x7420, 0x7423),
+       regmap_reg_range(0x7500, 0x7507),
+       regmap_reg_range(0x7600, 0x7613),
+       regmap_reg_range(0x7800, 0x780f),
+       regmap_reg_range(0x7820, 0x7827),
+       regmap_reg_range(0x7830, 0x7837),
+       regmap_reg_range(0x7840, 0x784b),
+       regmap_reg_range(0x7900, 0x7907),
+       regmap_reg_range(0x7914, 0x791b),
+       regmap_reg_range(0x7920, 0x7920),
+       regmap_reg_range(0x7923, 0x7927),
+       regmap_reg_range(0x7a00, 0x7a03),
+       regmap_reg_range(0x7a04, 0x7a07),
+       regmap_reg_range(0x7b00, 0x7b01),
+       regmap_reg_range(0x7b04, 0x7b04),
+       regmap_reg_range(0x7c00, 0x7c05),
+       regmap_reg_range(0x7c08, 0x7c1b),
+};
+
+static const struct regmap_access_table ksz9477_register_set = {
+       .yes_ranges = ksz9477_valid_regs,
+       .n_yes_ranges = ARRAY_SIZE(ksz9477_valid_regs),
+};
+
 const struct ksz_chip_data ksz_switch_chips[] = {
+       [KSZ8563] = {
+               .chip_id = KSZ8563_CHIP_ID,
+               .dev_name = "KSZ8563",
+               .num_vlans = 4096,
+               .num_alus = 4096,
+               .num_statics = 16,
+               .cpu_ports = 0x07,      /* can be configured as cpu port */
+               .port_cnt = 3,          /* total port count */
+               .ops = &ksz9477_dev_ops,
+               .mib_names = ksz9477_mib_names,
+               .mib_cnt = ARRAY_SIZE(ksz9477_mib_names),
+               .reg_mib_cnt = MIB_COUNTER_NUM,
+               .regs = ksz9477_regs,
+               .masks = ksz9477_masks,
+               .shifts = ksz9477_shifts,
+               .xmii_ctrl0 = ksz9477_xmii_ctrl0,
+               .xmii_ctrl1 = ksz8795_xmii_ctrl1, /* Same as ksz8795 */
+               .supports_mii = {false, false, true},
+               .supports_rmii = {false, false, true},
+               .supports_rgmii = {false, false, true},
+               .internal_phy = {true, true, false},
+               .gbit_capable = {false, false, true},
+               .wr_table = &ksz8563_register_set,
+               .rd_table = &ksz8563_register_set,
+       },
+
        [KSZ8795] = {
                .chip_id = KSZ8795_CHIP_ID,
                .dev_name = "KSZ8795",
@@ -545,6 +960,9 @@ const struct ksz_chip_data ksz_switch_chips[] = {
                                   false, true, false},
                .internal_phy   = {true, true, true, true,
                                   true, false, false},
+               .gbit_capable   = {true, true, true, true, true, true, true},
+               .wr_table = &ksz9477_register_set,
+               .rd_table = &ksz9477_register_set,
        },
 
        [KSZ9897] = {
@@ -573,6 +991,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
                                   false, true, true},
                .internal_phy   = {true, true, true, true,
                                   true, false, false},
+               .gbit_capable   = {true, true, true, true, true, true, true},
        },
 
        [KSZ9893] = {
@@ -596,6 +1015,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
                .supports_rmii = {false, false, true},
                .supports_rgmii = {false, false, true},
                .internal_phy = {true, true, false},
+               .gbit_capable = {true, true, true},
        },
 
        [KSZ9567] = {
@@ -624,6 +1044,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
                                   false, true, true},
                .internal_phy   = {true, true, true, true,
                                   true, false, false},
+               .gbit_capable   = {true, true, true, true, true, true, true},
        },
 
        [LAN9370] = {
@@ -1104,8 +1525,11 @@ static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
 {
        struct ksz_device *dev = ds->priv;
        u16 val = 0xffff;
+       int ret;
 
-       dev->dev_ops->r_phy(dev, addr, reg, &val);
+       ret = dev->dev_ops->r_phy(dev, addr, reg, &val);
+       if (ret)
+               return ret;
 
        return val;
 }
@@ -1113,8 +1537,11 @@ static int ksz_phy_read16(struct dsa_switch *ds, int addr, int reg)
 static int ksz_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
 {
        struct ksz_device *dev = ds->priv;
+       int ret;
 
-       dev->dev_ops->w_phy(dev, addr, reg, val);
+       ret = dev->dev_ops->w_phy(dev, addr, reg, val);
+       if (ret)
+               return ret;
 
        return 0;
 }
@@ -1366,6 +1793,7 @@ static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
                proto = DSA_TAG_PROTO_KSZ8795;
 
        if (dev->chip_id == KSZ8830_CHIP_ID ||
+           dev->chip_id == KSZ8563_CHIP_ID ||
            dev->chip_id == KSZ9893_CHIP_ID)
                proto = DSA_TAG_PROTO_KSZ9893;
 
@@ -1484,7 +1912,8 @@ static void ksz_set_xmii(struct ksz_device *dev, int port,
        case PHY_INTERFACE_MODE_RGMII_RXID:
                data8 |= bitval[P_RGMII_SEL];
                /* On KSZ9893, disable RGMII in-band status support */
-               if (dev->features & IS_9893)
+               if (dev->chip_id == KSZ9893_CHIP_ID ||
+                   dev->chip_id == KSZ8563_CHIP_ID)
                        data8 &= ~P_MII_MAC_MODE;
                break;
        default:
@@ -1685,7 +2114,7 @@ static void ksz_phylink_mac_link_up(struct dsa_switch *ds, int port,
 
 static int ksz_switch_detect(struct ksz_device *dev)
 {
-       u8 id1, id2;
+       u8 id1, id2, id4;
        u16 id16;
        u32 id32;
        int ret;
@@ -1731,7 +2160,6 @@ static int ksz_switch_detect(struct ksz_device *dev)
                switch (id32) {
                case KSZ9477_CHIP_ID:
                case KSZ9897_CHIP_ID:
-               case KSZ9893_CHIP_ID:
                case KSZ9567_CHIP_ID:
                case LAN9370_CHIP_ID:
                case LAN9371_CHIP_ID:
@@ -1739,6 +2167,18 @@ static int ksz_switch_detect(struct ksz_device *dev)
                case LAN9373_CHIP_ID:
                case LAN9374_CHIP_ID:
                        dev->chip_id = id32;
+                       break;
+               case KSZ9893_CHIP_ID:
+                       ret = ksz_read8(dev, REG_CHIP_ID4,
+                                       &id4);
+                       if (ret)
+                               return ret;
+
+                       if (id4 == SKU_ID_KSZ8563)
+                               dev->chip_id = KSZ8563_CHIP_ID;
+                       else
+                               dev->chip_id = KSZ9893_CHIP_ID;
+
                        break;
                default:
                        dev_err(dev->dev,
index 0d9520d..c01989c 100644 (file)
@@ -61,6 +61,9 @@ struct ksz_chip_data {
        bool supports_rmii[KSZ_MAX_NUM_PORTS];
        bool supports_rgmii[KSZ_MAX_NUM_PORTS];
        bool internal_phy[KSZ_MAX_NUM_PORTS];
+       bool gbit_capable[KSZ_MAX_NUM_PORTS];
+       const struct regmap_access_table *wr_table;
+       const struct regmap_access_table *rd_table;
 };
 
 struct ksz_port {
@@ -70,9 +73,7 @@ struct ksz_port {
        struct phy_device phydev;
 
        u32 on:1;                       /* port is not disabled by hardware */
-       u32 phy:1;                      /* port has a PHY */
        u32 fiber:1;                    /* port is fiber */
-       u32 sgmii:1;                    /* port is SGMII */
        u32 force:1;
        u32 read:1;                     /* read MIB counters in background */
        u32 freeze:1;                   /* MIB counter freeze is enabled */
@@ -118,12 +119,12 @@ struct ksz_device {
        unsigned long mib_read_interval;
        u16 mirror_rx;
        u16 mirror_tx;
-       u32 features;                   /* chip specific features */
        u16 port_mask;
 };
 
 /* List of supported models */
 enum ksz_model {
+       KSZ8563,
        KSZ8795,
        KSZ8794,
        KSZ8765,
@@ -140,6 +141,7 @@ enum ksz_model {
 };
 
 enum ksz_chip_id {
+       KSZ8563_CHIP_ID = 0x8563,
        KSZ8795_CHIP_ID = 0x8795,
        KSZ8794_CHIP_ID = 0x8794,
        KSZ8765_CHIP_ID = 0x8765,
@@ -259,8 +261,8 @@ struct ksz_dev_ops {
        void (*flush_dyn_mac_table)(struct ksz_device *dev, int port);
        void (*port_cleanup)(struct ksz_device *dev, int port);
        void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port);
-       void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
-       void (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
+       int (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val);
+       int (*w_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 val);
        void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
                          u64 *cnt);
        void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
@@ -330,6 +332,10 @@ 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);
 
+       if (ret)
+               dev_err(dev->dev, "can't read 8bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+
        *val = value;
        return ret;
 }
@@ -339,6 +345,10 @@ 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);
 
+       if (ret)
+               dev_err(dev->dev, "can't read 16bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+
        *val = value;
        return ret;
 }
@@ -348,6 +358,10 @@ 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);
 
+       if (ret)
+               dev_err(dev->dev, "can't read 32bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+
        *val = value;
        return ret;
 }
@@ -358,7 +372,10 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
        int ret;
 
        ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
-       if (!ret)
+       if (ret)
+               dev_err(dev->dev, "can't read 64bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+       else
                *val = (u64)value[0] << 32 | value[1];
 
        return ret;
@@ -366,17 +383,38 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
 
 static inline int ksz_write8(struct ksz_device *dev, u32 reg, u8 value)
 {
-       return regmap_write(dev->regmap[0], reg, value);
+       int ret;
+
+       ret = regmap_write(dev->regmap[0], reg, value);
+       if (ret)
+               dev_err(dev->dev, "can't write 8bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+
+       return ret;
 }
 
 static inline int ksz_write16(struct ksz_device *dev, u32 reg, u16 value)
 {
-       return regmap_write(dev->regmap[1], reg, value);
+       int ret;
+
+       ret = regmap_write(dev->regmap[1], reg, value);
+       if (ret)
+               dev_err(dev->dev, "can't write 16bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+
+       return ret;
 }
 
 static inline int ksz_write32(struct ksz_device *dev, u32 reg, u32 value)
 {
-       return regmap_write(dev->regmap[2], reg, value);
+       int ret;
+
+       ret = regmap_write(dev->regmap[2], reg, value);
+       if (ret)
+               dev_err(dev->dev, "can't write 32bit reg: 0x%x %pe\n", reg,
+                       ERR_PTR(ret));
+
+       return ret;
 }
 
 static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
@@ -391,40 +429,42 @@ static inline int ksz_write64(struct ksz_device *dev, u32 reg, u64 value)
        return regmap_bulk_write(dev->regmap[2], reg, val, 2);
 }
 
-static inline void ksz_pread8(struct ksz_device *dev, int port, int offset,
-                             u8 *data)
+static inline int ksz_pread8(struct ksz_device *dev, int port, int offset,
+                            u8 *data)
 {
-       ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data);
+       return ksz_read8(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-static inline void ksz_pread16(struct ksz_device *dev, int port, int offset,
-                              u16 *data)
+static inline int ksz_pread16(struct ksz_device *dev, int port, int offset,
+                             u16 *data)
 {
-       ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data);
+       return ksz_read16(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-static inline void ksz_pread32(struct ksz_device *dev, int port, int offset,
-                              u32 *data)
+static inline int ksz_pread32(struct ksz_device *dev, int port, int offset,
+                             u32 *data)
 {
-       ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data);
+       return ksz_read32(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-static inline void ksz_pwrite8(struct ksz_device *dev, int port, int offset,
-                              u8 data)
+static inline int ksz_pwrite8(struct ksz_device *dev, int port, int offset,
+                             u8 data)
 {
-       ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data);
+       return ksz_write8(dev, dev->dev_ops->get_port_addr(port, offset), data);
 }
 
-static inline void ksz_pwrite16(struct ksz_device *dev, int port, int offset,
-                               u16 data)
+static inline int ksz_pwrite16(struct ksz_device *dev, int port, int offset,
+                              u16 data)
 {
-       ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset), data);
+       return ksz_write16(dev, dev->dev_ops->get_port_addr(port, offset),
+                          data);
 }
 
-static inline void ksz_pwrite32(struct ksz_device *dev, int port, int offset,
-                               u32 data)
+static inline int ksz_pwrite32(struct ksz_device *dev, int port, int offset,
+                              u32 data)
 {
-       ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset), data);
+       return ksz_write32(dev, dev->dev_ops->get_port_addr(port, offset),
+                          data);
 }
 
 static inline void ksz_prmw8(struct ksz_device *dev, int port, int offset,
@@ -483,6 +523,10 @@ static inline int is_lan937x(struct ksz_device *dev)
 
 #define SW_REV_ID_M                    GENMASK(7, 4)
 
+/* KSZ9893, KSZ9563, KSZ8563 specific register  */
+#define REG_CHIP_ID4                   0x0f
+#define SKU_ID_KSZ8563                 0x3c
+
 /* Driver set switch broadcast storm protection at 10% rate. */
 #define BROADCAST_STORM_PROT_RATE      10
 
@@ -497,10 +541,6 @@ static inline int is_lan937x(struct ksz_device *dev)
 
 #define SW_START                       0x01
 
-/* Used with variable features to indicate capabilities. */
-#define GBIT_SUPPORT                   BIT(0)
-#define IS_9893                                BIT(2)
-
 /* xMII configuration */
 #define P_MII_DUPLEX_M                 BIT(6)
 #define P_MII_100MBIT_M                        BIT(4)
index 05bd089..44c2d99 100644 (file)
@@ -66,7 +66,10 @@ static int ksz_spi_probe(struct spi_device *spi)
        for (i = 0; i < ARRAY_SIZE(ksz8795_regmap_config); i++) {
                rc = 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_spi(spi, &rc);
+
                if (IS_ERR(dev->regmap[i])) {
                        ret = PTR_ERR(dev->regmap[i]);
                        dev_err(&spi->dev,
@@ -160,7 +163,7 @@ static const struct of_device_id ksz_dt_ids[] = {
        },
        {
                .compatible = "microchip,ksz8563",
-               .data = &ksz_switch_chips[KSZ9893]
+               .data = &ksz_switch_chips[KSZ8563]
        },
        {
                .compatible = "microchip,ksz9567",
index 4e0b1dc..5d78d03 100644 (file)
@@ -12,8 +12,8 @@ void lan937x_port_setup(struct ksz_device *dev, int port, bool cpu_port);
 void lan937x_config_cpu_port(struct dsa_switch *ds);
 int lan937x_switch_init(struct ksz_device *dev);
 void lan937x_switch_exit(struct ksz_device *dev);
-void lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
-void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
+int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data);
+int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val);
 int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu);
 void lan937x_phylink_get_caps(struct ksz_device *dev, int port,
                              struct phylink_config *config);
index daedd2b..7b464f1 100644 (file)
@@ -128,14 +128,14 @@ static int lan937x_internal_phy_read(struct ksz_device *dev, int addr, int reg,
        return ksz_read16(dev, REG_VPHY_IND_DATA__2, val);
 }
 
-void lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
+int lan937x_r_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 *data)
 {
-       lan937x_internal_phy_read(dev, addr, reg, data);
+       return lan937x_internal_phy_read(dev, addr, reg, data);
 }
 
-void lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
+int lan937x_w_phy(struct ksz_device *dev, u16 addr, u16 reg, u16 val)
 {
-       lan937x_internal_phy_write(dev, addr, reg, val);
+       return lan937x_internal_phy_write(dev, addr, reg, val);
 }
 
 static int lan937x_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
index 07e9a4d..6f4ea39 100644 (file)
@@ -816,6 +816,14 @@ static void mv88e6393x_phylink_get_caps(struct mv88e6xxx_chip *chip, int port,
                                MAC_10000FD;
                }
        }
+
+       if (port == 0) {
+               __set_bit(PHY_INTERFACE_MODE_RMII, supported);
+               __set_bit(PHY_INTERFACE_MODE_RGMII, supported);
+               __set_bit(PHY_INTERFACE_MODE_RGMII_ID, supported);
+               __set_bit(PHY_INTERFACE_MODE_RGMII_RXID, supported);
+               __set_bit(PHY_INTERFACE_MODE_RGMII_TXID, supported);
+       }
 }
 
 static void mv88e6xxx_get_caps(struct dsa_switch *ds, int port,
@@ -1128,7 +1136,7 @@ static void mv88e6xxx_atu_vtu_get_strings(uint8_t *data)
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(mv88e6xxx_atu_vtu_stats_strings); i++)
-               strlcpy(data + i * ETH_GSTRING_LEN,
+               strscpy(data + i * ETH_GSTRING_LEN,
                        mv88e6xxx_atu_vtu_stats_strings[i],
                        ETH_GSTRING_LEN);
 }
index 807aeaa..7536b8b 100644 (file)
 #define MV88E6352_G2_SCRATCH_CONFIG_DATA1      0x71
 #define MV88E6352_G2_SCRATCH_CONFIG_DATA1_NO_CPU       BIT(2)
 #define MV88E6352_G2_SCRATCH_CONFIG_DATA2      0x72
-#define MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK 0x3
+#define MV88E6352_G2_SCRATCH_CONFIG_DATA2_P0_MODE_MASK 0xf
 #define MV88E6352_G2_SCRATCH_CONFIG_DATA3      0x73
 #define MV88E6352_G2_SCRATCH_CONFIG_DATA3_S_SEL                BIT(1)
 
index 90c55f2..5c4195c 100644 (file)
@@ -517,6 +517,12 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
        case PHY_INTERFACE_MODE_RMII:
                cmode = MV88E6XXX_PORT_STS_CMODE_RMII;
                break;
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+               cmode = MV88E6XXX_PORT_STS_CMODE_RGMII;
+               break;
        case PHY_INTERFACE_MODE_1000BASEX:
                cmode = MV88E6XXX_PORT_STS_CMODE_1000BASEX;
                break;
@@ -634,6 +640,19 @@ int mv88e6393x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
        if (port != 0 && port != 9 && port != 10)
                return -EOPNOTSUPP;
 
+       if (port == 9 || port == 10) {
+               switch (mode) {
+               case PHY_INTERFACE_MODE_RMII:
+               case PHY_INTERFACE_MODE_RGMII:
+               case PHY_INTERFACE_MODE_RGMII_ID:
+               case PHY_INTERFACE_MODE_RGMII_RXID:
+               case PHY_INTERFACE_MODE_RGMII_TXID:
+                       return -EINVAL;
+               default:
+                       break;
+               }
+       }
+
        /* mv88e6393x errata 4.5: EEE should be disabled on SERDES ports */
        err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
        if (err)
index aadb0bd..ee19ed9 100644 (file)
@@ -445,6 +445,9 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)
        if (err)
                return err;
 
+       dsa_switch_for_each_cpu_port(dp, ds)
+               ocelot_port_setup_dsa_8021q_cpu(ocelot, dp->index);
+
        dsa_switch_for_each_user_port(dp, ds)
                ocelot_port_assign_dsa_8021q_cpu(ocelot, dp->index,
                                                 dp->cpu_dp->index);
@@ -493,6 +496,9 @@ static void felix_tag_8021q_teardown(struct dsa_switch *ds)
        dsa_switch_for_each_user_port(dp, ds)
                ocelot_port_unassign_dsa_8021q_cpu(ocelot, dp->index);
 
+       dsa_switch_for_each_cpu_port(dp, ds)
+               ocelot_port_teardown_dsa_8021q_cpu(ocelot, dp->index);
+
        dsa_tag_8021q_unregister(ds);
 }
 
index 3887ed3..fa62263 100644 (file)
@@ -109,6 +109,7 @@ static void xrs700x_read_port_counters(struct xrs700x *priv, int port)
 {
        struct xrs700x_port *p = &priv->ports[port];
        struct rtnl_link_stats64 stats;
+       unsigned long flags;
        int i;
 
        memset(&stats, 0, sizeof(stats));
@@ -138,9 +139,9 @@ static void xrs700x_read_port_counters(struct xrs700x *priv, int port)
         */
        stats.rx_packets += stats.multicast;
 
-       u64_stats_update_begin(&p->syncp);
+       flags = u64_stats_update_begin_irqsave(&p->syncp);
        p->stats64 = stats;
-       u64_stats_update_end(&p->syncp);
+       u64_stats_update_end_irqrestore(&p->syncp, flags);
 
        mutex_unlock(&p->mib_mutex);
 }
index f82ad74..aa0fc00 100644 (file)
@@ -102,7 +102,7 @@ static const struct net_device_ops dummy_netdev_ops = {
 static void dummy_get_drvinfo(struct net_device *dev,
                              struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
 }
 
 static const struct ethtool_ops dummy_ethtool_ops = {
index 846fa3a..fb68339 100644 (file)
@@ -1135,7 +1135,7 @@ el3_netdev_set_ecmd(struct net_device *dev,
 
 static void el3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
 }
 
 static int el3_get_link_ksettings(struct net_device *dev,
index 1d124b0..d2f4358 100644 (file)
@@ -1527,7 +1527,7 @@ static void set_rx_mode(struct net_device *dev)
 static void netdev_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        snprintf(info->bus_info, sizeof(info->bus_info), "ISA 0x%lx",
                 dev->base_addr);
 }
index 4673bc1..82f94b1 100644 (file)
@@ -480,7 +480,7 @@ static void tc589_reset(struct net_device *dev)
 static void netdev_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        snprintf(info->bus_info, sizeof(info->bus_info),
                "PCMCIA 0x%lx", dev->base_addr);
 }
index ccf0766..082388b 100644 (file)
@@ -2959,13 +2959,13 @@ static void vortex_get_drvinfo(struct net_device *dev,
 {
        struct vortex_private *vp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        if (VORTEX_PCI(vp)) {
-               strlcpy(info->bus_info, pci_name(VORTEX_PCI(vp)),
+               strscpy(info->bus_info, pci_name(VORTEX_PCI(vp)),
                        sizeof(info->bus_info));
        } else {
                if (VORTEX_EISA(vp))
-                       strlcpy(info->bus_info, dev_name(vp->gendev),
+                       strscpy(info->bus_info, dev_name(vp->gendev),
                                sizeof(info->bus_info));
                else
                        snprintf(info->bus_info, sizeof(info->bus_info),
index cad4f35..aaaff3b 100644 (file)
@@ -969,12 +969,12 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 
        smp_rmb();
        if (tp->card_state == Sleeping) {
-               strlcpy(info->fw_version, "Sleep image",
+               strscpy(info->fw_version, "Sleep image",
                        sizeof(info->fw_version));
        } else {
                INIT_COMMAND_WITH_RESPONSE(&xp_cmd, TYPHOON_CMD_READ_VERSIONS);
                if (typhoon_issue_command(tp, 1, &xp_cmd, 3, xp_resp) < 0) {
-                       strlcpy(info->fw_version, "Unknown runtime",
+                       strscpy(info->fw_version, "Unknown runtime",
                                sizeof(info->fw_version));
                } else {
                        u32 sleep_ver = le32_to_cpu(xp_resp[0].parm2);
@@ -984,8 +984,8 @@ typhoon_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
                }
        }
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info));
 }
 
 static int
index 1f8acbb..af60325 100644 (file)
@@ -579,9 +579,9 @@ static void ax_get_drvinfo(struct net_device *dev,
 {
        struct platform_device *pdev = to_platform_device(dev->dev.parent);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pdev->name, sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pdev->name, sizeof(info->bus_info));
 }
 
 static u32 ax_get_msglevel(struct net_device *dev)
index e7b8791..05d39ec 100644 (file)
@@ -555,9 +555,9 @@ static int __init etherm_addr(char *addr)
 
 static void etherh_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(dev->dev.parent),
                sizeof(info->bus_info));
 }
 
index 8f0a6b9..857361c 100644 (file)
@@ -1844,8 +1844,8 @@ static int check_if_running(struct net_device *dev)
 static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct netdev_private *np = netdev_priv(dev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int get_link_ksettings(struct net_device *dev,
index 447dc64..9c4fe25 100644 (file)
@@ -1112,9 +1112,9 @@ static void greth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *in
 {
        struct greth_private *greth = netdev_priv(dev);
 
-       strlcpy(info->driver, dev_driver_string(greth->dev),
+       strscpy(info->driver, dev_driver_string(greth->dev),
                sizeof(info->driver));
-       strlcpy(info->bus_info, greth->dev->bus->name, sizeof(info->bus_info));
+       strscpy(info->bus_info, greth->dev->bus->name, sizeof(info->bus_info));
 }
 
 static void greth_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *p)
index d19d157..28334b1 100644 (file)
@@ -2952,8 +2952,8 @@ static void et131x_get_drvinfo(struct net_device *netdev,
 {
        struct et131x_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(adapter->pdev),
+       strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(adapter->pdev),
                sizeof(info->bus_info));
 }
 
index ce353b0..4cea61f 100644 (file)
@@ -1531,8 +1531,8 @@ static void slic_get_drvinfo(struct net_device *dev,
 {
        struct slic_device *sdev = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(sdev->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(sdev->pdev), sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops slic_ethtool_ops = {
index 621ce74..a94c629 100644 (file)
@@ -331,8 +331,8 @@ prepare_err:
 static void emac_get_drvinfo(struct net_device *dev,
                              struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(&dev->dev), sizeof(info->bus_info));
 }
 
 static u32 emac_get_msglevel(struct net_device *dev)
index 22fe985..d7762da 100644 (file)
@@ -2691,12 +2691,12 @@ static void ace_get_drvinfo(struct net_device *dev,
 {
        struct ace_private *ap = netdev_priv(dev);
 
-       strlcpy(info->driver, "acenic", sizeof(info->driver));
+       strscpy(info->driver, "acenic", sizeof(info->driver));
        snprintf(info->fw_version, sizeof(info->version), "%i.%i.%i",
                 ap->firmware_major, ap->firmware_minor, ap->firmware_fix);
 
        if (ap->pdev)
-               strlcpy(info->bus_info, pci_name(ap->pdev),
+               strscpy(info->bus_info, pci_name(ap->pdev),
                        sizeof(info->bus_info));
 
 }
index 4299f13..3081e58 100644 (file)
@@ -233,6 +233,7 @@ static const struct ethtool_ops tse_ethtool_ops = {
        .set_msglevel = tse_set_msglevel,
        .get_link_ksettings = phy_ethtool_get_link_ksettings,
        .set_link_ksettings = phy_ethtool_set_link_ksettings,
+       .get_ts_info = ethtool_op_get_ts_info,
 };
 
 void altera_tse_set_ethtool_ops(struct net_device *netdev)
index 39242c5..98d6386 100644 (file)
@@ -462,8 +462,8 @@ static void ena_get_drvinfo(struct net_device *dev,
 {
        struct ena_adapter *adapter = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(adapter->pdev),
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(adapter->pdev),
                sizeof(info->bus_info));
 }
 
index 6a356a6..371269e 100644 (file)
@@ -3166,7 +3166,7 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev, struct pci_dev *pd
        host_info->bdf = (pdev->bus->number << 8) | pdev->devfn;
        host_info->os_type = ENA_ADMIN_OS_LINUX;
        host_info->kernel_ver = LINUX_VERSION_CODE;
-       strlcpy(host_info->kernel_ver_str, utsname()->version,
+       strscpy(host_info->kernel_ver_str, utsname()->version,
                sizeof(host_info->kernel_ver_str) - 1);
        host_info->os_dist = 0;
        strncpy(host_info->os_dist_str, utsname()->release,
index 5d1baa0..fb6a5f6 100644 (file)
@@ -1364,10 +1364,10 @@ static void amd8111e_get_drvinfo(struct net_device *dev,
 {
        struct amd8111e_priv *lp = netdev_priv(dev);
        struct pci_dev *pci_dev = lp->pci_dev;
-       strlcpy(info->driver, MODULE_NAME, sizeof(info->driver));
+       strscpy(info->driver, MODULE_NAME, sizeof(info->driver));
        snprintf(info->fw_version, sizeof(info->fw_version),
                "%u", chip_version);
-       strlcpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info));
+       strscpy(info->bus_info, pci_name(pci_dev), sizeof(info->bus_info));
 }
 
 static int amd8111e_get_regs_len(struct net_device *dev)
index d5f2c69..81d5af0 100644 (file)
@@ -650,7 +650,7 @@ au1000_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct au1000_private *aup = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        snprintf(info->bus_info, sizeof(info->bus_info), "%s %d", DRV_NAME,
                 aup->mac_id);
 }
index 30ee532..df8874b 100644 (file)
@@ -815,7 +815,7 @@ static int mace_close(struct net_device *dev)
 static void netdev_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        snprintf(info->bus_info, sizeof(info->bus_info),
                "PCMCIA 0x%lx", dev->base_addr);
 }
index b5ff472..c913817 100644 (file)
@@ -797,9 +797,9 @@ static void pcnet32_get_drvinfo(struct net_device *dev,
 {
        struct pcnet32_private *lp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        if (lp->pci_dev)
-               strlcpy(info->bus_info, pci_name(lp->pci_dev),
+               strscpy(info->bus_info, pci_name(lp->pci_dev),
                        sizeof(info->bus_info));
        else
                snprintf(info->bus_info, sizeof(info->bus_info),
index 22d6095..4ed2ebb 100644 (file)
@@ -1276,7 +1276,7 @@ static void lance_free_hwresources(struct lance_private *lp)
 /* Ethtool support... */
 static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "sunlance", sizeof(info->driver));
+       strscpy(info->driver, "sunlance", sizeof(info->driver));
 }
 
 static const struct ethtool_ops sparc_lance_ethtool_ops = {
index 6ceb1cd..6e83ff5 100644 (file)
@@ -402,8 +402,8 @@ static void xgbe_get_drvinfo(struct net_device *netdev,
        struct xgbe_prv_data *pdata = netdev_priv(netdev);
        struct xgbe_hw_features *hw_feat = &pdata->hw_feat;
 
-       strlcpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, dev_name(pdata->dev),
+       strscpy(drvinfo->driver, XGBE_DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, dev_name(pdata->dev),
                sizeof(drvinfo->bus_info));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d",
                 XGMAC_GET_BITS(hw_feat->version, MAC_VR, USERVER),
index 1daecd4..a08f221 100644 (file)
@@ -238,7 +238,7 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev,
                 "%u.%u.%u", firmware_version >> 24,
                 (firmware_version >> 16) & 0xFFU, firmware_version & 0xFFFFU);
 
-       strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
+       strscpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "",
                sizeof(drvinfo->bus_info));
        drvinfo->n_stats = aq_ethtool_n_stats(ndev);
        drvinfo->testinfo_len = 0;
index 288e296..ba0646b 100644 (file)
@@ -91,7 +91,7 @@ static void arc_emac_get_drvinfo(struct net_device *ndev,
 {
        struct arc_emac_priv *priv = netdev_priv(ndev);
 
-       strlcpy(info->driver, priv->drv_name, sizeof(info->driver));
+       strscpy(info->driver, priv->drv_name, sizeof(info->driver));
 }
 
 static const struct ethtool_ops arc_emac_ethtool_ops = {
index e461f47..cc932b3 100644 (file)
@@ -451,8 +451,8 @@ static void ag71xx_get_drvinfo(struct net_device *ndev,
 {
        struct ag71xx *ag = netdev_priv(ndev);
 
-       strlcpy(info->driver, "ag71xx", sizeof(info->driver));
-       strlcpy(info->bus_info, of_node_full_name(ag->pdev->dev.of_node),
+       strscpy(info->driver, "ag71xx", sizeof(info->driver));
+       strscpy(info->bus_info, of_node_full_name(ag->pdev->dev.of_node),
                sizeof(info->bus_info));
 }
 
index e2eb7b8..0bce122 100644 (file)
@@ -220,8 +220,8 @@ static void atl1c_get_drvinfo(struct net_device *netdev,
 {
        struct atl1c_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver,  atl1c_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 0cbde35..68f1832 100644 (file)
@@ -306,9 +306,9 @@ static void atl1e_get_drvinfo(struct net_device *netdev,
 {
        struct atl1e_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  atl1e_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver,  atl1e_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index ff1fe09..7fcfba3 100644 (file)
@@ -3340,8 +3340,8 @@ static void atl1_get_drvinfo(struct net_device *netdev,
 {
        struct atl1_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver, ATLX_DRIVER_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index bbc4d7b..1b487c0 100644 (file)
@@ -1980,9 +1980,9 @@ static void atl2_get_drvinfo(struct net_device *netdev,
 {
        struct atl2_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  atl2_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->fw_version, "L2", sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver,  atl2_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->fw_version, "L2", sizeof(drvinfo->fw_version));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index e5857e8..7821084 100644 (file)
@@ -1790,13 +1790,13 @@ static void b44_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *inf
        struct b44 *bp = netdev_priv(dev);
        struct ssb_bus *bus = bp->sdev->bus;
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
        switch (bus->bustype) {
        case SSB_BUSTYPE_PCI:
-               strlcpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
+               strscpy(info->bus_info, pci_name(bus->host_pci), sizeof(info->bus_info));
                break;
        case SSB_BUSTYPE_SSB:
-               strlcpy(info->bus_info, "SSB", sizeof(info->bus_info));
+               strscpy(info->bus_info, "SSB", sizeof(info->bus_info));
                break;
        case SSB_BUSTYPE_PCMCIA:
        case SSB_BUSTYPE_SDIO:
index c131d81..e5e17a1 100644 (file)
@@ -507,7 +507,7 @@ static int bcm4908_enet_stop(struct net_device *netdev)
        return 0;
 }
 
-static int bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+static netdev_tx_t bcm4908_enet_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
        struct bcm4908_enet *enet = netdev_priv(netdev);
        struct bcm4908_enet_dma_ring *ring = &enet->tx_ring;
index 1c6aea1..d91fdb0 100644 (file)
@@ -1321,8 +1321,8 @@ static const u32 unused_mib_regs[] = {
 static void bcm_enet_get_drvinfo(struct net_device *netdev,
                                 struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, bcm_enet_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, "bcm63xx", sizeof(drvinfo->bus_info));
+       strscpy(drvinfo->driver, bcm_enet_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, "bcm63xx", sizeof(drvinfo->bus_info));
 }
 
 static int bcm_enet_get_sset_count(struct net_device *netdev,
index 47fc8e6..52144ea 100644 (file)
@@ -308,8 +308,8 @@ static const struct bcm_sysport_stats bcm_sysport_gstrings_stats[] = {
 static void bcm_sysport_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->bus_info, "platform", sizeof(info->bus_info));
 }
 
 static u32 bcm_sysport_get_msglvl(struct net_device *dev)
index 9358048..29a9ab2 100644 (file)
@@ -1367,7 +1367,7 @@ static void bgmac_get_strings(struct net_device *dev, u32 stringset,
                return;
 
        for (i = 0; i < BGMAC_STATS_LEN; i++)
-               strlcpy(data + i * ETH_GSTRING_LEN,
+               strscpy(data + i * ETH_GSTRING_LEN,
                        bgmac_get_strings_stats[i].name, ETH_GSTRING_LEN);
 }
 
@@ -1395,8 +1395,8 @@ static void bgmac_get_ethtool_stats(struct net_device *dev,
 static void bgmac_get_drvinfo(struct net_device *net_dev,
                              struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->bus_info, "AXI", sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->bus_info, "AXI", sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops bgmac_ethtool_ops = {
index b97ed9b..b612781 100644 (file)
@@ -7042,9 +7042,9 @@ bnx2_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct bnx2 *bp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
-       strlcpy(info->fw_version, bp->fw_version, sizeof(info->fw_version));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
+       strscpy(info->fw_version, bp->fw_version, sizeof(info->fw_version));
 }
 
 #define BNX2_REGDUMP_LEN               (32 * 1024)
index 712b559..e704e42 100644 (file)
@@ -150,7 +150,7 @@ void bnx2x_fill_fw_str(struct bnx2x *bp, char *buf, size_t buf_len)
                phy_fw_ver[0] = '\0';
                bnx2x_get_ext_phy_fw_version(&bp->link_params,
                                             phy_fw_ver, PHY_FW_VER_LEN);
-               strlcpy(buf, bp->fw_ver, buf_len);
+               strscpy(buf, bp->fw_ver, buf_len);
                snprintf(buf + strlen(bp->fw_ver), 32 - strlen(bp->fw_ver),
                         "bc %d.%d.%d%s%s",
                         (bp->common.bc_ver & 0xff0000) >> 16,
index 0e319ac..bda3ccc 100644 (file)
@@ -1112,7 +1112,7 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
        int ext_dev_info_offset;
        u32 mbi;
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
 
        if (SHMEM2_HAS(bp, extended_dev_info_shared_addr)) {
                ext_dev_info_offset = SHMEM2_RD(bp,
@@ -1126,7 +1126,7 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
                                 (mbi & 0xff000000) >> 24,
                                 (mbi & 0x00ff0000) >> 16,
                                 (mbi & 0x0000ff00) >> 8);
-                       strlcpy(info->fw_version, version,
+                       strscpy(info->fw_version, version,
                                sizeof(info->fw_version));
                }
        }
@@ -1135,7 +1135,7 @@ static void bnx2x_get_drvinfo(struct net_device *dev,
        bnx2x_fill_fw_str(bp, version, ETHTOOL_FWVERS_LEN);
        strlcat(info->fw_version, version, sizeof(info->fw_version));
 
-       strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
+       strscpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
 }
 
 static void bnx2x_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
index 962253d..51b1690 100644 (file)
@@ -3385,7 +3385,7 @@ static void bnx2x_drv_info_ether_stat(struct bnx2x *bp)
                &bp->sp_objs->mac_obj;
        int i;
 
-       strlcpy(ether_stat->version, DRV_MODULE_VERSION,
+       strscpy(ether_stat->version, DRV_MODULE_VERSION,
                ETH_STAT_INFO_VERSION_LEN);
 
        /* get DRV_INFO_ETH_STAT_NUM_MACS_REQUIRED macs, placing them in the
index 2dac704..02a4e55 100644 (file)
@@ -518,7 +518,7 @@ int bnx2x_vfpf_storm_rx_mode(struct bnx2x *bp);
 static inline void bnx2x_vf_fill_fw_str(struct bnx2x *bp, char *buf,
                                        size_t buf_len)
 {
-       strlcpy(buf, bp->acquire_resp.pfdev_info.fw_ver, buf_len);
+       strscpy(buf, bp->acquire_resp.pfdev_info.fw_ver, buf_len);
 }
 
 static inline int bnx2x_vf_ustorm_prods_offset(struct bnx2x *bp,
index c9129b9..0657a0f 100644 (file)
@@ -380,7 +380,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
        bp->igu_base_sb = bp->acquire_resp.resc.hw_sbs[0].hw_sb_id;
        bp->vlan_credit = bp->acquire_resp.resc.num_vlan_filters;
 
-       strlcpy(bp->fw_ver, bp->acquire_resp.pfdev_info.fw_ver,
+       strscpy(bp->fw_ver, bp->acquire_resp.pfdev_info.fw_ver,
                sizeof(bp->fw_ver));
 
        if (is_valid_ether_addr(bp->acquire_resp.resc.current_mac_addr))
index 87eb536..f57e524 100644 (file)
@@ -1371,9 +1371,9 @@ static void bnxt_get_drvinfo(struct net_device *dev,
 {
        struct bnxt *bp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->fw_version, bp->fw_ver_str, sizeof(info->fw_version));
-       strlcpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->fw_version, bp->fw_ver_str, sizeof(info->fw_version));
+       strscpy(info->bus_info, pci_name(bp->pdev), sizeof(info->bus_info));
        info->n_stats = bnxt_get_num_stats(bp);
        info->testinfo_len = bp->num_tests;
        /* TODO CHIMP_FW: eeprom dump details */
@@ -3876,7 +3876,7 @@ void bnxt_ethtool_init(struct bnxt *bp)
                } else if (i == BNXT_IRQ_TEST_IDX) {
                        strcpy(str, "Interrupt_test (offline)");
                } else {
-                       strlcpy(str, fw_str, ETH_GSTRING_LEN);
+                       strscpy(str, fw_str, ETH_GSTRING_LEN);
                        strncat(str, " test", ETH_GSTRING_LEN - strlen(str));
                        if (test_info->offline_mask & (1 << i))
                                strncat(str, " (offline)",
index eb4803b..fcc6589 100644 (file)
@@ -222,7 +222,7 @@ static int bnxt_vf_rep_get_phys_port_name(struct net_device *dev, char *buf,
 static void bnxt_vf_rep_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
 }
 
 static int bnxt_vf_rep_get_port_parent_id(struct net_device *dev,
index 8309fb9..667e660 100644 (file)
@@ -1146,7 +1146,7 @@ static const struct bcmgenet_stats bcmgenet_gstrings_stats[] = {
 static void bcmgenet_get_drvinfo(struct net_device *dev,
                                 struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "bcmgenet", sizeof(info->driver));
+       strscpy(info->driver, "bcmgenet", sizeof(info->driver));
 }
 
 static int bcmgenet_get_sset_count(struct net_device *dev, int string_set)
index db1e9d8..59d2d90 100644 (file)
@@ -12302,9 +12302,9 @@ static void tg3_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
 {
        struct tg3 *tp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->fw_version, tp->fw_ver, sizeof(info->fw_version));
-       strlcpy(info->bus_info, pci_name(tp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->fw_version, tp->fw_ver, sizeof(info->fw_version));
+       strscpy(info->bus_info, pci_name(tp->pdev), sizeof(info->bus_info));
 }
 
 static void tg3_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
@@ -18076,16 +18076,20 @@ static void tg3_shutdown(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct tg3 *tp = netdev_priv(dev);
 
+       tg3_reset_task_cancel(tp);
+
        rtnl_lock();
+
        netif_device_detach(dev);
 
        if (netif_running(dev))
                dev_close(dev);
 
-       if (system_state == SYSTEM_POWER_OFF)
-               tg3_power_down(tp);
+       tg3_power_down(tp);
 
        rtnl_unlock();
+
+       pci_disable_device(pdev);
 }
 
 /**
index 8aca768..5d2c68e 100644 (file)
@@ -283,7 +283,7 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
        struct bfa_ioc_attr *ioc_attr;
        unsigned long flags;
 
-       strlcpy(drvinfo->driver, BNAD_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, BNAD_NAME, sizeof(drvinfo->driver));
 
        ioc_attr = kzalloc(sizeof(*ioc_attr), GFP_KERNEL);
        if (ioc_attr) {
@@ -291,12 +291,12 @@ bnad_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
                bfa_nw_ioc_get_attr(&bnad->bna.ioceth.ioc, ioc_attr);
                spin_unlock_irqrestore(&bnad->bna_lock, flags);
 
-               strlcpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
+               strscpy(drvinfo->fw_version, ioc_attr->adapter_attr.fw_ver,
                        sizeof(drvinfo->fw_version));
                kfree(ioc_attr);
        }
 
-       strlcpy(drvinfo->bus_info, pci_name(bnad->pcidev),
+       strscpy(drvinfo->bus_info, pci_name(bnad->pcidev),
                sizeof(drvinfo->bus_info));
 }
 
index 103591d..369bfd3 100644 (file)
@@ -1342,7 +1342,7 @@ static void octeon_mgmt_poll_controller(struct net_device *netdev)
 static void octeon_mgmt_get_drvinfo(struct net_device *netdev,
                                    struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
 }
 
 static int octeon_mgmt_nway_reset(struct net_device *dev)
index 5a9fad6..e5c71f9 100644 (file)
@@ -191,8 +191,8 @@ static void nicvf_get_drvinfo(struct net_device *netdev,
 {
        struct nicvf *nic = netdev_priv(netdev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(nic->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(nic->pdev), sizeof(info->bus_info));
 }
 
 static u32 nicvf_get_msglevel(struct net_device *netdev)
index f4054d2..17043c4 100644 (file)
@@ -429,8 +429,8 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct adapter *adapter = dev->ml_priv;
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(adapter->pdev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(adapter->pdev),
                sizeof(info->bus_info));
 }
 
index 174b1e1..a46afc0 100644 (file)
@@ -1627,8 +1627,8 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        t3_get_tp_version(adapter, &tp_vers);
        spin_unlock(&adapter->stats_lock);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(adapter->pdev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(adapter->pdev),
                sizeof(info->bus_info));
        if (fw_vers)
                snprintf(info->fw_version, sizeof(info->fw_version),
index 77897ed..8477a93 100644 (file)
@@ -199,8 +199,8 @@ static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        struct adapter *adapter = netdev2adap(dev);
        u32 exprom_vers;
 
-       strlcpy(info->driver, cxgb4_driver_name, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(adapter->pdev),
+       strscpy(info->driver, cxgb4_driver_name, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(adapter->pdev),
                sizeof(info->bus_info));
        info->regdump_len = get_regs_len(dev);
 
index d006192..9cbce1f 100644 (file)
@@ -3903,8 +3903,8 @@ static void cxgb4_mgmt_get_drvinfo(struct net_device *dev,
 {
        struct adapter *adapter = netdev2adap(dev);
 
-       strlcpy(info->driver, cxgb4_driver_name, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(adapter->pdev),
+       strscpy(info->driver, cxgb4_driver_name, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(adapter->pdev),
                sizeof(info->bus_info));
 }
 
index c2822e6..54db79f 100644 (file)
@@ -1553,8 +1553,8 @@ static void cxgb4vf_get_drvinfo(struct net_device *dev,
 {
        struct adapter *adapter = netdev2adap(dev);
 
-       strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(to_pci_dev(dev->dev.parent)),
+       strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, pci_name(to_pci_dev(dev->dev.parent)),
                sizeof(drvinfo->bus_info));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                 "%u.%u.%u.%u, TP %u.%u.%u.%u",
index 9098b3e..1e55b12 100644 (file)
@@ -193,7 +193,7 @@ static void chtls_register_dev(struct chtls_dev *cdev)
 {
        struct tls_toe_device *tlsdev = &cdev->tlsdev;
 
-       strlcpy(tlsdev->name, "chtls", TLS_TOE_DEVICE_NAME_MAX);
+       strscpy(tlsdev->name, "chtls", TLS_TOE_DEVICE_NAME_MAX);
        strlcat(tlsdev->name, cdev->lldi->ports[0]->name,
                TLS_TOE_DEVICE_NAME_MAX);
        tlsdev->feature = chtls_inline_feature;
index 21ba6e8..8885061 100644 (file)
@@ -689,7 +689,7 @@ static int ep93xx_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 
 static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
 }
 
 static int ep93xx_get_link_ksettings(struct net_device *dev,
index 60d8c0f..08b7cc0 100644 (file)
@@ -131,10 +131,10 @@ static void enic_get_drvinfo(struct net_device *netdev,
        if (err == -ENOMEM)
                return;
 
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->fw_version, fw_info->fw_version,
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->fw_version, fw_info->fw_version,
                sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(enic->pdev),
+       strscpy(drvinfo->bus_info, pci_name(enic->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 9e6de2f..6dae768 100644 (file)
@@ -1919,7 +1919,7 @@ static void gmac_get_stats64(struct net_device *netdev,
 
        /* Racing with RX NAPI */
        do {
-               start = u64_stats_fetch_begin(&port->rx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
 
                stats->rx_packets = port->stats.rx_packets;
                stats->rx_bytes = port->stats.rx_bytes;
@@ -1931,11 +1931,11 @@ static void gmac_get_stats64(struct net_device *netdev,
                stats->rx_crc_errors = port->stats.rx_crc_errors;
                stats->rx_frame_errors = port->stats.rx_frame_errors;
 
-       } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
 
        /* Racing with MIB and TX completion interrupts */
        do {
-               start = u64_stats_fetch_begin(&port->ir_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
 
                stats->tx_errors = port->stats.tx_errors;
                stats->tx_packets = port->stats.tx_packets;
@@ -1945,15 +1945,15 @@ static void gmac_get_stats64(struct net_device *netdev,
                stats->rx_missed_errors = port->stats.rx_missed_errors;
                stats->rx_fifo_errors = port->stats.rx_fifo_errors;
 
-       } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
 
        /* Racing with hard_start_xmit */
        do {
-               start = u64_stats_fetch_begin(&port->tx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
 
                stats->tx_dropped = port->stats.tx_dropped;
 
-       } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
 
        stats->rx_dropped += stats->rx_missed_errors;
 }
@@ -2031,18 +2031,18 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
        /* Racing with MIB interrupt */
        do {
                p = values;
-               start = u64_stats_fetch_begin(&port->ir_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->ir_stats_syncp);
 
                for (i = 0; i < RX_STATS_NUM; i++)
                        *p++ = port->hw_stats[i];
 
-       } while (u64_stats_fetch_retry(&port->ir_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->ir_stats_syncp, start));
        values = p;
 
        /* Racing with RX NAPI */
        do {
                p = values;
-               start = u64_stats_fetch_begin(&port->rx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->rx_stats_syncp);
 
                for (i = 0; i < RX_STATUS_NUM; i++)
                        *p++ = port->rx_stats[i];
@@ -2050,13 +2050,13 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
                        *p++ = port->rx_csum_stats[i];
                *p++ = port->rx_napi_exits;
 
-       } while (u64_stats_fetch_retry(&port->rx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->rx_stats_syncp, start));
        values = p;
 
        /* Racing with TX start_xmit */
        do {
                p = values;
-               start = u64_stats_fetch_begin(&port->tx_stats_syncp);
+               start = u64_stats_fetch_begin_irq(&port->tx_stats_syncp);
 
                for (i = 0; i < TX_MAX_FRAGS; i++) {
                        *values++ = port->tx_frag_stats[i];
@@ -2065,7 +2065,7 @@ static void gmac_get_ethtool_stats(struct net_device *netdev,
                *values++ = port->tx_frags_linearized;
                *values++ = port->tx_hw_csummed;
 
-       } while (u64_stats_fetch_retry(&port->tx_stats_syncp, start));
+       } while (u64_stats_fetch_retry_irq(&port->tx_stats_syncp, start));
 }
 
 static int gmac_get_ksettings(struct net_device *netdev,
index 0985ab2..77229e5 100644 (file)
@@ -540,8 +540,8 @@ static void dm9000_get_drvinfo(struct net_device *dev,
 {
        struct board_info *dm = to_dm9000_board(dev);
 
-       strlcpy(info->driver, CARDNAME, sizeof(info->driver));
-       strlcpy(info->bus_info, to_platform_device(dm->dev)->name,
+       strscpy(info->driver, CARDNAME, sizeof(info->driver));
+       strscpy(info->bus_info, to_platform_device(dm->dev)->name,
                sizeof(info->bus_info));
 }
 
index d51b3d2..cd3dc4b 100644 (file)
@@ -1606,8 +1606,8 @@ static void de_get_drvinfo (struct net_device *dev,struct ethtool_drvinfo *info)
 {
        struct de_private *de = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(de->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(de->pdev), sizeof(info->bus_info));
 }
 
 static int de_get_regs_len(struct net_device *dev)
index 83f1727..3188ba7 100644 (file)
@@ -1074,8 +1074,8 @@ static void dmfe_ethtool_get_drvinfo(struct net_device *dev,
 {
        struct dmfe_board_info *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
 }
 
 static int dmfe_ethtool_set_wol(struct net_device *dev,
index b8e46c4..ecfad43 100644 (file)
@@ -858,8 +858,8 @@ static struct net_device_stats *tulip_get_stats(struct net_device *dev)
 static void tulip_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct tulip_private *np = netdev_priv(dev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
 }
 
 
index 77d9058..ff080ab 100644 (file)
@@ -971,8 +971,8 @@ static void netdev_get_drvinfo(struct net_device *dev,
 {
        struct uli526x_board_info *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
 }
 
 static int netdev_get_link_ksettings(struct net_device *dev,
index 1db1946..37fba39 100644 (file)
@@ -1374,8 +1374,8 @@ static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *
 {
        struct netdev_private *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int netdev_get_link_ksettings(struct net_device *dev,
index a301f7e..2c67a85 100644 (file)
@@ -1235,8 +1235,8 @@ static void rio_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
 {
        struct netdev_private *np = netdev_priv(dev);
 
-       strlcpy(info->driver, "dl2k", sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, "dl2k", sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pdev), sizeof(info->bus_info));
 }
 
 static int rio_get_link_ksettings(struct net_device *dev,
index 8dd7bf9..43def19 100644 (file)
@@ -1644,8 +1644,8 @@ static int check_if_running(struct net_device *dev)
 static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct netdev_private *np = netdev_priv(dev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int get_link_ksettings(struct net_device *dev,
index 92462ed..99e6f76 100644 (file)
@@ -725,8 +725,8 @@ static struct net_device_stats *dnet_get_stats(struct net_device *dev)
 static void dnet_get_drvinfo(struct net_device *dev,
                             struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, "0", sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, "0", sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops dnet_ethtool_ops = {
index b4f5e57..08ec84c 100644 (file)
@@ -1878,9 +1878,9 @@ int be_cmd_get_fw_ver(struct be_adapter *adapter)
        if (!status) {
                struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb);
 
-               strlcpy(adapter->fw_ver, resp->firmware_version_string,
+               strscpy(adapter->fw_ver, resp->firmware_version_string,
                        sizeof(adapter->fw_ver));
-               strlcpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
+               strscpy(adapter->fw_on_flash, resp->fw_on_flash_version_string,
                        sizeof(adapter->fw_on_flash));
        }
 err:
@@ -2373,7 +2373,7 @@ static int lancer_cmd_write_object(struct be_adapter *adapter,
 
        be_dws_cpu_to_le(ctxt, sizeof(req->context));
        req->write_offset = cpu_to_le32(data_offset);
-       strlcpy(req->object_name, obj_name, sizeof(req->object_name));
+       strscpy(req->object_name, obj_name, sizeof(req->object_name));
        req->descriptor_count = cpu_to_le32(1);
        req->buf_len = cpu_to_le32(data_size);
        req->addr_low = cpu_to_le32((cmd->dma +
@@ -2442,9 +2442,9 @@ int be_cmd_query_sfp_info(struct be_adapter *adapter)
        status = be_cmd_read_port_transceiver_data(adapter, TR_PAGE_A0,
                                                   0, PAGE_DATA_LEN, page_data);
        if (!status) {
-               strlcpy(adapter->phy.vendor_name, page_data +
+               strscpy(adapter->phy.vendor_name, page_data +
                        SFP_VENDOR_NAME_OFFSET, SFP_VENDOR_NAME_LEN - 1);
-               strlcpy(adapter->phy.vendor_pn,
+               strscpy(adapter->phy.vendor_pn,
                        page_data + SFP_VENDOR_PN_OFFSET,
                        SFP_VENDOR_NAME_LEN - 1);
        }
@@ -2473,7 +2473,7 @@ static int lancer_cmd_delete_object(struct be_adapter *adapter,
                               OPCODE_COMMON_DELETE_OBJECT,
                               sizeof(*req), wrb, NULL);
 
-       strlcpy(req->object_name, obj_name, sizeof(req->object_name));
+       strscpy(req->object_name, obj_name, sizeof(req->object_name));
 
        status = be_mcc_notify_wait(adapter);
 err:
index bd0df18..77edc3d 100644 (file)
@@ -220,15 +220,15 @@ static void be_get_drvinfo(struct net_device *netdev,
 {
        struct be_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
        if (!memcmp(adapter->fw_ver, adapter->fw_on_flash, FW_VER_LEN))
-               strlcpy(drvinfo->fw_version, adapter->fw_ver,
+               strscpy(drvinfo->fw_version, adapter->fw_ver,
                        sizeof(drvinfo->fw_version));
        else
                snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                         "%s [%s]", adapter->fw_ver, adapter->fw_on_flash);
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 23bbece..147fe03 100644 (file)
@@ -87,6 +87,7 @@ struct tsnep_rx_entry {
 struct tsnep_rx {
        struct tsnep_adapter *adapter;
        void __iomem *addr;
+       int queue_index;
 
        void *page[TSNEP_RING_PAGE_COUNT];
        dma_addr_t page_dma[TSNEP_RING_PAGE_COUNT];
index 916ceac..e03aaaf 100644 (file)
@@ -92,8 +92,7 @@
 
 /* tsnep register */
 #define TSNEP_INFO 0x0100
-#define TSNEP_INFO_RX_ASSIGN 0x00010000
-#define TSNEP_INFO_TX_TIME 0x00020000
+#define TSNEP_INFO_TX_TIME 0x00010000
 #define TSNEP_CONTROL 0x0108
 #define TSNEP_CONTROL_TX_RESET 0x00000001
 #define TSNEP_CONTROL_TX_ENABLE 0x00000002
index a5f7152..19db8b1 100644 (file)
@@ -124,30 +124,51 @@ static int tsnep_mdiobus_write(struct mii_bus *bus, int addr, int regnum,
        return 0;
 }
 
+static void tsnep_set_link_mode(struct tsnep_adapter *adapter)
+{
+       u32 mode;
+
+       switch (adapter->phydev->speed) {
+       case SPEED_100:
+               mode = ECM_LINK_MODE_100;
+               break;
+       case SPEED_1000:
+               mode = ECM_LINK_MODE_1000;
+               break;
+       default:
+               mode = ECM_LINK_MODE_OFF;
+               break;
+       }
+       iowrite32(mode, adapter->addr + ECM_STATUS);
+}
+
 static void tsnep_phy_link_status_change(struct net_device *netdev)
 {
        struct tsnep_adapter *adapter = netdev_priv(netdev);
        struct phy_device *phydev = netdev->phydev;
-       u32 mode;
 
-       if (phydev->link) {
-               switch (phydev->speed) {
-               case SPEED_100:
-                       mode = ECM_LINK_MODE_100;
-                       break;
-               case SPEED_1000:
-                       mode = ECM_LINK_MODE_1000;
-                       break;
-               default:
-                       mode = ECM_LINK_MODE_OFF;
-                       break;
-               }
-               iowrite32(mode, adapter->addr + ECM_STATUS);
-       }
+       if (phydev->link)
+               tsnep_set_link_mode(adapter);
 
        phy_print_status(netdev->phydev);
 }
 
+static int tsnep_phy_loopback(struct tsnep_adapter *adapter, bool enable)
+{
+       int retval;
+
+       retval = phy_loopback(adapter->phydev, enable);
+
+       /* PHY link state change is not signaled if loopback is enabled, it
+        * would delay a working loopback anyway, let's ensure that loopback
+        * is working immediately by setting link mode directly
+        */
+       if (!retval && enable)
+               tsnep_set_link_mode(adapter);
+
+       return retval;
+}
+
 static int tsnep_phy_open(struct tsnep_adapter *adapter)
 {
        struct phy_device *phydev;
@@ -241,14 +262,14 @@ alloc_failed:
        return retval;
 }
 
-static void tsnep_tx_activate(struct tsnep_tx *tx, int index, bool last)
+static void tsnep_tx_activate(struct tsnep_tx *tx, int index, int length,
+                             bool last)
 {
        struct tsnep_tx_entry *entry = &tx->entry[index];
 
        entry->properties = 0;
        if (entry->skb) {
-               entry->properties =
-                       skb_pagelen(entry->skb) & TSNEP_DESC_LENGTH_MASK;
+               entry->properties = length & TSNEP_DESC_LENGTH_MASK;
                entry->properties |= TSNEP_DESC_INTERRUPT_FLAG;
                if (skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS)
                        entry->properties |= TSNEP_DESC_EXTENDED_WRITEBACK_FLAG;
@@ -313,6 +334,7 @@ static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count)
        struct tsnep_tx_entry *entry;
        unsigned int len;
        dma_addr_t dma;
+       int map_len = 0;
        int i;
 
        for (i = 0; i < count; i++) {
@@ -335,15 +357,18 @@ static int tsnep_tx_map(struct sk_buff *skb, struct tsnep_tx *tx, int count)
                dma_unmap_addr_set(entry, dma, dma);
 
                entry->desc->tx = __cpu_to_le64(dma);
+
+               map_len += len;
        }
 
-       return 0;
+       return map_len;
 }
 
-static void tsnep_tx_unmap(struct tsnep_tx *tx, int index, int count)
+static int tsnep_tx_unmap(struct tsnep_tx *tx, int index, int count)
 {
        struct device *dmadev = tx->adapter->dmadev;
        struct tsnep_tx_entry *entry;
+       int map_len = 0;
        int i;
 
        for (i = 0; i < count; i++) {
@@ -360,9 +385,12 @@ static void tsnep_tx_unmap(struct tsnep_tx *tx, int index, int count)
                                               dma_unmap_addr(entry, dma),
                                               dma_unmap_len(entry, len),
                                               DMA_TO_DEVICE);
+                       map_len += entry->len;
                        entry->len = 0;
                }
        }
+
+       return map_len;
 }
 
 static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
@@ -371,6 +399,7 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
        unsigned long flags;
        int count = 1;
        struct tsnep_tx_entry *entry;
+       int length;
        int i;
        int retval;
 
@@ -394,7 +423,7 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
        entry->skb = skb;
 
        retval = tsnep_tx_map(skb, tx, count);
-       if (retval != 0) {
+       if (retval < 0) {
                tsnep_tx_unmap(tx, tx->write, count);
                dev_kfree_skb_any(entry->skb);
                entry->skb = NULL;
@@ -407,12 +436,13 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
 
                return NETDEV_TX_OK;
        }
+       length = retval;
 
        if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
 
        for (i = 0; i < count; i++)
-               tsnep_tx_activate(tx, (tx->write + i) % TSNEP_RING_SIZE,
+               tsnep_tx_activate(tx, (tx->write + i) % TSNEP_RING_SIZE, length,
                                  i == (count - 1));
        tx->write = (tx->write + count) % TSNEP_RING_SIZE;
 
@@ -428,9 +458,6 @@ static netdev_tx_t tsnep_xmit_frame_ring(struct sk_buff *skb,
                netif_stop_queue(tx->adapter->netdev);
        }
 
-       tx->packets++;
-       tx->bytes += skb_pagelen(entry->skb) + ETH_FCS_LEN;
-
        spin_unlock_irqrestore(&tx->lock, flags);
 
        return NETDEV_TX_OK;
@@ -442,6 +469,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
        int budget = 128;
        struct tsnep_tx_entry *entry;
        int count;
+       int length;
 
        spin_lock_irqsave(&tx->lock, flags);
 
@@ -464,7 +492,7 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
                if (skb_shinfo(entry->skb)->nr_frags > 0)
                        count += skb_shinfo(entry->skb)->nr_frags;
 
-               tsnep_tx_unmap(tx, tx->read, count);
+               length = tsnep_tx_unmap(tx, tx->read, count);
 
                if ((skb_shinfo(entry->skb)->tx_flags & SKBTX_IN_PROGRESS) &&
                    (__le32_to_cpu(entry->desc_wb->properties) &
@@ -491,6 +519,9 @@ static bool tsnep_tx_poll(struct tsnep_tx *tx, int napi_budget)
 
                tx->read = (tx->read + count) % TSNEP_RING_SIZE;
 
+               tx->packets++;
+               tx->bytes += length + ETH_FCS_LEN;
+
                budget--;
        } while (likely(budget));
 
@@ -718,6 +749,7 @@ static int tsnep_rx_poll(struct tsnep_rx *rx, struct napi_struct *napi,
                                hwtstamps->netdev_data = rx_inline;
                        }
                        skb_pull(skb, TSNEP_RX_INLINE_METADATA_SIZE);
+                       skb_record_rx_queue(skb, rx->queue_index);
                        skb->protocol = eth_type_trans(skb,
                                                       rx->adapter->netdev);
 
@@ -752,7 +784,7 @@ static int tsnep_rx_poll(struct tsnep_rx *rx, struct napi_struct *napi,
 }
 
 static int tsnep_rx_open(struct tsnep_adapter *adapter, void __iomem *addr,
-                        struct tsnep_rx *rx)
+                        int queue_index, struct tsnep_rx *rx)
 {
        dma_addr_t dma;
        int i;
@@ -761,6 +793,7 @@ static int tsnep_rx_open(struct tsnep_adapter *adapter, void __iomem *addr,
        memset(rx, 0, sizeof(*rx));
        rx->adapter = adapter;
        rx->addr = addr;
+       rx->queue_index = queue_index;
 
        retval = tsnep_rx_ring_init(rx);
        if (retval)
@@ -847,6 +880,7 @@ static int tsnep_netdev_open(struct net_device *netdev)
                if (adapter->queue[i].rx) {
                        addr = adapter->addr + TSNEP_QUEUE(rx_queue_index);
                        retval = tsnep_rx_open(adapter, addr,
+                                              rx_queue_index,
                                               adapter->queue[i].rx);
                        if (retval)
                                goto failed;
@@ -1017,6 +1051,22 @@ static int tsnep_netdev_set_mac_address(struct net_device *netdev, void *addr)
        return 0;
 }
 
+static int tsnep_netdev_set_features(struct net_device *netdev,
+                                    netdev_features_t features)
+{
+       struct tsnep_adapter *adapter = netdev_priv(netdev);
+       netdev_features_t changed = netdev->features ^ features;
+       bool enable;
+       int retval = 0;
+
+       if (changed & NETIF_F_LOOPBACK) {
+               enable = !!(features & NETIF_F_LOOPBACK);
+               retval = tsnep_phy_loopback(adapter, enable);
+       }
+
+       return retval;
+}
+
 static ktime_t tsnep_netdev_get_tstamp(struct net_device *netdev,
                                       const struct skb_shared_hwtstamps *hwtstamps,
                                       bool cycles)
@@ -1038,9 +1088,9 @@ static const struct net_device_ops tsnep_netdev_ops = {
        .ndo_start_xmit = tsnep_netdev_xmit_frame,
        .ndo_eth_ioctl = tsnep_netdev_ioctl,
        .ndo_set_rx_mode = tsnep_netdev_set_multicast,
-
        .ndo_get_stats64 = tsnep_netdev_get_stats64,
        .ndo_set_mac_address = tsnep_netdev_set_mac_address,
+       .ndo_set_features = tsnep_netdev_set_features,
        .ndo_get_tstamp = tsnep_netdev_get_tstamp,
        .ndo_setup_tc = tsnep_tc_setup,
 };
@@ -1192,6 +1242,13 @@ static int tsnep_probe(struct platform_device *pdev)
        adapter->queue[0].rx = &adapter->rx[0];
        adapter->queue[0].irq_mask = ECM_INT_TX_0 | ECM_INT_RX_0;
 
+       retval = dma_set_mask_and_coherent(&adapter->pdev->dev,
+                                          DMA_BIT_MASK(64));
+       if (retval) {
+               dev_err(&adapter->pdev->dev, "no usable DMA configuration.\n");
+               return retval;
+       }
+
        tsnep_disable_irq(adapter, ECM_INT_ALL);
        retval = devm_request_irq(&adapter->pdev->dev, adapter->irq, tsnep_irq,
                                  0, TSNEP, adapter);
@@ -1225,7 +1282,7 @@ static int tsnep_probe(struct platform_device *pdev)
        netdev->netdev_ops = &tsnep_netdev_ops;
        netdev->ethtool_ops = &tsnep_ethtool_ops;
        netdev->features = NETIF_F_SG;
-       netdev->hw_features = netdev->features;
+       netdev->hw_features = netdev->features | NETIF_F_LOOPBACK;
 
        /* carrier off reporting is important to ethtool even BEFORE open */
        netif_carrier_off(netdev);
index c036637..9277d5f 100644 (file)
@@ -1063,8 +1063,8 @@ static int ftgmac100_mdiobus_write(struct mii_bus *bus, int phy_addr,
 static void ftgmac100_get_drvinfo(struct net_device *netdev,
                                  struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
 }
 
 static void
index 8a341e2..bf6e664 100644 (file)
@@ -807,8 +807,8 @@ static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
 static void ftmac100_get_drvinfo(struct net_device *netdev,
                                 struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(&netdev->dev), sizeof(info->bus_info));
 }
 
 static int ftmac100_get_link_ksettings(struct net_device *netdev,
@@ -1075,6 +1075,11 @@ static int ftmac100_probe(struct platform_device *pdev)
        SET_NETDEV_DEV(netdev, &pdev->dev);
        netdev->ethtool_ops = &ftmac100_ethtool_ops;
        netdev->netdev_ops = &ftmac100_netdev_ops;
+       netdev->max_mtu = MAX_PKT_SIZE;
+
+       err = platform_get_ethdev_address(&pdev->dev, netdev);
+       if (err == -EPROBE_DEFER)
+               goto defer_get_mac;
 
        platform_set_drvdata(pdev, netdev);
 
@@ -1137,6 +1142,7 @@ err_ioremap:
        release_resource(priv->res);
 err_req_mem:
        netif_napi_del(&priv->napi);
+defer_get_mac:
        free_netdev(netdev);
 err_alloc_etherdev:
        return err;
index b3939a5..ed18450 100644 (file)
@@ -1809,8 +1809,8 @@ static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
 {
        struct netdev_private *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int netdev_get_link_ksettings(struct net_device *dev,
index a770bab..e974d90 100644 (file)
@@ -288,9 +288,11 @@ static int dpaa_stop(struct net_device *net_dev)
         */
        msleep(200);
 
-       err = mac_dev->stop(mac_dev);
+       if (mac_dev->phy_dev)
+               phy_stop(mac_dev->phy_dev);
+       err = mac_dev->disable(mac_dev->fman_mac);
        if (err < 0)
-               netif_err(priv, ifdown, net_dev, "mac_dev->stop() = %d\n",
+               netif_err(priv, ifdown, net_dev, "mac_dev->disable() = %d\n",
                          err);
 
        for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
@@ -2946,11 +2948,12 @@ static int dpaa_open(struct net_device *net_dev)
                        goto mac_start_failed;
        }
 
-       err = priv->mac_dev->start(mac_dev);
+       err = priv->mac_dev->enable(mac_dev->fman_mac);
        if (err < 0) {
-               netif_err(priv, ifup, net_dev, "mac_dev->start() = %d\n", err);
+               netif_err(priv, ifup, net_dev, "mac_dev->enable() = %d\n", err);
                goto mac_start_failed;
        }
+       phy_start(priv->mac_dev->phy_dev);
 
        netif_tx_start_all_queues(net_dev);
 
index 73f0788..769e936 100644 (file)
@@ -80,9 +80,9 @@ static int dpaa_set_link_ksettings(struct net_device *net_dev,
 static void dpaa_get_drvinfo(struct net_device *net_dev,
                             struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, KBUILD_MODNAME,
+       strscpy(drvinfo->driver, KBUILD_MODNAME,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
+       strscpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
                sizeof(drvinfo->bus_info));
 }
 
index c9bee9a..49ff856 100644 (file)
@@ -549,7 +549,7 @@ void dpaa2_mac_get_strings(u8 *data)
        int i;
 
        for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) {
-               strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
+               strscpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN);
                p += ETH_GSTRING_LEN;
        }
 }
index ff872e4..dec721e 100644 (file)
@@ -236,7 +236,7 @@ static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
        switch (stringset) {
        case ETH_SS_STATS:
                for (i = 0; i < ARRAY_SIZE(enetc_si_counters); i++) {
-                       strlcpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN);
+                       strscpy(p, enetc_si_counters[i].name, ETH_GSTRING_LEN);
                        p += ETH_GSTRING_LEN;
                }
                for (i = 0; i < priv->num_tx_rings; i++) {
@@ -258,7 +258,7 @@ static void enetc_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
                        break;
 
                for (i = 0; i < ARRAY_SIZE(enetc_port_counters); i++) {
-                       strlcpy(p, enetc_port_counters[i].name,
+                       strscpy(p, enetc_port_counters[i].name,
                                ETH_GSTRING_LEN);
                        p += ETH_GSTRING_LEN;
                }
index 0cebe4b..68bc160 100644 (file)
@@ -18,6 +18,8 @@
 #include <linux/net_tstamp.h>
 #include <linux/ptp_clock_kernel.h>
 #include <linux/timecounter.h>
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/firmware/imx/sci.h>
 
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
     defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
@@ -641,6 +643,8 @@ struct fec_enet_private {
                u8 at_inc_corr;
        } ptp_saved_state;
 
+       struct imx_sc_ipc *ipc_handle;
+
        u64 ethtool_stats[];
 };
 
index b0d60f8..8ba8eb3 100644 (file)
@@ -1181,6 +1181,34 @@ fec_restart(struct net_device *ndev)
 
 }
 
+static int fec_enet_ipc_handle_init(struct fec_enet_private *fep)
+{
+       if (!(of_machine_is_compatible("fsl,imx8qm") ||
+             of_machine_is_compatible("fsl,imx8qxp") ||
+             of_machine_is_compatible("fsl,imx8dxl")))
+               return 0;
+
+       return imx_scu_get_handle(&fep->ipc_handle);
+}
+
+static void fec_enet_ipg_stop_set(struct fec_enet_private *fep, bool enabled)
+{
+       struct device_node *np = fep->pdev->dev.of_node;
+       u32 rsrc_id, val;
+       int idx;
+
+       if (!np || !fep->ipc_handle)
+               return;
+
+       idx = of_alias_get_id(np, "ethernet");
+       if (idx < 0)
+               idx = 0;
+       rsrc_id = idx ? IMX_SC_R_ENET_1 : IMX_SC_R_ENET_0;
+
+       val = enabled ? 1 : 0;
+       imx_sc_misc_set_control(fep->ipc_handle, rsrc_id, IMX_SC_C_IPG_STOP, val);
+}
+
 static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
 {
        struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
@@ -1196,6 +1224,8 @@ static void fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
                                           BIT(stop_gpr->bit), 0);
        } else if (pdata && pdata->sleep_mode_enable) {
                pdata->sleep_mode_enable(enabled);
+       } else {
+               fec_enet_ipg_stop_set(fep, enabled);
        }
 }
 
@@ -2138,13 +2168,13 @@ static int fec_enet_mii_probe(struct net_device *ndev)
                                continue;
                        if (dev_id--)
                                continue;
-                       strlcpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
+                       strscpy(mdio_bus_id, fep->mii_bus->id, MII_BUS_ID_SIZE);
                        break;
                }
 
                if (phy_id >= PHY_MAX_ADDR) {
                        netdev_info(ndev, "no PHY, assuming direct connection to switch\n");
-                       strlcpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
+                       strscpy(mdio_bus_id, "fixed-0", MII_BUS_ID_SIZE);
                        phy_id = 0;
                }
 
@@ -2328,9 +2358,9 @@ static void fec_enet_get_drvinfo(struct net_device *ndev,
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
 
-       strlcpy(info->driver, fep->pdev->dev.driver->name,
+       strscpy(info->driver, fep->pdev->dev.driver->name,
                sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(&ndev->dev), sizeof(info->bus_info));
+       strscpy(info->bus_info, dev_name(&ndev->dev), sizeof(info->bus_info));
 }
 
 static int fec_enet_get_regs_len(struct net_device *ndev)
@@ -3851,6 +3881,10 @@ fec_probe(struct platform_device *pdev)
            !of_property_read_bool(np, "fsl,err006687-workaround-present"))
                fep->quirks |= FEC_QUIRK_ERR006687;
 
+       ret = fec_enet_ipc_handle_init(fep);
+       if (ret)
+               goto failed_ipc_init;
+
        if (of_get_property(np, "fsl,magic-packet", NULL))
                fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
 
@@ -4048,6 +4082,7 @@ failed_rgmii_delay:
                of_phy_deregister_fixed_link(np);
        of_node_put(phy_node);
 failed_stop_mode:
+failed_ipc_init:
 failed_phy:
        dev_id--;
 failed_ioremap:
index c74d04f..dc856eb 100644 (file)
@@ -578,7 +578,7 @@ void fec_ptp_init(struct platform_device *pdev, int irq_idx)
        int ret;
 
        fep->ptp_caps.owner = THIS_MODULE;
-       strlcpy(fep->ptp_caps.name, "fec ptp", sizeof(fep->ptp_caps.name));
+       strscpy(fep->ptp_caps.name, "fec ptp", sizeof(fep->ptp_caps.name));
 
        fep->ptp_caps.max_adj = 250000000;
        fep->ptp_caps.n_alarm = 0;
index 8f0db61..9d85fb1 100644 (file)
@@ -1,34 +1,7 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  * Copyright 2020 NXP
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index f2ede13..2ea575a 100644 (file)
@@ -1,34 +1,7 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  * Copyright 2020 NXP
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __FM_H
index 1950a89..7f4f3d7 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -860,53 +833,45 @@ int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val)
        return 0;
 }
 
-static void graceful_start(struct fman_mac *dtsec, enum comm_mode mode)
+static void graceful_start(struct fman_mac *dtsec)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
 
-       if (mode & COMM_MODE_TX)
-               iowrite32be(ioread32be(&regs->tctrl) &
-                               ~TCTRL_GTS, &regs->tctrl);
-       if (mode & COMM_MODE_RX)
-               iowrite32be(ioread32be(&regs->rctrl) &
-                               ~RCTRL_GRS, &regs->rctrl);
+       iowrite32be(ioread32be(&regs->tctrl) & ~TCTRL_GTS, &regs->tctrl);
+       iowrite32be(ioread32be(&regs->rctrl) & ~RCTRL_GRS, &regs->rctrl);
 }
 
-static void graceful_stop(struct fman_mac *dtsec, enum comm_mode mode)
+static void graceful_stop(struct fman_mac *dtsec)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
        u32 tmp;
 
        /* Graceful stop - Assert the graceful Rx stop bit */
-       if (mode & COMM_MODE_RX) {
-               tmp = ioread32be(&regs->rctrl) | RCTRL_GRS;
-               iowrite32be(tmp, &regs->rctrl);
+       tmp = ioread32be(&regs->rctrl) | RCTRL_GRS;
+       iowrite32be(tmp, &regs->rctrl);
 
-               if (dtsec->fm_rev_info.major == 2) {
-                       /* Workaround for dTSEC Errata A002 */
-                       usleep_range(100, 200);
-               } else {
-                       /* Workaround for dTSEC Errata A004839 */
-                       usleep_range(10, 50);
-               }
+       if (dtsec->fm_rev_info.major == 2) {
+               /* Workaround for dTSEC Errata A002 */
+               usleep_range(100, 200);
+       } else {
+               /* Workaround for dTSEC Errata A004839 */
+               usleep_range(10, 50);
        }
 
        /* Graceful stop - Assert the graceful Tx stop bit */
-       if (mode & COMM_MODE_TX) {
-               if (dtsec->fm_rev_info.major == 2) {
-                       /* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */
-                       pr_debug("GTS not supported due to DTSEC_A004 Errata.\n");
-               } else {
-                       tmp = ioread32be(&regs->tctrl) | TCTRL_GTS;
-                       iowrite32be(tmp, &regs->tctrl);
+       if (dtsec->fm_rev_info.major == 2) {
+               /* dTSEC Errata A004: Do not use TCTRL[GTS]=1 */
+               pr_debug("GTS not supported due to DTSEC_A004 Errata.\n");
+       } else {
+               tmp = ioread32be(&regs->tctrl) | TCTRL_GTS;
+               iowrite32be(tmp, &regs->tctrl);
 
-                       /* Workaround for dTSEC Errata A0012, A0014 */
-                       usleep_range(10, 50);
-               }
+               /* Workaround for dTSEC Errata A0012, A0014 */
+               usleep_range(10, 50);
        }
 }
 
-int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
+int dtsec_enable(struct fman_mac *dtsec)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
        u32 tmp;
@@ -916,20 +881,16 @@ int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode)
 
        /* Enable */
        tmp = ioread32be(&regs->maccfg1);
-       if (mode & COMM_MODE_RX)
-               tmp |= MACCFG1_RX_EN;
-       if (mode & COMM_MODE_TX)
-               tmp |= MACCFG1_TX_EN;
-
+       tmp |= MACCFG1_RX_EN | MACCFG1_TX_EN;
        iowrite32be(tmp, &regs->maccfg1);
 
        /* Graceful start - clear the graceful Rx/Tx stop bit */
-       graceful_start(dtsec, mode);
+       graceful_start(dtsec);
 
        return 0;
 }
 
-int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode)
+int dtsec_disable(struct fman_mac *dtsec)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
        u32 tmp;
@@ -938,14 +899,10 @@ int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode)
                return -EINVAL;
 
        /* Graceful stop - Assert the graceful Rx/Tx stop bit */
-       graceful_stop(dtsec, mode);
+       graceful_stop(dtsec);
 
        tmp = ioread32be(&regs->maccfg1);
-       if (mode & COMM_MODE_RX)
-               tmp &= ~MACCFG1_RX_EN;
-       if (mode & COMM_MODE_TX)
-               tmp &= ~MACCFG1_TX_EN;
-
+       tmp &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
        iowrite32be(tmp, &regs->maccfg1);
 
        return 0;
@@ -956,18 +913,12 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
                              u16 pause_time, u16 __maybe_unused thresh_time)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
-       enum comm_mode mode = COMM_MODE_NONE;
        u32 ptv = 0;
 
        if (!is_init_done(dtsec->dtsec_drv_param))
                return -EINVAL;
 
-       if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-               mode |= COMM_MODE_RX;
-       if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-               mode |= COMM_MODE_TX;
-
-       graceful_stop(dtsec, mode);
+       graceful_stop(dtsec);
 
        if (pause_time) {
                /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 Errata workaround */
@@ -989,7 +940,7 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
                iowrite32be(ioread32be(&regs->maccfg1) & ~MACCFG1_TX_FLOW,
                            &regs->maccfg1);
 
-       graceful_start(dtsec, mode);
+       graceful_start(dtsec);
 
        return 0;
 }
@@ -997,18 +948,12 @@ int dtsec_set_tx_pause_frames(struct fman_mac *dtsec,
 int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
-       enum comm_mode mode = COMM_MODE_NONE;
        u32 tmp;
 
        if (!is_init_done(dtsec->dtsec_drv_param))
                return -EINVAL;
 
-       if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-               mode |= COMM_MODE_RX;
-       if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-               mode |= COMM_MODE_TX;
-
-       graceful_stop(dtsec, mode);
+       graceful_stop(dtsec);
 
        tmp = ioread32be(&regs->maccfg1);
        if (en)
@@ -1017,25 +962,17 @@ int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en)
                tmp &= ~MACCFG1_RX_FLOW;
        iowrite32be(tmp, &regs->maccfg1);
 
-       graceful_start(dtsec, mode);
+       graceful_start(dtsec);
 
        return 0;
 }
 
 int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_addr)
 {
-       struct dtsec_regs __iomem *regs = dtsec->regs;
-       enum comm_mode mode = COMM_MODE_NONE;
-
        if (!is_init_done(dtsec->dtsec_drv_param))
                return -EINVAL;
 
-       if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-               mode |= COMM_MODE_RX;
-       if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-               mode |= COMM_MODE_TX;
-
-       graceful_stop(dtsec, mode);
+       graceful_stop(dtsec);
 
        /* Initialize MAC Station Address registers (1 & 2)
         * Station address have to be swapped (big endian to little endian
@@ -1043,7 +980,7 @@ int dtsec_modify_mac_address(struct fman_mac *dtsec, const enet_addr_t *enet_add
        dtsec->addr = ENET_ADDR_TO_UINT64(*enet_addr);
        set_mac_address(dtsec->regs, (const u8 *)(*enet_addr));
 
-       graceful_start(dtsec, mode);
+       graceful_start(dtsec);
 
        return 0;
 }
@@ -1261,18 +1198,12 @@ int dtsec_set_promiscuous(struct fman_mac *dtsec, bool new_val)
 int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
 {
        struct dtsec_regs __iomem *regs = dtsec->regs;
-       enum comm_mode mode = COMM_MODE_NONE;
        u32 tmp;
 
        if (!is_init_done(dtsec->dtsec_drv_param))
                return -EINVAL;
 
-       if ((ioread32be(&regs->rctrl) & RCTRL_GRS) == 0)
-               mode |= COMM_MODE_RX;
-       if ((ioread32be(&regs->tctrl) & TCTRL_GTS) == 0)
-               mode |= COMM_MODE_TX;
-
-       graceful_stop(dtsec, mode);
+       graceful_stop(dtsec);
 
        tmp = ioread32be(&regs->maccfg2);
 
@@ -1293,7 +1224,7 @@ int dtsec_adjust_link(struct fman_mac *dtsec, u16 speed)
                tmp &= ~DTSEC_ECNTRL_R100M;
        iowrite32be(tmp, &regs->ecntrl);
 
-       graceful_start(dtsec, mode);
+       graceful_start(dtsec);
 
        return 0;
 }
index 68512c3..f072cdc 100644 (file)
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __DTSEC_H
@@ -43,8 +16,8 @@ int dtsec_adjust_link(struct fman_mac *dtsec,
 int dtsec_restart_autoneg(struct fman_mac *dtsec);
 int dtsec_cfg_max_frame_len(struct fman_mac *dtsec, u16 new_val);
 int dtsec_cfg_pad_and_crc(struct fman_mac *dtsec, bool new_val);
-int dtsec_enable(struct fman_mac *dtsec, enum comm_mode mode);
-int dtsec_disable(struct fman_mac *dtsec, enum comm_mode mode);
+int dtsec_enable(struct fman_mac *dtsec);
+int dtsec_disable(struct fman_mac *dtsec);
 int dtsec_init(struct fman_mac *dtsec);
 int dtsec_free(struct fman_mac *dtsec);
 int dtsec_accept_rx_pause_frames(struct fman_mac *dtsec, bool en);
index e1bdfed..e73f6ef 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
  * Copyright 2017 NXP
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of NXP nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY NXP ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NXP BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index c4640de..2cb0df4 100644 (file)
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
  * Copyright 2017 NXP
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of NXP nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY NXP ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL NXP BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __KEYGEN_H
index 19f327e..418d1de 100644 (file)
@@ -75,16 +75,6 @@ typedef u8 enet_addr_t[ETH_ALEN];
 #define ETH_HASH_ENTRY_OBJ(ptr)        \
        hlist_entry_safe(ptr, struct eth_hash_entry, node)
 
-/* Enumeration (bit flags) of communication modes (Transmit,
- * receive or both).
- */
-enum comm_mode {
-       COMM_MODE_NONE = 0,     /* No transmit/receive communication */
-       COMM_MODE_RX = 1,       /* Only receive communication */
-       COMM_MODE_TX = 2,       /* Only transmit communication */
-       COMM_MODE_RX_AND_TX = 3 /* Both transmit and receive communication */
-};
-
 /* FM MAC Exceptions */
 enum fman_mac_exceptions {
        FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
index 2216b7f..c34da49 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -712,7 +685,7 @@ static bool is_init_done(struct memac_cfg *memac_drv_params)
        return false;
 }
 
-int memac_enable(struct fman_mac *memac, enum comm_mode mode)
+int memac_enable(struct fman_mac *memac)
 {
        struct memac_regs __iomem *regs = memac->regs;
        u32 tmp;
@@ -721,17 +694,13 @@ int memac_enable(struct fman_mac *memac, enum comm_mode mode)
                return -EINVAL;
 
        tmp = ioread32be(&regs->command_config);
-       if (mode & COMM_MODE_RX)
-               tmp |= CMD_CFG_RX_EN;
-       if (mode & COMM_MODE_TX)
-               tmp |= CMD_CFG_TX_EN;
-
+       tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
        iowrite32be(tmp, &regs->command_config);
 
        return 0;
 }
 
-int memac_disable(struct fman_mac *memac, enum comm_mode mode)
+int memac_disable(struct fman_mac *memac)
 {
        struct memac_regs __iomem *regs = memac->regs;
        u32 tmp;
@@ -740,11 +709,7 @@ int memac_disable(struct fman_mac *memac, enum comm_mode mode)
                return -EINVAL;
 
        tmp = ioread32be(&regs->command_config);
-       if (mode & COMM_MODE_RX)
-               tmp &= ~CMD_CFG_RX_EN;
-       if (mode & COMM_MODE_TX)
-               tmp &= ~CMD_CFG_TX_EN;
-
+       tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
        iowrite32be(tmp, &regs->command_config);
 
        return 0;
index 3820f7a..535ecd2 100644 (file)
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __MEMAC_H
@@ -46,8 +19,8 @@ int memac_cfg_max_frame_len(struct fman_mac *memac, u16 new_val);
 int memac_cfg_reset_on_init(struct fman_mac *memac, bool enable);
 int memac_cfg_fixed_link(struct fman_mac *memac,
                         struct fixed_phy_status *fixed_link);
-int memac_enable(struct fman_mac *memac, enum comm_mode mode);
-int memac_disable(struct fman_mac *memac, enum comm_mode mode);
+int memac_enable(struct fman_mac *memac);
+int memac_disable(struct fman_mac *memac);
 int memac_init(struct fman_mac *memac);
 int memac_free(struct fman_mac *memac);
 int memac_accept_rx_pause_frames(struct fman_mac *memac, bool en);
index 7ad317e..f557d68 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #include "fman_muram.h"
index 453bf84..3643af6 100644 (file)
@@ -1,34 +1,8 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
+
 #ifndef __FM_MURAM_EXT
 #define __FM_MURAM_EXT
 
index 4c9d05c..ab90fe2 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
index 82f1266..4917fe8 100644 (file)
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __FMAN_PORT_H
index 248f5bc..0fac60a 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "fman_sp.h"
index 820b7f6..a62dd21 100644 (file)
@@ -1,32 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
  * Copyright 2008 - 2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *      names of its contributors may be used to endorse or promote products
- *      derived from this software without specific prior written permission.
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef __FM_SP_H
index 311c190..2b38d22 100644 (file)
@@ -1,33 +1,6 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -419,7 +392,7 @@ static bool is_init_done(struct tgec_cfg *cfg)
        return false;
 }
 
-int tgec_enable(struct fman_mac *tgec, enum comm_mode mode)
+int tgec_enable(struct fman_mac *tgec)
 {
        struct tgec_regs __iomem *regs = tgec->regs;
        u32 tmp;
@@ -428,16 +401,13 @@ int tgec_enable(struct fman_mac *tgec, enum comm_mode mode)
                return -EINVAL;
 
        tmp = ioread32be(&regs->command_config);
-       if (mode & COMM_MODE_RX)
-               tmp |= CMD_CFG_RX_EN;
-       if (mode & COMM_MODE_TX)
-               tmp |= CMD_CFG_TX_EN;
+       tmp |= CMD_CFG_RX_EN | CMD_CFG_TX_EN;
        iowrite32be(tmp, &regs->command_config);
 
        return 0;
 }
 
-int tgec_disable(struct fman_mac *tgec, enum comm_mode mode)
+int tgec_disable(struct fman_mac *tgec)
 {
        struct tgec_regs __iomem *regs = tgec->regs;
        u32 tmp;
@@ -446,10 +416,7 @@ int tgec_disable(struct fman_mac *tgec, enum comm_mode mode)
                return -EINVAL;
 
        tmp = ioread32be(&regs->command_config);
-       if (mode & COMM_MODE_RX)
-               tmp &= ~CMD_CFG_RX_EN;
-       if (mode & COMM_MODE_TX)
-               tmp &= ~CMD_CFG_TX_EN;
+       tmp &= ~(CMD_CFG_RX_EN | CMD_CFG_TX_EN);
        iowrite32be(tmp, &regs->command_config);
 
        return 0;
index b28b20b..5b25675 100644 (file)
@@ -1,33 +1,6 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
 /*
- * Copyright 2008-2015 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __TGEC_H
@@ -39,8 +12,8 @@ struct fman_mac *tgec_config(struct fman_mac_params *params);
 int tgec_set_promiscuous(struct fman_mac *tgec, bool new_val);
 int tgec_modify_mac_address(struct fman_mac *tgec, const enet_addr_t *enet_addr);
 int tgec_cfg_max_frame_len(struct fman_mac *tgec, u16 new_val);
-int tgec_enable(struct fman_mac *tgec, enum comm_mode mode);
-int tgec_disable(struct fman_mac *tgec, enum comm_mode mode);
+int tgec_enable(struct fman_mac *tgec);
+int tgec_disable(struct fman_mac *tgec);
 int tgec_init(struct fman_mac *tgec);
 int tgec_free(struct fman_mac *tgec);
 int tgec_accept_rx_pause_frames(struct fman_mac *tgec, bool en);
index 39ae965..f9a3f85 100644 (file)
@@ -1,32 +1,6 @@
-/* Copyright 2008-2015 Freescale Semiconductor, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *      names of its contributors may be used to endorse or promote products
- *      derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -54,20 +28,14 @@ MODULE_LICENSE("Dual BSD/GPL");
 MODULE_DESCRIPTION("FSL FMan MAC API based driver");
 
 struct mac_priv_s {
-       struct device                   *dev;
        void __iomem                    *vaddr;
        u8                              cell_index;
        struct fman                     *fman;
-       struct device_node              *internal_phy_node;
        /* List of multicast addresses */
        struct list_head                mc_addr_list;
        struct platform_device          *eth_dev;
-       struct fixed_phy_status         *fixed_link;
        u16                             speed;
        u16                             max_speed;
-
-       int (*enable)(struct fman_mac *mac_dev, enum comm_mode mode);
-       int (*disable)(struct fman_mac *mac_dev, enum comm_mode mode);
 };
 
 struct mac_address {
@@ -77,30 +45,26 @@ struct mac_address {
 
 static void mac_exception(void *handle, enum fman_mac_exceptions ex)
 {
-       struct mac_device       *mac_dev;
-       struct mac_priv_s       *priv;
-
-       mac_dev = handle;
-       priv = mac_dev->priv;
+       struct mac_device *mac_dev = handle;
 
        if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) {
                /* don't flag RX FIFO after the first */
                mac_dev->set_exception(mac_dev->fman_mac,
                                       FM_MAC_EX_10G_RX_FIFO_OVFL, false);
-               dev_err(priv->dev, "10G MAC got RX FIFO Error = %x\n", ex);
+               dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex);
        }
 
-       dev_dbg(priv->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
+       dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c",
                __func__, ex);
 }
 
-static int set_fman_mac_params(struct mac_device *mac_dev,
-                              struct fman_mac_params *params)
+int set_fman_mac_params(struct mac_device *mac_dev,
+                       struct fman_mac_params *params)
 {
        struct mac_priv_s *priv = mac_dev->priv;
 
        params->base_addr = (typeof(params->base_addr))
-               devm_ioremap(priv->dev, mac_dev->res->start,
+               devm_ioremap(mac_dev->dev, mac_dev->res->start,
                             resource_size(mac_dev->res));
        if (!params->base_addr)
                return -ENOMEM;
@@ -114,183 +78,11 @@ static int set_fman_mac_params(struct mac_device *mac_dev,
        params->exception_cb    = mac_exception;
        params->event_cb        = mac_exception;
        params->dev_id          = mac_dev;
-       params->internal_phy_node = priv->internal_phy_node;
 
        return 0;
 }
 
-static int tgec_initialization(struct mac_device *mac_dev)
-{
-       int err;
-       struct mac_priv_s       *priv;
-       struct fman_mac_params  params;
-       u32                     version;
-
-       priv = mac_dev->priv;
-
-       err = set_fman_mac_params(mac_dev, &params);
-       if (err)
-               goto _return;
-
-       mac_dev->fman_mac = tgec_config(&params);
-       if (!mac_dev->fman_mac) {
-               err = -EINVAL;
-               goto _return;
-       }
-
-       err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = tgec_init(mac_dev->fman_mac);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       /* For 10G MAC, disable Tx ECC exception */
-       err = mac_dev->set_exception(mac_dev->fman_mac,
-                                    FM_MAC_EX_10G_TX_ECC_ER, false);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = tgec_get_version(mac_dev->fman_mac, &version);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       dev_info(priv->dev, "FMan XGEC version: 0x%08x\n", version);
-
-       goto _return;
-
-_return_fm_mac_free:
-       tgec_free(mac_dev->fman_mac);
-
-_return:
-       return err;
-}
-
-static int dtsec_initialization(struct mac_device *mac_dev)
-{
-       int                     err;
-       struct mac_priv_s       *priv;
-       struct fman_mac_params  params;
-       u32                     version;
-
-       priv = mac_dev->priv;
-
-       err = set_fman_mac_params(mac_dev, &params);
-       if (err)
-               goto _return;
-
-       mac_dev->fman_mac = dtsec_config(&params);
-       if (!mac_dev->fman_mac) {
-               err = -EINVAL;
-               goto _return;
-       }
-
-       err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = dtsec_init(mac_dev->fman_mac);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       /* For 1G MAC, disable by default the MIB counters overflow interrupt */
-       err = mac_dev->set_exception(mac_dev->fman_mac,
-                                    FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = dtsec_get_version(mac_dev->fman_mac, &version);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       dev_info(priv->dev, "FMan dTSEC version: 0x%08x\n", version);
-
-       goto _return;
-
-_return_fm_mac_free:
-       dtsec_free(mac_dev->fman_mac);
-
-_return:
-       return err;
-}
-
-static int memac_initialization(struct mac_device *mac_dev)
-{
-       int                      err;
-       struct mac_priv_s       *priv;
-       struct fman_mac_params   params;
-
-       priv = mac_dev->priv;
-
-       err = set_fman_mac_params(mac_dev, &params);
-       if (err)
-               goto _return;
-
-       if (priv->max_speed == SPEED_10000)
-               params.phy_if = PHY_INTERFACE_MODE_XGMII;
-
-       mac_dev->fman_mac = memac_config(&params);
-       if (!mac_dev->fman_mac) {
-               err = -EINVAL;
-               goto _return;
-       }
-
-       err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = memac_cfg_fixed_link(mac_dev->fman_mac, priv->fixed_link);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       err = memac_init(mac_dev->fman_mac);
-       if (err < 0)
-               goto _return_fm_mac_free;
-
-       dev_info(priv->dev, "FMan MEMAC\n");
-
-       goto _return;
-
-_return_fm_mac_free:
-       memac_free(mac_dev->fman_mac);
-
-_return:
-       return err;
-}
-
-static int start(struct mac_device *mac_dev)
-{
-       int      err;
-       struct phy_device *phy_dev = mac_dev->phy_dev;
-       struct mac_priv_s *priv = mac_dev->priv;
-
-       err = priv->enable(mac_dev->fman_mac, COMM_MODE_RX_AND_TX);
-       if (!err && phy_dev)
-               phy_start(phy_dev);
-
-       return err;
-}
-
-static int stop(struct mac_device *mac_dev)
-{
-       struct mac_priv_s *priv = mac_dev->priv;
-
-       if (mac_dev->phy_dev)
-               phy_stop(mac_dev->phy_dev);
-
-       return priv->disable(mac_dev->fman_mac, COMM_MODE_RX_AND_TX);
-}
-
-static int set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
+int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev)
 {
        struct mac_priv_s       *priv;
        struct mac_address      *old_addr, *tmp;
@@ -446,7 +238,7 @@ static void adjust_link_dtsec(struct mac_device *mac_dev)
        fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
        err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
        if (err < 0)
-               dev_err(mac_dev->priv->dev, "fman_set_mac_active_pause() = %d\n",
+               dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
                        err);
 }
 
@@ -463,33 +255,17 @@ static void adjust_link_memac(struct mac_device *mac_dev)
        fman_get_pause_cfg(mac_dev, &rx_pause, &tx_pause);
        err = fman_set_mac_active_pause(mac_dev, rx_pause, tx_pause);
        if (err < 0)
-               dev_err(mac_dev->priv->dev, "fman_set_mac_active_pause() = %d\n",
+               dev_err(mac_dev->dev, "fman_set_mac_active_pause() = %d\n",
                        err);
 }
 
-static void setup_dtsec(struct mac_device *mac_dev)
+static int tgec_initialization(struct mac_device *mac_dev,
+                              struct device_node *mac_node)
 {
-       mac_dev->init                   = dtsec_initialization;
-       mac_dev->set_promisc            = dtsec_set_promiscuous;
-       mac_dev->change_addr            = dtsec_modify_mac_address;
-       mac_dev->add_hash_mac_addr      = dtsec_add_hash_mac_address;
-       mac_dev->remove_hash_mac_addr   = dtsec_del_hash_mac_address;
-       mac_dev->set_tx_pause           = dtsec_set_tx_pause_frames;
-       mac_dev->set_rx_pause           = dtsec_accept_rx_pause_frames;
-       mac_dev->set_exception          = dtsec_set_exception;
-       mac_dev->set_allmulti           = dtsec_set_allmulti;
-       mac_dev->set_tstamp             = dtsec_set_tstamp;
-       mac_dev->set_multi              = set_multi;
-       mac_dev->start                  = start;
-       mac_dev->stop                   = stop;
-       mac_dev->adjust_link            = adjust_link_dtsec;
-       mac_dev->priv->enable           = dtsec_enable;
-       mac_dev->priv->disable          = dtsec_disable;
-}
+       int err;
+       struct fman_mac_params  params;
+       u32                     version;
 
-static void setup_tgec(struct mac_device *mac_dev)
-{
-       mac_dev->init                   = tgec_initialization;
        mac_dev->set_promisc            = tgec_set_promiscuous;
        mac_dev->change_addr            = tgec_modify_mac_address;
        mac_dev->add_hash_mac_addr      = tgec_add_hash_mac_address;
@@ -499,17 +275,122 @@ static void setup_tgec(struct mac_device *mac_dev)
        mac_dev->set_exception          = tgec_set_exception;
        mac_dev->set_allmulti           = tgec_set_allmulti;
        mac_dev->set_tstamp             = tgec_set_tstamp;
-       mac_dev->set_multi              = set_multi;
-       mac_dev->start                  = start;
-       mac_dev->stop                   = stop;
+       mac_dev->set_multi              = fman_set_multi;
        mac_dev->adjust_link            = adjust_link_void;
-       mac_dev->priv->enable           = tgec_enable;
-       mac_dev->priv->disable          = tgec_disable;
+       mac_dev->enable                 = tgec_enable;
+       mac_dev->disable                = tgec_disable;
+
+       err = set_fman_mac_params(mac_dev, &params);
+       if (err)
+               goto _return;
+
+       mac_dev->fman_mac = tgec_config(&params);
+       if (!mac_dev->fman_mac) {
+               err = -EINVAL;
+               goto _return;
+       }
+
+       err = tgec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       err = tgec_init(mac_dev->fman_mac);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       /* For 10G MAC, disable Tx ECC exception */
+       err = mac_dev->set_exception(mac_dev->fman_mac,
+                                    FM_MAC_EX_10G_TX_ECC_ER, false);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       err = tgec_get_version(mac_dev->fman_mac, &version);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       dev_info(mac_dev->dev, "FMan XGEC version: 0x%08x\n", version);
+
+       goto _return;
+
+_return_fm_mac_free:
+       tgec_free(mac_dev->fman_mac);
+
+_return:
+       return err;
+}
+
+static int dtsec_initialization(struct mac_device *mac_dev,
+                               struct device_node *mac_node)
+{
+       int                     err;
+       struct fman_mac_params  params;
+       u32                     version;
+
+       mac_dev->set_promisc            = dtsec_set_promiscuous;
+       mac_dev->change_addr            = dtsec_modify_mac_address;
+       mac_dev->add_hash_mac_addr      = dtsec_add_hash_mac_address;
+       mac_dev->remove_hash_mac_addr   = dtsec_del_hash_mac_address;
+       mac_dev->set_tx_pause           = dtsec_set_tx_pause_frames;
+       mac_dev->set_rx_pause           = dtsec_accept_rx_pause_frames;
+       mac_dev->set_exception          = dtsec_set_exception;
+       mac_dev->set_allmulti           = dtsec_set_allmulti;
+       mac_dev->set_tstamp             = dtsec_set_tstamp;
+       mac_dev->set_multi              = fman_set_multi;
+       mac_dev->adjust_link            = adjust_link_dtsec;
+       mac_dev->enable                 = dtsec_enable;
+       mac_dev->disable                = dtsec_disable;
+
+       err = set_fman_mac_params(mac_dev, &params);
+       if (err)
+               goto _return;
+       params.internal_phy_node = of_parse_phandle(mac_node, "tbi-handle", 0);
+
+       mac_dev->fman_mac = dtsec_config(&params);
+       if (!mac_dev->fman_mac) {
+               err = -EINVAL;
+               goto _return;
+       }
+
+       err = dtsec_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       err = dtsec_cfg_pad_and_crc(mac_dev->fman_mac, true);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       err = dtsec_init(mac_dev->fman_mac);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       /* For 1G MAC, disable by default the MIB counters overflow interrupt */
+       err = mac_dev->set_exception(mac_dev->fman_mac,
+                                    FM_MAC_EX_1G_RX_MIB_CNT_OVFL, false);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       err = dtsec_get_version(mac_dev->fman_mac, &version);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       dev_info(mac_dev->dev, "FMan dTSEC version: 0x%08x\n", version);
+
+       goto _return;
+
+_return_fm_mac_free:
+       dtsec_free(mac_dev->fman_mac);
+
+_return:
+       return err;
 }
 
-static void setup_memac(struct mac_device *mac_dev)
+static int memac_initialization(struct mac_device *mac_dev,
+                               struct device_node *mac_node)
 {
-       mac_dev->init                   = memac_initialization;
+       int                      err;
+       struct fman_mac_params   params;
+       struct fixed_phy_status *fixed_link = NULL;
+
        mac_dev->set_promisc            = memac_set_promiscuous;
        mac_dev->change_addr            = memac_modify_mac_address;
        mac_dev->add_hash_mac_addr      = memac_add_hash_mac_address;
@@ -519,12 +400,81 @@ static void setup_memac(struct mac_device *mac_dev)
        mac_dev->set_exception          = memac_set_exception;
        mac_dev->set_allmulti           = memac_set_allmulti;
        mac_dev->set_tstamp             = memac_set_tstamp;
-       mac_dev->set_multi              = set_multi;
-       mac_dev->start                  = start;
-       mac_dev->stop                   = stop;
+       mac_dev->set_multi              = fman_set_multi;
        mac_dev->adjust_link            = adjust_link_memac;
-       mac_dev->priv->enable           = memac_enable;
-       mac_dev->priv->disable          = memac_disable;
+       mac_dev->enable                 = memac_enable;
+       mac_dev->disable                = memac_disable;
+
+       err = set_fman_mac_params(mac_dev, &params);
+       if (err)
+               goto _return;
+       params.internal_phy_node = of_parse_phandle(mac_node, "pcsphy-handle", 0);
+
+       if (params.max_speed == SPEED_10000)
+               params.phy_if = PHY_INTERFACE_MODE_XGMII;
+
+       mac_dev->fman_mac = memac_config(&params);
+       if (!mac_dev->fman_mac) {
+               err = -EINVAL;
+               goto _return;
+       }
+
+       err = memac_cfg_max_frame_len(mac_dev->fman_mac, fman_get_max_frm());
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       err = memac_cfg_reset_on_init(mac_dev->fman_mac, true);
+       if (err < 0)
+               goto _return_fm_mac_free;
+
+       if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
+               struct phy_device *phy;
+
+               err = of_phy_register_fixed_link(mac_node);
+               if (err)
+                       goto _return_fm_mac_free;
+
+               fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
+               if (!fixed_link) {
+                       err = -ENOMEM;
+                       goto _return_fm_mac_free;
+               }
+
+               mac_dev->phy_node = of_node_get(mac_node);
+               phy = of_phy_find_device(mac_dev->phy_node);
+               if (!phy) {
+                       err = -EINVAL;
+                       of_node_put(mac_dev->phy_node);
+                       goto _return_fixed_link_free;
+               }
+
+               fixed_link->link = phy->link;
+               fixed_link->speed = phy->speed;
+               fixed_link->duplex = phy->duplex;
+               fixed_link->pause = phy->pause;
+               fixed_link->asym_pause = phy->asym_pause;
+
+               put_device(&phy->mdio.dev);
+
+               err = memac_cfg_fixed_link(mac_dev->fman_mac, fixed_link);
+               if (err < 0)
+                       goto _return_fixed_link_free;
+       }
+
+       err = memac_init(mac_dev->fman_mac);
+       if (err < 0)
+               goto _return_fixed_link_free;
+
+       dev_info(mac_dev->dev, "FMan MEMAC\n");
+
+       goto _return;
+
+_return_fixed_link_free:
+       kfree(fixed_link);
+_return_fm_mac_free:
+       memac_free(mac_dev->fman_mac);
+_return:
+       return err;
 }
 
 #define DTSEC_SUPPORTED \
@@ -577,7 +527,7 @@ static struct platform_device *dpaa_eth_add_device(int fman_id,
                goto no_mem;
        }
 
-       pdev->dev.parent = priv->dev;
+       pdev->dev.parent = mac_dev->dev;
 
        ret = platform_device_add_data(pdev, &data, sizeof(data));
        if (ret)
@@ -601,9 +551,9 @@ no_mem:
 }
 
 static const struct of_device_id mac_match[] = {
-       { .compatible   = "fsl,fman-dtsec" },
-       { .compatible   = "fsl,fman-xgec" },
-       { .compatible   = "fsl,fman-memac" },
+       { .compatible   = "fsl,fman-dtsec", .data = dtsec_initialization },
+       { .compatible   = "fsl,fman-xgec", .data = tgec_initialization },
+       { .compatible   = "fsl,fman-memac", .data = memac_initialization },
        {}
 };
 MODULE_DEVICE_TABLE(of, mac_match);
@@ -611,6 +561,7 @@ MODULE_DEVICE_TABLE(of, mac_match);
 static int mac_probe(struct platform_device *_of_dev)
 {
        int                      err, i, nph;
+       int (*init)(struct mac_device *mac_dev, struct device_node *mac_node);
        struct device           *dev;
        struct device_node      *mac_node, *dev_node;
        struct mac_device       *mac_dev;
@@ -623,6 +574,7 @@ static int mac_probe(struct platform_device *_of_dev)
 
        dev = &_of_dev->dev;
        mac_node = dev->of_node;
+       init = of_device_get_match_data(dev);
 
        mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL);
        if (!mac_dev) {
@@ -637,24 +589,7 @@ static int mac_probe(struct platform_device *_of_dev)
 
        /* Save private information */
        mac_dev->priv = priv;
-       priv->dev = dev;
-
-       if (of_device_is_compatible(mac_node, "fsl,fman-dtsec")) {
-               setup_dtsec(mac_dev);
-               priv->internal_phy_node = of_parse_phandle(mac_node,
-                                                         "tbi-handle", 0);
-       } else if (of_device_is_compatible(mac_node, "fsl,fman-xgec")) {
-               setup_tgec(mac_dev);
-       } else if (of_device_is_compatible(mac_node, "fsl,fman-memac")) {
-               setup_memac(mac_dev);
-               priv->internal_phy_node = of_parse_phandle(mac_node,
-                                                         "pcsphy-handle", 0);
-       } else {
-               dev_err(dev, "MAC node (%pOF) contains unsupported MAC\n",
-                       mac_node);
-               err = -EINVAL;
-               goto _return;
-       }
+       mac_dev->dev = dev;
 
        INIT_LIST_HEAD(&priv->mc_addr_list);
 
@@ -664,7 +599,7 @@ static int mac_probe(struct platform_device *_of_dev)
                dev_err(dev, "of_get_parent(%pOF) failed\n",
                        mac_node);
                err = -EINVAL;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        of_dev = of_find_device_by_node(dev_node);
@@ -698,7 +633,7 @@ static int mac_probe(struct platform_device *_of_dev)
        if (err < 0) {
                dev_err(dev, "of_address_to_resource(%pOF) = %d\n",
                        mac_node, err);
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        mac_dev->res = __devm_request_region(dev,
@@ -708,7 +643,7 @@ static int mac_probe(struct platform_device *_of_dev)
        if (!mac_dev->res) {
                dev_err(dev, "__devm_request_mem_region(mac) failed\n");
                err = -EBUSY;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        priv->vaddr = devm_ioremap(dev, mac_dev->res->start,
@@ -716,12 +651,12 @@ static int mac_probe(struct platform_device *_of_dev)
        if (!priv->vaddr) {
                dev_err(dev, "devm_ioremap() failed\n");
                err = -EIO;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        if (!of_device_is_available(mac_node)) {
                err = -ENODEV;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        /* Get the cell-index */
@@ -729,7 +664,7 @@ static int mac_probe(struct platform_device *_of_dev)
        if (err) {
                dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
                err = -EINVAL;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
        priv->cell_index = (u8)val;
 
@@ -744,14 +679,14 @@ static int mac_probe(struct platform_device *_of_dev)
                dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
                        mac_node);
                err = nph;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        if (nph != ARRAY_SIZE(mac_dev->port)) {
                dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
                        mac_node);
                err = -EINVAL;
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
@@ -810,42 +745,12 @@ static int mac_probe(struct platform_device *_of_dev)
 
        /* Get the rest of the PHY information */
        mac_dev->phy_node = of_parse_phandle(mac_node, "phy-handle", 0);
-       if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
-               struct phy_device *phy;
-
-               err = of_phy_register_fixed_link(mac_node);
-               if (err)
-                       goto _return_of_get_parent;
-
-               priv->fixed_link = kzalloc(sizeof(*priv->fixed_link),
-                                          GFP_KERNEL);
-               if (!priv->fixed_link) {
-                       err = -ENOMEM;
-                       goto _return_of_get_parent;
-               }
-
-               mac_dev->phy_node = of_node_get(mac_node);
-               phy = of_phy_find_device(mac_dev->phy_node);
-               if (!phy) {
-                       err = -EINVAL;
-                       of_node_put(mac_dev->phy_node);
-                       goto _return_of_get_parent;
-               }
 
-               priv->fixed_link->link = phy->link;
-               priv->fixed_link->speed = phy->speed;
-               priv->fixed_link->duplex = phy->duplex;
-               priv->fixed_link->pause = phy->pause;
-               priv->fixed_link->asym_pause = phy->asym_pause;
-
-               put_device(&phy->mdio.dev);
-       }
-
-       err = mac_dev->init(mac_dev);
+       err = init(mac_dev, mac_node);
        if (err < 0) {
                dev_err(dev, "mac_dev->init() = %d\n", err);
                of_node_put(mac_dev->phy_node);
-               goto _return_of_get_parent;
+               goto _return_of_node_put;
        }
 
        /* pause frame autonegotiation enabled */
@@ -876,8 +781,6 @@ static int mac_probe(struct platform_device *_of_dev)
 
 _return_of_node_put:
        of_node_put(dev_node);
-_return_of_get_parent:
-       kfree(priv->fixed_link);
 _return:
        return err;
 }
index daa285a..da410a7 100644 (file)
@@ -1,32 +1,6 @@
-/* Copyright 2008-2015 Freescale Semiconductor, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *      notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *      notice, this list of conditions and the following disclaimer in the
- *      documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *      names of its contributors may be used to endorse or promote products
- *      derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later */
+/*
+ * Copyright 2008 - 2015 Freescale Semiconductor Inc.
  */
 
 #ifndef __MAC_H
@@ -45,6 +19,7 @@ struct fman_mac;
 struct mac_priv_s;
 
 struct mac_device {
+       struct device           *dev;
        struct resource         *res;
        u8                       addr[ETH_ALEN];
        struct fman_port        *port[2];
@@ -61,9 +36,8 @@ struct mac_device {
        bool promisc;
        bool allmulti;
 
-       int (*init)(struct mac_device *mac_dev);
-       int (*start)(struct mac_device *mac_dev);
-       int (*stop)(struct mac_device *mac_dev);
+       int (*enable)(struct fman_mac *mac_dev);
+       int (*disable)(struct fman_mac *mac_dev);
        void (*adjust_link)(struct mac_device *mac_dev);
        int (*set_promisc)(struct fman_mac *mac_dev, bool enable);
        int (*change_addr)(struct fman_mac *mac_dev, const enet_addr_t *enet_addr);
@@ -97,5 +71,8 @@ int fman_set_mac_active_pause(struct mac_device *mac_dev, bool rx, bool tx);
 
 void fman_get_pause_cfg(struct mac_device *mac_dev, bool *rx_pause,
                        bool *tx_pause);
+int set_fman_mac_params(struct mac_device *mac_dev,
+                       struct fman_mac_params *params);
+int fman_set_multi(struct net_device *net_dev, struct mac_device *mac_dev);
 
 #endif /* __MAC_H */
index b3dae17..5b76043 100644 (file)
@@ -791,7 +791,7 @@ static int fs_enet_close(struct net_device *dev)
 static void fs_get_drvinfo(struct net_device *dev,
                            struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
 }
 
 static int fs_get_regs_len(struct net_device *dev)
index 81fb687..b2b0d3c 100644 (file)
@@ -163,7 +163,7 @@ static int gfar_sset_count(struct net_device *dev, int sset)
 static void gfar_gdrvinfo(struct net_device *dev,
                          struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
 }
 
 /* Return the length of the register structure */
index 69b2b98..601beb9 100644 (file)
@@ -337,8 +337,8 @@ static void
 uec_get_drvinfo(struct net_device *netdev,
                        struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, "QUICC ENGINE", sizeof(drvinfo->bus_info));
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, "QUICC ENGINE", sizeof(drvinfo->bus_info));
 }
 
 #ifdef CONFIG_PM
index ec90da1..d7d39a5 100644 (file)
@@ -355,7 +355,7 @@ static int xgmac_mdio_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       fwnode = pdev->dev.fwnode;
+       fwnode = dev_fwnode(&pdev->dev);
        if (is_of_node(fwnode))
                ret = of_mdiobus_register(bus, to_of_node(fwnode));
        else if (is_acpi_node(fwnode))
index b0d733e..4859493 100644 (file)
@@ -1046,8 +1046,8 @@ static void fjn_rx(struct net_device *dev)
 static void netdev_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
        snprintf(info->bus_info, sizeof(info->bus_info),
                "PCMCIA 0x%lx", dev->base_addr);
 }
index f247b7a..b6de2ad 100644 (file)
@@ -1802,16 +1802,14 @@ static int fun_create_netdev(struct fun_ethdev *ed, unsigned int portid)
        if (rc)
                goto unreg_devlink;
 
-       if (fp->dl_port.devlink)
-               devlink_port_type_eth_set(&fp->dl_port, netdev);
+       devlink_port_type_eth_set(&fp->dl_port, netdev);
 
        return 0;
 
 unreg_devlink:
        ed->netdevs[portid] = NULL;
        fun_ktls_cleanup(fp);
-       if (fp->dl_port.devlink)
-               devlink_port_unregister(&fp->dl_port);
+       devlink_port_unregister(&fp->dl_port);
 free_stats:
        fun_free_stats_area(fp);
 free_rss:
@@ -1830,10 +1828,8 @@ static void fun_destroy_netdev(struct net_device *netdev)
        struct funeth_priv *fp;
 
        fp = netdev_priv(netdev);
-       if (fp->dl_port.devlink) {
-               devlink_port_type_clear(&fp->dl_port);
-               devlink_port_unregister(&fp->dl_port);
-       }
+       devlink_port_type_clear(&fp->dl_port);
+       devlink_port_unregister(&fp->dl_port);
        unregister_netdev(netdev);
        fun_ktls_cleanup(fp);
        fun_free_stats_area(fp);
index 53b7e95..671f511 100644 (file)
@@ -206,9 +206,9 @@ struct funeth_rxq {
 
 #define FUN_QSTAT_READ(q, seq, stats_copy) \
        do { \
-               seq = u64_stats_fetch_begin(&(q)->syncp); \
+               seq = u64_stats_fetch_begin_irq(&(q)->syncp); \
                stats_copy = (q)->stats; \
-       } while (u64_stats_fetch_retry(&(q)->syncp, (seq)))
+       } while (u64_stats_fetch_retry_irq(&(q)->syncp, (seq)))
 
 #define FUN_INT_NAME_LEN (IFNAMSIZ + 16)
 
index 50b3849..7b9a2d9 100644 (file)
@@ -177,14 +177,14 @@ gve_get_ethtool_stats(struct net_device *netdev,
                                struct gve_rx_ring *rx = &priv->rx[ring];
 
                                start =
-                                 u64_stats_fetch_begin(&priv->rx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
                                tmp_rx_pkts = rx->rpackets;
                                tmp_rx_bytes = rx->rbytes;
                                tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
                                tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
                                tmp_rx_desc_err_dropped_pkt =
                                        rx->rx_desc_err_dropped_pkt;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
                                                       start));
                        rx_pkts += tmp_rx_pkts;
                        rx_bytes += tmp_rx_bytes;
@@ -198,10 +198,10 @@ gve_get_ethtool_stats(struct net_device *netdev,
                if (priv->tx) {
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->tx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
                                tmp_tx_pkts = priv->tx[ring].pkt_done;
                                tmp_tx_bytes = priv->tx[ring].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
                                                       start));
                        tx_pkts += tmp_tx_pkts;
                        tx_bytes += tmp_tx_bytes;
@@ -259,13 +259,13 @@ gve_get_ethtool_stats(struct net_device *netdev,
                        data[i++] = rx->fill_cnt - rx->cnt;
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->rx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
                                tmp_rx_bytes = rx->rbytes;
                                tmp_rx_skb_alloc_fail = rx->rx_skb_alloc_fail;
                                tmp_rx_buf_alloc_fail = rx->rx_buf_alloc_fail;
                                tmp_rx_desc_err_dropped_pkt =
                                        rx->rx_desc_err_dropped_pkt;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
                                                       start));
                        data[i++] = tmp_rx_bytes;
                        data[i++] = rx->rx_cont_packet_cnt;
@@ -331,9 +331,9 @@ gve_get_ethtool_stats(struct net_device *netdev,
                        }
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->tx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
                                tmp_tx_bytes = tx->bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
                                                       start));
                        data[i++] = tmp_tx_bytes;
                        data[i++] = tx->wake_queue;
index 6cafee5..044db3e 100644 (file)
@@ -51,10 +51,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                for (ring = 0; ring < priv->rx_cfg.num_queues; ring++) {
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->rx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->rx[ring].statss);
                                packets = priv->rx[ring].rpackets;
                                bytes = priv->rx[ring].rbytes;
-                       } while (u64_stats_fetch_retry(&priv->rx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->rx[ring].statss,
                                                       start));
                        s->rx_packets += packets;
                        s->rx_bytes += bytes;
@@ -64,10 +64,10 @@ static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
                for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
                        do {
                                start =
-                                 u64_stats_fetch_begin(&priv->tx[ring].statss);
+                                 u64_stats_fetch_begin_irq(&priv->tx[ring].statss);
                                packets = priv->tx[ring].pkt_done;
                                bytes = priv->tx[ring].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[ring].statss,
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[ring].statss,
                                                       start));
                        s->tx_packets += packets;
                        s->tx_bytes += bytes;
@@ -1274,9 +1274,9 @@ void gve_handle_report_stats(struct gve_priv *priv)
                        }
 
                        do {
-                               start = u64_stats_fetch_begin(&priv->tx[idx].statss);
+                               start = u64_stats_fetch_begin_irq(&priv->tx[idx].statss);
                                tx_bytes = priv->tx[idx].bytes_done;
-                       } while (u64_stats_fetch_retry(&priv->tx[idx].statss, start));
+                       } while (u64_stats_fetch_retry_irq(&priv->tx[idx].statss, start));
                        stats[stats_idx++] = (struct stats) {
                                .stat_name = cpu_to_be32(TX_WAKE_CNT),
                                .value = cpu_to_be64(priv->tx[idx].wake_queue),
index c84ef49..ddeceb2 100644 (file)
@@ -830,8 +830,8 @@ static int hip04_set_coalesce(struct net_device *netdev,
 static void hip04_get_drvinfo(struct net_device *netdev,
                              struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
 }
 
 static const struct ethtool_ops hip04_ethtool_ops = {
index 94f80e1..795df71 100644 (file)
@@ -99,11 +99,11 @@ enum HNAE3_DEV_CAP_BITS {
        HNAE3_DEV_SUPPORT_CQ_B,
 };
 
-#define hnae3_dev_fd_supported(hdev) \
-       test_bit(HNAE3_DEV_SUPPORT_FD_B, (hdev)->ae_dev->caps)
+#define hnae3_ae_dev_fd_supported(ae_dev) \
+               test_bit(HNAE3_DEV_SUPPORT_FD_B, (ae_dev)->caps)
 
-#define hnae3_dev_gro_supported(hdev) \
-       test_bit(HNAE3_DEV_SUPPORT_GRO_B, (hdev)->ae_dev->caps)
+#define hnae3_ae_dev_gro_supported(ae_dev) \
+               test_bit(HNAE3_DEV_SUPPORT_GRO_B, (ae_dev)->caps)
 
 #define hnae3_dev_fec_supported(hdev) \
        test_bit(HNAE3_DEV_SUPPORT_FEC_B, (hdev)->ae_dev->caps)
@@ -223,6 +223,8 @@ enum hnae3_fec_mode {
        HNAE3_FEC_AUTO = 0,
        HNAE3_FEC_BASER,
        HNAE3_FEC_RS,
+       HNAE3_FEC_LLRS,
+       HNAE3_FEC_NONE,
        HNAE3_FEC_USER_DEF,
 };
 
index c8b151d..f9bd3fc 100644 (file)
@@ -52,9 +52,9 @@ void hclge_comm_cmd_reuse_desc(struct hclge_desc *desc, bool is_read)
 static void hclge_comm_set_default_capability(struct hnae3_ae_dev *ae_dev,
                                              bool is_pf)
 {
-       set_bit(HNAE3_DEV_SUPPORT_FD_B, ae_dev->caps);
        set_bit(HNAE3_DEV_SUPPORT_GRO_B, ae_dev->caps);
-       if (is_pf && ae_dev->dev_version == HNAE3_DEVICE_VERSION_V2) {
+       if (is_pf) {
+               set_bit(HNAE3_DEV_SUPPORT_FD_B, ae_dev->caps);
                set_bit(HNAE3_DEV_SUPPORT_FEC_B, ae_dev->caps);
                set_bit(HNAE3_DEV_SUPPORT_PAUSE_B, ae_dev->caps);
        }
@@ -91,6 +91,7 @@ int hclge_comm_firmware_compat_config(struct hnae3_ae_dev *ae_dev,
                        hnae3_set_bit(compat, HCLGE_COMM_PHY_IMP_EN_B, 1);
                hnae3_set_bit(compat, HCLGE_COMM_MAC_STATS_EXT_EN_B, 1);
                hnae3_set_bit(compat, HCLGE_COMM_SYNC_RX_RING_HEAD_EN_B, 1);
+               hnae3_set_bit(compat, HCLGE_COMM_LLRS_FEC_EN_B, 1);
 
                req->compat = cpu_to_le32(compat);
        }
@@ -150,6 +151,8 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
         HNAE3_DEV_SUPPORT_PORT_VLAN_BYPASS_B},
        {HCLGE_COMM_CAP_PORT_VLAN_BYPASS_B, HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B},
        {HCLGE_COMM_CAP_CQ_B, HNAE3_DEV_SUPPORT_CQ_B},
+       {HCLGE_COMM_CAP_GRO_B, HNAE3_DEV_SUPPORT_GRO_B},
+       {HCLGE_COMM_CAP_FD_B, HNAE3_DEV_SUPPORT_FD_B},
 };
 
 static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
@@ -162,6 +165,7 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
        {HCLGE_COMM_CAP_TX_PUSH_B, HNAE3_DEV_SUPPORT_TX_PUSH_B},
        {HCLGE_COMM_CAP_RXD_ADV_LAYOUT_B, HNAE3_DEV_SUPPORT_RXD_ADV_LAYOUT_B},
        {HCLGE_COMM_CAP_CQ_B, HNAE3_DEV_SUPPORT_CQ_B},
+       {HCLGE_COMM_CAP_GRO_B, HNAE3_DEV_SUPPORT_GRO_B},
 };
 
 static void
@@ -220,8 +224,10 @@ int hclge_comm_cmd_query_version_and_capability(struct hnae3_ae_dev *ae_dev,
                                         HNAE3_PCI_REVISION_BIT_SIZE;
        ae_dev->dev_version |= ae_dev->pdev->revision;
 
-       if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
+       if (ae_dev->dev_version == HNAE3_DEVICE_VERSION_V2) {
                hclge_comm_set_default_capability(ae_dev, is_pf);
+               return 0;
+       }
 
        hclge_comm_parse_capability(ae_dev, is_pf, resp);
 
index 7a7d4cf..8aaa5fd 100644 (file)
@@ -20,6 +20,7 @@
 #define HCLGE_COMM_PHY_IMP_EN_B                        2
 #define HCLGE_COMM_MAC_STATS_EXT_EN_B          3
 #define HCLGE_COMM_SYNC_RX_RING_HEAD_EN_B      4
+#define HCLGE_COMM_LLRS_FEC_EN_B               5
 
 #define hclge_comm_dev_phy_imp_supported(ae_dev) \
        test_bit(HNAE3_DEV_SUPPORT_PHY_IMP_B, (ae_dev)->caps)
@@ -339,6 +340,8 @@ enum HCLGE_COMM_CAP_BITS {
        HCLGE_COMM_CAP_RXD_ADV_LAYOUT_B = 15,
        HCLGE_COMM_CAP_PORT_VLAN_BYPASS_B = 17,
        HCLGE_COMM_CAP_CQ_B = 18,
+       HCLGE_COMM_CAP_GRO_B = 20,
+       HCLGE_COMM_CAP_FD_B = 21,
 };
 
 enum HCLGE_COMM_API_CAP_BITS {
index 35d7004..481a300 100644 (file)
@@ -3271,12 +3271,11 @@ static void hns3_set_default_feature(struct net_device *netdev)
                NETIF_F_GSO_GRE_CSUM | NETIF_F_GSO_UDP_TUNNEL |
                NETIF_F_SCTP_CRC | NETIF_F_FRAGLIST;
 
-       if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
+       if (hnae3_ae_dev_gro_supported(ae_dev))
                netdev->features |= NETIF_F_GRO_HW;
 
-               if (!(h->flags & HNAE3_SUPPORT_VF))
-                       netdev->features |= NETIF_F_NTUPLE;
-       }
+       if (hnae3_ae_dev_fd_supported(ae_dev))
+               netdev->features |= NETIF_F_NTUPLE;
 
        if (test_bit(HNAE3_DEV_SUPPORT_UDP_GSO_B, ae_dev->caps))
                netdev->features |= NETIF_F_GSO_UDP_L4;
index 4c7988e..3ca9c2b 100644 (file)
@@ -1621,12 +1621,12 @@ static unsigned int loc_to_eth_fec(u8 loc_fec)
                eth_fec |= ETHTOOL_FEC_AUTO;
        if (loc_fec & BIT(HNAE3_FEC_RS))
                eth_fec |= ETHTOOL_FEC_RS;
+       if (loc_fec & BIT(HNAE3_FEC_LLRS))
+               eth_fec |= ETHTOOL_FEC_LLRS;
        if (loc_fec & BIT(HNAE3_FEC_BASER))
                eth_fec |= ETHTOOL_FEC_BASER;
-
-       /* if nothing is set, then FEC is off */
-       if (!eth_fec)
-               eth_fec = ETHTOOL_FEC_OFF;
+       if (loc_fec & BIT(HNAE3_FEC_NONE))
+               eth_fec |= ETHTOOL_FEC_OFF;
 
        return eth_fec;
 }
@@ -1637,12 +1637,13 @@ static unsigned int eth_to_loc_fec(unsigned int eth_fec)
        u32 loc_fec = 0;
 
        if (eth_fec & ETHTOOL_FEC_OFF)
-               return loc_fec;
-
+               loc_fec |= BIT(HNAE3_FEC_NONE);
        if (eth_fec & ETHTOOL_FEC_AUTO)
                loc_fec |= BIT(HNAE3_FEC_AUTO);
        if (eth_fec & ETHTOOL_FEC_RS)
                loc_fec |= BIT(HNAE3_FEC_RS);
+       if (eth_fec & ETHTOOL_FEC_LLRS)
+               loc_fec |= BIT(HNAE3_FEC_LLRS);
        if (eth_fec & ETHTOOL_FEC_BASER)
                loc_fec |= BIT(HNAE3_FEC_BASER);
 
@@ -1668,6 +1669,8 @@ static int hns3_get_fecparam(struct net_device *netdev,
 
        fec->fec = loc_to_eth_fec(fec_ability);
        fec->active_fec = loc_to_eth_fec(fec_mode);
+       if (!fec->active_fec)
+               fec->active_fec = ETHTOOL_FEC_OFF;
 
        return 0;
 }
index f9d8951..489a87e 100644 (file)
@@ -347,7 +347,8 @@ struct hclge_sfp_info_cmd {
        u8 autoneg_ability; /* whether support autoneg */
        __le32 speed_ability; /* speed ability for current media */
        __le32 module_type;
-       u8 rsv[8];
+       u8 fec_ability;
+       u8 rsv[7];
 };
 
 #define HCLGE_MAC_CFG_FEC_AUTO_EN_B    0
@@ -359,6 +360,7 @@ struct hclge_sfp_info_cmd {
 #define HCLGE_MAC_FEC_OFF              0
 #define HCLGE_MAC_FEC_BASER            1
 #define HCLGE_MAC_FEC_RS               2
+#define HCLGE_MAC_FEC_LLRS             3
 struct hclge_config_fec_cmd {
        u8 fec_mode;
        u8 default_config;
index 9b870e7..5912176 100644 (file)
@@ -1517,7 +1517,7 @@ static int hclge_dbg_dump_fd_tcam(struct hclge_dev *hdev, char *buf, int len)
        char *tcam_buf;
        int pos = 0;
 
-       if (!hnae3_dev_fd_supported(hdev)) {
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev)) {
                dev_err(&hdev->pdev->dev,
                        "Only FD-supported dev supports dump fd tcam\n");
                return -EOPNOTSUPP;
@@ -1585,6 +1585,9 @@ static int hclge_dbg_dump_fd_counter(struct hclge_dev *hdev, char *buf, int len)
        u64 cnt;
        u8 i;
 
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
+               return -EOPNOTSUPP;
+
        pos += scnprintf(buf + pos, len - pos,
                         "func_id\thit_times\n");
 
index fae7976..fcdc978 100644 (file)
@@ -1003,6 +1003,27 @@ static int hclge_check_port_speed(struct hnae3_handle *handle, u32 speed)
        return -EINVAL;
 }
 
+static void hclge_update_fec_support(struct hclge_mac *mac)
+{
+       linkmode_clear_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, mac->supported);
+       linkmode_clear_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, mac->supported);
+       linkmode_clear_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT, mac->supported);
+       linkmode_clear_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT, mac->supported);
+
+       if (mac->fec_ability & BIT(HNAE3_FEC_BASER))
+               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT,
+                                mac->supported);
+       if (mac->fec_ability & BIT(HNAE3_FEC_RS))
+               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT,
+                                mac->supported);
+       if (mac->fec_ability & BIT(HNAE3_FEC_LLRS))
+               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
+                                mac->supported);
+       if (mac->fec_ability & BIT(HNAE3_FEC_NONE))
+               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_NONE_BIT,
+                                mac->supported);
+}
+
 static void hclge_convert_setting_sr(u16 speed_ability,
                                     unsigned long *link_mode)
 {
@@ -1101,34 +1122,36 @@ static void hclge_convert_setting_kr(u16 speed_ability,
 
 static void hclge_convert_setting_fec(struct hclge_mac *mac)
 {
-       linkmode_clear_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT, mac->supported);
-       linkmode_clear_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, mac->supported);
+       /* If firmware has reported fec_ability, don't need to convert by speed */
+       if (mac->fec_ability)
+               goto out;
 
        switch (mac->speed) {
        case HCLGE_MAC_SPEED_10G:
        case HCLGE_MAC_SPEED_40G:
-               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT,
-                                mac->supported);
-               mac->fec_ability =
-                       BIT(HNAE3_FEC_BASER) | BIT(HNAE3_FEC_AUTO);
+               mac->fec_ability = BIT(HNAE3_FEC_BASER) | BIT(HNAE3_FEC_AUTO) |
+                                  BIT(HNAE3_FEC_NONE);
                break;
        case HCLGE_MAC_SPEED_25G:
        case HCLGE_MAC_SPEED_50G:
-               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT,
-                                mac->supported);
-               mac->fec_ability =
-                       BIT(HNAE3_FEC_BASER) | BIT(HNAE3_FEC_RS) |
-                       BIT(HNAE3_FEC_AUTO);
+               mac->fec_ability = BIT(HNAE3_FEC_BASER) | BIT(HNAE3_FEC_RS) |
+                                  BIT(HNAE3_FEC_AUTO) | BIT(HNAE3_FEC_NONE);
                break;
        case HCLGE_MAC_SPEED_100G:
+               mac->fec_ability = BIT(HNAE3_FEC_RS) | BIT(HNAE3_FEC_AUTO) |
+                                  BIT(HNAE3_FEC_NONE);
+               break;
        case HCLGE_MAC_SPEED_200G:
-               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT, mac->supported);
-               mac->fec_ability = BIT(HNAE3_FEC_RS) | BIT(HNAE3_FEC_AUTO);
+               mac->fec_ability = BIT(HNAE3_FEC_RS) | BIT(HNAE3_FEC_AUTO) |
+                                  BIT(HNAE3_FEC_LLRS);
                break;
        default:
                mac->fec_ability = 0;
                break;
        }
+
+out:
+       hclge_update_fec_support(mac);
 }
 
 static void hclge_parse_fiber_link_mode(struct hclge_dev *hdev,
@@ -1574,7 +1597,7 @@ static int hclge_configure(struct hclge_dev *hdev)
        if (cfg.vlan_fliter_cap == HCLGE_VLAN_FLTR_CAN_MDF)
                set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps);
 
-       if (hnae3_dev_fd_supported(hdev)) {
+       if (hnae3_ae_dev_fd_supported(hdev->ae_dev)) {
                hdev->fd_en = true;
                hdev->fd_active_type = HCLGE_FD_RULE_NONE;
        }
@@ -1617,7 +1640,7 @@ static int hclge_config_gro(struct hclge_dev *hdev)
        struct hclge_desc desc;
        int ret;
 
-       if (!hnae3_dev_gro_supported(hdev))
+       if (!hnae3_ae_dev_gro_supported(hdev->ae_dev))
                return 0;
 
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GRO_GENERIC_CONFIG, false);
@@ -2744,6 +2767,9 @@ static int hclge_set_fec_hw(struct hclge_dev *hdev, u32 fec_mode)
        if (fec_mode & BIT(HNAE3_FEC_RS))
                hnae3_set_field(req->fec_mode, HCLGE_MAC_CFG_FEC_MODE_M,
                                HCLGE_MAC_CFG_FEC_MODE_S, HCLGE_MAC_FEC_RS);
+       if (fec_mode & BIT(HNAE3_FEC_LLRS))
+               hnae3_set_field(req->fec_mode, HCLGE_MAC_CFG_FEC_MODE_M,
+                               HCLGE_MAC_CFG_FEC_MODE_S, HCLGE_MAC_FEC_LLRS);
        if (fec_mode & BIT(HNAE3_FEC_BASER))
                hnae3_set_field(req->fec_mode, HCLGE_MAC_CFG_FEC_MODE_M,
                                HCLGE_MAC_CFG_FEC_MODE_S, HCLGE_MAC_FEC_BASER);
@@ -2988,6 +3014,9 @@ static void hclge_update_fec_advertising(struct hclge_mac *mac)
        if (mac->fec_mode & BIT(HNAE3_FEC_RS))
                linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_RS_BIT,
                                 mac->advertising);
+       else if (mac->fec_mode & BIT(HNAE3_FEC_LLRS))
+               linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_LLRS_BIT,
+                                mac->advertising);
        else if (mac->fec_mode & BIT(HNAE3_FEC_BASER))
                linkmode_set_bit(ETHTOOL_LINK_MODE_FEC_BASER_BIT,
                                 mac->advertising);
@@ -3037,7 +3066,6 @@ static void hclge_update_port_capability(struct hclge_dev *hdev,
                                         struct hclge_mac *mac)
 {
        if (hnae3_dev_fec_supported(hdev))
-               /* update fec ability by speed */
                hclge_convert_setting_fec(mac);
 
        /* firmware can not identify back plane type, the media type
@@ -3123,6 +3151,7 @@ static int hclge_get_sfp_info(struct hclge_dev *hdev, struct hclge_mac *mac)
                        mac->fec_mode = 0;
                else
                        mac->fec_mode = BIT(resp->active_fec);
+               mac->fec_ability = resp->fec_ability;
        } else {
                mac->speed_type = QUERY_SFP_SPEED;
        }
@@ -5334,7 +5363,7 @@ static int hclge_init_fd_config(struct hclge_dev *hdev)
        struct hclge_fd_key_cfg *key_cfg;
        int ret;
 
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return 0;
 
        ret = hclge_get_fd_mode(hdev, &hdev->fd_cfg.fd_mode);
@@ -6339,7 +6368,7 @@ static int hclge_add_fd_entry(struct hnae3_handle *handle,
        u8 action;
        int ret;
 
-       if (!hnae3_dev_fd_supported(hdev)) {
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev)) {
                dev_err(&hdev->pdev->dev,
                        "flow table director is not supported\n");
                return -EOPNOTSUPP;
@@ -6395,7 +6424,7 @@ static int hclge_del_fd_entry(struct hnae3_handle *handle,
        struct ethtool_rx_flow_spec *fs;
        int ret;
 
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return -EOPNOTSUPP;
 
        fs = (struct ethtool_rx_flow_spec *)&cmd->fs;
@@ -6431,7 +6460,7 @@ static void hclge_clear_fd_rules_in_list(struct hclge_dev *hdev,
        struct hlist_node *node;
        u16 location;
 
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return;
 
        spin_lock_bh(&hdev->fd_rule_lock);
@@ -6473,7 +6502,7 @@ static int hclge_restore_fd_entries(struct hnae3_handle *handle)
         * return value. If error is returned here, the reset process will
         * fail.
         */
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return 0;
 
        /* if fd is disabled, should not restore it when reset */
@@ -6497,7 +6526,7 @@ static int hclge_get_fd_rule_cnt(struct hnae3_handle *handle,
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
 
-       if (!hnae3_dev_fd_supported(hdev) || hclge_is_cls_flower_active(handle))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev) || hclge_is_cls_flower_active(handle))
                return -EOPNOTSUPP;
 
        cmd->rule_cnt = hdev->hclge_fd_rule_num;
@@ -6715,7 +6744,7 @@ static int hclge_get_fd_rule_info(struct hnae3_handle *handle,
        struct hclge_dev *hdev = vport->back;
        struct ethtool_rx_flow_spec *fs;
 
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return -EOPNOTSUPP;
 
        fs = (struct ethtool_rx_flow_spec *)&cmd->fs;
@@ -6778,7 +6807,7 @@ static int hclge_get_all_rules(struct hnae3_handle *handle,
        struct hlist_node *node2;
        int cnt = 0;
 
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return -EOPNOTSUPP;
 
        cmd->data = hdev->fd_cfg.rule_num[HCLGE_FD_STAGE_1];
@@ -6878,7 +6907,7 @@ static int hclge_add_fd_entry_by_arfs(struct hnae3_handle *handle, u16 queue_id,
        struct hclge_fd_rule *rule;
        u16 bit_id;
 
-       if (!hnae3_dev_fd_supported(hdev))
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
                return -EOPNOTSUPP;
 
        /* when there is already fd rule existed add by user,
@@ -7167,6 +7196,12 @@ static int hclge_add_cls_flower(struct hnae3_handle *handle,
        struct hclge_fd_rule *rule;
        int ret;
 
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev)) {
+               dev_err(&hdev->pdev->dev,
+                       "cls flower is not supported\n");
+               return -EOPNOTSUPP;
+       }
+
        ret = hclge_check_cls_flower(hdev, cls_flower, tc);
        if (ret) {
                dev_err(&hdev->pdev->dev,
@@ -7220,6 +7255,9 @@ static int hclge_del_cls_flower(struct hnae3_handle *handle,
        struct hclge_fd_rule *rule;
        int ret;
 
+       if (!hnae3_ae_dev_fd_supported(hdev->ae_dev))
+               return -EOPNOTSUPP;
+
        spin_lock_bh(&hdev->fd_rule_lock);
 
        rule = hclge_find_cls_flower(hdev, cls_flower->cookie);
@@ -11443,6 +11481,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
        if (ret)
                goto err_mdiobus_unreg;
 
+       ret = hclge_update_port_info(hdev);
+       if (ret)
+               goto err_mdiobus_unreg;
+
        INIT_KFIFO(hdev->mac_tnl_log);
 
        hclge_dcb_ops_set(hdev);
index 26f8733..14e338f 100644 (file)
@@ -2125,7 +2125,7 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev)
        struct hclge_desc desc;
        int ret;
 
-       if (!hnae3_dev_gro_supported(hdev))
+       if (!hnae3_ae_dev_gro_supported(hdev->ae_dev))
                return 0;
 
        hclgevf_cmd_setup_basic_desc(&desc, HCLGE_OPC_GRO_GENERIC_CONFIG,
index a866bea..e5828a6 100644 (file)
@@ -74,14 +74,14 @@ void hinic_rxq_get_stats(struct hinic_rxq *rxq, struct hinic_rxq_stats *stats)
        unsigned int start;
 
        do {
-               start = u64_stats_fetch_begin(&rxq_stats->syncp);
+               start = u64_stats_fetch_begin_irq(&rxq_stats->syncp);
                stats->pkts = rxq_stats->pkts;
                stats->bytes = rxq_stats->bytes;
                stats->errors = rxq_stats->csum_errors +
                                rxq_stats->other_errors;
                stats->csum_errors = rxq_stats->csum_errors;
                stats->other_errors = rxq_stats->other_errors;
-       } while (u64_stats_fetch_retry(&rxq_stats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&rxq_stats->syncp, start));
 }
 
 /**
index 5051cdf..3b6c7b5 100644 (file)
@@ -99,14 +99,14 @@ void hinic_txq_get_stats(struct hinic_txq *txq, struct hinic_txq_stats *stats)
        unsigned int start;
 
        do {
-               start = u64_stats_fetch_begin(&txq_stats->syncp);
+               start = u64_stats_fetch_begin_irq(&txq_stats->syncp);
                stats->pkts    = txq_stats->pkts;
                stats->bytes   = txq_stats->bytes;
                stats->tx_busy = txq_stats->tx_busy;
                stats->tx_wake = txq_stats->tx_wake;
                stats->tx_dropped = txq_stats->tx_dropped;
                stats->big_frags_pkts = txq_stats->big_frags_pkts;
-       } while (u64_stats_fetch_retry(&txq_stats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&txq_stats->syncp, start));
 }
 
 /**
index 6cb8603..1db5b67 100644 (file)
@@ -159,8 +159,8 @@ static int ehea_nway_reset(struct net_device *dev)
 static void ehea_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static u32 ehea_get_msglevel(struct net_device *dev)
index fbea9f7..0a4d04a 100644 (file)
@@ -2284,8 +2284,8 @@ static void emac_ethtool_get_drvinfo(struct net_device *ndev,
 {
        struct emac_instance *dev = netdev_priv(ndev);
 
-       strlcpy(info->driver, "ibm_emac", sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, "ibm_emac", sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
        snprintf(info->bus_info, sizeof(info->bus_info), "PPC 4xx EMAC-%d %pOF",
                 dev->cell_index, dev->ofdev->dev.of_node);
 }
index 5c6a04d..ee4548e 100644 (file)
@@ -727,8 +727,8 @@ static void ibmveth_init_link_settings(struct net_device *dev)
 static void netdev_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, ibmveth_driver_name, sizeof(info->driver));
-       strlcpy(info->version, ibmveth_driver_version, sizeof(info->version));
+       strscpy(info->driver, ibmveth_driver_name, sizeof(info->driver));
+       strscpy(info->version, ibmveth_driver_version, sizeof(info->version));
 }
 
 static netdev_features_t ibmveth_fix_features(struct net_device *dev,
index 11a884a..560d1d4 100644 (file)
@@ -2431,8 +2431,8 @@ static void e100_get_drvinfo(struct net_device *netdev,
        struct ethtool_drvinfo *info)
 {
        struct nic *nic = netdev_priv(netdev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(nic->pdev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(nic->pdev),
                sizeof(info->bus_info));
 }
 
index 32803b0..d06d29c 100644 (file)
@@ -531,10 +531,10 @@ static void e1000_get_drvinfo(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  e1000_driver_name,
+       strscpy(drvinfo->driver,  e1000_driver_name,
                sizeof(drvinfo->driver));
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index b80ae9a..51a5afe 100644 (file)
@@ -639,7 +639,7 @@ static void e1000_get_drvinfo(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, e1000e_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, e1000e_driver_name, sizeof(drvinfo->driver));
 
        /* EEPROM image version # is reported as firmware version # for
         * PCI-E controllers
@@ -650,7 +650,7 @@ static void e1000_get_drvinfo(struct net_device *netdev,
                 (adapter->eeprom_vers & 0x0FF0) >> 4,
                 (adapter->eeprom_vers & 0x000F));
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 321f2a9..5698480 100644 (file)
@@ -7267,7 +7267,7 @@ static void e1000_print_device_info(struct e1000_adapter *adapter)
        ret_val = e1000_read_pba_string_generic(hw, pba_str,
                                                E1000_PBANUM_LENGTH);
        if (ret_val)
-               strlcpy((char *)pba_str, "Unknown", sizeof(pba_str));
+               strscpy((char *)pba_str, "Unknown", sizeof(pba_str));
        e_info("MAC: %d, PHY: %d, PBA No: %s\n",
               hw->mac.type, hw->phy.type, pba_str);
 }
@@ -7480,7 +7480,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        e1000e_set_ethtool_ops(netdev);
        netdev->watchdog_timeo = 5 * HZ;
        netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64);
-       strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
+       strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
 
        netdev->mem_start = mmio_start;
        netdev->mem_end = mmio_start + mmio_len;
@@ -7676,7 +7676,7 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (hw->mac.type >= e1000_pch_cnp)
                adapter->flags2 |= FLAG2_ENABLE_S0IX_FLOWS;
 
-       strlcpy(netdev->name, "eth%d", sizeof(netdev->name));
+       strscpy(netdev->name, "eth%d", sizeof(netdev->name));
        err = register_netdev(netdev);
        if (err)
                goto err_register;
index e9cd0fa..7e75706 100644 (file)
@@ -2001,10 +2001,10 @@ static void i40e_get_drvinfo(struct net_device *netdev,
        struct i40e_vsi *vsi = np->vsi;
        struct i40e_pf *pf = vsi->back;
 
-       strlcpy(drvinfo->driver, i40e_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->fw_version, i40e_nvm_version_str(&pf->hw),
+       strscpy(drvinfo->driver, i40e_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->fw_version, i40e_nvm_version_str(&pf->hw),
                sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(pf->pdev),
+       strscpy(drvinfo->bus_info, pci_name(pf->pdev),
                sizeof(drvinfo->bus_info));
        drvinfo->n_priv_flags = I40E_PRIV_FLAGS_STR_LEN;
        if (pf->hw.pf_id == 0)
index 9f1d5de..5e52900 100644 (file)
@@ -10701,7 +10701,7 @@ static void i40e_send_version(struct i40e_pf *pf)
        dv.minor_version = 0xff;
        dv.build_version = 0xff;
        dv.subbuild_version = 0;
-       strlcpy(dv.driver_string, UTS_RELEASE, sizeof(dv.driver_string));
+       strscpy(dv.driver_string, UTS_RELEASE, sizeof(dv.driver_string));
        i40e_aq_send_driver_version(&pf->hw, &dv, NULL);
 }
 
@@ -16049,23 +16049,23 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
                switch (hw->bus.speed) {
                case i40e_bus_speed_8000:
-                       strlcpy(speed, "8.0", PCI_SPEED_SIZE); break;
+                       strscpy(speed, "8.0", PCI_SPEED_SIZE); break;
                case i40e_bus_speed_5000:
-                       strlcpy(speed, "5.0", PCI_SPEED_SIZE); break;
+                       strscpy(speed, "5.0", PCI_SPEED_SIZE); break;
                case i40e_bus_speed_2500:
-                       strlcpy(speed, "2.5", PCI_SPEED_SIZE); break;
+                       strscpy(speed, "2.5", PCI_SPEED_SIZE); break;
                default:
                        break;
                }
                switch (hw->bus.width) {
                case i40e_bus_width_pcie_x8:
-                       strlcpy(width, "8", PCI_WIDTH_SIZE); break;
+                       strscpy(width, "8", PCI_WIDTH_SIZE); break;
                case i40e_bus_width_pcie_x4:
-                       strlcpy(width, "4", PCI_WIDTH_SIZE); break;
+                       strscpy(width, "4", PCI_WIDTH_SIZE); break;
                case i40e_bus_width_pcie_x2:
-                       strlcpy(width, "2", PCI_WIDTH_SIZE); break;
+                       strscpy(width, "2", PCI_WIDTH_SIZE); break;
                case i40e_bus_width_pcie_x1:
-                       strlcpy(width, "1", PCI_WIDTH_SIZE); break;
+                       strscpy(width, "1", PCI_WIDTH_SIZE); break;
                default:
                        break;
                }
index 2d3533f..ffea0c9 100644 (file)
@@ -1390,7 +1390,7 @@ static long i40e_ptp_create_clock(struct i40e_pf *pf)
        if (!IS_ERR_OR_NULL(pf->ptp_clock))
                return 0;
 
-       strlcpy(pf->ptp_caps.name, i40e_driver_name,
+       strscpy(pf->ptp_caps.name, i40e_driver_name,
                sizeof(pf->ptp_caps.name) - 1);
        pf->ptp_caps.owner = THIS_MODULE;
        pf->ptp_caps.max_adj = 999999999;
index e535d4c..a056e15 100644 (file)
@@ -581,9 +581,9 @@ static void iavf_get_drvinfo(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, iavf_driver_name, 32);
-       strlcpy(drvinfo->fw_version, "N/A", 4);
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+       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;
 }
 
index 841fa14..001500a 100644 (file)
@@ -864,6 +864,7 @@ ice_fetch_u64_stats_per_ring(struct u64_stats_sync *syncp,
                             struct ice_q_stats stats, u64 *pkts, u64 *bytes);
 int ice_up(struct ice_vsi *vsi);
 int ice_down(struct ice_vsi *vsi);
+int ice_down_up(struct ice_vsi *vsi);
 int ice_vsi_cfg(struct ice_vsi *vsi);
 struct ice_vsi *ice_lb_vsi_setup(struct ice_pf *pf, struct ice_port_info *pi);
 int ice_vsi_determine_xdp_res(struct ice_vsi *vsi);
index 9939238..1bdc70a 100644 (file)
@@ -1423,6 +1423,56 @@ struct ice_aqc_set_port_id_led {
        u8 rsvd[13];
 };
 
+/* Get Port Options (indirect, 0x06EA) */
+struct ice_aqc_get_port_options {
+       u8 lport_num;
+       u8 lport_num_valid;
+       u8 port_options_count;
+#define ICE_AQC_PORT_OPT_COUNT_M       GENMASK(3, 0)
+#define ICE_AQC_PORT_OPT_MAX           16
+
+       u8 innermost_phy_index;
+       u8 port_options;
+#define ICE_AQC_PORT_OPT_ACTIVE_M      GENMASK(3, 0)
+#define ICE_AQC_PORT_OPT_VALID         BIT(7)
+
+       u8 pending_port_option_status;
+#define ICE_AQC_PENDING_PORT_OPT_IDX_M GENMASK(3, 0)
+#define ICE_AQC_PENDING_PORT_OPT_VALID BIT(7)
+
+       u8 rsvd[2];
+       __le32 addr_high;
+       __le32 addr_low;
+};
+
+struct ice_aqc_get_port_options_elem {
+       u8 pmd;
+#define ICE_AQC_PORT_OPT_PMD_COUNT_M   GENMASK(3, 0)
+
+       u8 max_lane_speed;
+#define ICE_AQC_PORT_OPT_MAX_LANE_M    GENMASK(3, 0)
+#define ICE_AQC_PORT_OPT_MAX_LANE_100M 0
+#define ICE_AQC_PORT_OPT_MAX_LANE_1G   1
+#define ICE_AQC_PORT_OPT_MAX_LANE_2500M        2
+#define ICE_AQC_PORT_OPT_MAX_LANE_5G   3
+#define ICE_AQC_PORT_OPT_MAX_LANE_10G  4
+#define ICE_AQC_PORT_OPT_MAX_LANE_25G  5
+#define ICE_AQC_PORT_OPT_MAX_LANE_50G  6
+#define ICE_AQC_PORT_OPT_MAX_LANE_100G 7
+
+       u8 global_scid[2];
+       u8 phy_scid[2];
+       u8 pf2port_cid[2];
+};
+
+/* Set Port Option (direct, 0x06EB) */
+struct ice_aqc_set_port_option {
+       u8 lport_num;
+       u8 lport_num_valid;
+       u8 selected_port_option;
+       u8 rsvd[13];
+};
+
 /* Set/Get GPIO (direct, 0x06EC/0x06ED) */
 struct ice_aqc_gpio {
        __le16 gpio_ctrl_handle;
@@ -1489,6 +1539,12 @@ struct ice_aqc_nvm {
 #define ICE_AQC_NVM_PERST_FLAG         1
 #define ICE_AQC_NVM_EMPR_FLAG          2
 #define ICE_AQC_NVM_EMPR_ENA           BIT(0) /* Write Activate reply only */
+       /* For Write Activate, several flags are sent as part of a separate
+        * flags2 field using a separate byte. For simplicity of the software
+        * interface, we pass the flags as a 16 bit value so these flags are
+        * all offset by 8 bits
+        */
+#define ICE_AQC_NVM_ACTIV_REQ_EMPR     BIT(8) /* NVM Write Activate only */
        __le16 module_typeid;
        __le16 length;
 #define ICE_AQC_NVM_ERASE_LEN  0xFFFF
@@ -2082,6 +2138,8 @@ struct ice_aq_desc {
                struct ice_aqc_gpio read_write_gpio;
                struct ice_aqc_sff_eeprom read_write_sff_param;
                struct ice_aqc_set_port_id_led set_port_id_led;
+               struct ice_aqc_get_port_options get_port_options;
+               struct ice_aqc_set_port_option set_port_option;
                struct ice_aqc_get_sw_cfg get_sw_conf;
                struct ice_aqc_set_port_params set_port_params;
                struct ice_aqc_sw_rules sw_rules;
@@ -2243,6 +2301,8 @@ enum ice_adminq_opc {
        ice_aqc_opc_read_i2c                            = 0x06E2,
        ice_aqc_opc_write_i2c                           = 0x06E3,
        ice_aqc_opc_set_port_id_led                     = 0x06E9,
+       ice_aqc_opc_get_port_options                    = 0x06EA,
+       ice_aqc_opc_set_port_option                     = 0x06EB,
        ice_aqc_opc_set_gpio                            = 0x06EC,
        ice_aqc_opc_get_gpio                            = 0x06ED,
        ice_aqc_opc_sff_eeprom                          = 0x06EE,
index 136d791..6f092e0 100644 (file)
@@ -417,7 +417,7 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
        /* Strip the Ethernet CRC bytes before the packet is posted to host
         * memory.
         */
-       rlan_ctx.crcstrip = 1;
+       rlan_ctx.crcstrip = !(ring->flags & ICE_RX_FLAGS_CRC_STRIP_DIS);
 
        /* L2TSEL flag defines the reported L2 Tags in the receive descriptor
         * and it needs to remain 1 for non-DVM capable configurations to not
index 27d0cbb..40e4c28 100644 (file)
@@ -8,6 +8,108 @@
 
 #define ICE_PF_RESET_WAIT_COUNT        300
 
+static const char * const ice_link_mode_str_low[] = {
+       [0] = "100BASE_TX",
+       [1] = "100M_SGMII",
+       [2] = "1000BASE_T",
+       [3] = "1000BASE_SX",
+       [4] = "1000BASE_LX",
+       [5] = "1000BASE_KX",
+       [6] = "1G_SGMII",
+       [7] = "2500BASE_T",
+       [8] = "2500BASE_X",
+       [9] = "2500BASE_KX",
+       [10] = "5GBASE_T",
+       [11] = "5GBASE_KR",
+       [12] = "10GBASE_T",
+       [13] = "10G_SFI_DA",
+       [14] = "10GBASE_SR",
+       [15] = "10GBASE_LR",
+       [16] = "10GBASE_KR_CR1",
+       [17] = "10G_SFI_AOC_ACC",
+       [18] = "10G_SFI_C2C",
+       [19] = "25GBASE_T",
+       [20] = "25GBASE_CR",
+       [21] = "25GBASE_CR_S",
+       [22] = "25GBASE_CR1",
+       [23] = "25GBASE_SR",
+       [24] = "25GBASE_LR",
+       [25] = "25GBASE_KR",
+       [26] = "25GBASE_KR_S",
+       [27] = "25GBASE_KR1",
+       [28] = "25G_AUI_AOC_ACC",
+       [29] = "25G_AUI_C2C",
+       [30] = "40GBASE_CR4",
+       [31] = "40GBASE_SR4",
+       [32] = "40GBASE_LR4",
+       [33] = "40GBASE_KR4",
+       [34] = "40G_XLAUI_AOC_ACC",
+       [35] = "40G_XLAUI",
+       [36] = "50GBASE_CR2",
+       [37] = "50GBASE_SR2",
+       [38] = "50GBASE_LR2",
+       [39] = "50GBASE_KR2",
+       [40] = "50G_LAUI2_AOC_ACC",
+       [41] = "50G_LAUI2",
+       [42] = "50G_AUI2_AOC_ACC",
+       [43] = "50G_AUI2",
+       [44] = "50GBASE_CP",
+       [45] = "50GBASE_SR",
+       [46] = "50GBASE_FR",
+       [47] = "50GBASE_LR",
+       [48] = "50GBASE_KR_PAM4",
+       [49] = "50G_AUI1_AOC_ACC",
+       [50] = "50G_AUI1",
+       [51] = "100GBASE_CR4",
+       [52] = "100GBASE_SR4",
+       [53] = "100GBASE_LR4",
+       [54] = "100GBASE_KR4",
+       [55] = "100G_CAUI4_AOC_ACC",
+       [56] = "100G_CAUI4",
+       [57] = "100G_AUI4_AOC_ACC",
+       [58] = "100G_AUI4",
+       [59] = "100GBASE_CR_PAM4",
+       [60] = "100GBASE_KR_PAM4",
+       [61] = "100GBASE_CP2",
+       [62] = "100GBASE_SR2",
+       [63] = "100GBASE_DR",
+};
+
+static const char * const ice_link_mode_str_high[] = {
+       [0] = "100GBASE_KR2_PAM4",
+       [1] = "100G_CAUI2_AOC_ACC",
+       [2] = "100G_CAUI2",
+       [3] = "100G_AUI2_AOC_ACC",
+       [4] = "100G_AUI2",
+};
+
+/**
+ * ice_dump_phy_type - helper function to dump phy_type
+ * @hw: pointer to the HW structure
+ * @low: 64 bit value for phy_type_low
+ * @high: 64 bit value for phy_type_high
+ * @prefix: prefix string to differentiate multiple dumps
+ */
+static void
+ice_dump_phy_type(struct ice_hw *hw, u64 low, u64 high, const char *prefix)
+{
+       ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_low: 0x%016llx\n", prefix, low);
+
+       for (u32 i = 0; i < BITS_PER_TYPE(typeof(low)); i++) {
+               if (low & BIT_ULL(i))
+                       ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
+                                 prefix, i, ice_link_mode_str_low[i]);
+       }
+
+       ice_debug(hw, ICE_DBG_PHY, "%s: phy_type_high: 0x%016llx\n", prefix, high);
+
+       for (u32 i = 0; i < BITS_PER_TYPE(typeof(high)); i++) {
+               if (high & BIT_ULL(i))
+                       ice_debug(hw, ICE_DBG_PHY, "%s:   bit(%d): %s\n",
+                                 prefix, i, ice_link_mode_str_high[i]);
+       }
+}
+
 /**
  * ice_set_mac_type - Sets MAC type
  * @hw: pointer to the HW structure
@@ -183,6 +285,7 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
        struct ice_aqc_get_phy_caps *cmd;
        u16 pcaps_size = sizeof(*pcaps);
        struct ice_aq_desc desc;
+       const char *prefix;
        struct ice_hw *hw;
        int status;
 
@@ -204,29 +307,48 @@ ice_aq_get_phy_caps(struct ice_port_info *pi, bool qual_mods, u8 report_mode,
        cmd->param0 |= cpu_to_le16(report_mode);
        status = ice_aq_send_cmd(hw, &desc, pcaps, pcaps_size, cd);
 
-       ice_debug(hw, ICE_DBG_LINK, "get phy caps - report_mode = 0x%x\n",
-                 report_mode);
-       ice_debug(hw, ICE_DBG_LINK, "   phy_type_low = 0x%llx\n",
-                 (unsigned long long)le64_to_cpu(pcaps->phy_type_low));
-       ice_debug(hw, ICE_DBG_LINK, "   phy_type_high = 0x%llx\n",
-                 (unsigned long long)le64_to_cpu(pcaps->phy_type_high));
-       ice_debug(hw, ICE_DBG_LINK, "   caps = 0x%x\n", pcaps->caps);
-       ice_debug(hw, ICE_DBG_LINK, "   low_power_ctrl_an = 0x%x\n",
+       ice_debug(hw, ICE_DBG_LINK, "get phy caps dump\n");
+
+       switch (report_mode) {
+       case ICE_AQC_REPORT_TOPO_CAP_MEDIA:
+               prefix = "phy_caps_media";
+               break;
+       case ICE_AQC_REPORT_TOPO_CAP_NO_MEDIA:
+               prefix = "phy_caps_no_media";
+               break;
+       case ICE_AQC_REPORT_ACTIVE_CFG:
+               prefix = "phy_caps_active";
+               break;
+       case ICE_AQC_REPORT_DFLT_CFG:
+               prefix = "phy_caps_default";
+               break;
+       default:
+               prefix = "phy_caps_invalid";
+       }
+
+       ice_dump_phy_type(hw, le64_to_cpu(pcaps->phy_type_low),
+                         le64_to_cpu(pcaps->phy_type_high), prefix);
+
+       ice_debug(hw, ICE_DBG_LINK, "%s: report_mode = 0x%x\n",
+                 prefix, report_mode);
+       ice_debug(hw, ICE_DBG_LINK, "%s: caps = 0x%x\n", prefix, pcaps->caps);
+       ice_debug(hw, ICE_DBG_LINK, "%s: low_power_ctrl_an = 0x%x\n", prefix,
                  pcaps->low_power_ctrl_an);
-       ice_debug(hw, ICE_DBG_LINK, "   eee_cap = 0x%x\n", pcaps->eee_cap);
-       ice_debug(hw, ICE_DBG_LINK, "   eeer_value = 0x%x\n",
+       ice_debug(hw, ICE_DBG_LINK, "%s: eee_cap = 0x%x\n", prefix,
+                 pcaps->eee_cap);
+       ice_debug(hw, ICE_DBG_LINK, "%s: eeer_value = 0x%x\n", prefix,
                  pcaps->eeer_value);
-       ice_debug(hw, ICE_DBG_LINK, "   link_fec_options = 0x%x\n",
+       ice_debug(hw, ICE_DBG_LINK, "%s: link_fec_options = 0x%x\n", prefix,
                  pcaps->link_fec_options);
-       ice_debug(hw, ICE_DBG_LINK, "   module_compliance_enforcement = 0x%x\n",
-                 pcaps->module_compliance_enforcement);
-       ice_debug(hw, ICE_DBG_LINK, "   extended_compliance_code = 0x%x\n",
-                 pcaps->extended_compliance_code);
-       ice_debug(hw, ICE_DBG_LINK, "   module_type[0] = 0x%x\n",
+       ice_debug(hw, ICE_DBG_LINK, "%s: module_compliance_enforcement = 0x%x\n",
+                 prefix, pcaps->module_compliance_enforcement);
+       ice_debug(hw, ICE_DBG_LINK, "%s: extended_compliance_code = 0x%x\n",
+                 prefix, pcaps->extended_compliance_code);
+       ice_debug(hw, ICE_DBG_LINK, "%s: module_type[0] = 0x%x\n", prefix,
                  pcaps->module_type[0]);
-       ice_debug(hw, ICE_DBG_LINK, "   module_type[1] = 0x%x\n",
+       ice_debug(hw, ICE_DBG_LINK, "%s: module_type[1] = 0x%x\n", prefix,
                  pcaps->module_type[1]);
-       ice_debug(hw, ICE_DBG_LINK, "   module_type[2] = 0x%x\n",
+       ice_debug(hw, ICE_DBG_LINK, "%s: module_type[2] = 0x%x\n", prefix,
                  pcaps->module_type[2]);
 
        if (!status && report_mode == ICE_AQC_REPORT_TOPO_CAP_MEDIA) {
@@ -2775,6 +2897,26 @@ ice_aq_set_port_params(struct ice_port_info *pi, bool double_vlan,
        return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 }
 
+/**
+ * ice_is_100m_speed_supported
+ * @hw: pointer to the HW struct
+ *
+ * returns true if 100M speeds are supported by the device,
+ * false otherwise.
+ */
+bool ice_is_100m_speed_supported(struct ice_hw *hw)
+{
+       switch (hw->device_id) {
+       case ICE_DEV_ID_E822C_SGMII:
+       case ICE_DEV_ID_E822L_SGMII:
+       case ICE_DEV_ID_E823L_1GBE:
+       case ICE_DEV_ID_E823C_SGMII:
+               return true;
+       default:
+               return false;
+       }
+}
+
 /**
  * ice_get_link_speed_based_on_phy_type - returns link speed
  * @phy_type_low: lower part of phy_type
@@ -3534,6 +3676,121 @@ ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
        return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
 }
 
+/**
+ * ice_aq_get_port_options
+ * @hw: pointer to the HW struct
+ * @options: buffer for the resultant port options
+ * @option_count: input - size of the buffer in port options structures,
+ *                output - number of returned port options
+ * @lport: logical port to call the command with (optional)
+ * @lport_valid: when false, FW uses port owned by the PF instead of lport,
+ *               when PF owns more than 1 port it must be true
+ * @active_option_idx: index of active port option in returned buffer
+ * @active_option_valid: active option in returned buffer is valid
+ * @pending_option_idx: index of pending port option in returned buffer
+ * @pending_option_valid: pending option in returned buffer is valid
+ *
+ * Calls Get Port Options AQC (0x06ea) and verifies result.
+ */
+int
+ice_aq_get_port_options(struct ice_hw *hw,
+                       struct ice_aqc_get_port_options_elem *options,
+                       u8 *option_count, u8 lport, bool lport_valid,
+                       u8 *active_option_idx, bool *active_option_valid,
+                       u8 *pending_option_idx, bool *pending_option_valid)
+{
+       struct ice_aqc_get_port_options *cmd;
+       struct ice_aq_desc desc;
+       int status;
+       u8 i;
+
+       /* options buffer shall be able to hold max returned options */
+       if (*option_count < ICE_AQC_PORT_OPT_COUNT_M)
+               return -EINVAL;
+
+       cmd = &desc.params.get_port_options;
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_get_port_options);
+
+       if (lport_valid)
+               cmd->lport_num = lport;
+       cmd->lport_num_valid = lport_valid;
+
+       status = ice_aq_send_cmd(hw, &desc, options,
+                                *option_count * sizeof(*options), NULL);
+       if (status)
+               return status;
+
+       /* verify direct FW response & set output parameters */
+       *option_count = FIELD_GET(ICE_AQC_PORT_OPT_COUNT_M,
+                                 cmd->port_options_count);
+       ice_debug(hw, ICE_DBG_PHY, "options: %x\n", *option_count);
+       *active_option_valid = FIELD_GET(ICE_AQC_PORT_OPT_VALID,
+                                        cmd->port_options);
+       if (*active_option_valid) {
+               *active_option_idx = FIELD_GET(ICE_AQC_PORT_OPT_ACTIVE_M,
+                                              cmd->port_options);
+               if (*active_option_idx > (*option_count - 1))
+                       return -EIO;
+               ice_debug(hw, ICE_DBG_PHY, "active idx: %x\n",
+                         *active_option_idx);
+       }
+
+       *pending_option_valid = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_VALID,
+                                         cmd->pending_port_option_status);
+       if (*pending_option_valid) {
+               *pending_option_idx = FIELD_GET(ICE_AQC_PENDING_PORT_OPT_IDX_M,
+                                               cmd->pending_port_option_status);
+               if (*pending_option_idx > (*option_count - 1))
+                       return -EIO;
+               ice_debug(hw, ICE_DBG_PHY, "pending idx: %x\n",
+                         *pending_option_idx);
+       }
+
+       /* mask output options fields */
+       for (i = 0; i < *option_count; i++) {
+               options[i].pmd = FIELD_GET(ICE_AQC_PORT_OPT_PMD_COUNT_M,
+                                          options[i].pmd);
+               options[i].max_lane_speed = FIELD_GET(ICE_AQC_PORT_OPT_MAX_LANE_M,
+                                                     options[i].max_lane_speed);
+               ice_debug(hw, ICE_DBG_PHY, "pmds: %x max speed: %x\n",
+                         options[i].pmd, options[i].max_lane_speed);
+       }
+
+       return 0;
+}
+
+/**
+ * ice_aq_set_port_option
+ * @hw: pointer to the HW struct
+ * @lport: logical port to call the command with
+ * @lport_valid: when false, FW uses port owned by the PF instead of lport,
+ *               when PF owns more than 1 port it must be true
+ * @new_option: new port option to be written
+ *
+ * Calls Set Port Options AQC (0x06eb).
+ */
+int
+ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
+                      u8 new_option)
+{
+       struct ice_aqc_set_port_option *cmd;
+       struct ice_aq_desc desc;
+
+       if (new_option > ICE_AQC_PORT_OPT_COUNT_M)
+               return -EINVAL;
+
+       cmd = &desc.params.set_port_option;
+       ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_set_port_option);
+
+       if (lport_valid)
+               cmd->lport_num = lport;
+
+       cmd->lport_num_valid = lport_valid;
+       cmd->selected_port_option = new_option;
+
+       return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
+}
+
 /**
  * ice_aq_sff_eeprom
  * @hw: pointer to the HW struct
index 61b7c60..8b6712b 100644 (file)
@@ -151,6 +151,15 @@ int
 ice_aq_set_port_id_led(struct ice_port_info *pi, bool is_orig_mode,
                       struct ice_sq_cd *cd);
 int
+ice_aq_get_port_options(struct ice_hw *hw,
+                       struct ice_aqc_get_port_options_elem *options,
+                       u8 *option_count, u8 lport, bool lport_valid,
+                       u8 *active_option_idx, bool *active_option_valid,
+                       u8 *pending_option_idx, bool *pending_option_valid);
+int
+ice_aq_set_port_option(struct ice_hw *hw, u8 lport, u8 lport_valid,
+                      u8 new_option);
+int
 ice_aq_sff_eeprom(struct ice_hw *hw, u16 lport, u8 bus_addr,
                  u16 mem_addr, u8 page, u8 set_page, u8 *data, u8 length,
                  bool write, struct ice_sq_cd *cd);
@@ -204,6 +213,7 @@ ice_aq_set_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx, bool value,
 int
 ice_aq_get_gpio(struct ice_hw *hw, u16 gpio_ctrl_handle, u8 pin_idx,
                bool *value, struct ice_sq_cd *cd);
+bool ice_is_100m_speed_supported(struct ice_hw *hw);
 int
 ice_aq_set_lldp_mib(struct ice_hw *hw, u8 mib_type, void *buf, u16 buf_size,
                    struct ice_sq_cd *cd);
index 3337314..e6ec200 100644 (file)
@@ -9,6 +9,8 @@
 #include "ice_eswitch.h"
 #include "ice_fw_update.h"
 
+static int ice_active_port_option = -1;
+
 /* context for devlink info version reporting */
 struct ice_info_ctx {
        char buf[128];
@@ -466,12 +468,259 @@ ice_devlink_reload_empr_finish(struct devlink *devlink,
        return 0;
 }
 
+/**
+ * ice_devlink_port_opt_speed_str - convert speed to a string
+ * @speed: speed value
+ */
+static const char *ice_devlink_port_opt_speed_str(u8 speed)
+{
+       switch (speed & ICE_AQC_PORT_OPT_MAX_LANE_M) {
+       case ICE_AQC_PORT_OPT_MAX_LANE_100M:
+               return "0.1";
+       case ICE_AQC_PORT_OPT_MAX_LANE_1G:
+               return "1";
+       case ICE_AQC_PORT_OPT_MAX_LANE_2500M:
+               return "2.5";
+       case ICE_AQC_PORT_OPT_MAX_LANE_5G:
+               return "5";
+       case ICE_AQC_PORT_OPT_MAX_LANE_10G:
+               return "10";
+       case ICE_AQC_PORT_OPT_MAX_LANE_25G:
+               return "25";
+       case ICE_AQC_PORT_OPT_MAX_LANE_50G:
+               return "50";
+       case ICE_AQC_PORT_OPT_MAX_LANE_100G:
+               return "100";
+       }
+
+       return "-";
+}
+
+#define ICE_PORT_OPT_DESC_LEN  50
+/**
+ * ice_devlink_port_options_print - Print available port split options
+ * @pf: the PF to print split port options
+ *
+ * Prints a table with available port split options and max port speeds
+ */
+static void ice_devlink_port_options_print(struct ice_pf *pf)
+{
+       u8 i, j, options_count, cnt, speed, pending_idx, active_idx;
+       struct ice_aqc_get_port_options_elem *options, *opt;
+       struct device *dev = ice_pf_to_dev(pf);
+       bool active_valid, pending_valid;
+       char desc[ICE_PORT_OPT_DESC_LEN];
+       const char *str;
+       int status;
+
+       options = kcalloc(ICE_AQC_PORT_OPT_MAX * ICE_MAX_PORT_PER_PCI_DEV,
+                         sizeof(*options), GFP_KERNEL);
+       if (!options)
+               return;
+
+       for (i = 0; i < ICE_MAX_PORT_PER_PCI_DEV; i++) {
+               opt = options + i * ICE_AQC_PORT_OPT_MAX;
+               options_count = ICE_AQC_PORT_OPT_MAX;
+               active_valid = 0;
+
+               status = ice_aq_get_port_options(&pf->hw, opt, &options_count,
+                                                i, true, &active_idx,
+                                                &active_valid, &pending_idx,
+                                                &pending_valid);
+               if (status) {
+                       dev_dbg(dev, "Couldn't read port option for port %d, err %d\n",
+                               i, status);
+                       goto err;
+               }
+       }
+
+       dev_dbg(dev, "Available port split options and max port speeds (Gbps):\n");
+       dev_dbg(dev, "Status  Split      Quad 0          Quad 1\n");
+       dev_dbg(dev, "        count  L0  L1  L2  L3  L4  L5  L6  L7\n");
+
+       for (i = 0; i < options_count; i++) {
+               cnt = 0;
+
+               if (i == ice_active_port_option)
+                       str = "Active";
+               else if ((i == pending_idx) && pending_valid)
+                       str = "Pending";
+               else
+                       str = "";
+
+               cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
+                               "%-8s", str);
+
+               cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
+                               "%-6u", options[i].pmd);
+
+               for (j = 0; j < ICE_MAX_PORT_PER_PCI_DEV; ++j) {
+                       speed = options[i + j * ICE_AQC_PORT_OPT_MAX].max_lane_speed;
+                       str = ice_devlink_port_opt_speed_str(speed);
+                       cnt += snprintf(&desc[cnt], ICE_PORT_OPT_DESC_LEN - cnt,
+                                       "%3s ", str);
+               }
+
+               dev_dbg(dev, "%s\n", desc);
+       }
+
+err:
+       kfree(options);
+}
+
+/**
+ * ice_devlink_aq_set_port_option - Send set port option admin queue command
+ * @pf: the PF to print split port options
+ * @option_idx: selected port option
+ * @extack: extended netdev ack structure
+ *
+ * Sends set port option admin queue command with selected port option and
+ * calls NVM write activate.
+ */
+static int
+ice_devlink_aq_set_port_option(struct ice_pf *pf, u8 option_idx,
+                              struct netlink_ext_ack *extack)
+{
+       struct device *dev = ice_pf_to_dev(pf);
+       int status;
+
+       status = ice_aq_set_port_option(&pf->hw, 0, true, option_idx);
+       if (status) {
+               dev_dbg(dev, "ice_aq_set_port_option, err %d aq_err %d\n",
+                       status, pf->hw.adminq.sq_last_status);
+               NL_SET_ERR_MSG_MOD(extack, "Port split request failed");
+               return -EIO;
+       }
+
+       status = ice_acquire_nvm(&pf->hw, ICE_RES_WRITE);
+       if (status) {
+               dev_dbg(dev, "ice_acquire_nvm failed, err %d aq_err %d\n",
+                       status, pf->hw.adminq.sq_last_status);
+               NL_SET_ERR_MSG_MOD(extack, "Failed to acquire NVM semaphore");
+               return -EIO;
+       }
+
+       status = ice_nvm_write_activate(&pf->hw, ICE_AQC_NVM_ACTIV_REQ_EMPR, NULL);
+       if (status) {
+               dev_dbg(dev, "ice_nvm_write_activate failed, err %d aq_err %d\n",
+                       status, pf->hw.adminq.sq_last_status);
+               NL_SET_ERR_MSG_MOD(extack, "Port split request failed to save data");
+               ice_release_nvm(&pf->hw);
+               return -EIO;
+       }
+
+       ice_release_nvm(&pf->hw);
+
+       NL_SET_ERR_MSG_MOD(extack, "Reboot required to finish port split");
+       return 0;
+}
+
+/**
+ * ice_devlink_port_split - .port_split devlink handler
+ * @devlink: devlink instance structure
+ * @port: devlink port structure
+ * @count: number of ports to split to
+ * @extack: extended netdev ack structure
+ *
+ * Callback for the devlink .port_split operation.
+ *
+ * Unfortunately, the devlink expression of available options is limited
+ * to just a number, so search for an FW port option which supports
+ * the specified number. As there could be multiple FW port options with
+ * the same port split count, allow switching between them. When the same
+ * port split count request is issued again, switch to the next FW port
+ * option with the same port split count.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_split(struct devlink *devlink, struct devlink_port *port,
+                      unsigned int count, struct netlink_ext_ack *extack)
+{
+       struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
+       u8 i, j, active_idx, pending_idx, new_option;
+       struct ice_pf *pf = devlink_priv(devlink);
+       u8 option_count = ICE_AQC_PORT_OPT_MAX;
+       struct device *dev = ice_pf_to_dev(pf);
+       bool active_valid, pending_valid;
+       int status;
+
+       status = ice_aq_get_port_options(&pf->hw, options, &option_count,
+                                        0, true, &active_idx, &active_valid,
+                                        &pending_idx, &pending_valid);
+       if (status) {
+               dev_dbg(dev, "Couldn't read port split options, err = %d\n",
+                       status);
+               NL_SET_ERR_MSG_MOD(extack, "Failed to get available port split options");
+               return -EIO;
+       }
+
+       new_option = ICE_AQC_PORT_OPT_MAX;
+       active_idx = pending_valid ? pending_idx : active_idx;
+       for (i = 1; i <= option_count; i++) {
+               /* In order to allow switching between FW port options with
+                * the same port split count, search for a new option starting
+                * from the active/pending option (with array wrap around).
+                */
+               j = (active_idx + i) % option_count;
+
+               if (count == options[j].pmd) {
+                       new_option = j;
+                       break;
+               }
+       }
+
+       if (new_option == active_idx) {
+               dev_dbg(dev, "request to split: count: %u is already set and there are no other options\n",
+                       count);
+               NL_SET_ERR_MSG_MOD(extack, "Requested split count is already set");
+               ice_devlink_port_options_print(pf);
+               return -EINVAL;
+       }
+
+       if (new_option == ICE_AQC_PORT_OPT_MAX) {
+               dev_dbg(dev, "request to split: count: %u not found\n", count);
+               NL_SET_ERR_MSG_MOD(extack, "Port split requested unsupported port config");
+               ice_devlink_port_options_print(pf);
+               return -EINVAL;
+       }
+
+       status = ice_devlink_aq_set_port_option(pf, new_option, extack);
+       if (status)
+               return status;
+
+       ice_devlink_port_options_print(pf);
+
+       return 0;
+}
+
+/**
+ * ice_devlink_port_unsplit - .port_unsplit devlink handler
+ * @devlink: devlink instance structure
+ * @port: devlink port structure
+ * @extack: extended netdev ack structure
+ *
+ * Callback for the devlink .port_unsplit operation.
+ * Calls ice_devlink_port_split with split count set to 1.
+ * There could be no FW option available with split count 1.
+ *
+ * Return: zero on success or an error code on failure.
+ */
+static int
+ice_devlink_port_unsplit(struct devlink *devlink, struct devlink_port *port,
+                        struct netlink_ext_ack *extack)
+{
+       return ice_devlink_port_split(devlink, port, 1, extack);
+}
+
 static const struct devlink_ops ice_devlink_ops = {
        .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
        .reload_actions = BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
        /* The ice driver currently does not support driver reinit */
        .reload_down = ice_devlink_reload_empr_start,
        .reload_up = ice_devlink_reload_empr_finish,
+       .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,
@@ -694,6 +943,39 @@ void ice_devlink_unregister_params(struct ice_pf *pf)
                                  ARRAY_SIZE(ice_devlink_params));
 }
 
+/**
+ * ice_devlink_set_port_split_options - Set port split options
+ * @pf: the PF to set port split options
+ * @attrs: devlink attributes
+ *
+ * Sets devlink port split options based on available FW port options
+ */
+static void
+ice_devlink_set_port_split_options(struct ice_pf *pf,
+                                  struct devlink_port_attrs *attrs)
+{
+       struct ice_aqc_get_port_options_elem options[ICE_AQC_PORT_OPT_MAX];
+       u8 i, active_idx, pending_idx, option_count = ICE_AQC_PORT_OPT_MAX;
+       bool active_valid, pending_valid;
+       int status;
+
+       status = ice_aq_get_port_options(&pf->hw, options, &option_count,
+                                        0, true, &active_idx, &active_valid,
+                                        &pending_idx, &pending_valid);
+       if (status) {
+               dev_dbg(ice_pf_to_dev(pf), "Couldn't read port split options, err = %d\n",
+                       status);
+               return;
+       }
+
+       /* find the biggest available port split count */
+       for (i = 0; i < option_count; i++)
+               attrs->lanes = max_t(int, attrs->lanes, options[i].pmd);
+
+       attrs->splittable = attrs->lanes ? 1 : 0;
+       ice_active_port_option = active_idx;
+}
+
 /**
  * ice_devlink_create_pf_port - Create a devlink port for this PF
  * @pf: the PF to create a devlink port for
@@ -722,6 +1004,12 @@ int ice_devlink_create_pf_port(struct ice_pf *pf)
        attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL;
        attrs.phys.port_number = pf->hw.bus.func;
 
+       /* As FW supports only port split options for whole device,
+        * set port split options only for first PF.
+        */
+       if (pf->hw.pf_id == 0)
+               ice_devlink_set_port_split_options(pf, &attrs);
+
        ice_devlink_set_switch_id(pf, &attrs.switch_id);
 
        devlink_port_attrs_set(devlink_port, &attrs);
index a6fff8e..b7be84b 100644 (file)
@@ -136,6 +136,11 @@ static const struct ice_stats ice_gstrings_pf_stats[] = {
        ICE_PF_STAT("mac_remote_faults.nic", stats.mac_remote_faults),
        ICE_PF_STAT("fdir_sb_match.nic", stats.fd_sb_match),
        ICE_PF_STAT("fdir_sb_status.nic", stats.fd_sb_status),
+       ICE_PF_STAT("tx_hwtstamp_skipped", ptp.tx_hwtstamp_skipped),
+       ICE_PF_STAT("tx_hwtstamp_timeouts", ptp.tx_hwtstamp_timeouts),
+       ICE_PF_STAT("tx_hwtstamp_flushed", ptp.tx_hwtstamp_flushed),
+       ICE_PF_STAT("tx_hwtstamp_discarded", ptp.tx_hwtstamp_discarded),
+       ICE_PF_STAT("late_cached_phc_updates", ptp.late_cached_phc_updates),
 };
 
 static const u32 ice_regs_dump_list[] = {
@@ -1284,10 +1289,7 @@ static int ice_set_priv_flags(struct net_device *netdev, u32 flags)
        }
        if (test_bit(ICE_FLAG_LEGACY_RX, change_flags)) {
                /* down and up VSI so that changes of Rx cfg are reflected. */
-               if (!test_and_set_bit(ICE_VSI_DOWN, vsi->state)) {
-                       ice_down(vsi);
-                       ice_up(vsi);
-               }
+               ice_down_up(vsi);
        }
        /* don't allow modification of this flag when a single VF is in
         * promiscuous mode because it's not supported
@@ -1468,20 +1470,22 @@ ice_get_ethtool_stats(struct net_device *netdev,
 
 /**
  * ice_mask_min_supported_speeds
+ * @hw: pointer to the HW structure
  * @phy_types_high: PHY type high
  * @phy_types_low: PHY type low to apply minimum supported speeds mask
  *
  * Apply minimum supported speeds mask to PHY type low. These are the speeds
  * for ethtool supported link mode.
  */
-static
-void ice_mask_min_supported_speeds(u64 phy_types_high, u64 *phy_types_low)
+static void
+ice_mask_min_supported_speeds(struct ice_hw *hw,
+                             u64 phy_types_high, u64 *phy_types_low)
 {
        /* if QSFP connection with 100G speed, minimum supported speed is 25G */
        if (*phy_types_low & ICE_PHY_TYPE_LOW_MASK_100G ||
            phy_types_high & ICE_PHY_TYPE_HIGH_MASK_100G)
                *phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_25G;
-       else
+       else if (!ice_is_100m_speed_supported(hw))
                *phy_types_low &= ~ICE_PHY_TYPE_LOW_MASK_MIN_1G;
 }
 
@@ -1531,7 +1535,8 @@ ice_phy_type_to_ethtool(struct net_device *netdev,
                phy_types_low = le64_to_cpu(pf->nvm_phy_type_lo);
                phy_types_high = le64_to_cpu(pf->nvm_phy_type_hi);
 
-               ice_mask_min_supported_speeds(phy_types_high, &phy_types_low);
+               ice_mask_min_supported_speeds(&pf->hw, phy_types_high,
+                                             &phy_types_low);
                /* determine advertised modes based on link override only
                 * if it's supported and if the FW doesn't abstract the
                 * driver from having to account for link overrides
@@ -2826,6 +2831,7 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
                tx_rings[i].count = new_tx_cnt;
                tx_rings[i].desc = NULL;
                tx_rings[i].tx_buf = NULL;
+               tx_rings[i].tx_tstamps = &pf->ptp.port.tx;
                err = ice_setup_tx_ring(&tx_rings[i]);
                if (err) {
                        while (i--)
@@ -2884,6 +2890,7 @@ process_rx:
                /* clone ring and setup updated count */
                rx_rings[i] = *vsi->rx_rings[i];
                rx_rings[i].count = new_rx_cnt;
+               rx_rings[i].cached_phctime = pf->ptp.cached_phc_time;
                rx_rings[i].desc = NULL;
                rx_rings[i].rx_buf = NULL;
                /* this is to allow wr32 to have something to write to
index c9f7393..ee5b369 100644 (file)
@@ -61,13 +61,13 @@ static void ice_lag_set_backup(struct ice_lag *lag)
  */
 static void ice_display_lag_info(struct ice_lag *lag)
 {
-       const char *name, *peer, *upper, *role, *bonded, *master;
+       const char *name, *peer, *upper, *role, *bonded, *primary;
        struct device *dev = &lag->pf->pdev->dev;
 
        name = lag->netdev ? netdev_name(lag->netdev) : "unset";
        peer = lag->peer_netdev ? netdev_name(lag->peer_netdev) : "unset";
        upper = lag->upper_netdev ? netdev_name(lag->upper_netdev) : "unset";
-       master = lag->master ? "TRUE" : "FALSE";
+       primary = lag->primary ? "TRUE" : "FALSE";
        bonded = lag->bonded ? "BONDED" : "UNBONDED";
 
        switch (lag->role) {
@@ -87,8 +87,8 @@ static void ice_display_lag_info(struct ice_lag *lag)
                role = "ERROR";
        }
 
-       dev_dbg(dev, "%s %s, peer:%s, upper:%s, role:%s, master:%s\n", name,
-               bonded, peer, upper, role, master);
+       dev_dbg(dev, "%s %s, peer:%s, upper:%s, role:%s, primary:%s\n", name,
+               bonded, peer, upper, role, primary);
 }
 
 /**
@@ -119,7 +119,7 @@ static void ice_lag_info_event(struct ice_lag *lag, void *ptr)
        }
 
        if (strcmp(bonding_info->slave.slave_name, lag_netdev_name)) {
-               netdev_dbg(lag->netdev, "Bonding event recv, but slave info not for us\n");
+               netdev_dbg(lag->netdev, "Bonding event recv, but secondary info not for us\n");
                goto lag_out;
        }
 
@@ -164,8 +164,8 @@ ice_lag_link(struct ice_lag *lag, struct netdev_notifier_changeupper_info *info)
        lag->bonded = true;
        lag->role = ICE_LAG_UNSET;
 
-       /* if this is the first element in an LAG mark as master */
-       lag->master = !!(peers == 1);
+       /* if this is the first element in an LAG mark as primary */
+       lag->primary = !!(peers == 1);
 }
 
 /**
@@ -264,7 +264,7 @@ static void ice_lag_changeupper_event(struct ice_lag *lag, void *ptr)
        netdev_dbg(netdev, "bonding %s\n", info->linking ? "LINK" : "UNLINK");
 
        if (!netif_is_lag_master(info->upper_dev)) {
-               netdev_dbg(netdev, "changeupper rcvd, but not master. bail\n");
+               netdev_dbg(netdev, "changeupper rcvd, but not primary. bail\n");
                return;
        }
 
index c2e3688..51b5cf4 100644 (file)
@@ -24,7 +24,7 @@ struct ice_lag {
        struct net_device *upper_netdev; /* upper bonding netdev */
        struct notifier_block notif_block;
        u8 bonded:1; /* currently bonded */
-       u8 master:1; /* this is a master */
+       u8 primary:1; /* this is primary */
        u8 handler:1; /* did we register a rx_netdev_handler */
        /* each thing blocking bonding will increment this value by one.
         * If this value is zero, then bonding is allowed.
index 0c4ec92..d126f4c 100644 (file)
@@ -1522,6 +1522,7 @@ static int ice_vsi_alloc_rings(struct ice_vsi *vsi)
                ring->netdev = vsi->netdev;
                ring->dev = dev;
                ring->count = vsi->num_rx_desc;
+               ring->cached_phctime = pf->ptp.cached_phc_time;
                WRITE_ONCE(vsi->rx_rings[i], ring);
        }
 
@@ -1561,6 +1562,22 @@ void ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena)
        kfree(lut);
 }
 
+/**
+ * ice_vsi_cfg_crc_strip - Configure CRC stripping for a VSI
+ * @vsi: VSI to be configured
+ * @disable: set to true to have FCS / CRC in the frame data
+ */
+void ice_vsi_cfg_crc_strip(struct ice_vsi *vsi, bool disable)
+{
+       int i;
+
+       ice_for_each_rxq(vsi, i)
+               if (disable)
+                       vsi->rx_rings[i]->flags |= ICE_RX_FLAGS_CRC_STRIP_DIS;
+               else
+                       vsi->rx_rings[i]->flags &= ~ICE_RX_FLAGS_CRC_STRIP_DIS;
+}
+
 /**
  * ice_vsi_cfg_rss_lut_key - Configure RSS params for a VSI
  * @vsi: VSI to be configured
@@ -3276,6 +3293,12 @@ int ice_vsi_rebuild(struct ice_vsi *vsi, bool init_vsi)
                         */
                        if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
                                ice_vsi_cfg_rss_lut_key(vsi);
+
+               /* disable or enable CRC stripping */
+               if (vsi->netdev)
+                       ice_vsi_cfg_crc_strip(vsi, !!(vsi->netdev->features &
+                                             NETIF_F_RXFCS));
+
                break;
        case ICE_VSI_VF:
                ret = ice_vsi_alloc_q_vectors(vsi);
index 8712b1d..ec4bf0c 100644 (file)
@@ -89,6 +89,8 @@ void ice_vsi_free_tx_rings(struct ice_vsi *vsi);
 
 void ice_vsi_manage_rss_lut(struct ice_vsi *vsi, bool ena);
 
+void ice_vsi_cfg_crc_strip(struct ice_vsi *vsi, bool disable);
+
 void ice_update_tx_ring_stats(struct ice_tx_ring *ring, u64 pkts, u64 bytes);
 
 void ice_update_rx_ring_stats(struct ice_rx_ring *ring, u64 pkts, u64 bytes);
index 173fe6c..14edf76 100644 (file)
@@ -3385,6 +3385,11 @@ static void ice_set_netdev_features(struct net_device *netdev)
        if (is_dvm_ena)
                netdev->hw_features |= NETIF_F_HW_VLAN_STAG_RX |
                        NETIF_F_HW_VLAN_STAG_TX;
+
+       /* Leave CRC / FCS stripping enabled by default, but allow the value to
+        * be changed at runtime
+        */
+       netdev->hw_features |= NETIF_F_RXFCS;
 }
 
 /**
@@ -4676,8 +4681,6 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
                ice_set_safe_mode_caps(hw);
        }
 
-       hw->ucast_shared = true;
-
        err = ice_init_pf(pf);
        if (err) {
                dev_err(dev, "ice_init_pf failed: %d\n", err);
@@ -5736,6 +5739,9 @@ ice_fdb_del(struct ndmsg *ndm, __always_unused struct nlattr *tb[],
                                         NETIF_F_HW_VLAN_STAG_RX | \
                                         NETIF_F_HW_VLAN_STAG_TX)
 
+#define NETIF_VLAN_STRIPPING_FEATURES  (NETIF_F_HW_VLAN_CTAG_RX | \
+                                        NETIF_F_HW_VLAN_STAG_RX)
+
 #define NETIF_VLAN_FILTERING_FEATURES  (NETIF_F_HW_VLAN_CTAG_FILTER | \
                                         NETIF_F_HW_VLAN_STAG_FILTER)
 
@@ -5822,6 +5828,14 @@ ice_fix_features(struct net_device *netdev, netdev_features_t features)
                              NETIF_F_HW_VLAN_STAG_TX);
        }
 
+       if (!(netdev->features & NETIF_F_RXFCS) &&
+           (features & NETIF_F_RXFCS) &&
+           (features & NETIF_VLAN_STRIPPING_FEATURES) &&
+           !ice_vsi_has_non_zero_vlans(np->vsi)) {
+               netdev_warn(netdev, "Disabling VLAN stripping as FCS/CRC stripping is also disabled and there is no VLAN configured\n");
+               features &= ~NETIF_VLAN_STRIPPING_FEATURES;
+       }
+
        return features;
 }
 
@@ -5915,6 +5929,13 @@ ice_set_vlan_features(struct net_device *netdev, netdev_features_t features)
        current_vlan_features = netdev->features & NETIF_VLAN_OFFLOAD_FEATURES;
        requested_vlan_features = features & NETIF_VLAN_OFFLOAD_FEATURES;
        if (current_vlan_features ^ requested_vlan_features) {
+               if ((features & NETIF_F_RXFCS) &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+                       dev_err(ice_pf_to_dev(vsi->back),
+                               "To enable VLAN stripping, you must first enable FCS/CRC stripping\n");
+                       return -EIO;
+               }
+
                err = ice_set_vlan_offload_features(vsi, features);
                if (err)
                        return err;
@@ -5996,6 +6017,23 @@ ice_set_features(struct net_device *netdev, netdev_features_t features)
        if (ret)
                return ret;
 
+       /* Turn on receive of FCS aka CRC, and after setting this
+        * flag the packet data will have the 4 byte CRC appended
+        */
+       if (changed & NETIF_F_RXFCS) {
+               if ((features & NETIF_F_RXFCS) &&
+                   (features & NETIF_VLAN_STRIPPING_FEATURES)) {
+                       dev_err(ice_pf_to_dev(vsi->back),
+                               "To disable FCS/CRC stripping, you must first disable VLAN stripping\n");
+                       return -EIO;
+               }
+
+               ice_vsi_cfg_crc_strip(vsi, !!(features & NETIF_F_RXFCS));
+               ret = ice_down_up(vsi);
+               if (ret)
+                       return ret;
+       }
+
        if (changed & NETIF_F_NTUPLE) {
                bool ena = !!(features & NETIF_F_NTUPLE);
 
@@ -6699,6 +6737,31 @@ int ice_down(struct ice_vsi *vsi)
        return 0;
 }
 
+/**
+ * ice_down_up - shutdown the VSI connection and bring it up
+ * @vsi: the VSI to be reconnected
+ */
+int ice_down_up(struct ice_vsi *vsi)
+{
+       int ret;
+
+       /* if DOWN already set, nothing to do */
+       if (test_and_set_bit(ICE_VSI_DOWN, vsi->state))
+               return 0;
+
+       ret = ice_down(vsi);
+       if (ret)
+               return ret;
+
+       ret = ice_up(vsi);
+       if (ret) {
+               netdev_err(vsi->netdev, "reallocating resources failed during netdev features change, may need to reload driver\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 /**
  * ice_vsi_setup_tx_rings - Allocate VSI Tx queue resources
  * @vsi: VSI having resources allocated
index 13cdb5e..c262dc8 100644 (file)
@@ -1114,14 +1114,18 @@ int ice_nvm_validate_checksum(struct ice_hw *hw)
  * Update the control word with the required banks' validity bits
  * and dumps the Shadow RAM to flash (0x0707)
  *
- * cmd_flags controls which banks to activate, and the preservation level to
- * use when activating the NVM bank.
+ * cmd_flags controls which banks to activate, the preservation level to use
+ * when activating the NVM bank, and whether an EMP reset is required for
+ * activation.
+ *
+ * Note that the 16bit cmd_flags value is split between two separate 1 byte
+ * flag values in the descriptor.
  *
  * On successful return of the firmware command, the response_flags variable
  * is updated with the flags reported by firmware indicating certain status,
  * such as whether EMP reset is enabled.
  */
-int ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags, u8 *response_flags)
+int ice_nvm_write_activate(struct ice_hw *hw, u16 cmd_flags, u8 *response_flags)
 {
        struct ice_aqc_nvm *cmd;
        struct ice_aq_desc desc;
@@ -1130,7 +1134,8 @@ int ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags, u8 *response_flags)
        cmd = &desc.params.nvm;
        ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write_activate);
 
-       cmd->cmd_flags = cmd_flags;
+       cmd->cmd_flags = (u8)(cmd_flags & 0xFF);
+       cmd->offset_high = (u8)((cmd_flags >> 8) & 0xFF);
 
        err = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
        if (!err && response_flags)
index 856d1ad..774c231 100644 (file)
@@ -34,7 +34,7 @@ ice_aq_update_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
 int
 ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd);
 int ice_nvm_validate_checksum(struct ice_hw *hw);
-int ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags, u8 *response_flags);
+int ice_nvm_write_activate(struct ice_hw *hw, u16 cmd_flags, u8 *response_flags);
 int ice_aq_nvm_update_empr(struct ice_hw *hw);
 int
 ice_nvm_set_pkg_data(struct ice_hw *hw, bool del_pkg_data_flag, u8 *data,
index 72b6631..5a2fd4d 100644 (file)
@@ -490,56 +490,6 @@ ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
        return ((u64)hi << 32) | lo;
 }
 
-/**
- * ice_ptp_update_cached_phctime - Update the cached PHC time values
- * @pf: Board specific private structure
- *
- * This function updates the system time values which are cached in the PF
- * structure and the Rx rings.
- *
- * This function must be called periodically to ensure that the cached value
- * is never more than 2 seconds old. It must also be called whenever the PHC
- * time has been changed.
- *
- * Return:
- * * 0 - OK, successfully updated
- * * -EAGAIN - PF was busy, need to reschedule the update
- */
-static int ice_ptp_update_cached_phctime(struct ice_pf *pf)
-{
-       u64 systime;
-       int i;
-
-       if (test_and_set_bit(ICE_CFG_BUSY, pf->state))
-               return -EAGAIN;
-
-       /* Read the current PHC time */
-       systime = ice_ptp_read_src_clk_reg(pf, NULL);
-
-       /* Update the cached PHC time stored in the PF structure */
-       WRITE_ONCE(pf->ptp.cached_phc_time, systime);
-
-       ice_for_each_vsi(pf, i) {
-               struct ice_vsi *vsi = pf->vsi[i];
-               int j;
-
-               if (!vsi)
-                       continue;
-
-               if (vsi->type != ICE_VSI_PF)
-                       continue;
-
-               ice_for_each_rxq(vsi, j) {
-                       if (!vsi->rx_rings[j])
-                               continue;
-                       WRITE_ONCE(vsi->rx_rings[j]->cached_phctime, systime);
-               }
-       }
-       clear_bit(ICE_CFG_BUSY, pf->state);
-
-       return 0;
-}
-
 /**
  * ice_ptp_extend_32b_ts - Convert a 32b nanoseconds timestamp to 64b
  * @cached_phc_time: recently cached copy of PHC time
@@ -636,94 +586,486 @@ static u64 ice_ptp_extend_32b_ts(u64 cached_phc_time, u32 in_tstamp)
 static u64 ice_ptp_extend_40b_ts(struct ice_pf *pf, u64 in_tstamp)
 {
        const u64 mask = GENMASK_ULL(31, 0);
+       unsigned long discard_time;
+
+       /* Discard the hardware timestamp if the cached PHC time is too old */
+       discard_time = pf->ptp.cached_phc_jiffies + msecs_to_jiffies(2000);
+       if (time_is_before_jiffies(discard_time)) {
+               pf->ptp.tx_hwtstamp_discarded++;
+               return 0;
+       }
 
        return ice_ptp_extend_32b_ts(pf->ptp.cached_phc_time,
                                     (in_tstamp >> 8) & mask);
 }
 
 /**
- * ice_ptp_read_time - Read the time from the device
- * @pf: Board private structure
- * @ts: timespec structure to hold the current time value
- * @sts: Optional parameter for holding a pair of system timestamps from
- *       the system clock. Will be ignored if NULL is given.
+ * ice_ptp_tx_tstamp_work - Process Tx timestamps for a port
+ * @work: pointer to the kthread_work struct
  *
- * This function reads the source clock registers and stores them in a timespec.
- * However, since the registers are 64 bits of nanoseconds, we must convert the
- * result to a timespec before we can return.
+ * Process timestamps captured by the PHY associated with this port. To do
+ * this, loop over each index with a waiting skb.
+ *
+ * If a given index has a valid timestamp, perform the following steps:
+ *
+ * 1) copy the timestamp out of the PHY register
+ * 4) clear the timestamp valid bit in the PHY register
+ * 5) unlock the index by clearing the associated in_use bit.
+ * 2) extend the 40b timestamp value to get a 64bit timestamp
+ * 3) send that timestamp to the stack
+ *
+ * After looping, if we still have waiting SKBs, then re-queue the work. 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 only take the tracking lock when clearing the bit and when
+ * checking if we need to re-queue this task. The only place where bits can be
+ * set is the hard xmit routine where an SKB has a request flag set. The only
+ * places where we clear bits are this work function, or the periodic cleanup
+ * thread. If the cleanup thread clears a bit we're processing we catch it
+ * when we lock to clear the bit and then grab the SKB pointer. If a Tx thread
+ * starts a new timestamp, we might not begin processing it right away but we
+ * will notice it at the end when we re-queue the work item. If a Tx thread
+ * starts a new timestamp just after this function exits without re-queuing,
+ * the interrupt when the timestamp finishes should trigger. Avoiding holding
+ * the lock for the entire function is important in order to ensure that Tx
+ * threads do not get blocked while waiting for the lock.
  */
-static void
-ice_ptp_read_time(struct ice_pf *pf, struct timespec64 *ts,
-                 struct ptp_system_timestamp *sts)
+static void ice_ptp_tx_tstamp_work(struct kthread_work *work)
 {
-       u64 time_ns = ice_ptp_read_src_clk_reg(pf, sts);
+       struct ice_ptp_port *ptp_port;
+       struct ice_ptp_tx *tx;
+       struct ice_pf *pf;
+       struct ice_hw *hw;
+       u8 idx;
 
-       *ts = ns_to_timespec64(time_ns);
+       tx = container_of(work, struct ice_ptp_tx, work);
+       if (!tx->init)
+               return;
+
+       ptp_port = container_of(tx, struct ice_ptp_port, tx);
+       pf = ptp_port_to_pf(ptp_port);
+       hw = &pf->hw;
+
+       for_each_set_bit(idx, tx->in_use, tx->len) {
+               struct skb_shared_hwtstamps shhwtstamps = {};
+               u8 phy_idx = idx + tx->quad_offset;
+               u64 raw_tstamp, tstamp;
+               struct sk_buff *skb;
+               int err;
+
+               ice_trace(tx_tstamp_fw_req, tx->tstamps[idx].skb, idx);
+
+               err = ice_read_phy_tstamp(hw, tx->quad, phy_idx,
+                                         &raw_tstamp);
+               if (err)
+                       continue;
+
+               ice_trace(tx_tstamp_fw_done, tx->tstamps[idx].skb, idx);
+
+               /* Check if the timestamp is invalid or stale */
+               if (!(raw_tstamp & ICE_PTP_TS_VALID) ||
+                   raw_tstamp == tx->tstamps[idx].cached_tstamp)
+                       continue;
+
+               /* The timestamp is valid, so we'll go ahead and clear this
+                * index and then send the timestamp up to the stack.
+                */
+               spin_lock(&tx->lock);
+               tx->tstamps[idx].cached_tstamp = raw_tstamp;
+               clear_bit(idx, tx->in_use);
+               skb = tx->tstamps[idx].skb;
+               tx->tstamps[idx].skb = NULL;
+               spin_unlock(&tx->lock);
+
+               /* it's (unlikely but) possible we raced with the cleanup
+                * thread for discarding old timestamp requests.
+                */
+               if (!skb)
+                       continue;
+
+               /* Extend the timestamp using cached PHC time */
+               tstamp = ice_ptp_extend_40b_ts(pf, raw_tstamp);
+               if (tstamp) {
+                       shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
+                       ice_trace(tx_tstamp_complete, skb, idx);
+               }
+
+               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.
+        */
+       spin_lock(&tx->lock);
+       if (!bitmap_empty(tx->in_use, tx->len))
+               kthread_queue_work(pf->ptp.kworker, &tx->work);
+       spin_unlock(&tx->lock);
 }
 
 /**
- * ice_ptp_write_init - Set PHC time to provided value
- * @pf: Board private structure
- * @ts: timespec structure that holds the new time value
+ * ice_ptp_alloc_tx_tracker - Initialize tracking for Tx timestamps
+ * @tx: Tx tracking structure to initialize
  *
- * Set the PHC time to the specified time provided in the timespec.
+ * Assumes that the length has already been initialized. Do not call directly,
+ * use the ice_ptp_init_tx_e822 or ice_ptp_init_tx_e810 instead.
  */
-static int ice_ptp_write_init(struct ice_pf *pf, struct timespec64 *ts)
+static int
+ice_ptp_alloc_tx_tracker(struct ice_ptp_tx *tx)
 {
-       u64 ns = timespec64_to_ns(ts);
-       struct ice_hw *hw = &pf->hw;
+       tx->tstamps = kcalloc(tx->len, sizeof(*tx->tstamps), GFP_KERNEL);
+       if (!tx->tstamps)
+               return -ENOMEM;
 
-       return ice_ptp_init_time(hw, ns);
+       tx->in_use = bitmap_zalloc(tx->len, GFP_KERNEL);
+       if (!tx->in_use) {
+               kfree(tx->tstamps);
+               tx->tstamps = NULL;
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&tx->lock);
+       kthread_init_work(&tx->work, ice_ptp_tx_tstamp_work);
+
+       tx->init = 1;
+
+       return 0;
 }
 
 /**
- * ice_ptp_write_adj - Adjust PHC clock time atomically
+ * ice_ptp_flush_tx_tracker - Flush any remaining timestamps from the tracker
  * @pf: Board private structure
- * @adj: Adjustment in nanoseconds
- *
- * Perform an atomic adjustment of the PHC time by the specified number of
- * nanoseconds.
+ * @tx: the tracker to flush
  */
-static int ice_ptp_write_adj(struct ice_pf *pf, s32 adj)
+static void
+ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
 {
-       struct ice_hw *hw = &pf->hw;
+       u8 idx;
 
-       return ice_ptp_adj_clock(hw, adj);
+       for (idx = 0; idx < tx->len; idx++) {
+               u8 phy_idx = idx + tx->quad_offset;
+
+               spin_lock(&tx->lock);
+               if (tx->tstamps[idx].skb) {
+                       dev_kfree_skb_any(tx->tstamps[idx].skb);
+                       tx->tstamps[idx].skb = NULL;
+                       pf->ptp.tx_hwtstamp_flushed++;
+               }
+               clear_bit(idx, tx->in_use);
+               spin_unlock(&tx->lock);
+
+               /* Clear any potential residual timestamp in the PHY block */
+               if (!pf->hw.reset_ongoing)
+                       ice_clear_phy_tstamp(&pf->hw, tx->quad, phy_idx);
+       }
 }
 
 /**
- * ice_base_incval - Get base timer increment value
+ * ice_ptp_release_tx_tracker - Release allocated memory for Tx tracker
  * @pf: Board private structure
+ * @tx: Tx tracking structure to release
  *
- * Look up the base timer increment value for this device. The base increment
- * value is used to define the nominal clock tick rate. This increment value
- * is programmed during device initialization. It is also used as the basis
- * for calculating adjustments using scaled_ppm.
+ * Free memory associated with the Tx timestamp tracker.
  */
-static u64 ice_base_incval(struct ice_pf *pf)
+static void
+ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
 {
-       struct ice_hw *hw = &pf->hw;
-       u64 incval;
+       tx->init = 0;
 
-       if (ice_is_e810(hw))
-               incval = ICE_PTP_NOMINAL_INCVAL_E810;
-       else if (ice_e822_time_ref(hw) < NUM_ICE_TIME_REF_FREQ)
-               incval = ice_e822_nominal_incval(ice_e822_time_ref(hw));
-       else
-               incval = UNKNOWN_INCVAL_E822;
+       kthread_cancel_work_sync(&tx->work);
 
-       dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n",
-               incval);
+       ice_ptp_flush_tx_tracker(pf, tx);
 
-       return incval;
+       kfree(tx->tstamps);
+       tx->tstamps = NULL;
+
+       bitmap_free(tx->in_use);
+       tx->in_use = NULL;
+
+       tx->len = 0;
 }
 
 /**
- * ice_ptp_reset_ts_memory_quad - Reset timestamp memory for one quad
- * @pf: The PF private data structure
- * @quad: The quad (0-4)
- */
-static void ice_ptp_reset_ts_memory_quad(struct ice_pf *pf, int quad)
+ * ice_ptp_init_tx_e822 - Initialize tracking for Tx timestamps
+ * @pf: Board private structure
+ * @tx: the Tx tracking structure to initialize
+ * @port: the port this structure tracks
+ *
+ * Initialize the Tx timestamp tracker for this port. For generic MAC devices,
+ * the timestamp block is shared for all ports in the same quad. To avoid
+ * ports using the same timestamp index, logically break the block of
+ * registers into chunks based on the port number.
+ */
+static int
+ice_ptp_init_tx_e822(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
+{
+       tx->quad = port / ICE_PORTS_PER_QUAD;
+       tx->quad_offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT;
+       tx->len = INDEX_PER_PORT;
+
+       return ice_ptp_alloc_tx_tracker(tx);
+}
+
+/**
+ * ice_ptp_init_tx_e810 - Initialize tracking for Tx timestamps
+ * @pf: Board private structure
+ * @tx: the Tx tracking structure to initialize
+ *
+ * Initialize the Tx timestamp tracker for this PF. For E810 devices, each
+ * port has its own block of timestamps, independent of the other ports.
+ */
+static int
+ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx)
+{
+       tx->quad = pf->hw.port_info->lport;
+       tx->quad_offset = 0;
+       tx->len = INDEX_PER_QUAD;
+
+       return ice_ptp_alloc_tx_tracker(tx);
+}
+
+/**
+ * ice_ptp_tx_tstamp_cleanup - Cleanup old timestamp requests that got dropped
+ * @pf: pointer to the PF struct
+ * @tx: PTP Tx tracker to clean up
+ *
+ * Loop through the Tx timestamp requests and see if any of them have been
+ * waiting for a long time. Discard any SKBs that have been waiting for more
+ * than 2 seconds. This is long enough to be reasonably sure that the
+ * timestamp will never be captured. This might happen if the packet gets
+ * discarded before it reaches the PHY timestamping block.
+ */
+static void ice_ptp_tx_tstamp_cleanup(struct ice_pf *pf, struct ice_ptp_tx *tx)
+{
+       struct ice_hw *hw = &pf->hw;
+       u8 idx;
+
+       if (!tx->init)
+               return;
+
+       for_each_set_bit(idx, tx->in_use, tx->len) {
+               struct sk_buff *skb;
+               u64 raw_tstamp;
+
+               /* Check if this SKB has been waiting for too long */
+               if (time_is_after_jiffies(tx->tstamps[idx].start + 2 * HZ))
+                       continue;
+
+               /* Read tstamp to be able to use this register again */
+               ice_read_phy_tstamp(hw, tx->quad, idx + tx->quad_offset,
+                                   &raw_tstamp);
+
+               spin_lock(&tx->lock);
+               skb = tx->tstamps[idx].skb;
+               tx->tstamps[idx].skb = NULL;
+               clear_bit(idx, tx->in_use);
+               spin_unlock(&tx->lock);
+
+               /* Count the number of Tx timestamps which have timed out */
+               pf->ptp.tx_hwtstamp_timeouts++;
+
+               /* Free the SKB after we've cleared the bit */
+               dev_kfree_skb_any(skb);
+       }
+}
+
+/**
+ * ice_ptp_update_cached_phctime - Update the cached PHC time values
+ * @pf: Board specific private structure
+ *
+ * This function updates the system time values which are cached in the PF
+ * structure and the Rx rings.
+ *
+ * This function must be called periodically to ensure that the cached value
+ * is never more than 2 seconds old.
+ *
+ * Note that the cached copy in the PF PTP structure is always updated, even
+ * if we can't update the copy in the Rx rings.
+ *
+ * Return:
+ * * 0 - OK, successfully updated
+ * * -EAGAIN - PF was busy, need to reschedule the update
+ */
+static int ice_ptp_update_cached_phctime(struct ice_pf *pf)
+{
+       struct device *dev = ice_pf_to_dev(pf);
+       unsigned long update_before;
+       u64 systime;
+       int i;
+
+       update_before = pf->ptp.cached_phc_jiffies + msecs_to_jiffies(2000);
+       if (pf->ptp.cached_phc_time &&
+           time_is_before_jiffies(update_before)) {
+               unsigned long time_taken = jiffies - pf->ptp.cached_phc_jiffies;
+
+               dev_warn(dev, "%u msecs passed between update to cached PHC time\n",
+                        jiffies_to_msecs(time_taken));
+               pf->ptp.late_cached_phc_updates++;
+       }
+
+       /* Read the current PHC time */
+       systime = ice_ptp_read_src_clk_reg(pf, NULL);
+
+       /* Update the cached PHC time stored in the PF structure */
+       WRITE_ONCE(pf->ptp.cached_phc_time, systime);
+       WRITE_ONCE(pf->ptp.cached_phc_jiffies, jiffies);
+
+       if (test_and_set_bit(ICE_CFG_BUSY, pf->state))
+               return -EAGAIN;
+
+       ice_for_each_vsi(pf, i) {
+               struct ice_vsi *vsi = pf->vsi[i];
+               int j;
+
+               if (!vsi)
+                       continue;
+
+               if (vsi->type != ICE_VSI_PF)
+                       continue;
+
+               ice_for_each_rxq(vsi, j) {
+                       if (!vsi->rx_rings[j])
+                               continue;
+                       WRITE_ONCE(vsi->rx_rings[j]->cached_phctime, systime);
+               }
+       }
+       clear_bit(ICE_CFG_BUSY, pf->state);
+
+       return 0;
+}
+
+/**
+ * ice_ptp_reset_cached_phctime - Reset cached PHC time after an update
+ * @pf: Board specific private structure
+ *
+ * This function must be called when the cached PHC time is no longer valid,
+ * such as after a time adjustment. It discards any outstanding Tx timestamps,
+ * and updates the cached PHC time for both the PF and Rx rings. If updating
+ * the PHC time cannot be done immediately, a warning message is logged and
+ * the work item is scheduled.
+ *
+ * These steps are required in order to ensure that we do not accidentally
+ * report a timestamp extended by the wrong PHC cached copy. Note that we
+ * do not directly update the cached timestamp here because it is possible
+ * this might produce an error when ICE_CFG_BUSY is set. If this occurred, we
+ * would have to try again. During that time window, timestamps might be
+ * requested and returned with an invalid extension. Thus, on failure to
+ * immediately update the cached PHC time we would need to zero the value
+ * anyways. For this reason, we just zero the value immediately and queue the
+ * update work item.
+ */
+static void ice_ptp_reset_cached_phctime(struct ice_pf *pf)
+{
+       struct device *dev = ice_pf_to_dev(pf);
+       int err;
+
+       /* Update the cached PHC time immediately if possible, otherwise
+        * schedule the work item to execute soon.
+        */
+       err = ice_ptp_update_cached_phctime(pf);
+       if (err) {
+               /* If another thread is updating the Rx rings, we won't
+                * properly reset them here. This could lead to reporting of
+                * invalid timestamps, but there isn't much we can do.
+                */
+               dev_warn(dev, "%s: ICE_CFG_BUSY, unable to immediately update cached PHC time\n",
+                        __func__);
+
+               /* Queue the work item to update the Rx rings when possible */
+               kthread_queue_delayed_work(pf->ptp.kworker, &pf->ptp.work,
+                                          msecs_to_jiffies(10));
+       }
+
+       /* Flush any outstanding Tx timestamps */
+       ice_ptp_flush_tx_tracker(pf, &pf->ptp.port.tx);
+}
+
+/**
+ * ice_ptp_read_time - Read the time from the device
+ * @pf: Board private structure
+ * @ts: timespec structure to hold the current time value
+ * @sts: Optional parameter for holding a pair of system timestamps from
+ *       the system clock. Will be ignored if NULL is given.
+ *
+ * This function reads the source clock registers and stores them in a timespec.
+ * However, since the registers are 64 bits of nanoseconds, we must convert the
+ * result to a timespec before we can return.
+ */
+static void
+ice_ptp_read_time(struct ice_pf *pf, struct timespec64 *ts,
+                 struct ptp_system_timestamp *sts)
+{
+       u64 time_ns = ice_ptp_read_src_clk_reg(pf, sts);
+
+       *ts = ns_to_timespec64(time_ns);
+}
+
+/**
+ * ice_ptp_write_init - Set PHC time to provided value
+ * @pf: Board private structure
+ * @ts: timespec structure that holds the new time value
+ *
+ * Set the PHC time to the specified time provided in the timespec.
+ */
+static int ice_ptp_write_init(struct ice_pf *pf, struct timespec64 *ts)
+{
+       u64 ns = timespec64_to_ns(ts);
+       struct ice_hw *hw = &pf->hw;
+
+       return ice_ptp_init_time(hw, ns);
+}
+
+/**
+ * ice_ptp_write_adj - Adjust PHC clock time atomically
+ * @pf: Board private structure
+ * @adj: Adjustment in nanoseconds
+ *
+ * Perform an atomic adjustment of the PHC time by the specified number of
+ * nanoseconds.
+ */
+static int ice_ptp_write_adj(struct ice_pf *pf, s32 adj)
+{
+       struct ice_hw *hw = &pf->hw;
+
+       return ice_ptp_adj_clock(hw, adj);
+}
+
+/**
+ * ice_base_incval - Get base timer increment value
+ * @pf: Board private structure
+ *
+ * Look up the base timer increment value for this device. The base increment
+ * value is used to define the nominal clock tick rate. This increment value
+ * is programmed during device initialization. It is also used as the basis
+ * for calculating adjustments using scaled_ppm.
+ */
+static u64 ice_base_incval(struct ice_pf *pf)
+{
+       struct ice_hw *hw = &pf->hw;
+       u64 incval;
+
+       if (ice_is_e810(hw))
+               incval = ICE_PTP_NOMINAL_INCVAL_E810;
+       else if (ice_e822_time_ref(hw) < NUM_ICE_TIME_REF_FREQ)
+               incval = ice_e822_nominal_incval(ice_e822_time_ref(hw));
+       else
+               incval = UNKNOWN_INCVAL_E822;
+
+       dev_dbg(ice_pf_to_dev(pf), "PTP: using base increment value of 0x%016llx\n",
+               incval);
+
+       return incval;
+}
+
+/**
+ * ice_ptp_reset_ts_memory_quad - Reset timestamp memory for one quad
+ * @pf: The PF private data structure
+ * @quad: The quad (0-4)
+ */
+static void ice_ptp_reset_ts_memory_quad(struct ice_pf *pf, int quad)
 {
        struct ice_hw *hw = &pf->hw;
 
@@ -1509,7 +1851,7 @@ ice_ptp_settime64(struct ptp_clock_info *info, const struct timespec64 *ts)
        ice_ptp_unlock(hw);
 
        if (!err)
-               ice_ptp_update_cached_phctime(pf);
+               ice_ptp_reset_cached_phctime(pf);
 
        /* Reenable periodic outputs */
        ice_ptp_enable_all_clkout(pf);
@@ -1588,7 +1930,7 @@ static int ice_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
                return err;
        }
 
-       ice_ptp_update_cached_phctime(pf);
+       ice_ptp_reset_cached_phctime(pf);
 
        return 0;
 }
@@ -1796,26 +2138,31 @@ void
 ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring,
                    union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb)
 {
+       struct skb_shared_hwtstamps *hwtstamps;
+       u64 ts_ns, cached_time;
        u32 ts_high;
-       u64 ts_ns;
 
-       /* Populate timesync data into skb */
-       if (rx_desc->wb.time_stamp_low & ICE_PTP_TS_VALID) {
-               struct skb_shared_hwtstamps *hwtstamps;
+       if (!(rx_desc->wb.time_stamp_low & ICE_PTP_TS_VALID))
+               return;
 
-               /* Use ice_ptp_extend_32b_ts directly, using the ring-specific
-                * cached PHC value, rather than accessing the PF. This also
-                * allows us to simply pass the upper 32bits of nanoseconds
-                * directly. Calling ice_ptp_extend_40b_ts is unnecessary as
-                * it would just discard these bits itself.
-                */
-               ts_high = le32_to_cpu(rx_desc->wb.flex_ts.ts_high);
-               ts_ns = ice_ptp_extend_32b_ts(rx_ring->cached_phctime, ts_high);
+       cached_time = READ_ONCE(rx_ring->cached_phctime);
 
-               hwtstamps = skb_hwtstamps(skb);
-               memset(hwtstamps, 0, sizeof(*hwtstamps));
-               hwtstamps->hwtstamp = ns_to_ktime(ts_ns);
-       }
+       /* Do not report a timestamp if we don't have a cached PHC time */
+       if (!cached_time)
+               return;
+
+       /* Use ice_ptp_extend_32b_ts directly, using the ring-specific cached
+        * PHC value, rather than accessing the PF. This also allows us to
+        * simply pass the upper 32bits of nanoseconds directly. Calling
+        * ice_ptp_extend_40b_ts is unnecessary as it would just discard these
+        * bits itself.
+        */
+       ts_high = le32_to_cpu(rx_desc->wb.flex_ts.ts_high);
+       ts_ns = ice_ptp_extend_32b_ts(cached_time, ts_high);
+
+       hwtstamps = skb_hwtstamps(skb);
+       memset(hwtstamps, 0, sizeof(*hwtstamps));
+       hwtstamps->hwtstamp = ns_to_ktime(ts_ns);
 }
 
 /**
@@ -2015,112 +2362,6 @@ static long ice_ptp_create_clock(struct ice_pf *pf)
        return 0;
 }
 
-/**
- * ice_ptp_tx_tstamp_work - Process Tx timestamps for a port
- * @work: pointer to the kthread_work struct
- *
- * Process timestamps captured by the PHY associated with this port. To do
- * this, loop over each index with a waiting skb.
- *
- * If a given index has a valid timestamp, perform the following steps:
- *
- * 1) copy the timestamp out of the PHY register
- * 4) clear the timestamp valid bit in the PHY register
- * 5) unlock the index by clearing the associated in_use bit.
- * 2) extend the 40b timestamp value to get a 64bit timestamp
- * 3) send that timestamp to the stack
- *
- * After looping, if we still have waiting SKBs, then re-queue the work. 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 only take the tracking lock when clearing the bit and when
- * checking if we need to re-queue this task. The only place where bits can be
- * set is the hard xmit routine where an SKB has a request flag set. The only
- * places where we clear bits are this work function, or the periodic cleanup
- * thread. If the cleanup thread clears a bit we're processing we catch it
- * when we lock to clear the bit and then grab the SKB pointer. If a Tx thread
- * starts a new timestamp, we might not begin processing it right away but we
- * will notice it at the end when we re-queue the work item. If a Tx thread
- * starts a new timestamp just after this function exits without re-queuing,
- * the interrupt when the timestamp finishes should trigger. Avoiding holding
- * the lock for the entire function is important in order to ensure that Tx
- * threads do not get blocked while waiting for the lock.
- */
-static void ice_ptp_tx_tstamp_work(struct kthread_work *work)
-{
-       struct ice_ptp_port *ptp_port;
-       struct ice_ptp_tx *tx;
-       struct ice_pf *pf;
-       struct ice_hw *hw;
-       u8 idx;
-
-       tx = container_of(work, struct ice_ptp_tx, work);
-       if (!tx->init)
-               return;
-
-       ptp_port = container_of(tx, struct ice_ptp_port, tx);
-       pf = ptp_port_to_pf(ptp_port);
-       hw = &pf->hw;
-
-       for_each_set_bit(idx, tx->in_use, tx->len) {
-               struct skb_shared_hwtstamps shhwtstamps = {};
-               u8 phy_idx = idx + tx->quad_offset;
-               u64 raw_tstamp, tstamp;
-               struct sk_buff *skb;
-               int err;
-
-               ice_trace(tx_tstamp_fw_req, tx->tstamps[idx].skb, idx);
-
-               err = ice_read_phy_tstamp(hw, tx->quad, phy_idx,
-                                         &raw_tstamp);
-               if (err)
-                       continue;
-
-               ice_trace(tx_tstamp_fw_done, tx->tstamps[idx].skb, idx);
-
-               /* Check if the timestamp is invalid or stale */
-               if (!(raw_tstamp & ICE_PTP_TS_VALID) ||
-                   raw_tstamp == tx->tstamps[idx].cached_tstamp)
-                       continue;
-
-               /* The timestamp is valid, so we'll go ahead and clear this
-                * index and then send the timestamp up to the stack.
-                */
-               spin_lock(&tx->lock);
-               tx->tstamps[idx].cached_tstamp = raw_tstamp;
-               clear_bit(idx, tx->in_use);
-               skb = tx->tstamps[idx].skb;
-               tx->tstamps[idx].skb = NULL;
-               spin_unlock(&tx->lock);
-
-               /* it's (unlikely but) possible we raced with the cleanup
-                * thread for discarding old timestamp requests.
-                */
-               if (!skb)
-                       continue;
-
-               /* Extend the timestamp using cached PHC time */
-               tstamp = ice_ptp_extend_40b_ts(pf, raw_tstamp);
-               shhwtstamps.hwtstamp = ns_to_ktime(tstamp);
-
-               ice_trace(tx_tstamp_complete, skb, idx);
-
-               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.
-        */
-       spin_lock(&tx->lock);
-       if (!bitmap_empty(tx->in_use, tx->len))
-               kthread_queue_work(pf->ptp.kworker, &tx->work);
-       spin_unlock(&tx->lock);
-}
-
 /**
  * ice_ptp_request_ts - Request an available Tx timestamp index
  * @tx: the PTP Tx timestamp tracker to request from
@@ -2173,167 +2414,6 @@ void ice_ptp_process_ts(struct ice_pf *pf)
                kthread_queue_work(pf->ptp.kworker, &pf->ptp.port.tx.work);
 }
 
-/**
- * ice_ptp_alloc_tx_tracker - Initialize tracking for Tx timestamps
- * @tx: Tx tracking structure to initialize
- *
- * Assumes that the length has already been initialized. Do not call directly,
- * use the ice_ptp_init_tx_e822 or ice_ptp_init_tx_e810 instead.
- */
-static int
-ice_ptp_alloc_tx_tracker(struct ice_ptp_tx *tx)
-{
-       tx->tstamps = kcalloc(tx->len, sizeof(*tx->tstamps), GFP_KERNEL);
-       if (!tx->tstamps)
-               return -ENOMEM;
-
-       tx->in_use = bitmap_zalloc(tx->len, GFP_KERNEL);
-       if (!tx->in_use) {
-               kfree(tx->tstamps);
-               tx->tstamps = NULL;
-               return -ENOMEM;
-       }
-
-       spin_lock_init(&tx->lock);
-       kthread_init_work(&tx->work, ice_ptp_tx_tstamp_work);
-
-       tx->init = 1;
-
-       return 0;
-}
-
-/**
- * ice_ptp_flush_tx_tracker - Flush any remaining timestamps from the tracker
- * @pf: Board private structure
- * @tx: the tracker to flush
- */
-static void
-ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
-{
-       u8 idx;
-
-       for (idx = 0; idx < tx->len; idx++) {
-               u8 phy_idx = idx + tx->quad_offset;
-
-               spin_lock(&tx->lock);
-               if (tx->tstamps[idx].skb) {
-                       dev_kfree_skb_any(tx->tstamps[idx].skb);
-                       tx->tstamps[idx].skb = NULL;
-               }
-               clear_bit(idx, tx->in_use);
-               spin_unlock(&tx->lock);
-
-               /* Clear any potential residual timestamp in the PHY block */
-               if (!pf->hw.reset_ongoing)
-                       ice_clear_phy_tstamp(&pf->hw, tx->quad, phy_idx);
-       }
-}
-
-/**
- * ice_ptp_release_tx_tracker - Release allocated memory for Tx tracker
- * @pf: Board private structure
- * @tx: Tx tracking structure to release
- *
- * Free memory associated with the Tx timestamp tracker.
- */
-static void
-ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
-{
-       tx->init = 0;
-
-       kthread_cancel_work_sync(&tx->work);
-
-       ice_ptp_flush_tx_tracker(pf, tx);
-
-       kfree(tx->tstamps);
-       tx->tstamps = NULL;
-
-       bitmap_free(tx->in_use);
-       tx->in_use = NULL;
-
-       tx->len = 0;
-}
-
-/**
- * ice_ptp_init_tx_e822 - Initialize tracking for Tx timestamps
- * @pf: Board private structure
- * @tx: the Tx tracking structure to initialize
- * @port: the port this structure tracks
- *
- * Initialize the Tx timestamp tracker for this port. For generic MAC devices,
- * the timestamp block is shared for all ports in the same quad. To avoid
- * ports using the same timestamp index, logically break the block of
- * registers into chunks based on the port number.
- */
-static int
-ice_ptp_init_tx_e822(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
-{
-       tx->quad = port / ICE_PORTS_PER_QUAD;
-       tx->quad_offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT;
-       tx->len = INDEX_PER_PORT;
-
-       return ice_ptp_alloc_tx_tracker(tx);
-}
-
-/**
- * ice_ptp_init_tx_e810 - Initialize tracking for Tx timestamps
- * @pf: Board private structure
- * @tx: the Tx tracking structure to initialize
- *
- * Initialize the Tx timestamp tracker for this PF. For E810 devices, each
- * port has its own block of timestamps, independent of the other ports.
- */
-static int
-ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx)
-{
-       tx->quad = pf->hw.port_info->lport;
-       tx->quad_offset = 0;
-       tx->len = INDEX_PER_QUAD;
-
-       return ice_ptp_alloc_tx_tracker(tx);
-}
-
-/**
- * ice_ptp_tx_tstamp_cleanup - Cleanup old timestamp requests that got dropped
- * @hw: pointer to the hw struct
- * @tx: PTP Tx tracker to clean up
- *
- * Loop through the Tx timestamp requests and see if any of them have been
- * waiting for a long time. Discard any SKBs that have been waiting for more
- * than 2 seconds. This is long enough to be reasonably sure that the
- * timestamp will never be captured. This might happen if the packet gets
- * discarded before it reaches the PHY timestamping block.
- */
-static void ice_ptp_tx_tstamp_cleanup(struct ice_hw *hw, struct ice_ptp_tx *tx)
-{
-       u8 idx;
-
-       if (!tx->init)
-               return;
-
-       for_each_set_bit(idx, tx->in_use, tx->len) {
-               struct sk_buff *skb;
-               u64 raw_tstamp;
-
-               /* Check if this SKB has been waiting for too long */
-               if (time_is_after_jiffies(tx->tstamps[idx].start + 2 * HZ))
-                       continue;
-
-               /* Read tstamp to be able to use this register again */
-               ice_read_phy_tstamp(hw, tx->quad, idx + tx->quad_offset,
-                                   &raw_tstamp);
-
-               spin_lock(&tx->lock);
-               skb = tx->tstamps[idx].skb;
-               tx->tstamps[idx].skb = NULL;
-               clear_bit(idx, tx->in_use);
-               spin_unlock(&tx->lock);
-
-               /* Free the SKB after we've cleared the bit */
-               dev_kfree_skb_any(skb);
-       }
-}
-
 static void ice_ptp_periodic_work(struct kthread_work *work)
 {
        struct ice_ptp *ptp = container_of(work, struct ice_ptp, work.work);
@@ -2345,7 +2425,7 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
 
        err = ice_ptp_update_cached_phctime(pf);
 
-       ice_ptp_tx_tstamp_cleanup(&pf->hw, &pf->ptp.port.tx);
+       ice_ptp_tx_tstamp_cleanup(pf, &pf->ptp.port.tx);
 
        /* Run twice a second or reschedule if phc update failed */
        kthread_queue_delayed_work(ptp->kworker, &ptp->work,
index 10e396a..d53dcd0 100644 (file)
@@ -163,6 +163,7 @@ struct ice_ptp_port {
  * @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
  * @ext_ts_irq: the external timestamp IRQ in use
  * @kworker: kwork thread for handling periodic work
@@ -171,12 +172,19 @@ struct ice_ptp_port {
  * @clock: pointer to registered PTP clock device
  * @tstamp_config: hardware timestamping configuration
  * @reset_time: kernel time after clock stop on reset
+ * @tx_hwtstamp_skipped: number of Tx time stamp requests skipped
+ * @tx_hwtstamp_timeouts: number of Tx skbs discarded with no time stamp
+ * @tx_hwtstamp_flushed: number of Tx skbs flushed due to interface closed
+ * @tx_hwtstamp_discarded: number of Tx skbs discarded due to cached PHC time
+ *                         being too old to correctly extend timestamp
+ * @late_cached_phc_updates: number of times cached PHC update is late
  */
 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;
        u8 ext_ts_irq;
        struct kthread_worker *kworker;
@@ -185,6 +193,11 @@ struct ice_ptp {
        struct ptp_clock *clock;
        struct hwtstamp_config tstamp_config;
        u64 reset_time;
+       u32 tx_hwtstamp_skipped;
+       u32 tx_hwtstamp_timeouts;
+       u32 tx_hwtstamp_flushed;
+       u32 tx_hwtstamp_discarded;
+       u32 late_cached_phc_updates;
 };
 
 #define __ptp_port_to_ptp(p) \
index 3808034..697feb8 100644 (file)
@@ -3449,31 +3449,15 @@ bool ice_vlan_fltr_exist(struct ice_hw *hw, u16 vlan_id, u16 vsi_handle)
  * ice_add_mac - Add a MAC address based filter rule
  * @hw: pointer to the hardware structure
  * @m_list: list of MAC addresses and forwarding information
- *
- * IMPORTANT: When the ucast_shared flag is set to false and m_list has
- * multiple unicast addresses, the function assumes that all the
- * addresses are unique in a given add_mac call. It doesn't
- * check for duplicates in this case, removing duplicates from a given
- * list should be taken care of in the caller of this function.
  */
 int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
 {
-       struct ice_sw_rule_lkup_rx_tx *s_rule, *r_iter;
        struct ice_fltr_list_entry *m_list_itr;
-       struct list_head *rule_head;
-       u16 total_elem_left, s_rule_size;
-       struct ice_switch_info *sw;
-       struct mutex *rule_lock; /* Lock to protect filter rule list */
-       u16 num_unicast = 0;
        int status = 0;
-       u8 elem_sent;
 
        if (!m_list || !hw)
                return -EINVAL;
 
-       s_rule = NULL;
-       sw = hw->switch_info;
-       rule_lock = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
        list_for_each_entry(m_list_itr, m_list, list_entry) {
                u8 *add = &m_list_itr->fltr_info.l_data.mac.mac_addr[0];
                u16 vsi_handle;
@@ -3492,106 +3476,13 @@ int ice_add_mac(struct ice_hw *hw, struct list_head *m_list)
                if (m_list_itr->fltr_info.lkup_type != ICE_SW_LKUP_MAC ||
                    is_zero_ether_addr(add))
                        return -EINVAL;
-               if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
-                       /* Don't overwrite the unicast address */
-                       mutex_lock(rule_lock);
-                       if (ice_find_rule_entry(hw, ICE_SW_LKUP_MAC,
-                                               &m_list_itr->fltr_info)) {
-                               mutex_unlock(rule_lock);
-                               return -EEXIST;
-                       }
-                       mutex_unlock(rule_lock);
-                       num_unicast++;
-               } else if (is_multicast_ether_addr(add) ||
-                          (is_unicast_ether_addr(add) && hw->ucast_shared)) {
-                       m_list_itr->status =
-                               ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
-                                                     m_list_itr);
-                       if (m_list_itr->status)
-                               return m_list_itr->status;
-               }
-       }
-
-       mutex_lock(rule_lock);
-       /* Exit if no suitable entries were found for adding bulk switch rule */
-       if (!num_unicast) {
-               status = 0;
-               goto ice_add_mac_exit;
-       }
-
-       rule_head = &sw->recp_list[ICE_SW_LKUP_MAC].filt_rules;
-
-       /* Allocate switch rule buffer for the bulk update for unicast */
-       s_rule_size = ICE_SW_RULE_RX_TX_ETH_HDR_SIZE(s_rule);
-       s_rule = devm_kcalloc(ice_hw_to_dev(hw), num_unicast, s_rule_size,
-                             GFP_KERNEL);
-       if (!s_rule) {
-               status = -ENOMEM;
-               goto ice_add_mac_exit;
-       }
-
-       r_iter = s_rule;
-       list_for_each_entry(m_list_itr, m_list, list_entry) {
-               struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
-               u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
-
-               if (is_unicast_ether_addr(mac_addr)) {
-                       ice_fill_sw_rule(hw, &m_list_itr->fltr_info, r_iter,
-                                        ice_aqc_opc_add_sw_rules);
-                       r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
-               }
-       }
-
-       /* Call AQ bulk switch rule update for all unicast addresses */
-       r_iter = s_rule;
-       /* Call AQ switch rule in AQ_MAX chunk */
-       for (total_elem_left = num_unicast; total_elem_left > 0;
-            total_elem_left -= elem_sent) {
-               struct ice_sw_rule_lkup_rx_tx *entry = r_iter;
-
-               elem_sent = min_t(u8, total_elem_left,
-                                 (ICE_AQ_MAX_BUF_LEN / s_rule_size));
-               status = ice_aq_sw_rules(hw, entry, elem_sent * s_rule_size,
-                                        elem_sent, ice_aqc_opc_add_sw_rules,
-                                        NULL);
-               if (status)
-                       goto ice_add_mac_exit;
-               r_iter = (typeof(s_rule))
-                       ((u8 *)r_iter + (elem_sent * s_rule_size));
-       }
-
-       /* Fill up rule ID based on the value returned from FW */
-       r_iter = s_rule;
-       list_for_each_entry(m_list_itr, m_list, list_entry) {
-               struct ice_fltr_info *f_info = &m_list_itr->fltr_info;
-               u8 *mac_addr = &f_info->l_data.mac.mac_addr[0];
-               struct ice_fltr_mgmt_list_entry *fm_entry;
-
-               if (is_unicast_ether_addr(mac_addr)) {
-                       f_info->fltr_rule_id = le16_to_cpu(r_iter->index);
-                       f_info->fltr_act = ICE_FWD_TO_VSI;
-                       /* Create an entry to track this MAC address */
-                       fm_entry = devm_kzalloc(ice_hw_to_dev(hw),
-                                               sizeof(*fm_entry), GFP_KERNEL);
-                       if (!fm_entry) {
-                               status = -ENOMEM;
-                               goto ice_add_mac_exit;
-                       }
-                       fm_entry->fltr_info = *f_info;
-                       fm_entry->vsi_count = 1;
-                       /* The book keeping entries will get removed when
-                        * base driver calls remove filter AQ command
-                        */
 
-                       list_add(&fm_entry->list_entry, rule_head);
-                       r_iter = (typeof(s_rule))((u8 *)r_iter + s_rule_size);
-               }
+               m_list_itr->status = ice_add_rule_internal(hw, ICE_SW_LKUP_MAC,
+                                                          m_list_itr);
+               if (m_list_itr->status)
+                       return m_list_itr->status;
        }
 
-ice_add_mac_exit:
-       mutex_unlock(rule_lock);
-       if (s_rule)
-               devm_kfree(ice_hw_to_dev(hw), s_rule);
        return status;
 }
 
@@ -3978,38 +3869,6 @@ ice_check_if_dflt_vsi(struct ice_port_info *pi, u16 vsi_handle,
        return ret;
 }
 
-/**
- * ice_find_ucast_rule_entry - Search for a unicast MAC filter rule entry
- * @hw: pointer to the hardware structure
- * @recp_id: lookup type for which the specified rule needs to be searched
- * @f_info: rule information
- *
- * Helper function to search for a unicast rule entry - this is to be used
- * to remove unicast MAC filter that is not shared with other VSIs on the
- * PF switch.
- *
- * Returns pointer to entry storing the rule if found
- */
-static struct ice_fltr_mgmt_list_entry *
-ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
-                         struct ice_fltr_info *f_info)
-{
-       struct ice_switch_info *sw = hw->switch_info;
-       struct ice_fltr_mgmt_list_entry *list_itr;
-       struct list_head *list_head;
-
-       list_head = &sw->recp_list[recp_id].filt_rules;
-       list_for_each_entry(list_itr, list_head, list_entry) {
-               if (!memcmp(&f_info->l_data, &list_itr->fltr_info.l_data,
-                           sizeof(f_info->l_data)) &&
-                   f_info->fwd_id.hw_vsi_id ==
-                   list_itr->fltr_info.fwd_id.hw_vsi_id &&
-                   f_info->flag == list_itr->fltr_info.flag)
-                       return list_itr;
-       }
-       return NULL;
-}
-
 /**
  * ice_remove_mac - remove a MAC address based filter rule
  * @hw: pointer to the hardware structure
@@ -4026,15 +3885,12 @@ ice_find_ucast_rule_entry(struct ice_hw *hw, u8 recp_id,
 int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
 {
        struct ice_fltr_list_entry *list_itr, *tmp;
-       struct mutex *rule_lock; /* Lock to protect filter rule list */
 
        if (!m_list)
                return -EINVAL;
 
-       rule_lock = &hw->switch_info->recp_list[ICE_SW_LKUP_MAC].filt_rule_lock;
        list_for_each_entry_safe(list_itr, tmp, m_list, list_entry) {
                enum ice_sw_lkup_type l_type = list_itr->fltr_info.lkup_type;
-               u8 *add = &list_itr->fltr_info.l_data.mac.mac_addr[0];
                u16 vsi_handle;
 
                if (l_type != ICE_SW_LKUP_MAC)
@@ -4046,19 +3902,7 @@ int ice_remove_mac(struct ice_hw *hw, struct list_head *m_list)
 
                list_itr->fltr_info.fwd_id.hw_vsi_id =
                                        ice_get_hw_vsi_num(hw, vsi_handle);
-               if (is_unicast_ether_addr(add) && !hw->ucast_shared) {
-                       /* Don't remove the unicast address that belongs to
-                        * another VSI on the switch, since it is not being
-                        * shared...
-                        */
-                       mutex_lock(rule_lock);
-                       if (!ice_find_ucast_rule_entry(hw, ICE_SW_LKUP_MAC,
-                                                      &list_itr->fltr_info)) {
-                               mutex_unlock(rule_lock);
-                               return -ENOENT;
-                       }
-                       mutex_unlock(rule_lock);
-               }
+
                list_itr->status = ice_remove_rule_internal(hw,
                                                            ICE_SW_LKUP_MAC,
                                                            list_itr);
index a298862..42df686 100644 (file)
@@ -36,6 +36,10 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
                     ICE_TC_FLWR_FIELD_ENC_DEST_IPV6))
                lkups_cnt++;
 
+       if (flags & (ICE_TC_FLWR_FIELD_ENC_IP_TOS |
+                    ICE_TC_FLWR_FIELD_ENC_IP_TTL))
+               lkups_cnt++;
+
        if (flags & ICE_TC_FLWR_FIELD_ENC_DEST_L4_PORT)
                lkups_cnt++;
 
@@ -64,6 +68,9 @@ ice_tc_count_lkups(u32 flags, struct ice_tc_flower_lyr_2_4_hdrs *headers,
                     ICE_TC_FLWR_FIELD_DEST_IPV6 | ICE_TC_FLWR_FIELD_SRC_IPV6))
                lkups_cnt++;
 
+       if (flags & (ICE_TC_FLWR_FIELD_IP_TOS | ICE_TC_FLWR_FIELD_IP_TTL))
+               lkups_cnt++;
+
        /* is L4 (TCP/UDP/any other L4 protocol fields) specified? */
        if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
                     ICE_TC_FLWR_FIELD_SRC_L4_PORT))
@@ -257,6 +264,50 @@ ice_tc_fill_tunnel_outer(u32 flags, struct ice_tc_flower_fltr *fltr,
                i++;
        }
 
+       if (fltr->inner_headers.l2_key.n_proto == htons(ETH_P_IP) &&
+           (flags & (ICE_TC_FLWR_FIELD_ENC_IP_TOS |
+                     ICE_TC_FLWR_FIELD_ENC_IP_TTL))) {
+               list[i].type = ice_proto_type_from_ipv4(false);
+
+               if (flags & ICE_TC_FLWR_FIELD_ENC_IP_TOS) {
+                       list[i].h_u.ipv4_hdr.tos = hdr->l3_key.tos;
+                       list[i].m_u.ipv4_hdr.tos = hdr->l3_mask.tos;
+               }
+
+               if (flags & ICE_TC_FLWR_FIELD_ENC_IP_TTL) {
+                       list[i].h_u.ipv4_hdr.time_to_live = hdr->l3_key.ttl;
+                       list[i].m_u.ipv4_hdr.time_to_live = hdr->l3_mask.ttl;
+               }
+
+               i++;
+       }
+
+       if (fltr->inner_headers.l2_key.n_proto == htons(ETH_P_IPV6) &&
+           (flags & (ICE_TC_FLWR_FIELD_ENC_IP_TOS |
+                     ICE_TC_FLWR_FIELD_ENC_IP_TTL))) {
+               struct ice_ipv6_hdr *hdr_h, *hdr_m;
+
+               hdr_h = &list[i].h_u.ipv6_hdr;
+               hdr_m = &list[i].m_u.ipv6_hdr;
+               list[i].type = ice_proto_type_from_ipv6(false);
+
+               if (flags & ICE_TC_FLWR_FIELD_ENC_IP_TOS) {
+                       be32p_replace_bits(&hdr_h->be_ver_tc_flow,
+                                          hdr->l3_key.tos,
+                                          ICE_IPV6_HDR_TC_MASK);
+                       be32p_replace_bits(&hdr_m->be_ver_tc_flow,
+                                          hdr->l3_mask.tos,
+                                          ICE_IPV6_HDR_TC_MASK);
+               }
+
+               if (flags & ICE_TC_FLWR_FIELD_ENC_IP_TTL) {
+                       hdr_h->hop_limit = hdr->l3_key.ttl;
+                       hdr_m->hop_limit = hdr->l3_mask.ttl;
+               }
+
+               i++;
+       }
+
        if ((flags & ICE_TC_FLWR_FIELD_ENC_DEST_L4_PORT) &&
            hdr->l3_key.ip_proto == IPPROTO_UDP) {
                list[i].type = ICE_UDP_OF;
@@ -420,6 +471,50 @@ ice_tc_fill_rules(struct ice_hw *hw, u32 flags,
                i++;
        }
 
+       if (headers->l2_key.n_proto == htons(ETH_P_IP) &&
+           (flags & (ICE_TC_FLWR_FIELD_IP_TOS | ICE_TC_FLWR_FIELD_IP_TTL))) {
+               list[i].type = ice_proto_type_from_ipv4(inner);
+
+               if (flags & ICE_TC_FLWR_FIELD_IP_TOS) {
+                       list[i].h_u.ipv4_hdr.tos = headers->l3_key.tos;
+                       list[i].m_u.ipv4_hdr.tos = headers->l3_mask.tos;
+               }
+
+               if (flags & ICE_TC_FLWR_FIELD_IP_TTL) {
+                       list[i].h_u.ipv4_hdr.time_to_live =
+                               headers->l3_key.ttl;
+                       list[i].m_u.ipv4_hdr.time_to_live =
+                               headers->l3_mask.ttl;
+               }
+
+               i++;
+       }
+
+       if (headers->l2_key.n_proto == htons(ETH_P_IPV6) &&
+           (flags & (ICE_TC_FLWR_FIELD_IP_TOS | ICE_TC_FLWR_FIELD_IP_TTL))) {
+               struct ice_ipv6_hdr *hdr_h, *hdr_m;
+
+               hdr_h = &list[i].h_u.ipv6_hdr;
+               hdr_m = &list[i].m_u.ipv6_hdr;
+               list[i].type = ice_proto_type_from_ipv6(inner);
+
+               if (flags & ICE_TC_FLWR_FIELD_IP_TOS) {
+                       be32p_replace_bits(&hdr_h->be_ver_tc_flow,
+                                          headers->l3_key.tos,
+                                          ICE_IPV6_HDR_TC_MASK);
+                       be32p_replace_bits(&hdr_m->be_ver_tc_flow,
+                                          headers->l3_mask.tos,
+                                          ICE_IPV6_HDR_TC_MASK);
+               }
+
+               if (flags & ICE_TC_FLWR_FIELD_IP_TTL) {
+                       hdr_h->hop_limit = headers->l3_key.ttl;
+                       hdr_m->hop_limit = headers->l3_mask.ttl;
+               }
+
+               i++;
+       }
+
        /* copy L4 (src, dest) port */
        if (flags & (ICE_TC_FLWR_FIELD_DEST_L4_PORT |
                     ICE_TC_FLWR_FIELD_SRC_L4_PORT)) {
@@ -838,6 +933,40 @@ ice_tc_set_ipv6(struct flow_match_ipv6_addrs *match,
        return 0;
 }
 
+/**
+ * ice_tc_set_tos_ttl - Parse IP ToS/TTL from TC flower filter
+ * @match: Pointer to flow match structure
+ * @fltr: Pointer to filter structure
+ * @headers: inner or outer header fields
+ * @is_encap: set true for tunnel
+ */
+static void
+ice_tc_set_tos_ttl(struct flow_match_ip *match,
+                  struct ice_tc_flower_fltr *fltr,
+                  struct ice_tc_flower_lyr_2_4_hdrs *headers,
+                  bool is_encap)
+{
+       if (match->mask->tos) {
+               if (is_encap)
+                       fltr->flags |= ICE_TC_FLWR_FIELD_ENC_IP_TOS;
+               else
+                       fltr->flags |= ICE_TC_FLWR_FIELD_IP_TOS;
+
+               headers->l3_key.tos = match->key->tos;
+               headers->l3_mask.tos = match->mask->tos;
+       }
+
+       if (match->mask->ttl) {
+               if (is_encap)
+                       fltr->flags |= ICE_TC_FLWR_FIELD_ENC_IP_TTL;
+               else
+                       fltr->flags |= ICE_TC_FLWR_FIELD_IP_TTL;
+
+               headers->l3_key.ttl = match->key->ttl;
+               headers->l3_mask.ttl = match->mask->ttl;
+       }
+}
+
 /**
  * ice_tc_set_port - Parse ports from TC flower filter
  * @match: Flow match structure
@@ -967,10 +1096,7 @@ ice_parse_tunnel_attr(struct net_device *dev, struct flow_rule *rule,
                struct flow_match_ip match;
 
                flow_rule_match_enc_ip(rule, &match);
-               headers->l3_key.tos = match.key->tos;
-               headers->l3_key.ttl = match.key->ttl;
-               headers->l3_mask.tos = match.mask->tos;
-               headers->l3_mask.ttl = match.mask->ttl;
+               ice_tc_set_tos_ttl(&match, fltr, headers, true);
        }
 
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ENC_PORTS) &&
@@ -1039,6 +1165,7 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
              BIT(FLOW_DISSECTOR_KEY_ENC_IPV6_ADDRS) |
              BIT(FLOW_DISSECTOR_KEY_ENC_PORTS) |
              BIT(FLOW_DISSECTOR_KEY_ENC_OPTS) |
+             BIT(FLOW_DISSECTOR_KEY_IP) |
              BIT(FLOW_DISSECTOR_KEY_ENC_IP) |
              BIT(FLOW_DISSECTOR_KEY_PORTS) |
              BIT(FLOW_DISSECTOR_KEY_PPPOE))) {
@@ -1217,6 +1344,13 @@ ice_parse_cls_flower(struct net_device *filter_dev, struct ice_vsi *vsi,
                        return -EINVAL;
        }
 
+       if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
+               struct flow_match_ip match;
+
+               flow_rule_match_ip(rule, &match);
+               ice_tc_set_tos_ttl(&match, fltr, headers, false);
+       }
+
        if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
                struct flow_match_ports match;
 
index 91cd3d3..f397ed0 100644 (file)
 #define ICE_TC_FLWR_FIELD_CVLAN                        BIT(19)
 #define ICE_TC_FLWR_FIELD_PPPOE_SESSID         BIT(20)
 #define ICE_TC_FLWR_FIELD_PPP_PROTO            BIT(21)
+#define ICE_TC_FLWR_FIELD_IP_TOS               BIT(22)
+#define ICE_TC_FLWR_FIELD_IP_TTL               BIT(23)
+#define ICE_TC_FLWR_FIELD_ENC_IP_TOS           BIT(24)
+#define ICE_TC_FLWR_FIELD_ENC_IP_TTL           BIT(25)
 
 #define ICE_TC_FLOWER_MASK_32   0xFFFFFFFF
 
+#define ICE_IPV6_HDR_TC_MASK 0xFF00000
+
 struct ice_indr_block_priv {
        struct net_device *netdev;
        struct ice_netdev_priv *np;
index 836dce8..42b42f4 100644 (file)
@@ -2255,8 +2255,10 @@ ice_tstamp(struct ice_tx_ring *tx_ring, struct sk_buff *skb,
 
        /* Grab an open timestamp slot */
        idx = ice_ptp_request_ts(tx_ring->tx_tstamps, skb);
-       if (idx < 0)
+       if (idx < 0) {
+               tx_ring->vsi->back->ptp.tx_hwtstamp_skipped++;
                return;
+       }
 
        off->cd_qw1 |= (u64)(ICE_TX_DESC_DTYPE_CTX |
                             (ICE_TX_CTX_DESC_TSYN << ICE_TXD_CTX_QW1_CMD_S) |
index ca902af..932b566 100644 (file)
@@ -295,10 +295,11 @@ struct ice_rx_ring {
        struct xsk_buff_pool *xsk_pool;
        struct sk_buff *skb;
        dma_addr_t dma;                 /* physical address of ring */
-#define ICE_RX_FLAGS_RING_BUILD_SKB    BIT(1)
        u64 cached_phctime;
        u8 dcb_tc;                      /* Traffic class of ring */
        u8 ptp_rx;
+#define ICE_RX_FLAGS_RING_BUILD_SKB    BIT(1)
+#define ICE_RX_FLAGS_CRC_STRIP_DIS     BIT(2)
        u8 flags;
 } ____cacheline_internodealigned_in_smp;
 
index 861b643..6ea54a3 100644 (file)
@@ -564,6 +564,8 @@ enum ice_rl_type {
 #define ICE_SCHED_INVAL_PROF_ID                0xFFFF
 #define ICE_SCHED_DFLT_BURST_SIZE      (15 * 1024)     /* in bytes (15k) */
 
+#define ICE_MAX_PORT_PER_PCI_DEV 8
+
  /* Data structure for saving BW information */
 enum ice_bw_type {
        ICE_BW_TYPE_PRIO,
@@ -885,8 +887,6 @@ struct ice_hw {
        /* INTRL granularity in 1 us */
        u8 intrl_gran;
 
-       u8 ucast_shared;        /* true if VSIs can share unicast addr */
-
 #define ICE_PHY_PER_NAC                1
 #define ICE_MAX_QUAD           2
 #define ICE_NUM_QUAD_TYPE      2
index c14fc87..e5f3e76 100644 (file)
@@ -850,14 +850,14 @@ static void igb_get_drvinfo(struct net_device *netdev,
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  igb_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver,  igb_driver_name, sizeof(drvinfo->driver));
 
        /* EEPROM image version # is reported as firmware version # for
         * 82575 controllers
         */
-       strlcpy(drvinfo->fw_version, adapter->fw_version,
+       strscpy(drvinfo->fw_version, adapter->fw_version,
                sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 
        drvinfo->n_priv_flags = IGB_PRIV_FLAGS_STR_LEN;
index 2796e81..ff0c7f0 100644 (file)
@@ -3138,7 +3138,7 @@ static s32 igb_init_i2c(struct igb_adapter *adapter)
        adapter->i2c_algo.data = adapter;
        adapter->i2c_adap.algo_data = &adapter->i2c_algo;
        adapter->i2c_adap.dev.parent = &adapter->pdev->dev;
-       strlcpy(adapter->i2c_adap.name, "igb BB",
+       strscpy(adapter->i2c_adap.name, "igb BB",
                sizeof(adapter->i2c_adap.name));
        status = i2c_bit_add_bus(&adapter->i2c_adap);
        return status;
index 9d4322b..83b9798 100644 (file)
@@ -169,8 +169,8 @@ static void igbvf_get_drvinfo(struct net_device *netdev,
 {
        struct igbvf_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  igbvf_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver,  igbvf_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index ebff0e0..bf6c461 100644 (file)
@@ -2129,65 +2129,102 @@ static bool igc_alloc_rx_buffers_zc(struct igc_ring *ring, u16 count)
        return ok;
 }
 
-static int igc_xdp_init_tx_buffer(struct igc_tx_buffer *buffer,
-                                 struct xdp_frame *xdpf,
-                                 struct igc_ring *ring)
-{
-       dma_addr_t dma;
-
-       dma = dma_map_single(ring->dev, xdpf->data, xdpf->len, DMA_TO_DEVICE);
-       if (dma_mapping_error(ring->dev, dma)) {
-               netdev_err_once(ring->netdev, "Failed to map DMA for TX\n");
-               return -ENOMEM;
-       }
-
-       buffer->type = IGC_TX_BUFFER_TYPE_XDP;
-       buffer->xdpf = xdpf;
-       buffer->protocol = 0;
-       buffer->bytecount = xdpf->len;
-       buffer->gso_segs = 1;
-       buffer->time_stamp = jiffies;
-       dma_unmap_len_set(buffer, len, xdpf->len);
-       dma_unmap_addr_set(buffer, dma, dma);
-       return 0;
-}
-
 /* This function requires __netif_tx_lock is held by the caller. */
 static int igc_xdp_init_tx_descriptor(struct igc_ring *ring,
                                      struct xdp_frame *xdpf)
 {
-       struct igc_tx_buffer *buffer;
-       union igc_adv_tx_desc *desc;
-       u32 cmd_type, olinfo_status;
-       int err;
+       struct skb_shared_info *sinfo = xdp_get_shared_info_from_frame(xdpf);
+       u8 nr_frags = unlikely(xdp_frame_has_frags(xdpf)) ? sinfo->nr_frags : 0;
+       u16 count, index = ring->next_to_use;
+       struct igc_tx_buffer *head = &ring->tx_buffer_info[index];
+       struct igc_tx_buffer *buffer = head;
+       union igc_adv_tx_desc *desc = IGC_TX_DESC(ring, index);
+       u32 olinfo_status, len = xdpf->len, cmd_type;
+       void *data = xdpf->data;
+       u16 i;
 
-       if (!igc_desc_unused(ring))
-               return -EBUSY;
+       count = TXD_USE_COUNT(len);
+       for (i = 0; i < nr_frags; i++)
+               count += TXD_USE_COUNT(skb_frag_size(&sinfo->frags[i]));
 
-       buffer = &ring->tx_buffer_info[ring->next_to_use];
-       err = igc_xdp_init_tx_buffer(buffer, xdpf, ring);
-       if (err)
-               return err;
+       if (igc_maybe_stop_tx(ring, count + 3)) {
+               /* this is a hard error */
+               return -EBUSY;
+       }
 
-       cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
-                  IGC_ADVTXD_DCMD_IFCS | IGC_TXD_DCMD |
-                  buffer->bytecount;
-       olinfo_status = buffer->bytecount << IGC_ADVTXD_PAYLEN_SHIFT;
+       i = 0;
+       head->bytecount = xdp_get_frame_len(xdpf);
+       head->type = IGC_TX_BUFFER_TYPE_XDP;
+       head->gso_segs = 1;
+       head->xdpf = xdpf;
 
-       desc = IGC_TX_DESC(ring, ring->next_to_use);
-       desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+       olinfo_status = head->bytecount << IGC_ADVTXD_PAYLEN_SHIFT;
        desc->read.olinfo_status = cpu_to_le32(olinfo_status);
-       desc->read.buffer_addr = cpu_to_le64(dma_unmap_addr(buffer, dma));
 
-       netdev_tx_sent_queue(txring_txq(ring), buffer->bytecount);
+       for (;;) {
+               dma_addr_t dma;
 
-       buffer->next_to_watch = desc;
+               dma = dma_map_single(ring->dev, data, len, DMA_TO_DEVICE);
+               if (dma_mapping_error(ring->dev, dma)) {
+                       netdev_err_once(ring->netdev,
+                                       "Failed to map DMA for TX\n");
+                       goto unmap;
+               }
 
-       ring->next_to_use++;
-       if (ring->next_to_use == ring->count)
-               ring->next_to_use = 0;
+               dma_unmap_len_set(buffer, len, len);
+               dma_unmap_addr_set(buffer, dma, dma);
+
+               cmd_type = IGC_ADVTXD_DTYP_DATA | IGC_ADVTXD_DCMD_DEXT |
+                          IGC_ADVTXD_DCMD_IFCS | len;
+
+               desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+               desc->read.buffer_addr = cpu_to_le64(dma);
+
+               buffer->protocol = 0;
+
+               if (++index == ring->count)
+                       index = 0;
+
+               if (i == nr_frags)
+                       break;
+
+               buffer = &ring->tx_buffer_info[index];
+               desc = IGC_TX_DESC(ring, index);
+               desc->read.olinfo_status = 0;
+
+               data = skb_frag_address(&sinfo->frags[i]);
+               len = skb_frag_size(&sinfo->frags[i]);
+               i++;
+       }
+       desc->read.cmd_type_len |= cpu_to_le32(IGC_TXD_DCMD);
+
+       netdev_tx_sent_queue(txring_txq(ring), head->bytecount);
+       /* set the timestamp */
+       head->time_stamp = jiffies;
+       /* set next_to_watch value indicating a packet is present */
+       head->next_to_watch = desc;
+       ring->next_to_use = index;
 
        return 0;
+
+unmap:
+       for (;;) {
+               buffer = &ring->tx_buffer_info[index];
+               if (dma_unmap_len(buffer, len))
+                       dma_unmap_page(ring->dev,
+                                      dma_unmap_addr(buffer, dma),
+                                      dma_unmap_len(buffer, len),
+                                      DMA_TO_DEVICE);
+               dma_unmap_len_set(buffer, len, 0);
+               if (buffer == head)
+                       break;
+
+               if (!index)
+                       index += ring->count;
+               index--;
+       }
+
+       return -ENOMEM;
 }
 
 static struct igc_ring *igc_xdp_get_tx_ring(struct igc_adapter *adapter,
@@ -2369,6 +2406,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
                        xdp_prepare_buff(&xdp, pktbuf - igc_rx_offset(rx_ring),
                                         igc_rx_offset(rx_ring) + pkt_offset,
                                         size, true);
+                       xdp_buff_clear_frags_flag(&xdp);
 
                        skb = igc_xdp_run_prog(adapter, &xdp);
                }
index 46efcfa..efa9805 100644 (file)
@@ -456,9 +456,9 @@ ixgb_get_drvinfo(struct net_device *netdev,
 {
        struct ixgb_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver,  ixgb_driver_name,
+       strscpy(drvinfo->driver,  ixgb_driver_name,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 04f453e..e88e3df 100644 (file)
@@ -1106,12 +1106,12 @@ static void ixgbe_get_drvinfo(struct net_device *netdev,
 {
        struct ixgbe_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, ixgbe_driver_name, sizeof(drvinfo->driver));
 
-       strlcpy(drvinfo->fw_version, adapter->eeprom_id,
+       strscpy(drvinfo->fw_version, adapter->eeprom_id,
                sizeof(drvinfo->fw_version));
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 
        drvinfo->n_priv_flags = IXGBE_PRIV_FLAGS_STR_LEN;
@@ -1964,15 +1964,13 @@ static bool ixgbe_check_lbtest_frame(struct ixgbe_rx_buffer *rx_buffer,
 
        frame_size >>= 1;
 
-       data = kmap(rx_buffer->page) + rx_buffer->page_offset;
+       data = page_address(rx_buffer->page) + rx_buffer->page_offset;
 
        if (data[3] != 0xFF ||
            data[frame_size + 10] != 0xBE ||
            data[frame_size + 12] != 0xAF)
                match = false;
 
-       kunmap(rx_buffer->page);
-
        return match;
 }
 
index 0fcd820..7311bd5 100644 (file)
@@ -1004,7 +1004,7 @@ int ixgbe_fcoe_get_hbainfo(struct net_device *netdev,
                 ixgbe_driver_name,
                 UTS_RELEASE);
        /* Firmware Version */
-       strlcpy(info->firmware_version, adapter->eeprom_id,
+       strscpy(info->firmware_version, adapter->eeprom_id,
                sizeof(info->firmware_version));
 
        /* Model */
index d1e430b..298cfbf 100644 (file)
@@ -10849,7 +10849,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        netdev->netdev_ops = &ixgbe_netdev_ops;
        ixgbe_set_ethtool_ops(netdev);
        netdev->watchdog_timeo = 5 * HZ;
-       strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
+       strscpy(netdev->name, pci_name(pdev), sizeof(netdev->name));
 
        /* Setup hw api */
        hw->mac.ops   = *ii->mac_ops;
@@ -11140,7 +11140,7 @@ skip_sriov:
 
        err = ixgbe_read_pba_string_generic(hw, part_str, sizeof(part_str));
        if (err)
-               strlcpy(part_str, "Unknown", sizeof(part_str));
+               strscpy(part_str, "Unknown", sizeof(part_str));
        if (ixgbe_is_sfp(hw) && hw->phy.sfp_type != ixgbe_sfp_type_not_present)
                e_dev_info("MAC: %d, PHY: %d, SFP+: %d, PBA No: %s\n",
                           hw->mac.type, hw->phy.type, hw->phy.sfp_type,
index 7f7ea46..2b00db9 100644 (file)
@@ -3712,7 +3712,9 @@ struct ixgbe_info {
 #define IXGBE_KRM_LINK_S1(P)           ((P) ? 0x8200 : 0x4200)
 #define IXGBE_KRM_LINK_CTRL_1(P)       ((P) ? 0x820C : 0x420C)
 #define IXGBE_KRM_AN_CNTL_1(P)         ((P) ? 0x822C : 0x422C)
+#define IXGBE_KRM_AN_CNTL_4(P)         ((P) ? 0x8238 : 0x4238)
 #define IXGBE_KRM_AN_CNTL_8(P)         ((P) ? 0x8248 : 0x4248)
+#define IXGBE_KRM_PCS_KX_AN(P)         ((P) ? 0x9918 : 0x5918)
 #define IXGBE_KRM_SGMII_CTRL(P)                ((P) ? 0x82A0 : 0x42A0)
 #define IXGBE_KRM_LP_BASE_PAGE_HIGH(P) ((P) ? 0x836C : 0x436C)
 #define IXGBE_KRM_DSP_TXFFE_STATE_4(P) ((P) ? 0x8634 : 0x4634)
@@ -3722,6 +3724,7 @@ struct ixgbe_info {
 #define IXGBE_KRM_PMD_FLX_MASK_ST20(P) ((P) ? 0x9054 : 0x5054)
 #define IXGBE_KRM_TX_COEFF_CTRL_1(P)   ((P) ? 0x9520 : 0x5520)
 #define IXGBE_KRM_RX_ANA_CTL(P)                ((P) ? 0x9A00 : 0x5A00)
+#define IXGBE_KRM_FLX_TMRS_CTRL_ST31(P)        ((P) ? 0x9180 : 0x5180)
 
 #define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_DA         ~(0x3 << 20)
 #define IXGBE_KRM_PMD_FLX_MASK_ST20_SFI_10G_SR         BIT(20)
index 35c2b9b..aa4bf6c 100644 (file)
@@ -1721,9 +1721,59 @@ static s32 ixgbe_setup_sfi_x550a(struct ixgbe_hw *hw, ixgbe_link_speed *speed)
                return IXGBE_ERR_LINK_SETUP;
        }
 
-       status = mac->ops.write_iosf_sb_reg(hw,
-                               IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
-                               IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+       (void)mac->ops.write_iosf_sb_reg(hw,
+                       IXGBE_KRM_PMD_FLX_MASK_ST20(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       /* change mode enforcement rules to hybrid */
+       (void)mac->ops.read_iosf_sb_reg(hw,
+                       IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       reg_val |= 0x0400;
+
+       (void)mac->ops.write_iosf_sb_reg(hw,
+                       IXGBE_KRM_FLX_TMRS_CTRL_ST31(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       /* manually control the config */
+       (void)mac->ops.read_iosf_sb_reg(hw,
+                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       reg_val |= 0x20002240;
+
+       (void)mac->ops.write_iosf_sb_reg(hw,
+                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       /* move the AN base page values */
+       (void)mac->ops.read_iosf_sb_reg(hw,
+                       IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       reg_val |= 0x1;
+
+       (void)mac->ops.write_iosf_sb_reg(hw,
+                       IXGBE_KRM_PCS_KX_AN(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       /* set the AN37 over CB mode */
+       (void)mac->ops.read_iosf_sb_reg(hw,
+                       IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       reg_val |= 0x20000000;
+
+       (void)mac->ops.write_iosf_sb_reg(hw,
+                       IXGBE_KRM_AN_CNTL_4(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
+
+       /* restart AN manually */
+       (void)mac->ops.read_iosf_sb_reg(hw,
+                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, &reg_val);
+       reg_val |= IXGBE_KRM_LINK_CTRL_1_TETH_AN_RESTART;
+
+       (void)mac->ops.write_iosf_sb_reg(hw,
+                       IXGBE_KRM_LINK_CTRL_1(hw->bus.lan_id),
+                       IXGBE_SB_IOSF_TARGET_KR_PHY, reg_val);
 
        /* Toggle port SW reset by AN reset. */
        status = ixgbe_restart_an_internal_phy_x550em(hw);
index fed4687..ccfa6b9 100644 (file)
@@ -213,8 +213,8 @@ static void ixgbevf_get_drvinfo(struct net_device *netdev,
 {
        struct ixgbevf_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, ixgbevf_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver, ixgbevf_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 
        drvinfo->n_priv_flags = IXGBEVF_PRIV_FLAGS_STR_LEN;
index f43d661..b565944 100644 (file)
@@ -2332,9 +2332,9 @@ jme_get_drvinfo(struct net_device *netdev,
 {
        struct jme_adapter *jme = netdev_priv(netdev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(jme->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(jme->pdev), sizeof(info->bus_info));
 }
 
 static int
index df9a8ee..90e458d 100644 (file)
@@ -938,9 +938,9 @@ static void netdev_get_drvinfo(struct net_device *dev,
 {
        struct korina_private *lp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, lp->dev->name, sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, lp->dev->name, sizeof(info->bus_info));
 }
 
 static int netdev_get_link_ksettings(struct net_device *dev,
index 7cedbe1..59aab40 100644 (file)
@@ -470,7 +470,7 @@ ltq_etop_stop(struct net_device *dev)
        return 0;
 }
 
-static int
+static netdev_tx_t
 ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
 {
        int queue = skb_get_queue_mapping(skb);
index b6be055..8b9abe6 100644 (file)
@@ -1603,12 +1603,12 @@ mv643xx_eth_set_link_ksettings(struct net_device *dev,
 static void mv643xx_eth_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, mv643xx_eth_driver_name,
+       strscpy(drvinfo->driver, mv643xx_eth_driver_name,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, mv643xx_eth_driver_version,
+       strscpy(drvinfo->version, mv643xx_eth_driver_version,
                sizeof(drvinfo->version));
-       strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
+       strscpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       strscpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
 }
 
 static int mv643xx_eth_get_coalesce(struct net_device *dev,
index 0caa2df..b500fe1 100644 (file)
@@ -4656,11 +4656,11 @@ mvneta_ethtool_get_coalesce(struct net_device *dev,
 static void mvneta_ethtool_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, MVNETA_DRIVER_NAME,
+       strscpy(drvinfo->driver, MVNETA_DRIVER_NAME,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, MVNETA_DRIVER_VERSION,
+       strscpy(drvinfo->version, MVNETA_DRIVER_VERSION,
                sizeof(drvinfo->version));
-       strlcpy(drvinfo->bus_info, dev_name(&dev->dev),
+       strscpy(drvinfo->bus_info, dev_name(&dev->dev),
                sizeof(drvinfo->bus_info));
 }
 
index b84128b..38e5b4b 100644 (file)
@@ -5425,11 +5425,11 @@ mvpp2_ethtool_get_coalesce(struct net_device *dev,
 static void mvpp2_ethtool_get_drvinfo(struct net_device *dev,
                                      struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, MVPP2_DRIVER_NAME,
+       strscpy(drvinfo->driver, MVPP2_DRIVER_NAME,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, MVPP2_DRIVER_VERSION,
+       strscpy(drvinfo->version, MVPP2_DRIVER_VERSION,
                sizeof(drvinfo->version));
-       strlcpy(drvinfo->bus_info, dev_name(&dev->dev),
+       strscpy(drvinfo->bus_info, dev_name(&dev->dev),
                sizeof(drvinfo->bus_info));
 }
 
index fd4f083..826f691 100644 (file)
@@ -86,8 +86,7 @@ int cn10k_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
        aq->sq.max_sqe_size = NIX_MAXSQESZ_W16; /* 128 byte */
        aq->sq.cq_ena = 1;
        aq->sq.ena = 1;
-       /* Only one SMQ is allocated, map all SQ's to that SMQ  */
-       aq->sq.smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+       aq->sq.smq = otx2_get_smq_idx(pfvf, qidx);
        aq->sq.smq_rr_weight = mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
        aq->sq.default_chan = pfvf->hw.tx_chan_base;
        aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */
index d686c7b..bc3e6aa 100644 (file)
@@ -586,8 +586,9 @@ void otx2_get_mac_from_af(struct net_device *netdev)
 }
 EXPORT_SYMBOL(otx2_get_mac_from_af);
 
-int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
+int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool txschq_for_pfc)
 {
+       u16 (*schq_list)[MAX_TXSCHQ_PER_FUNC];
        struct otx2_hw *hw = &pfvf->hw;
        struct nix_txschq_config *req;
        u64 schq, parent;
@@ -602,7 +603,13 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
        req->lvl = lvl;
        req->num_regs = 1;
 
-       schq = hw->txschq_list[lvl][0];
+       schq_list = hw->txschq_list;
+#ifdef CONFIG_DCB
+       if (txschq_for_pfc)
+               schq_list = pfvf->pfc_schq_list;
+#endif
+
+       schq = schq_list[lvl][prio];
        /* Set topology e.t.c configuration */
        if (lvl == NIX_TXSCH_LVL_SMQ) {
                req->reg[0] = NIX_AF_SMQX_CFG(schq);
@@ -611,7 +618,7 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
                                  (0x2ULL << 36);
                req->num_regs++;
                /* MDQ config */
-               parent =  hw->txschq_list[NIX_TXSCH_LVL_TL4][0];
+               parent = schq_list[NIX_TXSCH_LVL_TL4][prio];
                req->reg[1] = NIX_AF_MDQX_PARENT(schq);
                req->regval[1] = parent << 16;
                req->num_regs++;
@@ -619,14 +626,14 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
                req->reg[2] = NIX_AF_MDQX_SCHEDULE(schq);
                req->regval[2] =  dwrr_val;
        } else if (lvl == NIX_TXSCH_LVL_TL4) {
-               parent =  hw->txschq_list[NIX_TXSCH_LVL_TL3][0];
+               parent = schq_list[NIX_TXSCH_LVL_TL3][prio];
                req->reg[0] = NIX_AF_TL4X_PARENT(schq);
                req->regval[0] = parent << 16;
                req->num_regs++;
                req->reg[1] = NIX_AF_TL4X_SCHEDULE(schq);
                req->regval[1] = dwrr_val;
        } else if (lvl == NIX_TXSCH_LVL_TL3) {
-               parent = hw->txschq_list[NIX_TXSCH_LVL_TL2][0];
+               parent = schq_list[NIX_TXSCH_LVL_TL2][prio];
                req->reg[0] = NIX_AF_TL3X_PARENT(schq);
                req->regval[0] = parent << 16;
                req->num_regs++;
@@ -635,11 +642,13 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
                if (lvl == hw->txschq_link_cfg_lvl) {
                        req->num_regs++;
                        req->reg[2] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, hw->tx_link);
-                       /* Enable this queue and backpressure */
-                       req->regval[2] = BIT_ULL(13) | BIT_ULL(12);
+                       /* Enable this queue and backpressure
+                        * and set relative channel
+                        */
+                       req->regval[2] = BIT_ULL(13) | BIT_ULL(12) | prio;
                }
        } else if (lvl == NIX_TXSCH_LVL_TL2) {
-               parent =  hw->txschq_list[NIX_TXSCH_LVL_TL1][0];
+               parent = schq_list[NIX_TXSCH_LVL_TL1][prio];
                req->reg[0] = NIX_AF_TL2X_PARENT(schq);
                req->regval[0] = parent << 16;
 
@@ -650,8 +659,10 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
                if (lvl == hw->txschq_link_cfg_lvl) {
                        req->num_regs++;
                        req->reg[2] = NIX_AF_TL3_TL2X_LINKX_CFG(schq, hw->tx_link);
-                       /* Enable this queue and backpressure */
-                       req->regval[2] = BIT_ULL(13) | BIT_ULL(12);
+                       /* Enable this queue and backpressure
+                        * and set relative channel
+                        */
+                       req->regval[2] = BIT_ULL(13) | BIT_ULL(12) | prio;
                }
        } else if (lvl == NIX_TXSCH_LVL_TL1) {
                /* Default config for TL1.
@@ -676,6 +687,31 @@ int otx2_txschq_config(struct otx2_nic *pfvf, int lvl)
 
        return otx2_sync_mbox_msg(&pfvf->mbox);
 }
+EXPORT_SYMBOL(otx2_txschq_config);
+
+int otx2_smq_flush(struct otx2_nic *pfvf, int smq)
+{
+       struct nix_txschq_config *req;
+       int rc;
+
+       mutex_lock(&pfvf->mbox.lock);
+
+       req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
+       if (!req) {
+               mutex_unlock(&pfvf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       req->lvl = NIX_TXSCH_LVL_SMQ;
+       req->reg[0] = NIX_AF_SMQX_CFG(smq);
+       req->regval[0] |= BIT_ULL(49);
+       req->num_regs++;
+
+       rc = otx2_sync_mbox_msg(&pfvf->mbox);
+       mutex_unlock(&pfvf->mbox.lock);
+       return rc;
+}
+EXPORT_SYMBOL(otx2_smq_flush);
 
 int otx2_txsch_alloc(struct otx2_nic *pfvf)
 {
@@ -806,8 +842,7 @@ int otx2_sq_aq_init(void *dev, u16 qidx, u16 sqb_aura)
        aq->sq.max_sqe_size = NIX_MAXSQESZ_W16; /* 128 byte */
        aq->sq.cq_ena = 1;
        aq->sq.ena = 1;
-       /* Only one SMQ is allocated, map all SQ's to that SMQ  */
-       aq->sq.smq = pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+       aq->sq.smq = otx2_get_smq_idx(pfvf, qidx);
        aq->sq.smq_rr_quantum = mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
        aq->sq.default_chan = pfvf->hw.tx_chan_base;
        aq->sq.sqe_stype = NIX_STYPE_STF; /* Cache SQB */
index b28029c..2394862 100644 (file)
 
 #define NAME_SIZE                               32
 
+#ifdef CONFIG_DCB
+/* Max priority supported for PFC */
+#define NIX_PF_PFC_PRIO_MAX                    8
+#endif
+
 enum arua_mapped_qtypes {
        AURA_NIX_RQ,
        AURA_NIX_SQ,
@@ -196,7 +201,7 @@ struct otx2_hw {
 
        /* NIX */
        u8                      txschq_link_cfg_lvl;
-       u16             txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
+       u16                     txschq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
        u16                     matchall_ipolicer;
        u32                     dwrr_mtu;
 
@@ -415,6 +420,8 @@ struct otx2_nic {
        /* PFC */
        u8                      pfc_en;
        u8                      *queue_to_pfc_map;
+       u16                     pfc_schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
+       bool                    pfc_alloc_status[NIX_PF_PFC_PRIO_MAX];
 #endif
 
        /* napi event count. It is needed for adaptive irq coalescing. */
@@ -785,6 +792,16 @@ static inline void otx2_dma_unmap_page(struct otx2_nic *pfvf,
                             dir, DMA_ATTR_SKIP_CPU_SYNC);
 }
 
+static inline u16 otx2_get_smq_idx(struct otx2_nic *pfvf, u16 qidx)
+{
+#ifdef CONFIG_DCB
+       if (pfvf->pfc_alloc_status[qidx])
+               return pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][qidx];
+#endif
+
+       return pfvf->hw.txschq_list[NIX_TXSCH_LVL_SMQ][0];
+}
+
 /* MSI-X APIs */
 void otx2_free_cints(struct otx2_nic *pfvf, int n);
 void otx2_set_cints_affinity(struct otx2_nic *pfvf);
@@ -807,7 +824,7 @@ void otx2_free_aura_ptr(struct otx2_nic *pfvf, int type);
 void otx2_sq_free_sqbs(struct otx2_nic *pfvf);
 int otx2_config_nix(struct otx2_nic *pfvf);
 int otx2_config_nix_queues(struct otx2_nic *pfvf);
-int otx2_txschq_config(struct otx2_nic *pfvf, int lvl);
+int otx2_txschq_config(struct otx2_nic *pfvf, int lvl, int prio, bool pfc_en);
 int otx2_txsch_alloc(struct otx2_nic *pfvf);
 int otx2_txschq_stop(struct otx2_nic *pfvf);
 void otx2_sqb_flush(struct otx2_nic *pfvf);
@@ -888,6 +905,8 @@ bool otx2_xdp_sq_append_pkt(struct otx2_nic *pfvf, u64 iova, int len, u16 qidx);
 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);
+
 /* tc support */
 int otx2_init_tc(struct otx2_nic *nic);
 void otx2_shutdown_tc(struct otx2_nic *nic);
@@ -907,5 +926,10 @@ void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf);
 void otx2_update_bpid_in_rqctx(struct otx2_nic *pfvf, int vlan_prio, int qidx, bool pfc_enable);
 int otx2_config_priority_flow_ctrl(struct otx2_nic *pfvf);
 int otx2_dcbnl_set_ops(struct net_device *dev);
+/* PFC support */
+int otx2_pfc_txschq_config(struct otx2_nic *pfvf);
+int otx2_pfc_txschq_alloc(struct otx2_nic *pfvf);
+int otx2_pfc_txschq_update(struct otx2_nic *pfvf);
+int otx2_pfc_txschq_stop(struct otx2_nic *pfvf);
 #endif
 #endif /* OTX2_COMMON_H */
index 723d250..ccaf97b 100644 (file)
@@ -7,6 +7,289 @@
 
 #include "otx2_common.h"
 
+static int otx2_check_pfc_config(struct otx2_nic *pfvf)
+{
+       u8 tx_queues = pfvf->hw.tx_queues, prio;
+       u8 pfc_en = pfvf->pfc_en;
+
+       for (prio = 0; prio < NIX_PF_PFC_PRIO_MAX; prio++) {
+               if ((pfc_en & (1 << prio)) &&
+                   prio > tx_queues - 1) {
+                       dev_warn(pfvf->dev,
+                                "Increase number of tx queues from %d to %d to support PFC.\n",
+                                tx_queues, prio + 1);
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+int otx2_pfc_txschq_config(struct otx2_nic *pfvf)
+{
+       u8 pfc_en, pfc_bit_set;
+       int prio, lvl, err;
+
+       pfc_en = pfvf->pfc_en;
+       for (prio = 0; prio < NIX_PF_PFC_PRIO_MAX; prio++) {
+               pfc_bit_set = pfc_en & (1 << prio);
+
+               /* Either PFC bit is not set
+                * or tx scheduler is not allocated for the priority
+                */
+               if (!pfc_bit_set || !pfvf->pfc_alloc_status[prio])
+                       continue;
+
+               /* configure the scheduler for the tls*/
+               for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
+                       err = otx2_txschq_config(pfvf, lvl, prio, true);
+                       if (err) {
+                               dev_err(pfvf->dev,
+                                       "%s configure PFC tx schq for lvl:%d, prio:%d failed!\n",
+                                       __func__, lvl, prio);
+                               return err;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int otx2_pfc_txschq_alloc_one(struct otx2_nic *pfvf, u8 prio)
+{
+       struct nix_txsch_alloc_req *req;
+       struct nix_txsch_alloc_rsp *rsp;
+       int lvl, rc;
+
+       /* Get memory to put this msg */
+       req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
+       if (!req)
+               return -ENOMEM;
+
+       /* Request one schq per level upto max level as configured
+        * link config level. These rest of the scheduler can be
+        * same as hw.txschq_list.
+        */
+       for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++)
+               req->schq[lvl] = 1;
+
+       rc = otx2_sync_mbox_msg(&pfvf->mbox);
+       if (rc)
+               return rc;
+
+       rsp = (struct nix_txsch_alloc_rsp *)
+             otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
+       if (IS_ERR(rsp))
+               return PTR_ERR(rsp);
+
+       /* Setup transmit scheduler list */
+       for (lvl = 0; lvl < pfvf->hw.txschq_link_cfg_lvl; lvl++) {
+               if (!rsp->schq[lvl])
+                       return -ENOSPC;
+
+               pfvf->pfc_schq_list[lvl][prio] = rsp->schq_list[lvl][0];
+       }
+
+       /* Set the Tx schedulers for rest of the levels same as
+        * hw.txschq_list as those will be common for all.
+        */
+       for (; lvl < NIX_TXSCH_LVL_CNT; lvl++)
+               pfvf->pfc_schq_list[lvl][prio] = pfvf->hw.txschq_list[lvl][0];
+
+       pfvf->pfc_alloc_status[prio] = true;
+       return 0;
+}
+
+int otx2_pfc_txschq_alloc(struct otx2_nic *pfvf)
+{
+       u8 pfc_en = pfvf->pfc_en;
+       u8 pfc_bit_set;
+       int err, prio;
+
+       for (prio = 0; prio < NIX_PF_PFC_PRIO_MAX; prio++) {
+               pfc_bit_set = pfc_en & (1 << prio);
+
+               if (!pfc_bit_set || pfvf->pfc_alloc_status[prio])
+                       continue;
+
+               /* Add new scheduler to the priority */
+               err = otx2_pfc_txschq_alloc_one(pfvf, prio);
+               if (err) {
+                       dev_err(pfvf->dev, "%s failed to allocate PFC TX schedulers\n", __func__);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
+static int otx2_pfc_txschq_stop_one(struct otx2_nic *pfvf, u8 prio)
+{
+       struct nix_txsch_free_req *free_req;
+
+       mutex_lock(&pfvf->mbox.lock);
+       /* free PFC TLx nodes */
+       free_req = otx2_mbox_alloc_msg_nix_txsch_free(&pfvf->mbox);
+       if (!free_req) {
+               mutex_unlock(&pfvf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       free_req->flags = TXSCHQ_FREE_ALL;
+       otx2_sync_mbox_msg(&pfvf->mbox);
+       mutex_unlock(&pfvf->mbox.lock);
+
+       pfvf->pfc_alloc_status[prio] = false;
+       return 0;
+}
+
+static int otx2_pfc_update_sq_smq_mapping(struct otx2_nic *pfvf, int prio)
+{
+       struct nix_cn10k_aq_enq_req *cn10k_sq_aq;
+       struct net_device *dev = pfvf->netdev;
+       bool if_up = netif_running(dev);
+       struct nix_aq_enq_req *sq_aq;
+
+       if (if_up) {
+               if (pfvf->pfc_alloc_status[prio])
+                       netif_tx_stop_all_queues(pfvf->netdev);
+               else
+                       netif_tx_stop_queue(netdev_get_tx_queue(dev, prio));
+       }
+
+       if (test_bit(CN10K_LMTST, &pfvf->hw.cap_flag)) {
+               cn10k_sq_aq = otx2_mbox_alloc_msg_nix_cn10k_aq_enq(&pfvf->mbox);
+               if (!cn10k_sq_aq)
+                       return -ENOMEM;
+
+               /* Fill AQ info */
+               cn10k_sq_aq->qidx = prio;
+               cn10k_sq_aq->ctype = NIX_AQ_CTYPE_SQ;
+               cn10k_sq_aq->op = NIX_AQ_INSTOP_WRITE;
+
+               /* Fill fields to update */
+               cn10k_sq_aq->sq.ena = 1;
+               cn10k_sq_aq->sq_mask.ena = 1;
+               cn10k_sq_aq->sq_mask.smq = GENMASK(9, 0);
+               cn10k_sq_aq->sq.smq = otx2_get_smq_idx(pfvf, prio);
+       } else {
+               sq_aq = otx2_mbox_alloc_msg_nix_aq_enq(&pfvf->mbox);
+               if (!sq_aq)
+                       return -ENOMEM;
+
+               /* Fill AQ info */
+               sq_aq->qidx = prio;
+               sq_aq->ctype = NIX_AQ_CTYPE_SQ;
+               sq_aq->op = NIX_AQ_INSTOP_WRITE;
+
+               /* Fill fields to update */
+               sq_aq->sq.ena = 1;
+               sq_aq->sq_mask.ena = 1;
+               sq_aq->sq_mask.smq = GENMASK(8, 0);
+               sq_aq->sq.smq = otx2_get_smq_idx(pfvf, prio);
+       }
+
+       otx2_sync_mbox_msg(&pfvf->mbox);
+
+       if (if_up) {
+               if (pfvf->pfc_alloc_status[prio])
+                       netif_tx_start_all_queues(pfvf->netdev);
+               else
+                       netif_tx_start_queue(netdev_get_tx_queue(dev, prio));
+       }
+
+       return 0;
+}
+
+int otx2_pfc_txschq_update(struct otx2_nic *pfvf)
+{
+       bool if_up = netif_running(pfvf->netdev);
+       u8 pfc_en = pfvf->pfc_en, pfc_bit_set;
+       struct mbox *mbox = &pfvf->mbox;
+       int err, prio;
+
+       mutex_lock(&mbox->lock);
+       for (prio = 0; prio < NIX_PF_PFC_PRIO_MAX; prio++) {
+               pfc_bit_set = pfc_en & (1 << prio);
+
+               /* tx scheduler was created but user wants to disable now */
+               if (!pfc_bit_set && pfvf->pfc_alloc_status[prio]) {
+                       mutex_unlock(&mbox->lock);
+                       if (if_up)
+                               netif_tx_stop_all_queues(pfvf->netdev);
+
+                       otx2_smq_flush(pfvf, pfvf->pfc_schq_list[NIX_TXSCH_LVL_SMQ][prio]);
+                       if (if_up)
+                               netif_tx_start_all_queues(pfvf->netdev);
+
+                       /* delete the schq */
+                       err = otx2_pfc_txschq_stop_one(pfvf, prio);
+                       if (err) {
+                               dev_err(pfvf->dev,
+                                       "%s failed to stop PFC tx schedulers for priority: %d\n",
+                                       __func__, prio);
+                               return err;
+                       }
+
+                       mutex_lock(&mbox->lock);
+                       goto update_sq_smq_map;
+               }
+
+               /* Either PFC bit is not set
+                * or Tx scheduler is already mapped for the priority
+                */
+               if (!pfc_bit_set || pfvf->pfc_alloc_status[prio])
+                       continue;
+
+               /* Add new scheduler to the priority */
+               err = otx2_pfc_txschq_alloc_one(pfvf, prio);
+               if (err) {
+                       mutex_unlock(&mbox->lock);
+                       dev_err(pfvf->dev,
+                               "%s failed to allocate PFC tx schedulers for priority: %d\n",
+                               __func__, prio);
+                       return err;
+               }
+
+update_sq_smq_map:
+               err = otx2_pfc_update_sq_smq_mapping(pfvf, prio);
+               if (err) {
+                       mutex_unlock(&mbox->lock);
+                       dev_err(pfvf->dev, "%s failed PFC Tx schq sq:%d mapping", __func__, prio);
+                       return err;
+               }
+       }
+
+       err = otx2_pfc_txschq_config(pfvf);
+       mutex_unlock(&mbox->lock);
+       if (err)
+               return err;
+
+       return 0;
+}
+
+int otx2_pfc_txschq_stop(struct otx2_nic *pfvf)
+{
+       u8 pfc_en, pfc_bit_set;
+       int prio, err;
+
+       pfc_en = pfvf->pfc_en;
+       for (prio = 0; prio < NIX_PF_PFC_PRIO_MAX; prio++) {
+               pfc_bit_set = pfc_en & (1 << prio);
+               if (!pfc_bit_set || !pfvf->pfc_alloc_status[prio])
+                       continue;
+
+               /* Delete the existing scheduler */
+               err = otx2_pfc_txschq_stop_one(pfvf, prio);
+               if (err) {
+                       dev_err(pfvf->dev, "%s failed to stop PFC TX schedulers\n", __func__);
+                       return err;
+               }
+       }
+
+       return 0;
+}
+
 int otx2_config_priority_flow_ctrl(struct otx2_nic *pfvf)
 {
        struct cgx_pfc_cfg *req;
@@ -128,6 +411,17 @@ static int otx2_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
        /* Save PFC configuration to interface */
        pfvf->pfc_en = pfc->pfc_en;
 
+       if (pfvf->hw.tx_queues >= NIX_PF_PFC_PRIO_MAX)
+               goto process_pfc;
+
+       /* Check if the PFC configuration can be
+        * supported by the tx queue configuration
+        */
+       err = otx2_check_pfc_config(pfvf);
+       if (err)
+               return err;
+
+process_pfc:
        err = otx2_config_priority_flow_ctrl(pfvf);
        if (err)
                return err;
@@ -136,6 +430,12 @@ static int otx2_dcbnl_ieee_setpfc(struct net_device *dev, struct ieee_pfc *pfc)
        if (pfc->pfc_en)
                otx2_nix_config_bp(pfvf, true);
 
+       err = otx2_pfc_txschq_update(pfvf);
+       if (err) {
+               dev_err(pfvf->dev, "%s failed to update TX schedulers\n", __func__);
+               return err;
+       }
+
        return 0;
 }
 
index 3f60a80..5bd16e9 100644 (file)
@@ -76,8 +76,8 @@ static void otx2_get_drvinfo(struct net_device *netdev,
 {
        struct otx2_nic *pfvf = netdev_priv(netdev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(pfvf->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(pfvf->pdev), sizeof(info->bus_info));
 }
 
 static void otx2_get_qset_strings(struct otx2_nic *pfvf, u8 **data, int qset)
@@ -1313,8 +1313,8 @@ static void otx2vf_get_drvinfo(struct net_device *netdev,
 {
        struct otx2_nic *vf = netdev_priv(netdev);
 
-       strlcpy(info->driver, DRV_VF_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(vf->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_VF_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(vf->pdev), sizeof(info->bus_info));
 }
 
 static void otx2vf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
index 9376d0e..49a4ff0 100644 (file)
@@ -1389,18 +1389,40 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
                goto err_free_sq_ptrs;
        }
 
+#ifdef CONFIG_DCB
+       if (pf->pfc_en) {
+               err = otx2_pfc_txschq_alloc(pf);
+               if (err) {
+                       mutex_unlock(&mbox->lock);
+                       goto err_free_sq_ptrs;
+               }
+       }
+#endif
+
        err = otx2_config_nix_queues(pf);
        if (err) {
                mutex_unlock(&mbox->lock);
                goto err_free_txsch;
        }
+
        for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
-               err = otx2_txschq_config(pf, lvl);
+               err = otx2_txschq_config(pf, lvl, 0, false);
+               if (err) {
+                       mutex_unlock(&mbox->lock);
+                       goto err_free_nix_queues;
+               }
+       }
+
+#ifdef CONFIG_DCB
+       if (pf->pfc_en) {
+               err = otx2_pfc_txschq_config(pf);
                if (err) {
                        mutex_unlock(&mbox->lock);
                        goto err_free_nix_queues;
                }
        }
+#endif
+
        mutex_unlock(&mbox->lock);
        return err;
 
@@ -1455,6 +1477,11 @@ static void otx2_free_hw_resources(struct otx2_nic *pf)
        if (err)
                dev_err(pf->dev, "RVUPF: Failed to stop/free TX schedulers\n");
 
+#ifdef CONFIG_DCB
+       if (pf->pfc_en)
+               otx2_pfc_txschq_stop(pf);
+#endif
+
        mutex_lock(&mbox->lock);
        /* Disable backpressure */
        if (!(pf->pcifunc & RVU_PFVF_FUNC_MASK))
@@ -1853,6 +1880,30 @@ static netdev_tx_t otx2_xmit(struct sk_buff *skb, struct net_device *netdev)
        return NETDEV_TX_OK;
 }
 
+static u16 otx2_select_queue(struct net_device *netdev, struct sk_buff *skb,
+                            struct net_device *sb_dev)
+{
+       struct otx2_nic *pf = netdev_priv(netdev);
+#ifdef CONFIG_DCB
+       u8 vlan_prio;
+#endif
+
+#ifdef CONFIG_DCB
+       if (!skb->vlan_present)
+               goto pick_tx;
+
+       vlan_prio = skb->vlan_tci >> 13;
+       if ((vlan_prio > pf->hw.tx_queues - 1) ||
+           !pf->pfc_alloc_status[vlan_prio])
+               goto pick_tx;
+
+       return vlan_prio;
+
+pick_tx:
+#endif
+       return netdev_pick_tx(netdev, skb, NULL);
+}
+
 static netdev_features_t otx2_fix_features(struct net_device *dev,
                                           netdev_features_t features)
 {
@@ -2447,6 +2498,7 @@ static const struct net_device_ops otx2_netdev_ops = {
        .ndo_open               = otx2_open,
        .ndo_stop               = otx2_stop,
        .ndo_start_xmit         = otx2_xmit,
+       .ndo_select_queue       = otx2_select_queue,
        .ndo_fix_features       = otx2_fix_features,
        .ndo_set_mac_address    = otx2_set_mac_address,
        .ndo_change_mtu         = otx2_change_mtu,
index d395f41..df14cee 100644 (file)
@@ -4,6 +4,6 @@ prestera-objs           := prestera_main.o prestera_hw.o prestera_dsa.o \
                           prestera_rxtx.o prestera_devlink.o prestera_ethtool.o \
                           prestera_switchdev.o prestera_acl.o prestera_flow.o \
                           prestera_flower.o prestera_span.o prestera_counter.o \
-                          prestera_router.o prestera_router_hw.o
+                          prestera_router.o prestera_router_hw.o prestera_matchall.o
 
 obj-$(CONFIG_PRESTERA_PCI)     += prestera_pci.o
index 2f84d0f..e5a4381 100644 (file)
@@ -367,6 +367,8 @@ int prestera_port_learning_set(struct prestera_port *port, bool learn_enable);
 int prestera_port_uc_flood_set(struct prestera_port *port, bool flood);
 int prestera_port_mc_flood_set(struct prestera_port *port, bool flood);
 
+int prestera_port_br_locked_set(struct prestera_port *port, bool br_locked);
+
 int prestera_port_pvid_set(struct prestera_port *port, u16 vid);
 
 bool prestera_netdev_check(const struct net_device *dev);
index 3d4b85f..0fa7541 100644 (file)
@@ -54,6 +54,10 @@ struct prestera_acl_ruleset {
        struct prestera_acl_ruleset_ht_key ht_key;
        struct rhashtable rule_ht;
        struct prestera_acl *acl;
+       struct {
+               u32 min;
+               u32 max;
+       } prio;
        unsigned long rule_count;
        refcount_t refcount;
        void *keymask;
@@ -162,6 +166,9 @@ prestera_acl_ruleset_create(struct prestera_acl *acl,
        ruleset->pcl_id = PRESTERA_ACL_PCL_ID_MAKE((u8)uid, chain_index);
        ruleset->index = uid;
 
+       ruleset->prio.min = UINT_MAX;
+       ruleset->prio.max = 0;
+
        err = rhashtable_insert_fast(&acl->ruleset_ht, &ruleset->ht_node,
                                     prestera_acl_ruleset_ht_params);
        if (err)
@@ -365,6 +372,26 @@ prestera_acl_ruleset_block_unbind(struct prestera_acl_ruleset *ruleset,
        block->ruleset_zero = NULL;
 }
 
+static void
+prestera_acl_ruleset_prio_refresh(struct prestera_acl *acl,
+                                 struct prestera_acl_ruleset *ruleset)
+{
+       struct prestera_acl_rule *rule;
+
+       ruleset->prio.min = UINT_MAX;
+       ruleset->prio.max = 0;
+
+       list_for_each_entry(rule, &acl->rules, list) {
+               if (ruleset->ingress != rule->ruleset->ingress)
+                       continue;
+               if (ruleset->ht_key.chain_index != rule->chain_index)
+                       continue;
+
+               ruleset->prio.min = min(ruleset->prio.min, rule->priority);
+               ruleset->prio.max = max(ruleset->prio.max, rule->priority);
+       }
+}
+
 void
 prestera_acl_rule_keymask_pcl_id_set(struct prestera_acl_rule *rule, u16 pcl_id)
 {
@@ -389,6 +416,13 @@ u32 prestera_acl_ruleset_index_get(const struct prestera_acl_ruleset *ruleset)
        return ruleset->index;
 }
 
+void prestera_acl_ruleset_prio_get(struct prestera_acl_ruleset *ruleset,
+                                  u32 *prio_min, u32 *prio_max)
+{
+       *prio_min = ruleset->prio.min;
+       *prio_max = ruleset->prio.max;
+}
+
 bool prestera_acl_ruleset_is_offload(struct prestera_acl_ruleset *ruleset)
 {
        return ruleset->offload;
@@ -429,6 +463,13 @@ void prestera_acl_rule_destroy(struct prestera_acl_rule *rule)
        kfree(rule);
 }
 
+static void prestera_acl_ruleset_prio_update(struct prestera_acl_ruleset *ruleset,
+                                            u32 prio)
+{
+       ruleset->prio.min = min(ruleset->prio.min, prio);
+       ruleset->prio.max = max(ruleset->prio.max, prio);
+}
+
 int prestera_acl_rule_add(struct prestera_switch *sw,
                          struct prestera_acl_rule *rule)
 {
@@ -468,6 +509,7 @@ int prestera_acl_rule_add(struct prestera_switch *sw,
 
        list_add_tail(&rule->list, &sw->acl->rules);
        ruleset->rule_count++;
+       prestera_acl_ruleset_prio_update(ruleset, rule->priority);
        return 0;
 
 err_acl_block_bind:
@@ -492,6 +534,7 @@ void prestera_acl_rule_del(struct prestera_switch *sw,
        list_del(&rule->list);
 
        prestera_acl_rule_entry_destroy(sw->acl, rule->re);
+       prestera_acl_ruleset_prio_refresh(sw->acl, ruleset);
 
        /* unbind block (all ports) */
        if (!ruleset->ht_key.chain_index && !ruleset->rule_count)
index 03fc5b9..d45ee88 100644 (file)
@@ -195,6 +195,8 @@ int prestera_acl_ruleset_bind(struct prestera_acl_ruleset *ruleset,
 int prestera_acl_ruleset_unbind(struct prestera_acl_ruleset *ruleset,
                                struct prestera_port *port);
 u32 prestera_acl_ruleset_index_get(const struct prestera_acl_ruleset *ruleset);
+void prestera_acl_ruleset_prio_get(struct prestera_acl_ruleset *ruleset,
+                                  u32 *prio_min, u32 *prio_max);
 void
 prestera_acl_rule_keymask_pcl_id_set(struct prestera_acl_rule *rule,
                                     u16 pcl_id);
index 1da7ff8..2f52dab 100644 (file)
@@ -300,8 +300,8 @@ static void prestera_ethtool_get_drvinfo(struct net_device *dev,
        struct prestera_port *port = netdev_priv(dev);
        struct prestera_switch *sw = port->sw;
 
-       strlcpy(drvinfo->driver, driver_kind, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, dev_name(prestera_dev(sw)),
+       strscpy(drvinfo->driver, driver_kind, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, dev_name(prestera_dev(sw)),
                sizeof(drvinfo->bus_info));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                 "%d.%d.%d",
index 2262693..9f4267f 100644 (file)
@@ -7,8 +7,9 @@
 #include "prestera.h"
 #include "prestera_acl.h"
 #include "prestera_flow.h"
-#include "prestera_span.h"
 #include "prestera_flower.h"
+#include "prestera_matchall.h"
+#include "prestera_span.h"
 
 static LIST_HEAD(prestera_block_cb_list);
 
@@ -17,9 +18,9 @@ static int prestera_flow_block_mall_cb(struct prestera_flow_block *block,
 {
        switch (f->command) {
        case TC_CLSMATCHALL_REPLACE:
-               return prestera_span_replace(block, f);
+               return prestera_mall_replace(block, f);
        case TC_CLSMATCHALL_DESTROY:
-               prestera_span_destroy(block);
+               prestera_mall_destroy(block);
                return 0;
        default:
                return -EOPNOTSUPP;
@@ -89,6 +90,9 @@ prestera_flow_block_create(struct prestera_switch *sw,
        INIT_LIST_HEAD(&block->template_list);
        block->net = net;
        block->sw = sw;
+       block->mall.prio_min = UINT_MAX;
+       block->mall.prio_max = 0;
+       block->mall.bound = false;
        block->ingress = ingress;
 
        return block;
@@ -263,7 +267,7 @@ static void prestera_setup_flow_block_unbind(struct prestera_port *port,
 
        block = flow_block_cb_priv(block_cb);
 
-       prestera_span_destroy(block);
+       prestera_mall_destroy(block);
 
        err = prestera_flow_block_unbind(block, port);
        if (err)
index 0c9e132..a85a3eb 100644 (file)
@@ -22,6 +22,11 @@ struct prestera_flow_block {
        struct prestera_acl_ruleset *ruleset_zero;
        struct flow_block_cb *block_cb;
        struct list_head template_list;
+       struct {
+               u32 prio_min;
+               u32 prio_max;
+               bool bound;
+       } mall;
        unsigned int rule_count;
        bool ingress;
 };
index 19d3b55..f38e8b3 100644 (file)
@@ -5,6 +5,7 @@
 #include "prestera_acl.h"
 #include "prestera_flow.h"
 #include "prestera_flower.h"
+#include "prestera_matchall.h"
 
 struct prestera_flower_template {
        struct prestera_acl_ruleset *ruleset;
@@ -360,6 +361,49 @@ static int prestera_flower_parse(struct prestera_flow_block *block,
                                             f->common.extack);
 }
 
+static int prestera_flower_prio_check(struct prestera_flow_block *block,
+                                     struct flow_cls_offload *f)
+{
+       u32 mall_prio_min;
+       u32 mall_prio_max;
+       int err;
+
+       err = prestera_mall_prio_get(block, &mall_prio_min, &mall_prio_max);
+       if (err == -ENOENT)
+               /* No matchall filters installed on this chain. */
+               return 0;
+
+       if (err) {
+               NL_SET_ERR_MSG(f->common.extack, "Failed to get matchall priorities");
+               return err;
+       }
+
+       if (f->common.prio <= mall_prio_max && block->ingress) {
+               NL_SET_ERR_MSG(f->common.extack,
+                              "Failed to add in front of existing matchall rules");
+               return -EOPNOTSUPP;
+       }
+       if (f->common.prio >= mall_prio_min && !block->ingress) {
+               NL_SET_ERR_MSG(f->common.extack, "Failed to add behind of existing matchall rules");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+int prestera_flower_prio_get(struct prestera_flow_block *block, u32 chain_index,
+                            u32 *prio_min, u32 *prio_max)
+{
+       struct prestera_acl_ruleset *ruleset;
+
+       ruleset = prestera_acl_ruleset_lookup(block->sw->acl, block, chain_index);
+       if (IS_ERR(ruleset))
+               return PTR_ERR(ruleset);
+
+       prestera_acl_ruleset_prio_get(ruleset, prio_min, prio_max);
+       return 0;
+}
+
 int prestera_flower_replace(struct prestera_flow_block *block,
                            struct flow_cls_offload *f)
 {
@@ -368,6 +412,10 @@ int prestera_flower_replace(struct prestera_flow_block *block,
        struct prestera_acl_rule *rule;
        int err;
 
+       err = prestera_flower_prio_check(block, f);
+       if (err)
+               return err;
+
        ruleset = prestera_acl_ruleset_get(acl, block, f->common.chain_index);
        if (IS_ERR(ruleset))
                return PTR_ERR(ruleset);
index 495f151..1181115 100644 (file)
@@ -19,5 +19,7 @@ int prestera_flower_tmplt_create(struct prestera_flow_block *block,
 void prestera_flower_tmplt_destroy(struct prestera_flow_block *block,
                                   struct flow_cls_offload *f);
 void prestera_flower_template_cleanup(struct prestera_flow_block *block);
+int prestera_flower_prio_get(struct prestera_flow_block *block, u32 chain_index,
+                            u32 *prio_min, u32 *prio_max);
 
 #endif /* _PRESTERA_FLOWER_H_ */
index 962d7e0..5803a28 100644 (file)
@@ -78,9 +78,11 @@ enum prestera_cmd_type_t {
        PRESTERA_CMD_TYPE_STP_PORT_SET = 0x1000,
 
        PRESTERA_CMD_TYPE_SPAN_GET = 0x1100,
-       PRESTERA_CMD_TYPE_SPAN_BIND = 0x1101,
-       PRESTERA_CMD_TYPE_SPAN_UNBIND = 0x1102,
+       PRESTERA_CMD_TYPE_SPAN_INGRESS_BIND = 0x1101,
+       PRESTERA_CMD_TYPE_SPAN_INGRESS_UNBIND = 0x1102,
        PRESTERA_CMD_TYPE_SPAN_RELEASE = 0x1103,
+       PRESTERA_CMD_TYPE_SPAN_EGRESS_BIND = 0x1104,
+       PRESTERA_CMD_TYPE_SPAN_EGRESS_UNBIND = 0x1105,
 
        PRESTERA_CMD_TYPE_POLICER_CREATE = 0x1500,
        PRESTERA_CMD_TYPE_POLICER_RELEASE = 0x1501,
@@ -101,6 +103,7 @@ enum {
        PRESTERA_CMD_PORT_ATTR_LEARNING = 7,
        PRESTERA_CMD_PORT_ATTR_FLOOD = 8,
        PRESTERA_CMD_PORT_ATTR_CAPABILITY = 9,
+       PRESTERA_CMD_PORT_ATTR_LOCKED = 10,
        PRESTERA_CMD_PORT_ATTR_PHY_MODE = 12,
        PRESTERA_CMD_PORT_ATTR_TYPE = 13,
        PRESTERA_CMD_PORT_ATTR_STATS = 17,
@@ -285,6 +288,7 @@ union prestera_msg_port_param {
        u8 duplex;
        u8 fec;
        u8 fc;
+       u8 br_locked;
        union {
                struct {
                        u8 admin;
@@ -745,6 +749,7 @@ static void prestera_hw_build_tests(void)
        BUILD_BUG_ON(sizeof(struct prestera_msg_rif_resp) != 12);
        BUILD_BUG_ON(sizeof(struct prestera_msg_vr_resp) != 12);
        BUILD_BUG_ON(sizeof(struct prestera_msg_policer_resp) != 12);
+       BUILD_BUG_ON(sizeof(struct prestera_msg_flood_domain_create_resp) != 12);
 
        /* check events */
        BUILD_BUG_ON(sizeof(struct prestera_msg_event_port) != 20);
@@ -1431,27 +1436,39 @@ int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id)
        return 0;
 }
 
-int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id)
+int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id,
+                         bool ingress)
 {
        struct prestera_msg_span_req req = {
                .port = __cpu_to_le32(port->hw_id),
                .dev = __cpu_to_le32(port->dev_id),
                .id = span_id,
        };
+       enum prestera_cmd_type_t cmd_type;
+
+       if (ingress)
+               cmd_type = PRESTERA_CMD_TYPE_SPAN_INGRESS_BIND;
+       else
+               cmd_type = PRESTERA_CMD_TYPE_SPAN_EGRESS_BIND;
+
+       return prestera_cmd(port->sw, cmd_type, &req.cmd, sizeof(req));
 
-       return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_BIND,
-                           &req.cmd, sizeof(req));
 }
 
-int prestera_hw_span_unbind(const struct prestera_port *port)
+int prestera_hw_span_unbind(const struct prestera_port *port, bool ingress)
 {
        struct prestera_msg_span_req req = {
                .port = __cpu_to_le32(port->hw_id),
                .dev = __cpu_to_le32(port->dev_id),
        };
+       enum prestera_cmd_type_t cmd_type;
 
-       return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_SPAN_UNBIND,
-                           &req.cmd, sizeof(req));
+       if (ingress)
+               cmd_type = PRESTERA_CMD_TYPE_SPAN_INGRESS_UNBIND;
+       else
+               cmd_type = PRESTERA_CMD_TYPE_SPAN_EGRESS_UNBIND;
+
+       return prestera_cmd(port->sw, cmd_type, &req.cmd, sizeof(req));
 }
 
 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id)
@@ -1639,6 +1656,22 @@ int prestera_hw_port_mc_flood_set(const struct prestera_port *port, bool flood)
                            &req.cmd, sizeof(req));
 }
 
+int prestera_hw_port_br_locked_set(const struct prestera_port *port,
+                                  bool br_locked)
+{
+       struct prestera_msg_port_attr_req req = {
+               .attr = __cpu_to_le32(PRESTERA_CMD_PORT_ATTR_LOCKED),
+               .port = __cpu_to_le32(port->hw_id),
+               .dev = __cpu_to_le32(port->dev_id),
+               .param = {
+                       .br_locked = br_locked,
+               }
+       };
+
+       return prestera_cmd(port->sw, PRESTERA_CMD_TYPE_PORT_ATTR_SET,
+                           &req.cmd, sizeof(req));
+}
+
 int prestera_hw_vlan_create(struct prestera_switch *sw, u16 vid)
 {
        struct prestera_msg_vlan_req req = {
index 56e0431..21078a2 100644 (file)
@@ -183,6 +183,8 @@ int prestera_hw_port_speed_get(const struct prestera_port *port, u32 *speed);
 int prestera_hw_port_learning_set(struct prestera_port *port, bool enable);
 int prestera_hw_port_uc_flood_set(const struct prestera_port *port, bool flood);
 int prestera_hw_port_mc_flood_set(const struct prestera_port *port, bool flood);
+int prestera_hw_port_br_locked_set(const struct prestera_port *port,
+                                  bool br_locked);
 int prestera_hw_port_accept_frm_type(struct prestera_port *port,
                                     enum prestera_accept_frm_type type);
 /* Vlan API */
@@ -243,8 +245,9 @@ int prestera_hw_counter_clear(struct prestera_switch *sw, u32 block_id,
 
 /* SPAN API */
 int prestera_hw_span_get(const struct prestera_port *port, u8 *span_id);
-int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id);
-int prestera_hw_span_unbind(const struct prestera_port *port);
+int prestera_hw_span_bind(const struct prestera_port *port, u8 span_id,
+                         bool ingress);
+int prestera_hw_span_unbind(const struct prestera_port *port, bool ingress);
 int prestera_hw_span_release(struct prestera_switch *sw, u8 span_id);
 
 /* Router API */
index ede3e53..3956d6d 100644 (file)
@@ -51,6 +51,11 @@ int prestera_port_mc_flood_set(struct prestera_port *port, bool flood)
        return prestera_hw_port_mc_flood_set(port, flood);
 }
 
+int prestera_port_br_locked_set(struct prestera_port *port, bool br_locked)
+{
+       return prestera_hw_port_br_locked_set(port, br_locked);
+}
+
 int prestera_port_pvid_set(struct prestera_port *port, u16 vid)
 {
        enum prestera_accept_frm_type frm_type;
@@ -797,32 +802,30 @@ static void prestera_port_handle_event(struct prestera_switch *sw,
 
                caching_dw = &port->cached_hw_stats.caching_dw;
 
-               if (port->phy_link) {
-                       memset(&smac, 0, sizeof(smac));
-                       smac.valid = true;
-                       smac.oper = pevt->data.mac.oper;
-                       if (smac.oper) {
-                               smac.mode = pevt->data.mac.mode;
-                               smac.speed = pevt->data.mac.speed;
-                               smac.duplex = pevt->data.mac.duplex;
-                               smac.fc = pevt->data.mac.fc;
-                               smac.fec = pevt->data.mac.fec;
-                               phylink_mac_change(port->phy_link, true);
-                       } else {
-                               phylink_mac_change(port->phy_link, false);
-                       }
-                       prestera_port_mac_state_cache_write(port, &smac);
+               memset(&smac, 0, sizeof(smac));
+               smac.valid = true;
+               smac.oper = pevt->data.mac.oper;
+               if (smac.oper) {
+                       smac.mode = pevt->data.mac.mode;
+                       smac.speed = pevt->data.mac.speed;
+                       smac.duplex = pevt->data.mac.duplex;
+                       smac.fc = pevt->data.mac.fc;
+                       smac.fec = pevt->data.mac.fec;
                }
+               prestera_port_mac_state_cache_write(port, &smac);
 
                if (port->state_mac.oper) {
-                       if (!port->phy_link)
+                       if (port->phy_link)
+                               phylink_mac_change(port->phy_link, true);
+                       else
                                netif_carrier_on(port->dev);
 
                        if (!delayed_work_pending(caching_dw))
                                queue_delayed_work(prestera_wq, caching_dw, 0);
-               } else if (netif_running(port->dev) &&
-                          netif_carrier_ok(port->dev)) {
-                       if (!port->phy_link)
+               } else {
+                       if (port->phy_link)
+                               phylink_mac_change(port->phy_link, false);
+                       else if (netif_running(port->dev) && netif_carrier_ok(port->dev))
                                netif_carrier_off(port->dev);
 
                        if (delayed_work_pending(caching_dw))
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_matchall.c b/drivers/net/ethernet/marvell/prestera/prestera_matchall.c
new file mode 100644 (file)
index 0000000..6f2b95a
--- /dev/null
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/* Copyright (c) 2019-2022 Marvell International Ltd. All rights reserved */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+
+#include "prestera.h"
+#include "prestera_hw.h"
+#include "prestera_flow.h"
+#include "prestera_flower.h"
+#include "prestera_matchall.h"
+#include "prestera_span.h"
+
+static int prestera_mall_prio_check(struct prestera_flow_block *block,
+                                   struct tc_cls_matchall_offload *f)
+{
+       u32 flower_prio_min;
+       u32 flower_prio_max;
+       int err;
+
+       err = prestera_flower_prio_get(block, f->common.chain_index,
+                                      &flower_prio_min, &flower_prio_max);
+       if (err == -ENOENT)
+               /* No flower filters installed on this chain. */
+               return 0;
+
+       if (err) {
+               NL_SET_ERR_MSG(f->common.extack, "Failed to get flower priorities");
+               return err;
+       }
+
+       if (f->common.prio <= flower_prio_max && !block->ingress) {
+               NL_SET_ERR_MSG(f->common.extack, "Failed to add in front of existing flower rules");
+               return -EOPNOTSUPP;
+       }
+       if (f->common.prio >= flower_prio_min && block->ingress) {
+               NL_SET_ERR_MSG(f->common.extack, "Failed to add behind of existing flower rules");
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+int prestera_mall_prio_get(struct prestera_flow_block *block,
+                          u32 *prio_min, u32 *prio_max)
+{
+       if (!block->mall.bound)
+               return -ENOENT;
+
+       *prio_min = block->mall.prio_min;
+       *prio_max = block->mall.prio_max;
+       return 0;
+}
+
+static void prestera_mall_prio_update(struct prestera_flow_block *block,
+                                     struct tc_cls_matchall_offload *f)
+{
+       block->mall.prio_min = min(block->mall.prio_min, f->common.prio);
+       block->mall.prio_max = max(block->mall.prio_max, f->common.prio);
+}
+
+int prestera_mall_replace(struct prestera_flow_block *block,
+                         struct tc_cls_matchall_offload *f)
+{
+       struct prestera_flow_block_binding *binding;
+       __be16 protocol = f->common.protocol;
+       struct flow_action_entry *act;
+       struct prestera_port *port;
+       int err;
+
+       if (!flow_offload_has_one_action(&f->rule->action)) {
+               NL_SET_ERR_MSG(f->common.extack,
+                              "Only singular actions are supported");
+               return -EOPNOTSUPP;
+       }
+
+       act = &f->rule->action.entries[0];
+
+       if (!prestera_netdev_check(act->dev)) {
+               NL_SET_ERR_MSG(f->common.extack,
+                              "Only Marvell Prestera port is supported");
+               return -EINVAL;
+       }
+       if (!tc_cls_can_offload_and_chain0(act->dev, &f->common))
+               return -EOPNOTSUPP;
+       if (act->id != FLOW_ACTION_MIRRED)
+               return -EOPNOTSUPP;
+       if (protocol != htons(ETH_P_ALL))
+               return -EOPNOTSUPP;
+
+       err = prestera_mall_prio_check(block, f);
+       if (err)
+               return err;
+
+       port = netdev_priv(act->dev);
+
+       list_for_each_entry(binding, &block->binding_list, list) {
+               err = prestera_span_rule_add(binding, port, block->ingress);
+               if (err)
+                       goto rollback;
+       }
+
+       prestera_mall_prio_update(block, f);
+
+       block->mall.bound = true;
+       return 0;
+
+rollback:
+       list_for_each_entry_continue_reverse(binding,
+                                            &block->binding_list, list)
+               prestera_span_rule_del(binding, block->ingress);
+       return err;
+}
+
+void prestera_mall_destroy(struct prestera_flow_block *block)
+{
+       struct prestera_flow_block_binding *binding;
+
+       list_for_each_entry(binding, &block->binding_list, list)
+               prestera_span_rule_del(binding, block->ingress);
+
+       block->mall.prio_min = UINT_MAX;
+       block->mall.prio_max = 0;
+       block->mall.bound = false;
+}
diff --git a/drivers/net/ethernet/marvell/prestera/prestera_matchall.h b/drivers/net/ethernet/marvell/prestera/prestera_matchall.h
new file mode 100644 (file)
index 0000000..fed08be
--- /dev/null
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 */
+/* Copyright (c) 2022 Marvell International Ltd. All rights reserved. */
+
+#ifndef _PRESTERA_MATCHALL_H_
+#define _PRESTERA_MATCHALL_H_
+
+#include <net/pkt_cls.h>
+
+struct prestera_flow_block;
+
+int prestera_mall_replace(struct prestera_flow_block *block,
+                         struct tc_cls_matchall_offload *f);
+void prestera_mall_destroy(struct prestera_flow_block *block);
+int prestera_mall_prio_get(struct prestera_flow_block *block,
+                          u32 *prio_min, u32 *prio_max);
+
+#endif /* _PRESTERA_MATCHALL_H_ */
index 845e9d8..f0e9d6e 100644 (file)
@@ -120,8 +120,9 @@ static int prestera_span_put(struct prestera_switch *sw, u8 span_id)
        return 0;
 }
 
-static int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
-                                 struct prestera_port *to_port)
+int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
+                          struct prestera_port *to_port,
+                          bool ingress)
 {
        struct prestera_switch *sw = binding->port->sw;
        u8 span_id;
@@ -135,7 +136,7 @@ static int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
        if (err)
                return err;
 
-       err = prestera_hw_span_bind(binding->port, span_id);
+       err = prestera_hw_span_bind(binding->port, span_id, ingress);
        if (err) {
                prestera_span_put(sw, span_id);
                return err;
@@ -145,11 +146,12 @@ static int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
        return 0;
 }
 
-static int prestera_span_rule_del(struct prestera_flow_block_binding *binding)
+int prestera_span_rule_del(struct prestera_flow_block_binding *binding,
+                          bool ingress)
 {
        int err;
 
-       err = prestera_hw_span_unbind(binding->port);
+       err = prestera_hw_span_unbind(binding->port, ingress);
        if (err)
                return err;
 
@@ -161,60 +163,6 @@ static int prestera_span_rule_del(struct prestera_flow_block_binding *binding)
        return 0;
 }
 
-int prestera_span_replace(struct prestera_flow_block *block,
-                         struct tc_cls_matchall_offload *f)
-{
-       struct prestera_flow_block_binding *binding;
-       __be16 protocol = f->common.protocol;
-       struct flow_action_entry *act;
-       struct prestera_port *port;
-       int err;
-
-       if (!flow_offload_has_one_action(&f->rule->action)) {
-               NL_SET_ERR_MSG(f->common.extack,
-                              "Only singular actions are supported");
-               return -EOPNOTSUPP;
-       }
-
-       act = &f->rule->action.entries[0];
-
-       if (!prestera_netdev_check(act->dev)) {
-               NL_SET_ERR_MSG(f->common.extack,
-                              "Only Marvell Prestera port is supported");
-               return -EINVAL;
-       }
-       if (!tc_cls_can_offload_and_chain0(act->dev, &f->common))
-               return -EOPNOTSUPP;
-       if (act->id != FLOW_ACTION_MIRRED)
-               return -EOPNOTSUPP;
-       if (protocol != htons(ETH_P_ALL))
-               return -EOPNOTSUPP;
-
-       port = netdev_priv(act->dev);
-
-       list_for_each_entry(binding, &block->binding_list, list) {
-               err = prestera_span_rule_add(binding, port);
-               if (err)
-                       goto rollback;
-       }
-
-       return 0;
-
-rollback:
-       list_for_each_entry_continue_reverse(binding,
-                                            &block->binding_list, list)
-               prestera_span_rule_del(binding);
-       return err;
-}
-
-void prestera_span_destroy(struct prestera_flow_block *block)
-{
-       struct prestera_flow_block_binding *binding;
-
-       list_for_each_entry(binding, &block->binding_list, list)
-               prestera_span_rule_del(binding);
-}
-
 int prestera_span_init(struct prestera_switch *sw)
 {
        struct prestera_span *span;
index f064452..493b685 100644 (file)
@@ -8,13 +8,17 @@
 
 #define PRESTERA_SPAN_INVALID_ID -1
 
+struct prestera_port;
 struct prestera_switch;
-struct prestera_flow_block;
+struct prestera_flow_block_binding;
 
 int prestera_span_init(struct prestera_switch *sw);
 void prestera_span_fini(struct prestera_switch *sw);
-int prestera_span_replace(struct prestera_flow_block *block,
-                         struct tc_cls_matchall_offload *f);
-void prestera_span_destroy(struct prestera_flow_block *block);
+
+int prestera_span_rule_add(struct prestera_flow_block_binding *binding,
+                          struct prestera_port *to_port,
+                          bool ingress);
+int prestera_span_rule_del(struct prestera_flow_block_binding *binding,
+                          bool ingress);
 
 #endif /* _PRESTERA_SPAN_H_ */
index 71cde97..e548cd3 100644 (file)
@@ -143,6 +143,7 @@ prestera_br_port_flags_reset(struct prestera_bridge_port *br_port,
        prestera_port_uc_flood_set(port, false);
        prestera_port_mc_flood_set(port, false);
        prestera_port_learning_set(port, false);
+       prestera_port_br_locked_set(port, false);
 }
 
 static int prestera_br_port_flags_set(struct prestera_bridge_port *br_port,
@@ -162,6 +163,11 @@ static int prestera_br_port_flags_set(struct prestera_bridge_port *br_port,
        if (err)
                goto err_out;
 
+       err = prestera_port_br_locked_set(port,
+                                         br_port->flags & BR_PORT_LOCKED);
+       if (err)
+               goto err_out;
+
        return 0;
 
 err_out:
@@ -1163,7 +1169,7 @@ static int prestera_port_obj_attr_set(struct net_device *dev, const void *ctx,
                break;
        case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
                if (attr->u.brport_flags.mask &
-                   ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD))
+                   ~(BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_PORT_LOCKED))
                        err = -EINVAL;
                break;
        case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
index 349b8a9..cf456d6 100644 (file)
@@ -1354,10 +1354,10 @@ static void pxa168_eth_netpoll(struct net_device *dev)
 static void pxa168_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
-       strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
-       strlcpy(info->bus_info, "N/A", sizeof(info->bus_info));
+       strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+       strscpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
+       strscpy(info->bus_info, "N/A", sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops pxa168_ethtool_ops = {
index c1e9854..bcc4aa5 100644 (file)
@@ -394,9 +394,9 @@ static void skge_get_drvinfo(struct net_device *dev,
 {
        struct skge_port *skge = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(skge->hw->pdev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(skge->hw->pdev),
                sizeof(info->bus_info));
 }
 
index bbea545..e19acfc 100644 (file)
@@ -3687,9 +3687,9 @@ static void sky2_get_drvinfo(struct net_device *dev,
 {
        struct sky2_port *sky2 = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(sky2->hw->pdev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(sky2->hw->pdev),
                sizeof(info->bus_info));
 }
 
index 5ace460..c19c67a 100644 (file)
@@ -1573,8 +1573,8 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
                .last   = !xdp_frame_has_frags(xdpf),
        };
        int err, index = 0, n_desc = 1, nr_frags;
-       struct mtk_tx_dma *htxd, *txd, *txd_pdma;
        struct mtk_tx_buf *htx_buf, *tx_buf;
+       struct mtk_tx_dma *htxd, *txd;
        void *data = xdpf->data;
 
        if (unlikely(test_bit(MTK_RESETTING, &eth->state)))
@@ -1608,7 +1608,6 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
 
                if (MTK_HAS_CAPS(soc->caps, MTK_QDMA) || (index & 0x1)) {
                        txd = mtk_qdma_phys_to_virt(ring, txd->txd2);
-                       txd_pdma = qdma_to_pdma(ring, txd);
                        if (txd == ring->last_free)
                                goto unmap;
 
@@ -1629,7 +1628,8 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
        htx_buf->data = xdpf;
 
        if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
-               txd_pdma = qdma_to_pdma(ring, txd);
+               struct mtk_tx_dma *txd_pdma = qdma_to_pdma(ring, txd);
+
                if (index & 1)
                        txd_pdma->txd2 |= TX_DMA_LS0;
                else
@@ -1660,13 +1660,15 @@ static int mtk_xdp_submit_frame(struct mtk_eth *eth, struct xdp_frame *xdpf,
 
 unmap:
        while (htxd != txd) {
-               txd_pdma = qdma_to_pdma(ring, htxd);
                tx_buf = mtk_desc_to_tx_buf(ring, htxd, soc->txrx.txd_size);
                mtk_tx_unmap(eth, tx_buf, NULL, false);
 
                htxd->txd3 = TX_DMA_LS0 | TX_DMA_OWNER_CPU;
-               if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA))
+               if (!MTK_HAS_CAPS(soc->caps, MTK_QDMA)) {
+                       struct mtk_tx_dma *txd_pdma = qdma_to_pdma(ring, htxd);
+
                        txd_pdma->txd2 = TX_DMA_DESP2_DEF;
+               }
 
                htxd = mtk_qdma_phys_to_virt(ring, htxd->txd2);
        }
@@ -3556,8 +3558,8 @@ static void mtk_get_drvinfo(struct net_device *dev,
 {
        struct mtk_mac *mac = netdev_priv(dev);
 
-       strlcpy(info->driver, mac->hw->dev->driver->name, sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(mac->hw->dev), sizeof(info->bus_info));
+       strscpy(info->driver, mac->hw->dev->driver->name, sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(mac->hw->dev), sizeof(info->bus_info));
        info->n_stats = ARRAY_SIZE(mtk_ethtool_stats);
 }
 
index 3f0e5e6..f8db176 100644 (file)
@@ -1255,7 +1255,7 @@ static const struct net_device_ops mtk_star_netdev_ops = {
 static void mtk_star_get_drvinfo(struct net_device *dev,
                                 struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, MTK_STAR_DRVNAME, sizeof(info->driver));
+       strscpy(info->driver, MTK_STAR_DRVNAME, sizeof(info->driver));
 }
 
 /* TODO Add ethtool stats. */
index 6400a82..7d45f1d 100644 (file)
@@ -89,15 +89,15 @@ mlx4_en_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
 
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, DRV_VERSION,
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, DRV_VERSION,
                sizeof(drvinfo->version));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                "%d.%d.%d",
                (u16) (mdev->dev->caps.fw_ver >> 32),
                (u16) ((mdev->dev->caps.fw_ver >> 16) & 0xffff),
                (u16) (mdev->dev->caps.fw_ver & 0xffff));
-       strlcpy(drvinfo->bus_info, pci_name(mdev->dev->persist->pdev),
+       strscpy(drvinfo->bus_info, pci_name(mdev->dev->persist->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index dcb9eb1..fe48d20 100644 (file)
@@ -1779,7 +1779,7 @@ static void get_board_id(void *vsd, char *board_id)
 
        if (be16_to_cpup(vsd + VSD_OFFSET_SIG1) == VSD_SIGNATURE_TOPSPIN &&
            be16_to_cpup(vsd + VSD_OFFSET_SIG2) == VSD_SIGNATURE_TOPSPIN) {
-               strlcpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN);
+               strscpy(board_id, vsd + VSD_OFFSET_TS_BOARD_ID, MLX4_BOARD_ID_LEN);
        } else {
                /*
                 * The board ID is a string but the firmware byte
index d89a3da..59b8b3c 100644 (file)
@@ -208,7 +208,7 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
                                                chunk->sg, chunk->npages,
                                                DMA_BIDIRECTIONAL);
 
-                       if (chunk->nsg <= 0)
+                       if (!chunk->nsg)
                                goto fail;
                }
 
@@ -222,7 +222,7 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
                chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg,
                                        chunk->npages, DMA_BIDIRECTIONAL);
 
-               if (chunk->nsg <= 0)
+               if (!chunk->nsg)
                        goto fail;
        }
 
index 78c5f40..d3fc86c 100644 (file)
@@ -3071,6 +3071,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
        err = device_create_file(&dev->persist->pdev->dev, &info->port_attr);
        if (err) {
                mlx4_err(dev, "Failed to create file for port %d\n", port);
+               devlink_port_type_clear(&info->devlink_port);
                devl_port_unregister(&info->devlink_port);
                info->port = -1;
                return err;
@@ -3093,6 +3094,7 @@ static int mlx4_init_port_info(struct mlx4_dev *dev, int port)
                mlx4_err(dev, "Failed to create mtu file for port %d\n", port);
                device_remove_file(&info->dev->persist->pdev->dev,
                                   &info->port_attr);
+               devlink_port_type_clear(&info->devlink_port);
                devl_port_unregister(&info->devlink_port);
                info->port = -1;
                return err;
@@ -3109,6 +3111,7 @@ static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
        device_remove_file(&info->dev->persist->pdev->dev, &info->port_attr);
        device_remove_file(&info->dev->persist->pdev->dev,
                           &info->port_mtu_attr);
+       devlink_port_type_clear(&info->devlink_port);
        devl_port_unregister(&info->devlink_port);
 
 #ifdef CONFIG_RFS_ACCEL
index a560df4..e464024 100644 (file)
@@ -856,11 +856,6 @@ enum {
        MLX5E_STATE_XDP_ACTIVE,
 };
 
-enum {
-       MLX5E_TC_PRIO = 0,
-       MLX5E_NIC_PRIO
-};
-
 struct mlx5e_modify_sq_param {
        int curr_state;
        int next_state;
index 9b8cdf2..bf2741e 100644 (file)
@@ -8,6 +8,7 @@
 #include "lib/fs_ttc.h"
 
 struct mlx5e_post_act;
+struct mlx5e_tc_table;
 
 enum {
        MLX5E_TC_FT_LEVEL = 0,
@@ -15,6 +16,11 @@ enum {
        MLX5E_TC_MISS_LEVEL,
 };
 
+enum {
+       MLX5E_TC_PRIO = 0,
+       MLX5E_NIC_PRIO
+};
+
 struct mlx5e_flow_table {
        int num_groups;
        struct mlx5_flow_table *t;
@@ -83,54 +89,28 @@ enum {
 #endif
 };
 
-struct mlx5e_priv;
-
-#ifdef CONFIG_MLX5_EN_RXNFC
-
-struct mlx5e_ethtool_table {
-       struct mlx5_flow_table *ft;
-       int                    num_rules;
-};
-
-#define ETHTOOL_NUM_L3_L4_FTS 7
-#define ETHTOOL_NUM_L2_FTS 4
-
-struct mlx5e_ethtool_steering {
-       struct mlx5e_ethtool_table      l3_l4_ft[ETHTOOL_NUM_L3_L4_FTS];
-       struct mlx5e_ethtool_table      l2_ft[ETHTOOL_NUM_L2_FTS];
-       struct list_head                rules;
-       int                             tot_num_rules;
-};
-
-void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv);
-void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv);
-int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd);
-int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
-                           struct ethtool_rxnfc *info, u32 *rule_locs);
-#else
-static inline void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv)    { }
-static inline void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv) { }
-static inline int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd)
-{ return -EOPNOTSUPP; }
-static inline int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
-                                         struct ethtool_rxnfc *info, u32 *rule_locs)
-{ return -EOPNOTSUPP; }
-#endif /* CONFIG_MLX5_EN_RXNFC */
+struct mlx5e_flow_steering;
+struct mlx5e_rx_res;
 
 #ifdef CONFIG_MLX5_EN_ARFS
 struct mlx5e_arfs_tables;
 
-int mlx5e_arfs_create_tables(struct mlx5e_priv *priv);
-void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv);
-int mlx5e_arfs_enable(struct mlx5e_priv *priv);
-int mlx5e_arfs_disable(struct mlx5e_priv *priv);
+int mlx5e_arfs_create_tables(struct mlx5e_flow_steering *fs,
+                            struct mlx5e_rx_res *rx_res, bool ntuple);
+void mlx5e_arfs_destroy_tables(struct mlx5e_flow_steering *fs, bool ntuple);
+int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs);
+int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs);
 int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                        u16 rxq_index, u32 flow_id);
 #else
-static inline int mlx5e_arfs_create_tables(struct mlx5e_priv *priv) { return 0; }
-static inline void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv) {}
-static inline int mlx5e_arfs_enable(struct mlx5e_priv *priv) { return -EOPNOTSUPP; }
-static inline int mlx5e_arfs_disable(struct mlx5e_priv *priv) {        return -EOPNOTSUPP; }
+static inline int mlx5e_arfs_create_tables(struct mlx5e_flow_steering *fs,
+                                          struct mlx5e_rx_res *rx_res, bool ntuple)
+{ return 0; }
+static inline void mlx5e_arfs_destroy_tables(struct mlx5e_flow_steering *fs, bool ntuple) {}
+static inline int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs)
+{ return -EOPNOTSUPP; }
+static inline int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
+{ return -EOPNOTSUPP; }
 #endif
 
 #ifdef CONFIG_MLX5_EN_TLS
@@ -142,54 +122,63 @@ struct mlx5e_fs_udp;
 struct mlx5e_fs_any;
 struct mlx5e_ptp_fs;
 
-struct mlx5e_flow_steering {
-       bool                            state_destroy;
-       bool                            vlan_strip_disable;
-       struct mlx5_core_dev            *mdev;
-       struct mlx5_flow_namespace      *ns;
-#ifdef CONFIG_MLX5_EN_RXNFC
-       struct mlx5e_ethtool_steering   ethtool;
-#endif
-       struct mlx5e_tc_table           *tc;
-       struct mlx5e_promisc_table      promisc;
-       struct mlx5e_vlan_table         *vlan;
-       struct mlx5e_l2_table           l2;
-       struct mlx5_ttc_table           *ttc;
-       struct mlx5_ttc_table           *inner_ttc;
-#ifdef CONFIG_MLX5_EN_ARFS
-       struct mlx5e_arfs_tables       *arfs;
-#endif
-#ifdef CONFIG_MLX5_EN_TLS
-       struct mlx5e_accel_fs_tcp      *accel_tcp;
-#endif
-       struct mlx5e_fs_udp            *udp;
-       struct mlx5e_fs_any            *any;
-       struct mlx5e_ptp_fs            *ptp_fs;
-};
-
-void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
+void mlx5e_set_ttc_params(struct mlx5e_flow_steering *fs,
+                         struct mlx5e_rx_res *rx_res,
                          struct ttc_params *ttc_params, bool tunnel);
 
-void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv);
+void mlx5e_destroy_ttc_table(struct mlx5e_flow_steering *fs);
+int mlx5e_create_ttc_table(struct mlx5e_flow_steering  *fs,
+                          struct mlx5e_rx_res *rx_res);
 
 void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft);
 
-void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv);
-void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv);
+void mlx5e_enable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc);
+void mlx5e_disable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc);
 
-int mlx5e_create_flow_steering(struct mlx5e_priv *priv);
-void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv);
+int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
+                              struct mlx5e_rx_res *rx_res,
+                              const struct mlx5e_profile *profile,
+                              struct net_device *netdev);
+void mlx5e_destroy_flow_steering(struct mlx5e_flow_steering *fs, bool ntuple,
+                                const struct mlx5e_profile *profile);
 
 struct mlx5e_flow_steering *mlx5e_fs_init(const struct mlx5e_profile *profile,
                                          struct mlx5_core_dev *mdev,
                                          bool state_destroy);
 void mlx5e_fs_cleanup(struct mlx5e_flow_steering *fs);
-
-int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int  trap_id, int tir_num);
-void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv);
-int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int  trap_id, int tir_num);
-void mlx5e_remove_mac_trap(struct mlx5e_priv *priv);
+struct mlx5e_vlan_table *mlx5e_fs_get_vlan(struct mlx5e_flow_steering *fs);
+void mlx5e_fs_set_tc(struct mlx5e_flow_steering *fs, struct mlx5e_tc_table *tc);
+struct mlx5e_tc_table *mlx5e_fs_get_tc(struct mlx5e_flow_steering *fs);
+struct mlx5e_l2_table *mlx5e_fs_get_l2(struct mlx5e_flow_steering *fs);
+struct mlx5_flow_namespace *mlx5e_fs_get_ns(struct mlx5e_flow_steering *fs, bool egress);
+void mlx5e_fs_set_ns(struct mlx5e_flow_steering *fs, struct mlx5_flow_namespace *ns, bool egress);
+#ifdef CONFIG_MLX5_EN_RXNFC
+struct mlx5e_ethtool_steering *mlx5e_fs_get_ethtool(struct mlx5e_flow_steering *fs);
+#endif
+struct mlx5_ttc_table *mlx5e_fs_get_ttc(struct mlx5e_flow_steering *fs, bool inner);
+void mlx5e_fs_set_ttc(struct mlx5e_flow_steering *fs, struct mlx5_ttc_table *ttc, bool inner);
+#ifdef CONFIG_MLX5_EN_ARFS
+struct mlx5e_arfs_tables *mlx5e_fs_get_arfs(struct mlx5e_flow_steering *fs);
+void mlx5e_fs_set_arfs(struct mlx5e_flow_steering *fs, struct mlx5e_arfs_tables *arfs);
+#endif
+struct mlx5e_ptp_fs *mlx5e_fs_get_ptp(struct mlx5e_flow_steering *fs);
+void mlx5e_fs_set_ptp(struct mlx5e_flow_steering *fs, struct mlx5e_ptp_fs *ptp_fs);
+struct mlx5e_fs_any *mlx5e_fs_get_any(struct mlx5e_flow_steering *fs);
+void mlx5e_fs_set_any(struct mlx5e_flow_steering *fs, struct mlx5e_fs_any *any);
+struct mlx5e_fs_udp *mlx5e_fs_get_udp(struct mlx5e_flow_steering *fs);
+void mlx5e_fs_set_udp(struct mlx5e_flow_steering *fs, struct mlx5e_fs_udp *udp);
+#ifdef CONFIG_MLX5_EN_TLS
+struct mlx5e_accel_fs_tcp *mlx5e_fs_get_accel_tcp(struct mlx5e_flow_steering *fs);
+void mlx5e_fs_set_accel_tcp(struct mlx5e_flow_steering *fs, struct mlx5e_accel_fs_tcp *accel_tcp);
+#endif
+void mlx5e_fs_set_state_destroy(struct mlx5e_flow_steering *fs, bool state_destroy);
+void mlx5e_fs_set_vlan_strip_disable(struct mlx5e_flow_steering *fs, bool vlan_strip_disable);
+
+struct mlx5_core_dev *mlx5e_fs_get_mdev(struct mlx5e_flow_steering *fs);
+int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int  trap_id, int tir_num);
+void mlx5e_remove_vlan_trap(struct mlx5e_flow_steering *fs);
+int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int  trap_id, int tir_num);
+void mlx5e_remove_mac_trap(struct mlx5e_flow_steering *fs);
 void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs, struct net_device *netdev);
 int mlx5e_fs_vlan_rx_add_vid(struct mlx5e_flow_steering *fs,
                             struct net_device *netdev,
@@ -198,5 +187,18 @@ int mlx5e_fs_vlan_rx_kill_vid(struct mlx5e_flow_steering *fs,
                              struct net_device *netdev,
                              __be16 proto, u16 vid);
 void mlx5e_fs_init_l2_addr(struct mlx5e_flow_steering *fs, struct net_device *netdev);
+
+#define fs_err(fs, fmt, ...) \
+       mlx5_core_err(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)
+
+#define fs_dbg(fs, fmt, ...) \
+       mlx5_core_dbg(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)
+
+#define fs_warn(fs, fmt, ...) \
+       mlx5_core_warn(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)
+
+#define fs_warn_once(fs, fmt, ...) \
+       mlx5_core_warn_once(mlx5e_fs_get_mdev(fs), fmt, ##__VA_ARGS__)
+
 #endif /* __MLX5E_FLOW_STEER_H__ */
 
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/fs_ethtool.h b/drivers/net/ethernet/mellanox/mlx5/core/en/fs_ethtool.h
new file mode 100644 (file)
index 0000000..9e276fd
--- /dev/null
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. */
+
+#ifndef __MLX5E_FS_ETHTOOL_H__
+#define __MLX5E_FS_ETHTOOL_H__
+
+struct mlx5e_priv;
+struct mlx5e_ethtool_steering;
+#ifdef CONFIG_MLX5_EN_RXNFC
+int mlx5e_ethtool_alloc(struct mlx5e_ethtool_steering **ethtool);
+void mlx5e_ethtool_free(struct mlx5e_ethtool_steering *ethtool);
+void mlx5e_ethtool_init_steering(struct mlx5e_flow_steering *fs);
+void mlx5e_ethtool_cleanup_steering(struct mlx5e_flow_steering *fs);
+int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd);
+int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
+                           struct ethtool_rxnfc *info, u32 *rule_locs);
+#else
+static inline int mlx5e_ethtool_alloc(struct mlx5e_ethtool_steering **ethtool)
+{ return 0; }
+static inline void mlx5e_ethtool_free(struct mlx5e_ethtool_steering *ethtool) { }
+static inline void mlx5e_ethtool_init_steering(struct mlx5e_flow_steering *fs) { }
+static inline void mlx5e_ethtool_cleanup_steering(struct mlx5e_flow_steering *fs) { }
+static inline int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd)
+{ return -EOPNOTSUPP; }
+static inline int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
+                                         struct ethtool_rxnfc *info, u32 *rule_locs)
+{ return -EOPNOTSUPP; }
+#endif
+#endif
index e153d61..03cb79a 100644 (file)
@@ -1,9 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /* Copyright (c) 2021, Mellanox Technologies inc. All rights reserved. */
 
-#include <linux/netdevice.h>
 #include "en/fs_tt_redirect.h"
 #include "fs_core.h"
+#include "mlx5_core.h"
 
 enum fs_udp_type {
        FS_IPV4_UDP,
@@ -74,17 +74,17 @@ static void fs_udp_set_dport_flow(struct mlx5_flow_spec *spec, enum fs_udp_type
 }
 
 struct mlx5_flow_handle *
-mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
+mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_flow_steering *fs,
                                  enum mlx5_traffic_types ttc_type,
                                  u32 tir_num, u16 d_port)
 {
+       struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
        enum fs_udp_type type = tt2fs_udp(ttc_type);
        struct mlx5_flow_destination dest = {};
        struct mlx5_flow_table *ft = NULL;
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_handle *rule;
        struct mlx5_flow_spec *spec;
-       struct mlx5e_fs_udp *fs_udp;
        int err;
 
        if (type == FS_UDP_NUM_TYPES)
@@ -94,7 +94,6 @@ mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
        if (!spec)
                return ERR_PTR(-ENOMEM);
 
-       fs_udp = priv->fs->udp;
        ft = fs_udp->tables[type].t;
 
        fs_udp_set_dport_flow(spec, type, d_port);
@@ -106,31 +105,30 @@ mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
 
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               netdev_err(priv->netdev, "%s: add %s rule failed, err %d\n",
-                          __func__, fs_udp_type2str(type), err);
+               fs_err(fs, "%s: add %s rule failed, err %d\n",
+                      __func__, fs_udp_type2str(type), err);
        }
        return rule;
 }
 
-static int fs_udp_add_default_rule(struct mlx5e_priv *priv, enum fs_udp_type type)
+static int fs_udp_add_default_rule(struct mlx5e_flow_steering *fs, enum fs_udp_type type)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
+       struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
        struct mlx5e_flow_table *fs_udp_t;
        struct mlx5_flow_destination dest;
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_handle *rule;
-       struct mlx5e_fs_udp *fs_udp;
        int err;
 
-       fs_udp = priv->fs->udp;
        fs_udp_t = &fs_udp->tables[type];
 
-       dest = mlx5_ttc_get_default_dest(priv->fs->ttc, fs_udp2tt(type));
+       dest = mlx5_ttc_get_default_dest(ttc, fs_udp2tt(type));
        rule = mlx5_add_flow_rules(fs_udp_t->t, NULL, &flow_act, &dest, 1);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               netdev_err(priv->netdev,
-                          "%s: add default rule failed, fs type=%d, err %d\n",
-                          __func__, type, err);
+               fs_err(fs, "%s: add default rule failed, fs type=%d, err %d\n",
+                      __func__, type, err);
                return err;
        }
 
@@ -206,33 +204,36 @@ out:
        return err;
 }
 
-static int fs_udp_create_table(struct mlx5e_priv *priv, enum fs_udp_type type)
+static int fs_udp_create_table(struct mlx5e_flow_steering *fs, enum fs_udp_type type)
 {
-       struct mlx5e_flow_table *ft = &priv->fs->udp->tables[type];
+       struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs, false);
+       struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
        struct mlx5_flow_table_attr ft_attr = {};
+       struct mlx5e_flow_table *ft;
        int err;
 
+       ft = &fs_udp->tables[type];
        ft->num_groups = 0;
 
        ft_attr.max_fte = MLX5E_FS_UDP_TABLE_SIZE;
        ft_attr.level = MLX5E_FS_TT_UDP_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
 
-       ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
+       ft->t = mlx5_create_flow_table(ns, &ft_attr);
        if (IS_ERR(ft->t)) {
                err = PTR_ERR(ft->t);
                ft->t = NULL;
                return err;
        }
 
-       netdev_dbg(priv->netdev, "Created fs %s table id %u level %u\n",
-                  fs_udp_type2str(type), ft->t->id, ft->t->level);
+       mlx5_core_dbg(mlx5e_fs_get_mdev(fs), "Created fs %s table id %u level %u\n",
+                     fs_udp_type2str(type), ft->t->id, ft->t->level);
 
        err = fs_udp_create_groups(ft, type);
        if (err)
                goto err;
 
-       err = fs_udp_add_default_rule(priv, type);
+       err = fs_udp_add_default_rule(fs, type);
        if (err)
                goto err;
 
@@ -253,17 +254,17 @@ static void fs_udp_destroy_table(struct mlx5e_fs_udp *fs_udp, int i)
        fs_udp->tables[i].t = NULL;
 }
 
-static int fs_udp_disable(struct mlx5e_priv *priv)
+static int fs_udp_disable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
        int err, i;
 
        for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
                /* Modify ttc rules destination to point back to the indir TIRs */
-               err = mlx5_ttc_fwd_default_dest(priv->fs->ttc, fs_udp2tt(i));
+               err = mlx5_ttc_fwd_default_dest(ttc, fs_udp2tt(i));
                if (err) {
-                       netdev_err(priv->netdev,
-                                  "%s: modify ttc[%d] default destination failed, err(%d)\n",
-                                  __func__, fs_udp2tt(i), err);
+                       fs_err(fs, "%s: modify ttc[%d] default destination failed, err(%d)\n",
+                              __func__, fs_udp2tt(i), err);
                        return err;
                }
        }
@@ -271,30 +272,31 @@ static int fs_udp_disable(struct mlx5e_priv *priv)
        return 0;
 }
 
-static int fs_udp_enable(struct mlx5e_priv *priv)
+static int fs_udp_enable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
+       struct mlx5e_fs_udp *udp = mlx5e_fs_get_udp(fs);
        struct mlx5_flow_destination dest = {};
        int err, i;
 
        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
        for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
-               dest.ft = priv->fs->udp->tables[i].t;
+               dest.ft = udp->tables[i].t;
 
                /* Modify ttc rules destination to point on the accel_fs FTs */
-               err = mlx5_ttc_fwd_dest(priv->fs->ttc, fs_udp2tt(i), &dest);
+               err = mlx5_ttc_fwd_dest(ttc, fs_udp2tt(i), &dest);
                if (err) {
-                       netdev_err(priv->netdev,
-                                  "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
-                                  __func__, fs_udp2tt(i), err);
+                       fs_err(fs, "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
+                              __func__, fs_udp2tt(i), err);
                        return err;
                }
        }
        return 0;
 }
 
-void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv)
+void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_flow_steering *fs)
 {
-       struct mlx5e_fs_udp *fs_udp = priv->fs->udp;
+       struct mlx5e_fs_udp *fs_udp = mlx5e_fs_get_udp(fs);
        int i;
 
        if (!fs_udp)
@@ -303,48 +305,50 @@ void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv)
        if (--fs_udp->ref_cnt)
                return;
 
-       fs_udp_disable(priv);
+       fs_udp_disable(fs);
 
        for (i = 0; i < FS_UDP_NUM_TYPES; i++)
                fs_udp_destroy_table(fs_udp, i);
 
        kfree(fs_udp);
-       priv->fs->udp = NULL;
+       mlx5e_fs_set_udp(fs, NULL);
 }
 
-int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_priv *priv)
+int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_fs_udp *udp = mlx5e_fs_get_udp(fs);
        int i, err;
 
-       if (priv->fs->udp) {
-               priv->fs->udp->ref_cnt++;
+       if (udp) {
+               udp->ref_cnt++;
                return 0;
        }
 
-       priv->fs->udp = kzalloc(sizeof(*priv->fs->udp), GFP_KERNEL);
-       if (!priv->fs->udp)
+       udp = kzalloc(sizeof(*udp), GFP_KERNEL);
+       if (!udp)
                return -ENOMEM;
+       mlx5e_fs_set_udp(fs, udp);
 
        for (i = 0; i < FS_UDP_NUM_TYPES; i++) {
-               err = fs_udp_create_table(priv, i);
+               err = fs_udp_create_table(fs, i);
                if (err)
                        goto err_destroy_tables;
        }
 
-       err = fs_udp_enable(priv);
+       err = fs_udp_enable(fs);
        if (err)
                goto err_destroy_tables;
 
-       priv->fs->udp->ref_cnt = 1;
+       udp->ref_cnt = 1;
 
        return 0;
 
 err_destroy_tables:
        while (--i >= 0)
-               fs_udp_destroy_table(priv->fs->udp, i);
+               fs_udp_destroy_table(udp, i);
 
-       kfree(priv->fs->udp);
-       priv->fs->udp = NULL;
+       kfree(udp);
+       mlx5e_fs_set_udp(fs, NULL);
        return err;
 }
 
@@ -356,22 +360,21 @@ static void fs_any_set_ethertype_flow(struct mlx5_flow_spec *spec, u16 ether_typ
 }
 
 struct mlx5_flow_handle *
-mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,
+mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_flow_steering *fs,
                                  u32 tir_num, u16 ether_type)
 {
+       struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
        struct mlx5_flow_destination dest = {};
        struct mlx5_flow_table *ft = NULL;
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_handle *rule;
        struct mlx5_flow_spec *spec;
-       struct mlx5e_fs_any *fs_any;
        int err;
 
        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
        if (!spec)
                return ERR_PTR(-ENOMEM);
 
-       fs_any = priv->fs->any;
        ft = fs_any->table.t;
 
        fs_any_set_ethertype_flow(spec, ether_type);
@@ -383,31 +386,29 @@ mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,
 
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               netdev_err(priv->netdev, "%s: add ANY rule failed, err %d\n",
-                          __func__, err);
+               fs_err(fs, "%s: add ANY rule failed, err %d\n",
+                      __func__, err);
        }
        return rule;
 }
 
-static int fs_any_add_default_rule(struct mlx5e_priv *priv)
+static int fs_any_add_default_rule(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
+       struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
        struct mlx5e_flow_table *fs_any_t;
        struct mlx5_flow_destination dest;
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_handle *rule;
-       struct mlx5e_fs_any *fs_any;
        int err;
 
-       fs_any = priv->fs->any;
        fs_any_t = &fs_any->table;
-
-       dest = mlx5_ttc_get_default_dest(priv->fs->ttc, MLX5_TT_ANY);
+       dest = mlx5_ttc_get_default_dest(ttc, MLX5_TT_ANY);
        rule = mlx5_add_flow_rules(fs_any_t->t, NULL, &flow_act, &dest, 1);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               netdev_err(priv->netdev,
-                          "%s: add default rule failed, fs type=ANY, err %d\n",
-                          __func__, err);
+               fs_err(fs, "%s: add default rule failed, fs type=ANY, err %d\n",
+                      __func__, err);
                return err;
        }
 
@@ -472,9 +473,11 @@ err:
        return err;
 }
 
-static int fs_any_create_table(struct mlx5e_priv *priv)
+static int fs_any_create_table(struct mlx5e_flow_steering *fs)
 {
-       struct mlx5e_flow_table *ft = &priv->fs->any->table;
+       struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs, false);
+       struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
+       struct mlx5e_flow_table *ft = &fs_any->table;
        struct mlx5_flow_table_attr ft_attr = {};
        int err;
 
@@ -484,21 +487,21 @@ static int fs_any_create_table(struct mlx5e_priv *priv)
        ft_attr.level = MLX5E_FS_TT_ANY_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
 
-       ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
+       ft->t = mlx5_create_flow_table(ns, &ft_attr);
        if (IS_ERR(ft->t)) {
                err = PTR_ERR(ft->t);
                ft->t = NULL;
                return err;
        }
 
-       netdev_dbg(priv->netdev, "Created fs ANY table id %u level %u\n",
-                  ft->t->id, ft->t->level);
+       mlx5_core_dbg(mlx5e_fs_get_mdev(fs), "Created fs ANY table id %u level %u\n",
+                     ft->t->id, ft->t->level);
 
        err = fs_any_create_groups(ft);
        if (err)
                goto err;
 
-       err = fs_any_add_default_rule(priv);
+       err = fs_any_add_default_rule(fs);
        if (err)
                goto err;
 
@@ -509,35 +512,38 @@ err:
        return err;
 }
 
-static int fs_any_disable(struct mlx5e_priv *priv)
+static int fs_any_disable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
        int err;
 
        /* Modify ttc rules destination to point back to the indir TIRs */
-       err = mlx5_ttc_fwd_default_dest(priv->fs->ttc, MLX5_TT_ANY);
+       err = mlx5_ttc_fwd_default_dest(ttc, MLX5_TT_ANY);
        if (err) {
-               netdev_err(priv->netdev,
-                          "%s: modify ttc[%d] default destination failed, err(%d)\n",
-                          __func__, MLX5_TT_ANY, err);
+               fs_err(fs,
+                      "%s: modify ttc[%d] default destination failed, err(%d)\n",
+                      __func__, MLX5_TT_ANY, err);
                return err;
        }
        return 0;
 }
 
-static int fs_any_enable(struct mlx5e_priv *priv)
+static int fs_any_enable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
+       struct mlx5e_fs_any *any = mlx5e_fs_get_any(fs);
        struct mlx5_flow_destination dest = {};
        int err;
 
        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
-       dest.ft = priv->fs->any->table.t;
+       dest.ft = any->table.t;
 
        /* Modify ttc rules destination to point on the accel_fs FTs */
-       err = mlx5_ttc_fwd_dest(priv->fs->ttc, MLX5_TT_ANY, &dest);
+       err = mlx5_ttc_fwd_dest(ttc, MLX5_TT_ANY, &dest);
        if (err) {
-               netdev_err(priv->netdev,
-                          "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
-                          __func__, MLX5_TT_ANY, err);
+               fs_err(fs,
+                      "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
+                      __func__, MLX5_TT_ANY, err);
                return err;
        }
        return 0;
@@ -553,9 +559,9 @@ static void fs_any_destroy_table(struct mlx5e_fs_any *fs_any)
        fs_any->table.t = NULL;
 }
 
-void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv)
+void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_flow_steering *fs)
 {
-       struct mlx5e_fs_any *fs_any = priv->fs->any;
+       struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
 
        if (!fs_any)
                return;
@@ -563,43 +569,45 @@ void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv)
        if (--fs_any->ref_cnt)
                return;
 
-       fs_any_disable(priv);
+       fs_any_disable(fs);
 
        fs_any_destroy_table(fs_any);
 
        kfree(fs_any);
-       priv->fs->any = NULL;
+       mlx5e_fs_set_any(fs, NULL);
 }
 
-int mlx5e_fs_tt_redirect_any_create(struct mlx5e_priv *priv)
+int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_fs_any *fs_any = mlx5e_fs_get_any(fs);
        int err;
 
-       if (priv->fs->any) {
-               priv->fs->any->ref_cnt++;
+       if (fs_any) {
+               fs_any->ref_cnt++;
                return 0;
        }
 
-       priv->fs->any = kzalloc(sizeof(*priv->fs->any), GFP_KERNEL);
-       if (!priv->fs->any)
+       fs_any = kzalloc(sizeof(*fs_any), GFP_KERNEL);
+       if (!fs_any)
                return -ENOMEM;
+       mlx5e_fs_set_any(fs, fs_any);
 
-       err = fs_any_create_table(priv);
+       err = fs_any_create_table(fs);
        if (err)
                return err;
 
-       err = fs_any_enable(priv);
+       err = fs_any_enable(fs);
        if (err)
                goto err_destroy_table;
 
-       priv->fs->any->ref_cnt = 1;
+       fs_any->ref_cnt = 1;
 
        return 0;
 
 err_destroy_table:
-       fs_any_destroy_table(priv->fs->any);
+       fs_any_destroy_table(fs_any);
 
-       kfree(priv->fs->any);
-       priv->fs->any = NULL;
+       kfree(fs_any);
+       mlx5e_fs_set_any(fs, NULL);
        return err;
 }
index 7a70c4f..5780fd7 100644 (file)
@@ -4,23 +4,22 @@
 #ifndef __MLX5E_FS_TT_REDIRECT_H__
 #define __MLX5E_FS_TT_REDIRECT_H__
 
-#include "en.h"
 #include "en/fs.h"
 
 void mlx5e_fs_tt_redirect_del_rule(struct mlx5_flow_handle *rule);
 
 /* UDP traffic type redirect */
 struct mlx5_flow_handle *
-mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_priv *priv,
+mlx5e_fs_tt_redirect_udp_add_rule(struct mlx5e_flow_steering *fs,
                                  enum mlx5_traffic_types ttc_type,
                                  u32 tir_num, u16 d_port);
-void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_priv *priv);
-int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_priv *priv);
+void mlx5e_fs_tt_redirect_udp_destroy(struct mlx5e_flow_steering *fs);
+int mlx5e_fs_tt_redirect_udp_create(struct mlx5e_flow_steering *fs);
 
 /* ANY traffic type redirect*/
 struct mlx5_flow_handle *
-mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_priv *priv,
+mlx5e_fs_tt_redirect_any_add_rule(struct mlx5e_flow_steering *fs,
                                  u32 tir_num, u16 ether_type);
-void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_priv *priv);
-int mlx5e_fs_tt_redirect_any_create(struct mlx5e_priv *priv);
+void mlx5e_fs_tt_redirect_any_destroy(struct mlx5e_flow_steering *fs);
+int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs);
 #endif
index 903de88..6fefce3 100644 (file)
@@ -622,37 +622,39 @@ static int mlx5e_ptp_set_state(struct mlx5e_ptp *c, struct mlx5e_params *params)
        return bitmap_empty(c->state, MLX5E_PTP_STATE_NUM_STATES) ? -EINVAL : 0;
 }
 
-static void mlx5e_ptp_rx_unset_fs(struct mlx5e_priv *priv)
+static void mlx5e_ptp_rx_unset_fs(struct mlx5e_flow_steering *fs)
 {
-       struct mlx5e_ptp_fs *ptp_fs = priv->fs->ptp_fs;
+       struct mlx5e_ptp_fs *ptp_fs = mlx5e_fs_get_ptp(fs);
 
        if (!ptp_fs->valid)
                return;
 
        mlx5e_fs_tt_redirect_del_rule(ptp_fs->l2_rule);
-       mlx5e_fs_tt_redirect_any_destroy(priv);
+       mlx5e_fs_tt_redirect_any_destroy(fs);
 
        mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v6_rule);
        mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v4_rule);
-       mlx5e_fs_tt_redirect_udp_destroy(priv);
+       mlx5e_fs_tt_redirect_udp_destroy(fs);
        ptp_fs->valid = false;
 }
 
 static int mlx5e_ptp_rx_set_fs(struct mlx5e_priv *priv)
 {
        u32 tirn = mlx5e_rx_res_get_tirn_ptp(priv->rx_res);
-       struct mlx5e_ptp_fs *ptp_fs = priv->fs->ptp_fs;
+       struct mlx5e_flow_steering *fs = priv->fs;
        struct mlx5_flow_handle *rule;
+       struct mlx5e_ptp_fs *ptp_fs;
        int err;
 
+       ptp_fs = mlx5e_fs_get_ptp(fs);
        if (ptp_fs->valid)
                return 0;
 
-       err = mlx5e_fs_tt_redirect_udp_create(priv);
+       err = mlx5e_fs_tt_redirect_udp_create(fs);
        if (err)
                goto out_free;
 
-       rule = mlx5e_fs_tt_redirect_udp_add_rule(priv, MLX5_TT_IPV4_UDP,
+       rule = mlx5e_fs_tt_redirect_udp_add_rule(fs, MLX5_TT_IPV4_UDP,
                                                 tirn, PTP_EV_PORT);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
@@ -660,7 +662,7 @@ static int mlx5e_ptp_rx_set_fs(struct mlx5e_priv *priv)
        }
        ptp_fs->udp_v4_rule = rule;
 
-       rule = mlx5e_fs_tt_redirect_udp_add_rule(priv, MLX5_TT_IPV6_UDP,
+       rule = mlx5e_fs_tt_redirect_udp_add_rule(fs, MLX5_TT_IPV6_UDP,
                                                 tirn, PTP_EV_PORT);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
@@ -668,11 +670,11 @@ static int mlx5e_ptp_rx_set_fs(struct mlx5e_priv *priv)
        }
        ptp_fs->udp_v6_rule = rule;
 
-       err = mlx5e_fs_tt_redirect_any_create(priv);
+       err = mlx5e_fs_tt_redirect_any_create(fs);
        if (err)
                goto out_destroy_udp_v6_rule;
 
-       rule = mlx5e_fs_tt_redirect_any_add_rule(priv, tirn, ETH_P_1588);
+       rule = mlx5e_fs_tt_redirect_any_add_rule(fs, tirn, ETH_P_1588);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
                goto out_destroy_fs_any;
@@ -683,13 +685,13 @@ static int mlx5e_ptp_rx_set_fs(struct mlx5e_priv *priv)
        return 0;
 
 out_destroy_fs_any:
-       mlx5e_fs_tt_redirect_any_destroy(priv);
+       mlx5e_fs_tt_redirect_any_destroy(fs);
 out_destroy_udp_v6_rule:
        mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v6_rule);
 out_destroy_udp_v4_rule:
        mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v4_rule);
 out_destroy_fs_udp:
-       mlx5e_fs_tt_redirect_udp_destroy(priv);
+       mlx5e_fs_tt_redirect_udp_destroy(fs);
 out_free:
        return err;
 }
@@ -797,29 +799,31 @@ int mlx5e_ptp_get_rqn(struct mlx5e_ptp *c, u32 *rqn)
        return 0;
 }
 
-int mlx5e_ptp_alloc_rx_fs(struct mlx5e_priv *priv)
+int mlx5e_ptp_alloc_rx_fs(struct mlx5e_flow_steering *fs,
+                         const struct mlx5e_profile *profile)
 {
        struct mlx5e_ptp_fs *ptp_fs;
 
-       if (!mlx5e_profile_feature_cap(priv->profile, PTP_RX))
+       if (!mlx5e_profile_feature_cap(profile, PTP_RX))
                return 0;
 
        ptp_fs = kzalloc(sizeof(*ptp_fs), GFP_KERNEL);
        if (!ptp_fs)
                return -ENOMEM;
+       mlx5e_fs_set_ptp(fs, ptp_fs);
 
-       priv->fs->ptp_fs = ptp_fs;
        return 0;
 }
 
-void mlx5e_ptp_free_rx_fs(struct mlx5e_priv *priv)
+void mlx5e_ptp_free_rx_fs(struct mlx5e_flow_steering *fs,
+                         const struct mlx5e_profile *profile)
 {
-       struct mlx5e_ptp_fs *ptp_fs = priv->fs->ptp_fs;
+       struct mlx5e_ptp_fs *ptp_fs = mlx5e_fs_get_ptp(fs);
 
-       if (!mlx5e_profile_feature_cap(priv->profile, PTP_RX))
+       if (!mlx5e_profile_feature_cap(profile, PTP_RX))
                return;
 
-       mlx5e_ptp_rx_unset_fs(priv);
+       mlx5e_ptp_rx_unset_fs(fs);
        kfree(ptp_fs);
 }
 
@@ -845,6 +849,6 @@ int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set)
                netdev_WARN_ONCE(priv->netdev, "Don't try to remove PTP RX-FS rules");
                return -EINVAL;
        }
-       mlx5e_ptp_rx_unset_fs(priv);
+       mlx5e_ptp_rx_unset_fs(priv->fs);
        return 0;
 }
index 92dbbec..5bce554 100644 (file)
@@ -74,8 +74,10 @@ void mlx5e_ptp_close(struct mlx5e_ptp *c);
 void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c);
 void mlx5e_ptp_deactivate_channel(struct mlx5e_ptp *c);
 int mlx5e_ptp_get_rqn(struct mlx5e_ptp *c, u32 *rqn);
-int mlx5e_ptp_alloc_rx_fs(struct mlx5e_priv *priv);
-void mlx5e_ptp_free_rx_fs(struct mlx5e_priv *priv);
+int mlx5e_ptp_alloc_rx_fs(struct mlx5e_flow_steering *fs,
+                         const struct mlx5e_profile *profile);
+void mlx5e_ptp_free_rx_fs(struct mlx5e_flow_steering *fs,
+                         const struct mlx5e_profile *profile);
 int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set);
 
 enum {
index 69949ab..25174f6 100644 (file)
@@ -12,6 +12,7 @@ validate_goto_chain(struct mlx5e_priv *priv,
                    const struct flow_action_entry *act,
                    struct netlink_ext_ack *extack)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        bool is_esw = mlx5e_is_eswitch_flow(flow);
        bool ft_flow = mlx5e_is_ft_flow(flow);
        u32 dest_chain = act->chain_index;
@@ -21,7 +22,7 @@ validate_goto_chain(struct mlx5e_priv *priv,
        u32 max_chain;
 
        esw = priv->mdev->priv.eswitch;
-       chains = is_esw ? esw_chains(esw) : mlx5e_nic_chains(priv->fs->tc);
+       chains = is_esw ? esw_chains(esw) : mlx5e_nic_chains(tc);
        max_chain = mlx5_chains_get_chain_range(chains);
        reformat_and_fwd = is_esw ?
                           MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, reformat_and_fwd_to_table) :
index 11f2a7f..46c2e5f 100644 (file)
@@ -230,12 +230,12 @@ static int mlx5e_handle_action_trap(struct mlx5e_priv *priv, int trap_id)
 
        switch (trap_id) {
        case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
-               err = mlx5e_add_vlan_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
+               err = mlx5e_add_vlan_trap(priv->fs, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
                if (err)
                        goto err_out;
                break;
        case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
-               err = mlx5e_add_mac_trap(priv, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
+               err = mlx5e_add_mac_trap(priv->fs, trap_id, mlx5e_trap_get_tirn(priv->en_trap));
                if (err)
                        goto err_out;
                break;
@@ -256,10 +256,10 @@ static int mlx5e_handle_action_drop(struct mlx5e_priv *priv, int trap_id)
 {
        switch (trap_id) {
        case DEVLINK_TRAP_GENERIC_ID_INGRESS_VLAN_FILTER:
-               mlx5e_remove_vlan_trap(priv);
+               mlx5e_remove_vlan_trap(priv->fs);
                break;
        case DEVLINK_TRAP_GENERIC_ID_DMAC_FILTER:
-               mlx5e_remove_mac_trap(priv);
+               mlx5e_remove_mac_trap(priv->fs);
                break;
        default:
                netdev_warn(priv->netdev, "%s: Unknown trap id %d\n", __func__, trap_id);
index 20a4f1e..285d32d 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
 /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
 
-#include <linux/netdevice.h>
+#include <mlx5_core.h>
 #include "en_accel/fs_tcp.h"
 #include "fs_core.h"
 
@@ -71,13 +71,13 @@ void mlx5e_accel_fs_del_sk(struct mlx5_flow_handle *rule)
        mlx5_del_flow_rules(rule);
 }
 
-struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
+struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_flow_steering *fs,
                                               struct sock *sk, u32 tirn,
                                               uint32_t flow_tag)
 {
+       struct mlx5e_accel_fs_tcp *fs_tcp = mlx5e_fs_get_accel_tcp(fs);
        struct mlx5_flow_destination dest = {};
        struct mlx5e_flow_table *ft = NULL;
-       struct mlx5e_accel_fs_tcp *fs_tcp;
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_handle *flow;
        struct mlx5_flow_spec *spec;
@@ -86,19 +86,17 @@ struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
        if (!spec)
                return ERR_PTR(-ENOMEM);
 
-       fs_tcp = priv->fs->accel_tcp;
-
        spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
 
        switch (sk->sk_family) {
        case AF_INET:
                accel_fs_tcp_set_ipv4_flow(spec, sk);
                ft = &fs_tcp->tables[ACCEL_FS_IPV4_TCP];
-               mlx5e_dbg(HW, priv, "%s flow is %pI4:%d -> %pI4:%d\n", __func__,
-                         &inet_sk(sk)->inet_rcv_saddr,
-                         inet_sk(sk)->inet_sport,
-                         &inet_sk(sk)->inet_daddr,
-                         inet_sk(sk)->inet_dport);
+               fs_dbg(fs, "%s flow is %pI4:%d -> %pI4:%d\n", __func__,
+                      &inet_sk(sk)->inet_rcv_saddr,
+                      inet_sk(sk)->inet_sport,
+                      &inet_sk(sk)->inet_daddr,
+                      inet_sk(sk)->inet_dport);
                break;
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6:
@@ -140,34 +138,32 @@ struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
        flow = mlx5_add_flow_rules(ft->t, spec, &flow_act, &dest, 1);
 
        if (IS_ERR(flow))
-               netdev_err(priv->netdev, "mlx5_add_flow_rules() failed, flow is %ld\n",
-                          PTR_ERR(flow));
+               fs_err(fs, "mlx5_add_flow_rules() failed, flow is %ld\n", PTR_ERR(flow));
 
 out:
        kvfree(spec);
        return flow;
 }
 
-static int accel_fs_tcp_add_default_rule(struct mlx5e_priv *priv,
+static int accel_fs_tcp_add_default_rule(struct mlx5e_flow_steering *fs,
                                         enum accel_fs_tcp_type type)
 {
+       struct mlx5e_accel_fs_tcp *fs_tcp = mlx5e_fs_get_accel_tcp(fs);
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
        struct mlx5e_flow_table *accel_fs_t;
        struct mlx5_flow_destination dest;
-       struct mlx5e_accel_fs_tcp *fs_tcp;
        MLX5_DECLARE_FLOW_ACT(flow_act);
        struct mlx5_flow_handle *rule;
        int err = 0;
 
-       fs_tcp = priv->fs->accel_tcp;
        accel_fs_t = &fs_tcp->tables[type];
 
-       dest = mlx5_ttc_get_default_dest(priv->fs->ttc, fs_accel2tt(type));
+       dest = mlx5_ttc_get_default_dest(ttc, fs_accel2tt(type));
        rule = mlx5_add_flow_rules(accel_fs_t->t, NULL, &flow_act, &dest, 1);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               netdev_err(priv->netdev,
-                          "%s: add default rule failed, accel_fs type=%d, err %d\n",
-                          __func__, type, err);
+               fs_err(fs, "%s: add default rule failed, accel_fs type=%d, err %d\n",
+                      __func__, type, err);
                return err;
        }
 
@@ -265,9 +261,11 @@ out:
        return err;
 }
 
-static int accel_fs_tcp_create_table(struct mlx5e_priv *priv, enum accel_fs_tcp_type type)
+static int accel_fs_tcp_create_table(struct mlx5e_flow_steering *fs, enum accel_fs_tcp_type type)
 {
-       struct mlx5e_flow_table *ft = &priv->fs->accel_tcp->tables[type];
+       struct mlx5e_accel_fs_tcp *accel_tcp = mlx5e_fs_get_accel_tcp(fs);
+       struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs, false);
+       struct mlx5e_flow_table *ft = &accel_tcp->tables[type];
        struct mlx5_flow_table_attr ft_attr = {};
        int err;
 
@@ -277,21 +275,21 @@ static int accel_fs_tcp_create_table(struct mlx5e_priv *priv, enum accel_fs_tcp_
        ft_attr.level = MLX5E_ACCEL_FS_TCP_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
 
-       ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
+       ft->t = mlx5_create_flow_table(ns, &ft_attr);
        if (IS_ERR(ft->t)) {
                err = PTR_ERR(ft->t);
                ft->t = NULL;
                return err;
        }
 
-       netdev_dbg(priv->netdev, "Created fs accel table id %u level %u\n",
-                  ft->t->id, ft->t->level);
+       fs_dbg(fs, "Created fs accel table id %u level %u\n",
+              ft->t->id, ft->t->level);
 
        err = accel_fs_tcp_create_groups(ft, type);
        if (err)
                goto err;
 
-       err = accel_fs_tcp_add_default_rule(priv, type);
+       err = accel_fs_tcp_add_default_rule(fs, type);
        if (err)
                goto err;
 
@@ -301,17 +299,18 @@ err:
        return err;
 }
 
-static int accel_fs_tcp_disable(struct mlx5e_priv *priv)
+static int accel_fs_tcp_disable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
        int err, i;
 
        for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++) {
                /* Modify ttc rules destination to point back to the indir TIRs */
-               err = mlx5_ttc_fwd_default_dest(priv->fs->ttc, fs_accel2tt(i));
+               err = mlx5_ttc_fwd_default_dest(ttc, fs_accel2tt(i));
                if (err) {
-                       netdev_err(priv->netdev,
-                                  "%s: modify ttc[%d] default destination failed, err(%d)\n",
-                                  __func__, fs_accel2tt(i), err);
+                       fs_err(fs,
+                              "%s: modify ttc[%d] default destination failed, err(%d)\n",
+                              __func__, fs_accel2tt(i), err);
                        return err;
                }
        }
@@ -319,32 +318,32 @@ static int accel_fs_tcp_disable(struct mlx5e_priv *priv)
        return 0;
 }
 
-static int accel_fs_tcp_enable(struct mlx5e_priv *priv)
+static int accel_fs_tcp_enable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_accel_fs_tcp *accel_tcp = mlx5e_fs_get_accel_tcp(fs);
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
        struct mlx5_flow_destination dest = {};
        int err, i;
 
        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
        for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++) {
-               dest.ft = priv->fs->accel_tcp->tables[i].t;
+               dest.ft = accel_tcp->tables[i].t;
 
                /* Modify ttc rules destination to point on the accel_fs FTs */
-               err = mlx5_ttc_fwd_dest(priv->fs->ttc, fs_accel2tt(i), &dest);
+               err = mlx5_ttc_fwd_dest(ttc, fs_accel2tt(i), &dest);
                if (err) {
-                       netdev_err(priv->netdev,
-                                  "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
-                                  __func__, fs_accel2tt(i), err);
+                       fs_err(fs, "%s: modify ttc[%d] destination to accel failed, err(%d)\n",
+                              __func__, fs_accel2tt(i), err);
                        return err;
                }
        }
        return 0;
 }
 
-static void accel_fs_tcp_destroy_table(struct mlx5e_priv *priv, int i)
+static void accel_fs_tcp_destroy_table(struct mlx5e_flow_steering *fs, int i)
 {
-       struct mlx5e_accel_fs_tcp *fs_tcp;
+       struct mlx5e_accel_fs_tcp *fs_tcp = mlx5e_fs_get_accel_tcp(fs);
 
-       fs_tcp = priv->fs->accel_tcp;
        if (IS_ERR_OR_NULL(fs_tcp->tables[i].t))
                return;
 
@@ -353,40 +352,43 @@ static void accel_fs_tcp_destroy_table(struct mlx5e_priv *priv, int i)
        fs_tcp->tables[i].t = NULL;
 }
 
-void mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv)
+void mlx5e_accel_fs_tcp_destroy(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_accel_fs_tcp *accel_tcp = mlx5e_fs_get_accel_tcp(fs);
        int i;
 
-       if (!priv->fs->accel_tcp)
+       if (!accel_tcp)
                return;
 
-       accel_fs_tcp_disable(priv);
+       accel_fs_tcp_disable(fs);
 
        for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++)
-               accel_fs_tcp_destroy_table(priv, i);
+               accel_fs_tcp_destroy_table(fs, i);
 
-       kfree(priv->fs->accel_tcp);
-       priv->fs->accel_tcp = NULL;
+       kfree(accel_tcp);
+       mlx5e_fs_set_accel_tcp(fs, NULL);
 }
 
-int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv)
+int mlx5e_accel_fs_tcp_create(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_accel_fs_tcp *accel_tcp;
        int i, err;
 
-       if (!MLX5_CAP_FLOWTABLE_NIC_RX(priv->mdev, ft_field_support.outer_ip_version))
+       if (!MLX5_CAP_FLOWTABLE_NIC_RX(mlx5e_fs_get_mdev(fs), ft_field_support.outer_ip_version))
                return -EOPNOTSUPP;
 
-       priv->fs->accel_tcp = kzalloc(sizeof(*priv->fs->accel_tcp), GFP_KERNEL);
-       if (!priv->fs->accel_tcp)
+       accel_tcp = kvzalloc(sizeof(*accel_tcp), GFP_KERNEL);
+       if (!accel_tcp)
                return -ENOMEM;
+       mlx5e_fs_set_accel_tcp(fs, accel_tcp);
 
        for (i = 0; i < ACCEL_FS_TCP_NUM_TYPES; i++) {
-               err = accel_fs_tcp_create_table(priv, i);
+               err = accel_fs_tcp_create_table(fs, i);
                if (err)
                        goto err_destroy_tables;
        }
 
-       err = accel_fs_tcp_enable(priv);
+       err = accel_fs_tcp_enable(fs);
        if (err)
                goto err_destroy_tables;
 
@@ -394,9 +396,8 @@ int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv)
 
 err_destroy_tables:
        while (--i >= 0)
-               accel_fs_tcp_destroy_table(priv, i);
-
-       kfree(priv->fs->accel_tcp);
-       priv->fs->accel_tcp = NULL;
+               accel_fs_tcp_destroy_table(fs, i);
+       kfree(accel_tcp);
+       mlx5e_fs_set_accel_tcp(fs, NULL);
        return err;
 }
index 5892358..a032bff 100644 (file)
@@ -4,19 +4,19 @@
 #ifndef __MLX5E_ACCEL_FS_TCP_H__
 #define __MLX5E_ACCEL_FS_TCP_H__
 
-#include "en.h"
+#include "en/fs.h"
 
 #ifdef CONFIG_MLX5_EN_TLS
-int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv);
-void mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv);
-struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
+int mlx5e_accel_fs_tcp_create(struct mlx5e_flow_steering *fs);
+void mlx5e_accel_fs_tcp_destroy(struct mlx5e_flow_steering *fs);
+struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_flow_steering *fs,
                                               struct sock *sk, u32 tirn,
                                               uint32_t flow_tag);
 void mlx5e_accel_fs_del_sk(struct mlx5_flow_handle *rule);
 #else
-static inline int mlx5e_accel_fs_tcp_create(struct mlx5e_priv *priv) { return 0; }
-static inline void mlx5e_accel_fs_tcp_destroy(struct mlx5e_priv *priv) {}
-static inline struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_priv *priv,
+static inline int mlx5e_accel_fs_tcp_create(struct mlx5e_flow_steering *fs) { return 0; }
+static inline void mlx5e_accel_fs_tcp_destroy(struct mlx5e_flow_steering *fs) {}
+static inline struct mlx5_flow_handle *mlx5e_accel_fs_add_sk(struct mlx5e_flow_steering *fs,
                                                             struct sock *sk, u32 tirn,
                                                             uint32_t flow_tag)
 { return ERR_PTR(-EOPNOTSUPP); }
index f8113fd..e776b9f 100644 (file)
@@ -174,6 +174,8 @@ static void rx_destroy(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
 
 static int rx_create(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
 {
+       struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(priv->fs, false);
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(priv->fs, false);
        struct mlx5_flow_table_attr ft_attr = {};
        struct mlx5e_accel_fs_esp_prot *fs_prot;
        struct mlx5e_accel_fs_esp *accel_esp;
@@ -182,15 +184,14 @@ static int rx_create(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
 
        accel_esp = priv->ipsec->rx_fs;
        fs_prot = &accel_esp->fs_prot[type];
-
        fs_prot->default_dest =
-               mlx5_ttc_get_default_dest(priv->fs->ttc, fs_esp2tt(type));
+               mlx5_ttc_get_default_dest(ttc, fs_esp2tt(type));
 
        ft_attr.max_fte = 1;
        ft_attr.autogroup.max_num_groups = 1;
        ft_attr.level = MLX5E_ACCEL_FS_ESP_FT_ERR_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
-       ft = mlx5_create_auto_grouped_flow_table(priv->fs->ns, &ft_attr);
+       ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
        if (IS_ERR(ft))
                return PTR_ERR(ft);
 
@@ -205,7 +206,7 @@ static int rx_create(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
        ft_attr.prio = MLX5E_NIC_PRIO;
        ft_attr.autogroup.num_reserved_entries = 1;
        ft_attr.autogroup.max_num_groups = 1;
-       ft = mlx5_create_auto_grouped_flow_table(priv->fs->ns, &ft_attr);
+       ft = mlx5_create_auto_grouped_flow_table(ns, &ft_attr);
        if (IS_ERR(ft)) {
                err = PTR_ERR(ft);
                goto err_fs_ft;
@@ -230,6 +231,7 @@ err_add:
 
 static int rx_ft_get(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(priv->fs, false);
        struct mlx5e_accel_fs_esp_prot *fs_prot;
        struct mlx5_flow_destination dest = {};
        struct mlx5e_accel_fs_esp *accel_esp;
@@ -249,7 +251,7 @@ static int rx_ft_get(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
        /* connect */
        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
        dest.ft = fs_prot->ft;
-       mlx5_ttc_fwd_dest(priv->fs->ttc, fs_esp2tt(type), &dest);
+       mlx5_ttc_fwd_dest(ttc, fs_esp2tt(type), &dest);
 
 skip:
        fs_prot->refcnt++;
@@ -260,6 +262,7 @@ out:
 
 static void rx_ft_put(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(priv->fs, false);
        struct mlx5e_accel_fs_esp_prot *fs_prot;
        struct mlx5e_accel_fs_esp *accel_esp;
 
@@ -271,7 +274,7 @@ static void rx_ft_put(struct mlx5e_priv *priv, enum accel_fs_esp_type type)
                goto out;
 
        /* disconnect */
-       mlx5_ttc_fwd_default_dest(priv->fs->ttc, fs_esp2tt(type));
+       mlx5_ttc_fwd_default_dest(ttc, fs_esp2tt(type));
 
        /* remove FT */
        rx_destroy(priv, type);
index 30a70d1..c0b7796 100644 (file)
@@ -118,9 +118,9 @@ int mlx5e_ktls_set_feature_rx(struct net_device *netdev, bool enable)
 
        mutex_lock(&priv->state_lock);
        if (enable)
-               err = mlx5e_accel_fs_tcp_create(priv);
+               err = mlx5e_accel_fs_tcp_create(priv->fs);
        else
-               mlx5e_accel_fs_tcp_destroy(priv);
+               mlx5e_accel_fs_tcp_destroy(priv->fs);
        mutex_unlock(&priv->state_lock);
 
        return err;
@@ -138,7 +138,7 @@ int mlx5e_ktls_init_rx(struct mlx5e_priv *priv)
                return -ENOMEM;
 
        if (priv->netdev->features & NETIF_F_HW_TLS_RX) {
-               err = mlx5e_accel_fs_tcp_create(priv);
+               err = mlx5e_accel_fs_tcp_create(priv->fs);
                if (err) {
                        destroy_workqueue(priv->tls->rx_wq);
                        return err;
@@ -154,7 +154,7 @@ void mlx5e_ktls_cleanup_rx(struct mlx5e_priv *priv)
                return;
 
        if (priv->netdev->features & NETIF_F_HW_TLS_RX)
-               mlx5e_accel_fs_tcp_destroy(priv);
+               mlx5e_accel_fs_tcp_destroy(priv->fs);
 
        destroy_workqueue(priv->tls->rx_wq);
 }
index 27483aa..13145ec 100644 (file)
@@ -111,7 +111,7 @@ static void accel_rule_handle_work(struct work_struct *work)
        if (unlikely(test_bit(MLX5E_PRIV_RX_FLAG_DELETING, priv_rx->flags)))
                goto out;
 
-       rule = mlx5e_accel_fs_add_sk(accel_rule->priv, priv_rx->sk,
+       rule = mlx5e_accel_fs_add_sk(accel_rule->priv->fs, priv_rx->sk,
                                     mlx5e_tir_get_tirn(&priv_rx->tir),
                                     MLX5_FS_DEFAULT_FLOW_TAG);
        if (!IS_ERR_OR_NULL(rule))
index cd7f245..0ae1865 100644 (file)
@@ -114,47 +114,49 @@ static enum mlx5_traffic_types arfs_get_tt(enum arfs_type type)
        }
 }
 
-static int arfs_disable(struct mlx5e_priv *priv)
+static int arfs_disable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
        int err, i;
 
        for (i = 0; i < ARFS_NUM_TYPES; i++) {
                /* Modify ttc rules destination back to their default */
-               err = mlx5_ttc_fwd_default_dest(priv->fs->ttc, arfs_get_tt(i));
+               err = mlx5_ttc_fwd_default_dest(ttc, arfs_get_tt(i));
                if (err) {
-                       netdev_err(priv->netdev,
-                                  "%s: modify ttc[%d] default destination failed, err(%d)\n",
-                                  __func__, arfs_get_tt(i), err);
+                       fs_err(fs,
+                              "%s: modify ttc[%d] default destination failed, err(%d)\n",
+                              __func__, arfs_get_tt(i), err);
                        return err;
                }
        }
        return 0;
 }
 
-static void arfs_del_rules(struct mlx5e_priv *priv);
+static void arfs_del_rules(struct mlx5e_flow_steering *fs);
 
-int mlx5e_arfs_disable(struct mlx5e_priv *priv)
+int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
 {
-       arfs_del_rules(priv);
+       arfs_del_rules(fs);
 
-       return arfs_disable(priv);
+       return arfs_disable(fs);
 }
 
-int mlx5e_arfs_enable(struct mlx5e_priv *priv)
+int mlx5e_arfs_enable(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5_ttc_table *ttc = mlx5e_fs_get_ttc(fs, false);
+       struct mlx5e_arfs_tables *arfs =  mlx5e_fs_get_arfs(fs);
        struct mlx5_flow_destination dest = {};
        int err, i;
 
        dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
        for (i = 0; i < ARFS_NUM_TYPES; i++) {
-               dest.ft = priv->fs->arfs->arfs_tables[i].ft.t;
+               dest.ft = arfs->arfs_tables[i].ft.t;
                /* Modify ttc rules destination to point on the aRFS FTs */
-               err = mlx5_ttc_fwd_dest(priv->fs->ttc, arfs_get_tt(i), &dest);
+               err = mlx5_ttc_fwd_dest(ttc, arfs_get_tt(i), &dest);
                if (err) {
-                       netdev_err(priv->netdev,
-                                  "%s: modify ttc[%d] dest to arfs, failed err(%d)\n",
-                                  __func__, arfs_get_tt(i), err);
-                       arfs_disable(priv);
+                       fs_err(fs, "%s: modify ttc[%d] dest to arfs, failed err(%d)\n",
+                              __func__, arfs_get_tt(i), err);
+                       arfs_disable(fs);
                        return err;
                }
        }
@@ -167,31 +169,37 @@ static void arfs_destroy_table(struct arfs_table *arfs_t)
        mlx5e_destroy_flow_table(&arfs_t->ft);
 }
 
-static void _mlx5e_cleanup_tables(struct mlx5e_priv *priv)
+static void _mlx5e_cleanup_tables(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_arfs_tables *arfs =  mlx5e_fs_get_arfs(fs);
        int i;
 
-       arfs_del_rules(priv);
-       destroy_workqueue(priv->fs->arfs->wq);
+       arfs_del_rules(fs);
+       destroy_workqueue(arfs->wq);
        for (i = 0; i < ARFS_NUM_TYPES; i++) {
-               if (!IS_ERR_OR_NULL(priv->fs->arfs->arfs_tables[i].ft.t))
-                       arfs_destroy_table(&priv->fs->arfs->arfs_tables[i]);
+               if (!IS_ERR_OR_NULL(arfs->arfs_tables[i].ft.t))
+                       arfs_destroy_table(&arfs->arfs_tables[i]);
        }
 }
 
-void mlx5e_arfs_destroy_tables(struct mlx5e_priv *priv)
+void mlx5e_arfs_destroy_tables(struct mlx5e_flow_steering *fs, bool ntuple)
 {
-       if (!(priv->netdev->hw_features & NETIF_F_NTUPLE))
+       struct mlx5e_arfs_tables *arfs =  mlx5e_fs_get_arfs(fs);
+
+       if (!ntuple)
                return;
 
-       _mlx5e_cleanup_tables(priv);
-       kvfree(priv->fs->arfs);
+       _mlx5e_cleanup_tables(fs);
+       mlx5e_fs_set_arfs(fs, NULL);
+       kvfree(arfs);
 }
 
-static int arfs_add_default_rule(struct mlx5e_priv *priv,
+static int arfs_add_default_rule(struct mlx5e_flow_steering *fs,
+                                struct mlx5e_rx_res *rx_res,
                                 enum arfs_type type)
 {
-       struct arfs_table *arfs_t = &priv->fs->arfs->arfs_tables[type];
+       struct mlx5e_arfs_tables *arfs =  mlx5e_fs_get_arfs(fs);
+       struct arfs_table *arfs_t = &arfs->arfs_tables[type];
        struct mlx5_flow_destination dest = {};
        MLX5_DECLARE_FLOW_ACT(flow_act);
        enum mlx5_traffic_types tt;
@@ -200,23 +208,21 @@ static int arfs_add_default_rule(struct mlx5e_priv *priv,
        dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR;
        tt = arfs_get_tt(type);
        if (tt == -EINVAL) {
-               netdev_err(priv->netdev, "%s: bad arfs_type: %d\n",
-                          __func__, type);
+               fs_err(fs, "%s: bad arfs_type: %d\n", __func__, type);
                return -EINVAL;
        }
 
        /* FIXME: Must use mlx5_ttc_get_default_dest(),
         * but can't since TTC default is not setup yet !
         */
-       dest.tir_num = mlx5e_rx_res_get_tirn_rss(priv->rx_res, tt);
+       dest.tir_num = mlx5e_rx_res_get_tirn_rss(rx_res, tt);
        arfs_t->default_rule = mlx5_add_flow_rules(arfs_t->ft.t, NULL,
                                                   &flow_act,
                                                   &dest, 1);
        if (IS_ERR(arfs_t->default_rule)) {
                err = PTR_ERR(arfs_t->default_rule);
                arfs_t->default_rule = NULL;
-               netdev_err(priv->netdev, "%s: add rule failed, arfs type=%d\n",
-                          __func__, type);
+               fs_err(fs, "%s: add rule failed, arfs type=%d\n", __func__, type);
        }
 
        return err;
@@ -318,10 +324,12 @@ out:
        return err;
 }
 
-static int arfs_create_table(struct mlx5e_priv *priv,
+static int arfs_create_table(struct mlx5e_flow_steering *fs,
+                            struct mlx5e_rx_res *rx_res,
                             enum arfs_type type)
 {
-       struct mlx5e_arfs_tables *arfs = priv->fs->arfs;
+       struct mlx5_flow_namespace *ns = mlx5e_fs_get_ns(fs, false);
+       struct mlx5e_arfs_tables *arfs = mlx5e_fs_get_arfs(fs);
        struct mlx5e_flow_table *ft = &arfs->arfs_tables[type].ft;
        struct mlx5_flow_table_attr ft_attr = {};
        int err;
@@ -332,7 +340,7 @@ static int arfs_create_table(struct mlx5e_priv *priv,
        ft_attr.level = MLX5E_ARFS_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
 
-       ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
+       ft->t = mlx5_create_flow_table(ns, &ft_attr);
        if (IS_ERR(ft->t)) {
                err = PTR_ERR(ft->t);
                ft->t = NULL;
@@ -343,7 +351,7 @@ static int arfs_create_table(struct mlx5e_priv *priv,
        if (err)
                goto err;
 
-       err = arfs_add_default_rule(priv, type);
+       err = arfs_add_default_rule(fs, rx_res,  type);
        if (err)
                goto err;
 
@@ -353,35 +361,40 @@ err:
        return err;
 }
 
-int mlx5e_arfs_create_tables(struct mlx5e_priv *priv)
+int mlx5e_arfs_create_tables(struct mlx5e_flow_steering *fs,
+                            struct mlx5e_rx_res *rx_res, bool ntuple)
 {
+       struct mlx5e_arfs_tables *arfs;
        int err = -ENOMEM;
        int i;
 
-       if (!(priv->netdev->hw_features & NETIF_F_NTUPLE))
+       if (!ntuple)
                return 0;
 
-       priv->fs->arfs = kvzalloc(sizeof(*priv->fs->arfs), GFP_KERNEL);
-       if (!priv->fs->arfs)
+       arfs = kvzalloc(sizeof(*arfs), GFP_KERNEL);
+       if (!arfs)
                return -ENOMEM;
 
-       spin_lock_init(&priv->fs->arfs->arfs_lock);
-       INIT_LIST_HEAD(&priv->fs->arfs->rules);
-       priv->fs->arfs->wq = create_singlethread_workqueue("mlx5e_arfs");
-       if (!priv->fs->arfs->wq)
+       spin_lock_init(&arfs->arfs_lock);
+       INIT_LIST_HEAD(&arfs->rules);
+       arfs->wq = create_singlethread_workqueue("mlx5e_arfs");
+       if (!arfs->wq)
                goto err;
 
+       mlx5e_fs_set_arfs(fs, arfs);
+
        for (i = 0; i < ARFS_NUM_TYPES; i++) {
-               err = arfs_create_table(priv, i);
+               err = arfs_create_table(fs, rx_res, i);
                if (err)
                        goto err_des;
        }
        return 0;
 
 err_des:
-       _mlx5e_cleanup_tables(priv);
+       _mlx5e_cleanup_tables(fs);
 err:
-       kvfree(priv->fs->arfs);
+       mlx5e_fs_set_arfs(fs, NULL);
+       kvfree(arfs);
        return err;
 }
 
@@ -389,6 +402,7 @@ err:
 
 static void arfs_may_expire_flow(struct mlx5e_priv *priv)
 {
+       struct mlx5e_arfs_tables *arfs = mlx5e_fs_get_arfs(priv->fs);
        struct arfs_rule *arfs_rule;
        struct hlist_node *htmp;
        HLIST_HEAD(del_list);
@@ -396,8 +410,8 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
        int i;
        int j;
 
-       spin_lock_bh(&priv->fs->arfs->arfs_lock);
-       mlx5e_for_each_arfs_rule(arfs_rule, htmp, priv->fs->arfs->arfs_tables, i, j) {
+       spin_lock_bh(&arfs->arfs_lock);
+       mlx5e_for_each_arfs_rule(arfs_rule, htmp, arfs->arfs_tables, i, j) {
                if (!work_pending(&arfs_rule->arfs_work) &&
                    rps_may_expire_flow(priv->netdev,
                                        arfs_rule->rxq, arfs_rule->flow_id,
@@ -408,7 +422,7 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
                                break;
                }
        }
-       spin_unlock_bh(&priv->fs->arfs->arfs_lock);
+       spin_unlock_bh(&arfs->arfs_lock);
        hlist_for_each_entry_safe(arfs_rule, htmp, &del_list, hlist) {
                if (arfs_rule->rule)
                        mlx5_del_flow_rules(arfs_rule->rule);
@@ -417,20 +431,21 @@ static void arfs_may_expire_flow(struct mlx5e_priv *priv)
        }
 }
 
-static void arfs_del_rules(struct mlx5e_priv *priv)
+static void arfs_del_rules(struct mlx5e_flow_steering *fs)
 {
+       struct mlx5e_arfs_tables *arfs = mlx5e_fs_get_arfs(fs);
        struct hlist_node *htmp;
        struct arfs_rule *rule;
        HLIST_HEAD(del_list);
        int i;
        int j;
 
-       spin_lock_bh(&priv->fs->arfs->arfs_lock);
-       mlx5e_for_each_arfs_rule(rule, htmp, priv->fs->arfs->arfs_tables, i, j) {
+       spin_lock_bh(&arfs->arfs_lock);
+       mlx5e_for_each_arfs_rule(rule, htmp, arfs->arfs_tables, i, j) {
                hlist_del_init(&rule->hlist);
                hlist_add_head(&rule->hlist, &del_list);
        }
-       spin_unlock_bh(&priv->fs->arfs->arfs_lock);
+       spin_unlock_bh(&arfs->arfs_lock);
 
        hlist_for_each_entry_safe(rule, htmp, &del_list, hlist) {
                cancel_work_sync(&rule->arfs_work);
@@ -474,7 +489,7 @@ static struct arfs_table *arfs_get_table(struct mlx5e_arfs_tables *arfs,
 static struct mlx5_flow_handle *arfs_add_rule(struct mlx5e_priv *priv,
                                              struct arfs_rule *arfs_rule)
 {
-       struct mlx5e_arfs_tables *arfs = priv->fs->arfs;
+       struct mlx5e_arfs_tables *arfs = mlx5e_fs_get_arfs(priv->fs);
        struct arfs_tuple *tuple = &arfs_rule->tuple;
        struct mlx5_flow_handle *rule = NULL;
        struct mlx5_flow_destination dest = {};
@@ -588,13 +603,15 @@ static void arfs_handle_work(struct work_struct *work)
                                                   struct arfs_rule,
                                                   arfs_work);
        struct mlx5e_priv *priv = arfs_rule->priv;
+       struct mlx5e_arfs_tables *arfs;
        struct mlx5_flow_handle *rule;
 
+       arfs = mlx5e_fs_get_arfs(priv->fs);
        mutex_lock(&priv->state_lock);
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
-               spin_lock_bh(&priv->fs->arfs->arfs_lock);
+               spin_lock_bh(&arfs->arfs_lock);
                hlist_del(&arfs_rule->hlist);
-               spin_unlock_bh(&priv->fs->arfs->arfs_lock);
+               spin_unlock_bh(&arfs->arfs_lock);
 
                mutex_unlock(&priv->state_lock);
                kfree(arfs_rule);
@@ -620,6 +637,7 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
                                         const struct flow_keys *fk,
                                         u16 rxq, u32 flow_id)
 {
+       struct mlx5e_arfs_tables *arfs =  mlx5e_fs_get_arfs(priv->fs);
        struct arfs_rule *rule;
        struct arfs_tuple *tuple;
 
@@ -647,7 +665,7 @@ static struct arfs_rule *arfs_alloc_rule(struct mlx5e_priv *priv,
        tuple->dst_port = fk->ports.dst;
 
        rule->flow_id = flow_id;
-       rule->filter_id = priv->fs->arfs->last_filter_id++ % RPS_NO_FILTER;
+       rule->filter_id = arfs->last_filter_id++ % RPS_NO_FILTER;
 
        hlist_add_head(&rule->hlist,
                       arfs_hash_bucket(arfs_t, tuple->src_port,
@@ -691,11 +709,12 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                        u16 rxq_index, u32 flow_id)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
-       struct mlx5e_arfs_tables *arfs = priv->fs->arfs;
-       struct arfs_table *arfs_t;
+       struct mlx5e_arfs_tables *arfs;
        struct arfs_rule *arfs_rule;
+       struct arfs_table *arfs_t;
        struct flow_keys fk;
 
+       arfs =  mlx5e_fs_get_arfs(priv->fs);
        if (!skb_flow_dissect_flow_keys(skb, &fk, 0))
                return -EPROTONOSUPPORT;
 
@@ -725,7 +744,7 @@ int mlx5e_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb,
                        return -ENOMEM;
                }
        }
-       queue_work(priv->fs->arfs->wq, &arfs_rule->arfs_work);
+       queue_work(arfs->wq, &arfs_rule->arfs_work);
        spin_unlock_bh(&arfs->arfs_lock);
        return arfs_rule->filter_id;
 }
index b811207..29ed20a 100644 (file)
 #include "en/xsk/pool.h"
 #include "en/ptp.h"
 #include "lib/clock.h"
+#include "en/fs_ethtool.h"
 
 void mlx5e_ethtool_get_drvinfo(struct mlx5e_priv *priv,
                               struct ethtool_drvinfo *drvinfo)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
 
-       strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                 "%d.%d.%04d (%.16s)",
                 fw_rev_maj(mdev), fw_rev_min(mdev), fw_rev_sub(mdev),
                 mdev->board_id);
-       strlcpy(drvinfo->bus_info, dev_name(mdev->device),
+       strscpy(drvinfo->bus_info, dev_name(mdev->device),
                sizeof(drvinfo->bus_info));
 }
 
@@ -494,14 +495,14 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
 
        arfs_enabled = opened && (priv->netdev->features & NETIF_F_NTUPLE);
        if (arfs_enabled)
-               mlx5e_arfs_disable(priv);
+               mlx5e_arfs_disable(priv->fs);
 
        /* Switch to new channels, set new parameters and close old ones */
        err = mlx5e_safe_switch_params(priv, &new_params,
                                       mlx5e_num_channels_changed_ctx, NULL, true);
 
        if (arfs_enabled) {
-               int err2 = mlx5e_arfs_enable(priv);
+               int err2 = mlx5e_arfs_enable(priv->fs);
 
                if (err2)
                        netdev_err(priv->netdev, "%s: mlx5e_arfs_enable failed: %d\n",
index e0ce5a2..1892ccb 100644 (file)
 #include <linux/tcp.h>
 #include <linux/mlx5/fs.h>
 #include <linux/mlx5/mpfs.h>
-#include "en.h"
 #include "en_tc.h"
 #include "lib/mpfs.h"
 #include "en/ptp.h"
+#include "en/fs_ethtool.h"
+
+struct mlx5e_flow_steering {
+       struct work_struct              set_rx_mode_work;
+       bool                            state_destroy;
+       bool                            vlan_strip_disable;
+       struct mlx5_core_dev            *mdev;
+       struct net_device               *netdev;
+       struct mlx5_flow_namespace      *ns;
+       struct mlx5_flow_namespace      *egress_ns;
+#ifdef CONFIG_MLX5_EN_RXNFC
+       struct mlx5e_ethtool_steering   *ethtool;
+#endif
+       struct mlx5e_tc_table           *tc;
+       struct mlx5e_promisc_table      promisc;
+       struct mlx5e_vlan_table         *vlan;
+       struct mlx5e_l2_table           l2;
+       struct mlx5_ttc_table           *ttc;
+       struct mlx5_ttc_table           *inner_ttc;
+#ifdef CONFIG_MLX5_EN_ARFS
+       struct mlx5e_arfs_tables       *arfs;
+#endif
+#ifdef CONFIG_MLX5_EN_TLS
+       struct mlx5e_accel_fs_tcp      *accel_tcp;
+#endif
+       struct mlx5e_fs_udp            *udp;
+       struct mlx5e_fs_any            *any;
+       struct mlx5e_ptp_fs            *ptp_fs;
+};
 
 static int mlx5e_add_l2_flow_rule(struct mlx5e_flow_steering *fs,
                                  struct mlx5e_l2_rule *ai, int type);
@@ -148,9 +176,8 @@ static int mlx5e_vport_context_update_vlans(struct mlx5e_flow_steering *fs)
        max_list_size = 1 << MLX5_CAP_GEN(fs->mdev, log_max_vlan_list);
 
        if (list_size > max_list_size) {
-               mlx5_core_warn(fs->mdev,
-                              "netdev vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n",
-                              list_size, max_list_size);
+               fs_warn(fs, "netdev vlans list size (%d) > (%d) max vport list size, some vlans will be dropped\n",
+                       list_size, max_list_size);
                list_size = max_list_size;
        }
 
@@ -167,8 +194,8 @@ static int mlx5e_vport_context_update_vlans(struct mlx5e_flow_steering *fs)
 
        err = mlx5_modify_nic_vport_vlans(fs->mdev, vlans, list_size);
        if (err)
-               mlx5_core_err(fs->mdev, "Failed to modify vport vlans list err(%d)\n",
-                             err);
+               fs_err(fs, "Failed to modify vport vlans list err(%d)\n",
+                      err);
 
        kvfree(vlans);
        return err;
@@ -249,7 +276,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;
-               mlx5_core_err(fs->mdev, "%s: add rule failed\n", __func__);
+               fs_err(fs, "%s: add rule failed\n", __func__);
        }
 
        return err;
@@ -351,78 +378,78 @@ mlx5e_add_trap_rule(struct mlx5_flow_table *ft, int trap_id, int tir_num)
        return rule;
 }
 
-int mlx5e_add_vlan_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
+int mlx5e_add_vlan_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num)
 {
-       struct mlx5_flow_table *ft = priv->fs->vlan->ft.t;
+       struct mlx5_flow_table *ft = fs->vlan->ft.t;
        struct mlx5_flow_handle *rule;
        int err;
 
        rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               priv->fs->vlan->trap_rule = NULL;
-               mlx5_core_err(priv->fs->mdev, "%s: add VLAN trap rule failed, err %d\n",
-                             __func__, err);
+               fs->vlan->trap_rule = NULL;
+               fs_err(fs, "%s: add VLAN trap rule failed, err %d\n",
+                      __func__, err);
                return err;
        }
-       priv->fs->vlan->trap_rule = rule;
+       fs->vlan->trap_rule = rule;
        return 0;
 }
 
-void mlx5e_remove_vlan_trap(struct mlx5e_priv *priv)
+void mlx5e_remove_vlan_trap(struct mlx5e_flow_steering *fs)
 {
-       if (priv->fs->vlan->trap_rule) {
-               mlx5_del_flow_rules(priv->fs->vlan->trap_rule);
-               priv->fs->vlan->trap_rule = NULL;
+       if (fs->vlan->trap_rule) {
+               mlx5_del_flow_rules(fs->vlan->trap_rule);
+               fs->vlan->trap_rule = NULL;
        }
 }
 
-int mlx5e_add_mac_trap(struct mlx5e_priv *priv, int trap_id, int tir_num)
+int mlx5e_add_mac_trap(struct mlx5e_flow_steering *fs, int trap_id, int tir_num)
 {
-       struct mlx5_flow_table *ft = priv->fs->l2.ft.t;
+       struct mlx5_flow_table *ft = fs->l2.ft.t;
        struct mlx5_flow_handle *rule;
        int err;
 
        rule = mlx5e_add_trap_rule(ft, trap_id, tir_num);
        if (IS_ERR(rule)) {
                err = PTR_ERR(rule);
-               priv->fs->l2.trap_rule = NULL;
-               mlx5_core_err(priv->fs->mdev, "%s: add MAC trap rule failed, err %d\n",
-                             __func__, err);
+               fs->l2.trap_rule = NULL;
+               fs_err(fs, "%s: add MAC trap rule failed, err %d\n",
+                      __func__, err);
                return err;
        }
-       priv->fs->l2.trap_rule = rule;
+       fs->l2.trap_rule = rule;
        return 0;
 }
 
-void mlx5e_remove_mac_trap(struct mlx5e_priv *priv)
+void mlx5e_remove_mac_trap(struct mlx5e_flow_steering *fs)
 {
-       if (priv->fs->l2.trap_rule) {
-               mlx5_del_flow_rules(priv->fs->l2.trap_rule);
-               priv->fs->l2.trap_rule = NULL;
+       if (fs->l2.trap_rule) {
+               mlx5_del_flow_rules(fs->l2.trap_rule);
+               fs->l2.trap_rule = NULL;
        }
 }
 
-void mlx5e_enable_cvlan_filter(struct mlx5e_priv *priv)
+void mlx5e_enable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc)
 {
-       if (!priv->fs->vlan->cvlan_filter_disabled)
+       if (!fs->vlan->cvlan_filter_disabled)
                return;
 
-       priv->fs->vlan->cvlan_filter_disabled = false;
-       if (priv->netdev->flags & IFF_PROMISC)
+       fs->vlan->cvlan_filter_disabled = false;
+       if (promisc)
                return;
-       mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
+       mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 }
 
-void mlx5e_disable_cvlan_filter(struct mlx5e_priv *priv)
+void mlx5e_disable_cvlan_filter(struct mlx5e_flow_steering *fs, bool promisc)
 {
-       if (priv->fs->vlan->cvlan_filter_disabled)
+       if (fs->vlan->cvlan_filter_disabled)
                return;
 
-       priv->fs->vlan->cvlan_filter_disabled = true;
-       if (priv->netdev->flags & IFF_PROMISC)
+       fs->vlan->cvlan_filter_disabled = true;
+       if (promisc)
                return;
-       mlx5e_add_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
+       mlx5e_add_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0);
 }
 
 static int mlx5e_vlan_rx_add_cvid(struct mlx5e_flow_steering *fs, u16 vid)
@@ -462,7 +489,7 @@ int mlx5e_fs_vlan_rx_add_vid(struct mlx5e_flow_steering *fs,
 {
 
        if (!fs->vlan) {
-               mlx5_core_err(fs->mdev, "Vlan doesn't exist\n");
+               fs_err(fs, "Vlan doesn't exist\n");
                return -EINVAL;
        }
 
@@ -479,7 +506,7 @@ int mlx5e_fs_vlan_rx_kill_vid(struct mlx5e_flow_steering *fs,
                              __be16 proto, u16 vid)
 {
        if (!fs->vlan) {
-               mlx5_core_err(fs->mdev, "Vlan doesn't exist\n");
+               fs_err(fs, "Vlan doesn't exist\n");
                return -EINVAL;
        }
 
@@ -512,28 +539,28 @@ static void mlx5e_fs_add_vlan_rules(struct mlx5e_flow_steering *fs)
                mlx5e_fs_add_any_vid_rules(fs);
 }
 
-static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv)
+static void mlx5e_del_vlan_rules(struct mlx5e_flow_steering *fs)
 {
        int i;
 
-       mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
+       mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_UNTAGGED, 0);
 
-       for_each_set_bit(i, priv->fs->vlan->active_cvlans, VLAN_N_VID) {
-               mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
+       for_each_set_bit(i, fs->vlan->active_cvlans, VLAN_N_VID) {
+               mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID, i);
        }
 
-       for_each_set_bit(i, priv->fs->vlan->active_svlans, VLAN_N_VID)
-               mlx5e_fs_del_vlan_rule(priv->fs, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
+       for_each_set_bit(i, fs->vlan->active_svlans, VLAN_N_VID)
+               mlx5e_fs_del_vlan_rule(fs, MLX5E_VLAN_RULE_TYPE_MATCH_STAG_VID, i);
 
-       WARN_ON_ONCE(priv->fs->state_destroy);
+       WARN_ON_ONCE(fs->state_destroy);
 
-       mlx5e_remove_vlan_trap(priv);
+       mlx5e_remove_vlan_trap(fs);
 
        /* must be called after DESTROY bit is set and
         * set_rx_mode is called and flushed
         */
-       if (priv->fs->vlan->cvlan_filter_disabled)
-               mlx5e_fs_del_any_vid_rules(priv->fs);
+       if (fs->vlan->cvlan_filter_disabled)
+               mlx5e_fs_del_any_vid_rules(fs);
 }
 
 #define mlx5e_for_each_hash_node(hn, tmp, hash, i) \
@@ -568,8 +595,9 @@ static void mlx5e_execute_l2_action(struct mlx5e_flow_steering *fs,
        }
 
        if (l2_err)
-               mlx5_core_warn(fs->mdev, "MPFS, failed to %s mac %pM, err(%d)\n",
-                              action == MLX5E_ACTION_ADD ? "add" : "del", mac_addr, l2_err);
+               fs_warn(fs, "MPFS, failed to %s mac %pM, err(%d)\n",
+                       action == MLX5E_ACTION_ADD ? "add" : "del",
+                       mac_addr, l2_err);
 }
 
 static void mlx5e_sync_netdev_addr(struct mlx5e_flow_steering *fs,
@@ -640,9 +668,8 @@ static void mlx5e_vport_context_update_addr_list(struct mlx5e_flow_steering *fs,
                size++;
 
        if (size > max_size) {
-               mlx5_core_warn(fs->mdev,
-                              "mdev %s list size (%d) > (%d) max vport list size, some addresses will be dropped\n",
-                             is_uc ? "UC" : "MC", size, max_size);
+               fs_warn(fs, "mdev %s list size (%d) > (%d) max vport list size, some addresses will be dropped\n",
+                       is_uc ? "UC" : "MC", size, max_size);
                size = max_size;
        }
 
@@ -658,9 +685,8 @@ static void mlx5e_vport_context_update_addr_list(struct mlx5e_flow_steering *fs,
        err = mlx5_modify_nic_vport_mac_list(fs->mdev, list_type, addr_array, size);
 out:
        if (err)
-               mlx5_core_err(fs->mdev,
-                             "Failed to modify vport %s list err(%d)\n",
-                             is_uc ? "UC" : "MC", err);
+               fs_err(fs, "Failed to modify vport %s list err(%d)\n",
+                      is_uc ? "UC" : "MC", err);
        kfree(addr_array);
 }
 
@@ -730,7 +756,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;
-               mlx5_core_err(fs->mdev, "%s: add promiscuous rule failed\n", __func__);
+               fs_err(fs, "%s: add promiscuous rule failed\n", __func__);
        }
        kvfree(spec);
        return err;
@@ -750,7 +776,7 @@ static int mlx5e_create_promisc_table(struct mlx5e_flow_steering *fs)
        ft->t = mlx5_create_auto_grouped_flow_table(fs->ns, &ft_attr);
        if (IS_ERR(ft->t)) {
                err = PTR_ERR(ft->t);
-               mlx5_core_err(fs->mdev, "fail to create promisc table err=%d\n", err);
+               fs_err(fs, "fail to create promisc table err=%d\n", err);
                return err;
        }
 
@@ -807,8 +833,8 @@ void mlx5e_fs_set_rx_mode_work(struct mlx5e_flow_steering *fs,
                if (err)
                        enable_promisc = false;
                if (!fs->vlan_strip_disable && !err)
-                       mlx5_core_warn_once(fs->mdev,
-                                           "S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n");
+                       fs_warn_once(fs,
+                                    "S-tagged traffic will be dropped while C-tag vlan stripping is enabled\n");
        }
        if (enable_allmulti)
                mlx5e_add_l2_flow_rule(fs, &ea->allmulti, MLX5E_ALLMULTI);
@@ -856,14 +882,15 @@ void mlx5e_destroy_flow_table(struct mlx5e_flow_table *ft)
        ft->t = NULL;
 }
 
-static void mlx5e_set_inner_ttc_params(struct mlx5e_priv *priv,
+static void mlx5e_set_inner_ttc_params(struct mlx5e_flow_steering *fs,
+                                      struct mlx5e_rx_res *rx_res,
                                       struct ttc_params *ttc_params)
 {
        struct mlx5_flow_table_attr *ft_attr = &ttc_params->ft_attr;
        int tt;
 
        memset(ttc_params, 0, sizeof(*ttc_params));
-       ttc_params->ns = mlx5_get_flow_namespace(priv->fs->mdev,
+       ttc_params->ns = mlx5_get_flow_namespace(fs->mdev,
                                                 MLX5_FLOW_NAMESPACE_KERNEL);
        ft_attr->level = MLX5E_INNER_TTC_FT_LEVEL;
        ft_attr->prio = MLX5E_NIC_PRIO;
@@ -872,13 +899,14 @@ static void mlx5e_set_inner_ttc_params(struct mlx5e_priv *priv,
                ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
                ttc_params->dests[tt].tir_num =
                        tt == MLX5_TT_ANY ?
-                               mlx5e_rx_res_get_tirn_direct(priv->rx_res, 0) :
-                               mlx5e_rx_res_get_tirn_rss_inner(priv->rx_res,
+                               mlx5e_rx_res_get_tirn_direct(rx_res, 0) :
+                               mlx5e_rx_res_get_tirn_rss_inner(rx_res,
                                                                tt);
        }
 }
 
-void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
+void mlx5e_set_ttc_params(struct mlx5e_flow_steering *fs,
+                         struct mlx5e_rx_res *rx_res,
                          struct ttc_params *ttc_params, bool tunnel)
 
 {
@@ -886,7 +914,7 @@ void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
        int tt;
 
        memset(ttc_params, 0, sizeof(*ttc_params));
-       ttc_params->ns = mlx5_get_flow_namespace(priv->fs->mdev,
+       ttc_params->ns = mlx5_get_flow_namespace(fs->mdev,
                                                 MLX5_FLOW_NAMESPACE_KERNEL);
        ft_attr->level = MLX5E_TTC_FT_LEVEL;
        ft_attr->prio = MLX5E_NIC_PRIO;
@@ -895,19 +923,19 @@ void mlx5e_set_ttc_params(struct mlx5e_priv *priv,
                ttc_params->dests[tt].type = MLX5_FLOW_DESTINATION_TYPE_TIR;
                ttc_params->dests[tt].tir_num =
                        tt == MLX5_TT_ANY ?
-                               mlx5e_rx_res_get_tirn_direct(priv->rx_res, 0) :
-                               mlx5e_rx_res_get_tirn_rss(priv->rx_res, tt);
+                               mlx5e_rx_res_get_tirn_direct(rx_res, 0) :
+                               mlx5e_rx_res_get_tirn_rss(rx_res, tt);
        }
 
        ttc_params->inner_ttc = tunnel;
-       if (!tunnel || !mlx5_tunnel_inner_ft_supported(priv->fs->mdev))
+       if (!tunnel || !mlx5_tunnel_inner_ft_supported(fs->mdev))
                return;
 
        for (tt = 0; tt < MLX5_NUM_TUNNEL_TT; tt++) {
                ttc_params->tunnel_dests[tt].type =
                        MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
                ttc_params->tunnel_dests[tt].ft =
-                       mlx5_get_ttc_flow_table(priv->fs->inner_ttc);
+                       mlx5_get_ttc_flow_table(fs->inner_ttc);
        }
 }
 
@@ -959,8 +987,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)) {
-               mlx5_core_err(fs->mdev, "%s: add l2 rule(mac:%pM) failed\n",
-                             __func__, mv_dmac);
+               fs_err(fs, "%s: add l2 rule(mac:%pM) failed\n", __func__, mv_dmac);
                err = PTR_ERR(ai->rule);
                ai->rule = NULL;
        }
@@ -1044,14 +1071,14 @@ err_destroy_groups:
        return err;
 }
 
-static void mlx5e_destroy_l2_table(struct mlx5e_priv *priv)
+static void mlx5e_destroy_l2_table(struct mlx5e_flow_steering *fs)
 {
-       mlx5e_destroy_flow_table(&priv->fs->l2.ft);
+       mlx5e_destroy_flow_table(&fs->l2.ft);
 }
 
-static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
+static int mlx5e_create_l2_table(struct mlx5e_flow_steering *fs)
 {
-       struct mlx5e_l2_table *l2_table = &priv->fs->l2;
+       struct mlx5e_l2_table *l2_table = &fs->l2;
        struct mlx5e_flow_table *ft = &l2_table->ft;
        struct mlx5_flow_table_attr ft_attr = {};
        int err;
@@ -1062,7 +1089,7 @@ static int mlx5e_create_l2_table(struct mlx5e_priv *priv)
        ft_attr.level = MLX5E_L2_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
 
-       ft->t = mlx5_create_flow_table(priv->fs->ns, &ft_attr);
+       ft->t = mlx5_create_flow_table(fs->ns, &ft_attr);
        if (IS_ERR(ft->t)) {
                err = PTR_ERR(ft->t);
                ft->t = NULL;
@@ -1221,126 +1248,128 @@ err_destroy_vlan_table:
        return err;
 }
 
-static void mlx5e_destroy_vlan_table(struct mlx5e_priv *priv)
+static void mlx5e_destroy_vlan_table(struct mlx5e_flow_steering *fs)
 {
-       mlx5e_del_vlan_rules(priv);
-       mlx5e_destroy_flow_table(&priv->fs->vlan->ft);
+       mlx5e_del_vlan_rules(fs);
+       mlx5e_destroy_flow_table(&fs->vlan->ft);
 }
 
-static void mlx5e_destroy_inner_ttc_table(struct mlx5e_priv *priv)
+static void mlx5e_destroy_inner_ttc_table(struct mlx5e_flow_steering *fs)
 {
-       if (!mlx5_tunnel_inner_ft_supported(priv->fs->mdev))
+       if (!mlx5_tunnel_inner_ft_supported(fs->mdev))
                return;
-       mlx5_destroy_ttc_table(priv->fs->inner_ttc);
+       mlx5_destroy_ttc_table(fs->inner_ttc);
 }
 
-void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
+void mlx5e_destroy_ttc_table(struct mlx5e_flow_steering *fs)
 {
-       mlx5_destroy_ttc_table(priv->fs->ttc);
+       mlx5_destroy_ttc_table(fs->ttc);
 }
 
-static int mlx5e_create_inner_ttc_table(struct mlx5e_priv *priv)
+static int mlx5e_create_inner_ttc_table(struct mlx5e_flow_steering *fs,
+                                       struct mlx5e_rx_res *rx_res)
 {
        struct ttc_params ttc_params = {};
 
-       if (!mlx5_tunnel_inner_ft_supported(priv->fs->mdev))
+       if (!mlx5_tunnel_inner_ft_supported(fs->mdev))
                return 0;
 
-       mlx5e_set_inner_ttc_params(priv, &ttc_params);
-       priv->fs->inner_ttc = mlx5_create_inner_ttc_table(priv->fs->mdev,
-                                                         &ttc_params);
-       if (IS_ERR(priv->fs->inner_ttc))
-               return PTR_ERR(priv->fs->inner_ttc);
+       mlx5e_set_inner_ttc_params(fs, rx_res, &ttc_params);
+       fs->inner_ttc = mlx5_create_inner_ttc_table(fs->mdev,
+                                                   &ttc_params);
+       if (IS_ERR(fs->inner_ttc))
+               return PTR_ERR(fs->inner_ttc);
        return 0;
 }
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
+int mlx5e_create_ttc_table(struct mlx5e_flow_steering *fs,
+                          struct mlx5e_rx_res *rx_res)
 {
        struct ttc_params ttc_params = {};
 
-       mlx5e_set_ttc_params(priv, &ttc_params, true);
-       priv->fs->ttc = mlx5_create_ttc_table(priv->fs->mdev, &ttc_params);
-       if (IS_ERR(priv->fs->ttc))
-               return PTR_ERR(priv->fs->ttc);
+       mlx5e_set_ttc_params(fs, rx_res, &ttc_params, true);
+       fs->ttc = mlx5_create_ttc_table(fs->mdev, &ttc_params);
+       if (IS_ERR(fs->ttc))
+               return PTR_ERR(fs->ttc);
        return 0;
 }
 
-int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
+int mlx5e_create_flow_steering(struct mlx5e_flow_steering *fs,
+                              struct mlx5e_rx_res *rx_res,
+                              const struct mlx5e_profile *profile,
+                              struct net_device *netdev)
 {
+       struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(fs->mdev,
+                                                                MLX5_FLOW_NAMESPACE_KERNEL);
        int err;
 
-       priv->fs->ns = mlx5_get_flow_namespace(priv->fs->mdev,
-                                              MLX5_FLOW_NAMESPACE_KERNEL);
-
-       if (!priv->fs->ns)
+       if (!ns)
                return -EOPNOTSUPP;
 
-       err = mlx5e_arfs_create_tables(priv);
+       mlx5e_fs_set_ns(fs, ns, false);
+       err = mlx5e_arfs_create_tables(fs, rx_res,
+                                      !!(netdev->hw_features & NETIF_F_NTUPLE));
        if (err) {
-               mlx5_core_err(priv->fs->mdev, "Failed to create arfs tables, err=%d\n",
-                             err);
-               priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
+               fs_err(fs, "Failed to create arfs tables, err=%d\n", err);
+               netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_inner_ttc_table(priv);
+       err = mlx5e_create_inner_ttc_table(fs, rx_res);
        if (err) {
-               mlx5_core_err(priv->fs->mdev,
-                             "Failed to create inner ttc table, err=%d\n", err);
+               fs_err(fs, "Failed to create inner ttc table, err=%d\n", err);
                goto err_destroy_arfs_tables;
        }
 
-       err = mlx5e_create_ttc_table(priv);
+       err = mlx5e_create_ttc_table(fs, rx_res);
        if (err) {
-               mlx5_core_err(priv->fs->mdev, "Failed to create ttc table, err=%d\n",
-                             err);
+               fs_err(fs, "Failed to create ttc table, err=%d\n", err);
                goto err_destroy_inner_ttc_table;
        }
 
-       err = mlx5e_create_l2_table(priv);
+       err = mlx5e_create_l2_table(fs);
        if (err) {
-               mlx5_core_err(priv->fs->mdev, "Failed to create l2 table, err=%d\n",
-                             err);
+               fs_err(fs, "Failed to create l2 table, err=%d\n", err);
                goto err_destroy_ttc_table;
        }
 
-       err = mlx5e_fs_create_vlan_table(priv->fs);
+       err = mlx5e_fs_create_vlan_table(fs);
        if (err) {
-               mlx5_core_err(priv->fs->mdev, "Failed to create vlan table, err=%d\n",
-                             err);
+               fs_err(fs, "Failed to create vlan table, err=%d\n", err);
                goto err_destroy_l2_table;
        }
 
-       err = mlx5e_ptp_alloc_rx_fs(priv);
+       err = mlx5e_ptp_alloc_rx_fs(fs, profile);
        if (err)
                goto err_destory_vlan_table;
 
-       mlx5e_ethtool_init_steering(priv);
+       mlx5e_ethtool_init_steering(fs);
 
        return 0;
 
 err_destory_vlan_table:
-       mlx5e_destroy_vlan_table(priv);
+       mlx5e_destroy_vlan_table(fs);
 err_destroy_l2_table:
-       mlx5e_destroy_l2_table(priv);
+       mlx5e_destroy_l2_table(fs);
 err_destroy_ttc_table:
-       mlx5e_destroy_ttc_table(priv);
+       mlx5e_destroy_ttc_table(fs);
 err_destroy_inner_ttc_table:
-       mlx5e_destroy_inner_ttc_table(priv);
+       mlx5e_destroy_inner_ttc_table(fs);
 err_destroy_arfs_tables:
-       mlx5e_arfs_destroy_tables(priv);
+       mlx5e_arfs_destroy_tables(fs, !!(netdev->hw_features & NETIF_F_NTUPLE));
 
        return err;
 }
 
-void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv)
+void mlx5e_destroy_flow_steering(struct mlx5e_flow_steering *fs, bool ntuple,
+                                const struct mlx5e_profile *profile)
 {
-       mlx5e_ptp_free_rx_fs(priv);
-       mlx5e_destroy_vlan_table(priv);
-       mlx5e_destroy_l2_table(priv);
-       mlx5e_destroy_ttc_table(priv);
-       mlx5e_destroy_inner_ttc_table(priv);
-       mlx5e_arfs_destroy_tables(priv);
-       mlx5e_ethtool_cleanup_steering(priv);
+       mlx5e_ptp_free_rx_fs(fs, profile);
+       mlx5e_destroy_vlan_table(fs);
+       mlx5e_destroy_l2_table(fs);
+       mlx5e_destroy_ttc_table(fs);
+       mlx5e_destroy_inner_ttc_table(fs);
+       mlx5e_arfs_destroy_tables(fs, ntuple);
+       mlx5e_ethtool_cleanup_steering(fs);
 }
 
 static int mlx5e_fs_vlan_alloc(struct mlx5e_flow_steering *fs)
@@ -1356,6 +1385,11 @@ static void mlx5e_fs_vlan_free(struct mlx5e_flow_steering *fs)
        kvfree(fs->vlan);
 }
 
+struct mlx5e_vlan_table *mlx5e_fs_get_vlan(struct mlx5e_flow_steering *fs)
+{
+       return fs->vlan;
+}
+
 static int mlx5e_fs_tc_alloc(struct mlx5e_flow_steering *fs)
 {
        fs->tc = mlx5e_tc_table_alloc();
@@ -1369,6 +1403,32 @@ static void mlx5e_fs_tc_free(struct mlx5e_flow_steering *fs)
        mlx5e_tc_table_free(fs->tc);
 }
 
+struct mlx5e_tc_table *mlx5e_fs_get_tc(struct mlx5e_flow_steering *fs)
+{
+       return fs->tc;
+}
+
+#ifdef CONFIG_MLX5_EN_RXNFC
+static int mlx5e_fs_ethtool_alloc(struct mlx5e_flow_steering *fs)
+{
+       return mlx5e_ethtool_alloc(&fs->ethtool);
+}
+
+static void mlx5e_fs_ethtool_free(struct mlx5e_flow_steering *fs)
+{
+       mlx5e_ethtool_free(fs->ethtool);
+}
+
+struct mlx5e_ethtool_steering *mlx5e_fs_get_ethtool(struct mlx5e_flow_steering *fs)
+{
+       return fs->ethtool;
+}
+#else
+static int mlx5e_fs_ethtool_alloc(struct mlx5e_flow_steering *fs)
+{ return 0; }
+static void mlx5e_fs_ethtool_free(struct mlx5e_flow_steering *fs) { }
+#endif
+
 struct mlx5e_flow_steering *mlx5e_fs_init(const struct mlx5e_profile *profile,
                                          struct mlx5_core_dev *mdev,
                                          bool state_destroy)
@@ -1394,8 +1454,13 @@ struct mlx5e_flow_steering *mlx5e_fs_init(const struct mlx5e_profile *profile,
                        goto err_free_vlan;
        }
 
-       return fs;
+       err = mlx5e_fs_ethtool_alloc(fs);
+       if (err)
+               goto err_free_tc;
 
+       return fs;
+err_free_tc:
+       mlx5e_fs_tc_free(fs);
 err_free_vlan:
        mlx5e_fs_vlan_free(fs);
 err_free_fs:
@@ -1406,7 +1471,109 @@ err:
 
 void mlx5e_fs_cleanup(struct mlx5e_flow_steering *fs)
 {
+       mlx5e_fs_ethtool_free(fs);
        mlx5e_fs_tc_free(fs);
        mlx5e_fs_vlan_free(fs);
        kvfree(fs);
 }
+
+struct mlx5e_l2_table *mlx5e_fs_get_l2(struct mlx5e_flow_steering *fs)
+{
+       return &fs->l2;
+}
+
+struct mlx5_flow_namespace *mlx5e_fs_get_ns(struct mlx5e_flow_steering *fs, bool egress)
+{
+       return  egress ? fs->egress_ns : fs->ns;
+}
+
+void mlx5e_fs_set_ns(struct mlx5e_flow_steering *fs, struct mlx5_flow_namespace *ns, bool egress)
+{
+       if (!egress)
+               fs->ns = ns;
+       else
+               fs->egress_ns = ns;
+}
+
+struct mlx5_ttc_table *mlx5e_fs_get_ttc(struct mlx5e_flow_steering *fs, bool inner)
+{
+       return inner ? fs->inner_ttc : fs->ttc;
+}
+
+void mlx5e_fs_set_ttc(struct mlx5e_flow_steering *fs, struct mlx5_ttc_table *ttc, bool inner)
+{
+       if (!inner)
+               fs->ttc = ttc;
+       else
+               fs->inner_ttc = ttc;
+}
+
+#ifdef CONFIG_MLX5_EN_ARFS
+struct mlx5e_arfs_tables *mlx5e_fs_get_arfs(struct mlx5e_flow_steering *fs)
+{
+       return fs->arfs;
+}
+
+void mlx5e_fs_set_arfs(struct mlx5e_flow_steering *fs, struct mlx5e_arfs_tables *arfs)
+{
+       fs->arfs = arfs;
+}
+#endif
+
+struct mlx5e_ptp_fs *mlx5e_fs_get_ptp(struct mlx5e_flow_steering *fs)
+{
+       return fs->ptp_fs;
+}
+
+void mlx5e_fs_set_ptp(struct mlx5e_flow_steering *fs, struct mlx5e_ptp_fs *ptp_fs)
+{
+       fs->ptp_fs = ptp_fs;
+}
+
+struct mlx5e_fs_any *mlx5e_fs_get_any(struct mlx5e_flow_steering *fs)
+{
+       return fs->any;
+}
+
+void mlx5e_fs_set_any(struct mlx5e_flow_steering *fs, struct mlx5e_fs_any *any)
+{
+       fs->any = any;
+}
+
+#ifdef CONFIG_MLX5_EN_TLS
+struct mlx5e_accel_fs_tcp *mlx5e_fs_get_accel_tcp(struct mlx5e_flow_steering *fs)
+{
+       return fs->accel_tcp;
+}
+
+void mlx5e_fs_set_accel_tcp(struct mlx5e_flow_steering *fs, struct mlx5e_accel_fs_tcp *accel_tcp)
+{
+       fs->accel_tcp = accel_tcp;
+}
+#endif
+
+void mlx5e_fs_set_state_destroy(struct mlx5e_flow_steering *fs, bool state_destroy)
+{
+       fs->state_destroy = state_destroy;
+}
+
+void mlx5e_fs_set_vlan_strip_disable(struct mlx5e_flow_steering *fs,
+                                    bool vlan_strip_disable)
+{
+       fs->vlan_strip_disable = vlan_strip_disable;
+}
+
+struct mlx5e_fs_udp *mlx5e_fs_get_udp(struct mlx5e_flow_steering *fs)
+{
+       return fs->udp;
+}
+
+void mlx5e_fs_set_udp(struct mlx5e_flow_steering *fs, struct mlx5e_fs_udp *udp)
+{
+       fs->udp = udp;
+}
+
+struct mlx5_core_dev *mlx5e_fs_get_mdev(struct mlx5e_flow_steering *fs)
+{
+       return fs->mdev;
+}
index 3e4bc78..2a67798 100644 (file)
 #include "en.h"
 #include "en/params.h"
 #include "en/xsk/pool.h"
+#include "en/fs_ethtool.h"
+
+struct mlx5e_ethtool_table {
+       struct mlx5_flow_table *ft;
+       int                    num_rules;
+};
+
+#define ETHTOOL_NUM_L3_L4_FTS 7
+#define ETHTOOL_NUM_L2_FTS 4
+
+struct mlx5e_ethtool_steering {
+       struct mlx5e_ethtool_table      l3_l4_ft[ETHTOOL_NUM_L3_L4_FTS];
+       struct mlx5e_ethtool_table      l2_ft[ETHTOOL_NUM_L2_FTS];
+       struct list_head                rules;
+       int                             tot_num_rules;
+};
 
 static int flow_type_to_traffic_type(u32 flow_type);
 
@@ -66,6 +82,7 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
                                                  struct ethtool_rx_flow_spec *fs,
                                                  int num_tuples)
 {
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(priv->fs);
        struct mlx5_flow_table_attr ft_attr = {};
        struct mlx5e_ethtool_table *eth_ft;
        struct mlx5_flow_namespace *ns;
@@ -81,18 +98,18 @@ static struct mlx5e_ethtool_table *get_flow_table(struct mlx5e_priv *priv,
        case UDP_V6_FLOW:
                max_tuples = ETHTOOL_NUM_L3_L4_FTS;
                prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples);
-               eth_ft = &priv->fs->ethtool.l3_l4_ft[prio];
+               eth_ft = &ethtool->l3_l4_ft[prio];
                break;
        case IP_USER_FLOW:
        case IPV6_USER_FLOW:
                max_tuples = ETHTOOL_NUM_L3_L4_FTS;
                prio = MLX5E_ETHTOOL_L3_L4_PRIO + (max_tuples - num_tuples);
-               eth_ft = &priv->fs->ethtool.l3_l4_ft[prio];
+               eth_ft = &ethtool->l3_l4_ft[prio];
                break;
        case ETHER_FLOW:
                max_tuples = ETHTOOL_NUM_L2_FTS;
                prio = max_tuples - num_tuples;
-               eth_ft = &priv->fs->ethtool.l2_ft[prio];
+               eth_ft = &ethtool->l2_ft[prio];
                prio += MLX5E_ETHTOOL_L2_PRIO;
                break;
        default:
@@ -382,15 +399,16 @@ static int set_flow_attrs(u32 *match_c, u32 *match_v,
 static void add_rule_to_list(struct mlx5e_priv *priv,
                             struct mlx5e_ethtool_rule *rule)
 {
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(priv->fs);
+       struct list_head *head = &ethtool->rules;
        struct mlx5e_ethtool_rule *iter;
-       struct list_head *head = &priv->fs->ethtool.rules;
 
-       list_for_each_entry(iter, &priv->fs->ethtool.rules, list) {
+       list_for_each_entry(iter, &ethtool->rules, list) {
                if (iter->flow_spec.location > rule->flow_spec.location)
                        break;
                head = &iter->list;
        }
-       priv->fs->ethtool.tot_num_rules++;
+       ethtool->tot_num_rules++;
        list_add(&rule->list, head);
 }
 
@@ -499,15 +517,16 @@ free:
        return err ? ERR_PTR(err) : rule;
 }
 
-static void del_ethtool_rule(struct mlx5e_priv *priv,
+static void del_ethtool_rule(struct mlx5e_flow_steering *fs,
                             struct mlx5e_ethtool_rule *eth_rule)
 {
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(fs);
        if (eth_rule->rule)
                mlx5_del_flow_rules(eth_rule->rule);
        if (eth_rule->rss)
                mlx5e_rss_refcnt_dec(eth_rule->rss);
        list_del(&eth_rule->list);
-       priv->fs->ethtool.tot_num_rules--;
+       ethtool->tot_num_rules--;
        put_flow_table(eth_rule->eth_ft);
        kfree(eth_rule);
 }
@@ -515,9 +534,10 @@ static void del_ethtool_rule(struct mlx5e_priv *priv,
 static struct mlx5e_ethtool_rule *find_ethtool_rule(struct mlx5e_priv *priv,
                                                    int location)
 {
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(priv->fs);
        struct mlx5e_ethtool_rule *iter;
 
-       list_for_each_entry(iter, &priv->fs->ethtool.rules, list) {
+       list_for_each_entry(iter, &ethtool->rules, list) {
                if (iter->flow_spec.location == location)
                        return iter;
        }
@@ -531,7 +551,7 @@ static struct mlx5e_ethtool_rule *get_ethtool_rule(struct mlx5e_priv *priv,
 
        eth_rule = find_ethtool_rule(priv, location);
        if (eth_rule)
-               del_ethtool_rule(priv, eth_rule);
+               del_ethtool_rule(priv->fs, eth_rule);
 
        eth_rule = kzalloc(sizeof(*eth_rule), GFP_KERNEL);
        if (!eth_rule)
@@ -754,7 +774,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,
        return 0;
 
 del_ethtool_rule:
-       del_ethtool_rule(priv, eth_rule);
+       del_ethtool_rule(priv->fs, eth_rule);
 
        return err;
 }
@@ -774,7 +794,7 @@ mlx5e_ethtool_flow_remove(struct mlx5e_priv *priv, int location)
                goto out;
        }
 
-       del_ethtool_rule(priv, eth_rule);
+       del_ethtool_rule(priv->fs, eth_rule);
 out:
        return err;
 }
@@ -783,12 +803,13 @@ static int
 mlx5e_ethtool_get_flow(struct mlx5e_priv *priv,
                       struct ethtool_rxnfc *info, int location)
 {
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(priv->fs);
        struct mlx5e_ethtool_rule *eth_rule;
 
        if (location < 0 || location >= MAX_NUM_OF_ETHTOOL_RULES)
                return -EINVAL;
 
-       list_for_each_entry(eth_rule, &priv->fs->ethtool.rules, list) {
+       list_for_each_entry(eth_rule, &ethtool->rules, list) {
                int index;
 
                if (eth_rule->flow_spec.location != location)
@@ -826,18 +847,34 @@ mlx5e_ethtool_get_all_flows(struct mlx5e_priv *priv,
        return err;
 }
 
-void mlx5e_ethtool_cleanup_steering(struct mlx5e_priv *priv)
+int mlx5e_ethtool_alloc(struct mlx5e_ethtool_steering **ethtool)
+{
+       *ethtool =  kvzalloc(sizeof(**ethtool), GFP_KERNEL);
+       if (!*ethtool)
+               return -ENOMEM;
+       return 0;
+}
+
+void mlx5e_ethtool_free(struct mlx5e_ethtool_steering *ethtool)
 {
+       kvfree(ethtool);
+}
+
+void mlx5e_ethtool_cleanup_steering(struct mlx5e_flow_steering *fs)
+{
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(fs);
        struct mlx5e_ethtool_rule *iter;
        struct mlx5e_ethtool_rule *temp;
 
-       list_for_each_entry_safe(iter, temp, &priv->fs->ethtool.rules, list)
-               del_ethtool_rule(priv, iter);
+       list_for_each_entry_safe(iter, temp, &ethtool->rules, list)
+               del_ethtool_rule(fs, iter);
 }
 
-void mlx5e_ethtool_init_steering(struct mlx5e_priv *priv)
+void mlx5e_ethtool_init_steering(struct mlx5e_flow_steering *fs)
 {
-       INIT_LIST_HEAD(&priv->fs->ethtool.rules);
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(fs);
+
+       INIT_LIST_HEAD(&ethtool->rules);
 }
 
 static int flow_type_to_traffic_type(u32 flow_type)
@@ -959,11 +996,12 @@ int mlx5e_ethtool_set_rxnfc(struct mlx5e_priv *priv, struct ethtool_rxnfc *cmd)
 int mlx5e_ethtool_get_rxnfc(struct mlx5e_priv *priv,
                            struct ethtool_rxnfc *info, u32 *rule_locs)
 {
+       struct mlx5e_ethtool_steering *ethtool = mlx5e_fs_get_ethtool(priv->fs);
        int err = 0;
 
        switch (info->cmd) {
        case ETHTOOL_GRXCLSRLCNT:
-               info->rule_cnt = priv->fs->ethtool.tot_num_rules;
+               info->rule_cnt = ethtool->tot_num_rules;
                break;
        case ETHTOOL_GRXCLSRULE:
                err = mlx5e_ethtool_get_flow(priv, info, info->fs.location);
index 02eb2f0..7c1a137 100644 (file)
@@ -2738,7 +2738,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
        netif_tx_start_all_queues(priv->netdev);
 
        if (mlx5e_is_vport_rep(priv))
-               mlx5e_add_sqs_fwd_rules(priv);
+               mlx5e_rep_activate_channels(priv);
 
        mlx5e_wait_channels_min_rx_wqes(&priv->channels);
 
@@ -2752,7 +2752,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
                mlx5e_rx_res_channels_deactivate(priv->rx_res);
 
        if (mlx5e_is_vport_rep(priv))
-               mlx5e_remove_sqs_fwd_rules(priv);
+               mlx5e_rep_deactivate_channels(priv);
 
        /* The results of ndo_select_queue are unreliable, while netdev config
         * is being changed (real_num_tx_queues, num_tc). Stop all queues to
@@ -3669,9 +3669,11 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)
        struct mlx5e_priv *priv = netdev_priv(netdev);
 
        if (enable)
-               mlx5e_enable_cvlan_filter(priv);
+               mlx5e_enable_cvlan_filter(priv->fs,
+                                         !!(priv->netdev->flags & IFF_PROMISC));
        else
-               mlx5e_disable_cvlan_filter(priv);
+               mlx5e_disable_cvlan_filter(priv->fs,
+                                          !!(priv->netdev->flags & IFF_PROMISC));
 
        return 0;
 }
@@ -3780,7 +3782,7 @@ static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
 
        mutex_lock(&priv->state_lock);
 
-       priv->fs->vlan_strip_disable = !enable;
+       mlx5e_fs_set_vlan_strip_disable(priv->fs, !enable);
        priv->channels.params.vlan_strip_disable = !enable;
 
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
@@ -3788,7 +3790,7 @@ static int set_feature_rx_vlan(struct net_device *netdev, bool enable)
 
        err = mlx5e_modify_channels_vsd(&priv->channels, !enable);
        if (err) {
-               priv->fs->vlan_strip_disable = enable;
+               mlx5e_fs_set_vlan_strip_disable(priv->fs, enable);
                priv->channels.params.vlan_strip_disable = enable;
        }
 unlock:
@@ -3826,9 +3828,9 @@ static int set_feature_arfs(struct net_device *netdev, bool enable)
        int err;
 
        if (enable)
-               err = mlx5e_arfs_enable(priv);
+               err = mlx5e_arfs_enable(priv->fs);
        else
-               err = mlx5e_arfs_disable(priv);
+               err = mlx5e_arfs_disable(priv->fs);
 
        return err;
 }
@@ -3912,12 +3914,14 @@ static netdev_features_t mlx5e_fix_features(struct net_device *netdev,
                                            netdev_features_t features)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
+       struct mlx5e_vlan_table *vlan;
        struct mlx5e_params *params;
 
+       vlan = mlx5e_fs_get_vlan(priv->fs);
        mutex_lock(&priv->state_lock);
        params = &priv->channels.params;
-       if (!priv->fs->vlan ||
-           !bitmap_empty(mlx5e_vlan_get_active_svlans(priv->fs->vlan), VLAN_N_VID)) {
+       if (!vlan ||
+           !bitmap_empty(mlx5e_vlan_get_active_svlans(vlan), VLAN_N_VID)) {
                /* HW strips the outer C-tag header, this is a problem
                 * for S-tag traffic.
                 */
@@ -5097,7 +5101,8 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
        if (err)
                goto err_close_drop_rq;
 
-       err = mlx5e_create_flow_steering(priv);
+       err = mlx5e_create_flow_steering(priv->fs, priv->rx_res, priv->profile,
+                                        priv->netdev);
        if (err) {
                mlx5_core_warn(mdev, "create flow steering failed, %d\n", err);
                goto err_destroy_rx_res;
@@ -5120,7 +5125,8 @@ static int mlx5e_init_nic_rx(struct mlx5e_priv *priv)
 err_tc_nic_cleanup:
        mlx5e_tc_nic_cleanup(priv);
 err_destroy_flow_steering:
-       mlx5e_destroy_flow_steering(priv);
+       mlx5e_destroy_flow_steering(priv->fs, !!(priv->netdev->hw_features & NETIF_F_NTUPLE),
+                                   priv->profile);
 err_destroy_rx_res:
        mlx5e_rx_res_destroy(priv->rx_res);
 err_close_drop_rq:
@@ -5136,7 +5142,8 @@ static void mlx5e_cleanup_nic_rx(struct mlx5e_priv *priv)
 {
        mlx5e_accel_cleanup_rx(priv);
        mlx5e_tc_nic_cleanup(priv);
-       mlx5e_destroy_flow_steering(priv);
+       mlx5e_destroy_flow_steering(priv->fs, !!(priv->netdev->hw_features & NETIF_F_NTUPLE),
+                                   priv->profile);
        mlx5e_rx_res_destroy(priv->rx_res);
        mlx5e_close_drop_rq(&priv->drop_rq);
        mlx5e_destroy_q_counters(priv);
@@ -5512,7 +5519,8 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv)
 
        clear_bit(MLX5E_STATE_DESTROYING, &priv->state);
        if (priv->fs)
-               priv->fs->state_destroy = !test_bit(MLX5E_STATE_DESTROYING, &priv->state);
+               mlx5e_fs_set_state_destroy(priv->fs,
+                                          !test_bit(MLX5E_STATE_DESTROYING, &priv->state));
 
        /* max number of channels may have changed */
        max_nch = mlx5e_calc_max_nch(priv->mdev, priv->netdev, profile);
@@ -5573,7 +5581,8 @@ out:
        mlx5e_reset_channels(priv->netdev);
        set_bit(MLX5E_STATE_DESTROYING, &priv->state);
        if (priv->fs)
-               priv->fs->state_destroy = !test_bit(MLX5E_STATE_DESTROYING, &priv->state);
+               mlx5e_fs_set_state_destroy(priv->fs,
+                                          !test_bit(MLX5E_STATE_DESTROYING, &priv->state));
        cancel_work_sync(&priv->update_stats_work);
        return err;
 }
@@ -5584,7 +5593,8 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv)
 
        set_bit(MLX5E_STATE_DESTROYING, &priv->state);
        if (priv->fs)
-               priv->fs->state_destroy = !test_bit(MLX5E_STATE_DESTROYING, &priv->state);
+               mlx5e_fs_set_state_destroy(priv->fs,
+                                          !test_bit(MLX5E_STATE_DESTROYING, &priv->state));
 
        if (profile->disable)
                profile->disable(priv);
index 759f7d3..83b2feb 100644 (file)
@@ -56,6 +56,7 @@
 #include "en_accel/ipsec.h"
 #include "en/tc/int_port.h"
 #include "en/ptp.h"
+#include "en/fs_ethtool.h"
 
 #define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \
        max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
@@ -69,7 +70,7 @@ static void mlx5e_rep_get_drvinfo(struct net_device *dev,
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5_core_dev *mdev = priv->mdev;
 
-       strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
+       strscpy(drvinfo->driver, mlx5e_rep_driver_name,
                sizeof(drvinfo->driver));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                 "%d.%d.%04d (%.16s)",
@@ -397,7 +398,8 @@ out_err:
        return err;
 }
 
-int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
+static int
+mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
 {
        int sqs_per_channel = mlx5e_get_dcb_num_tc(&priv->channels.params);
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -451,7 +453,8 @@ out:
        return err;
 }
 
-void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
+static void
+mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
@@ -460,6 +463,49 @@ void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
        mlx5e_sqs2vport_stop(esw, rep);
 }
 
+static int
+mlx5e_rep_add_meta_tunnel_rule(struct mlx5e_priv *priv)
+{
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       struct mlx5_eswitch_rep *rep = rpriv->rep;
+       struct mlx5_flow_handle *flow_rule;
+       struct mlx5_flow_group *g;
+
+       g = esw->fdb_table.offloads.send_to_vport_meta_grp;
+       if (!g)
+               return 0;
+
+       flow_rule = mlx5_eswitch_add_send_to_vport_meta_rule(esw, rep->vport);
+       if (IS_ERR(flow_rule))
+               return PTR_ERR(flow_rule);
+
+       rpriv->send_to_vport_meta_rule = flow_rule;
+
+       return 0;
+}
+
+static void
+mlx5e_rep_del_meta_tunnel_rule(struct mlx5e_priv *priv)
+{
+       struct mlx5e_rep_priv *rpriv = priv->ppriv;
+
+       if (rpriv->send_to_vport_meta_rule)
+               mlx5_eswitch_del_send_to_vport_meta_rule(rpriv->send_to_vport_meta_rule);
+}
+
+void mlx5e_rep_activate_channels(struct mlx5e_priv *priv)
+{
+       mlx5e_add_sqs_fwd_rules(priv);
+       mlx5e_rep_add_meta_tunnel_rule(priv);
+}
+
+void mlx5e_rep_deactivate_channels(struct mlx5e_priv *priv)
+{
+       mlx5e_rep_del_meta_tunnel_rule(priv);
+       mlx5e_remove_sqs_fwd_rules(priv);
+}
+
 static int mlx5e_rep_open(struct net_device *dev)
 {
        struct mlx5e_priv *priv = netdev_priv(dev);
@@ -747,19 +793,20 @@ static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv)
        struct ttc_params ttc_params = {};
        int err;
 
-       priv->fs->ns = mlx5_get_flow_namespace(priv->mdev,
-                                              MLX5_FLOW_NAMESPACE_KERNEL);
+       mlx5e_fs_set_ns(priv->fs,
+                       mlx5_get_flow_namespace(priv->mdev,
+                                               MLX5_FLOW_NAMESPACE_KERNEL), false);
 
        /* The inner_ttc in the ttc params is intentionally not set */
-       mlx5e_set_ttc_params(priv, &ttc_params, false);
+       mlx5e_set_ttc_params(priv->fs, priv->rx_res, &ttc_params, false);
 
        if (rep->vport != MLX5_VPORT_UPLINK)
                /* To give uplik rep TTC a lower level for chaining from root ft */
                ttc_params.ft_attr.level = MLX5E_TTC_FT_LEVEL + 1;
 
-       priv->fs->ttc = mlx5_create_ttc_table(priv->mdev, &ttc_params);
-       if (IS_ERR(priv->fs->ttc)) {
-               err = PTR_ERR(priv->fs->ttc);
+       mlx5e_fs_set_ttc(priv->fs, mlx5_create_ttc_table(priv->mdev, &ttc_params), false);
+       if (IS_ERR(mlx5e_fs_get_ttc(priv->fs, false))) {
+               err = PTR_ERR(mlx5e_fs_get_ttc(priv->fs, false));
                netdev_err(priv->netdev, "Failed to create rep ttc table, err=%d\n",
                           err);
                return err;
@@ -779,7 +826,7 @@ static int mlx5e_create_rep_root_ft(struct mlx5e_priv *priv)
                /* non uplik reps will skip any bypass tables and go directly to
                 * their own ttc
                 */
-               rpriv->root_ft = mlx5_get_ttc_flow_table(priv->fs->ttc);
+               rpriv->root_ft = mlx5_get_ttc_flow_table(mlx5e_fs_get_ttc(priv->fs, false));
                return 0;
        }
 
@@ -887,14 +934,14 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
        if (err)
                goto err_destroy_root_ft;
 
-       mlx5e_ethtool_init_steering(priv);
+       mlx5e_ethtool_init_steering(priv->fs);
 
        return 0;
 
 err_destroy_root_ft:
        mlx5e_destroy_rep_root_ft(priv);
 err_destroy_ttc_table:
-       mlx5_destroy_ttc_table(priv->fs->ttc);
+       mlx5_destroy_ttc_table(mlx5e_fs_get_ttc(priv->fs, false));
 err_destroy_rx_res:
        mlx5e_rx_res_destroy(priv->rx_res);
 err_close_drop_rq:
@@ -908,10 +955,10 @@ err_free_fs:
 
 static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
 {
-       mlx5e_ethtool_cleanup_steering(priv);
+       mlx5e_ethtool_cleanup_steering(priv->fs);
        rep_vport_rx_rule_destroy(priv);
        mlx5e_destroy_rep_root_ft(priv);
-       mlx5_destroy_ttc_table(priv->fs->ttc);
+       mlx5_destroy_ttc_table(mlx5e_fs_get_ttc(priv->fs, false));
        mlx5e_rx_res_destroy(priv->rx_res);
        mlx5e_close_drop_rq(&priv->drop_rq);
        mlx5e_rx_res_free(priv->rx_res);
index dec183c..b4e6917 100644 (file)
@@ -111,6 +111,7 @@ struct mlx5e_rep_priv {
        struct list_head       vport_sqs_list;
        struct mlx5_rep_uplink_priv uplink_priv; /* valid for uplink rep */
        struct rtnl_link_stats64 prev_vf_vport_stats;
+       struct mlx5_flow_handle *send_to_vport_meta_rule;
        struct rhashtable tc_ht;
 };
 
@@ -241,8 +242,8 @@ int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev,
                                void *sp);
 
 bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv);
-int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv);
-void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv);
+void mlx5e_rep_activate_channels(struct mlx5e_priv *priv);
+void mlx5e_rep_deactivate_channels(struct mlx5e_priv *priv);
 
 void mlx5e_rep_queue_neigh_stats_work(struct mlx5e_priv *priv);
 
@@ -256,8 +257,8 @@ static inline bool mlx5e_eswitch_rep(const struct net_device *netdev)
 
 #else /* CONFIG_MLX5_ESWITCH */
 static inline bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) { return false; }
-static inline int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) { return 0; }
-static inline void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) {}
+static inline void mlx5e_rep_activate_channels(struct mlx5e_priv *priv) {}
+static inline void mlx5e_rep_deactivate_channels(struct mlx5e_priv *priv) {}
 static inline int mlx5e_rep_init(void) { return 0; };
 static inline void mlx5e_rep_cleanup(void) {};
 static inline bool mlx5e_rep_has_offload_stats(const struct net_device *dev,
index f154bda..0872a21 100644 (file)
@@ -311,6 +311,7 @@ mlx5e_get_flow_meters(struct mlx5_core_dev *dev)
 static struct mlx5_tc_ct_priv *
 get_ct_priv(struct mlx5e_priv *priv)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_rep_uplink_priv *uplink_priv;
        struct mlx5e_rep_priv *uplink_rpriv;
@@ -322,7 +323,7 @@ get_ct_priv(struct mlx5e_priv *priv)
                return uplink_priv->ct_priv;
        }
 
-       return priv->fs->tc->ct;
+       return tc->ct;
 }
 
 static struct mlx5e_tc_psample *
@@ -345,6 +346,7 @@ get_sample_priv(struct mlx5e_priv *priv)
 static struct mlx5e_post_act *
 get_post_action(struct mlx5e_priv *priv)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_rep_uplink_priv *uplink_priv;
        struct mlx5e_rep_priv *uplink_rpriv;
@@ -356,7 +358,7 @@ get_post_action(struct mlx5e_priv *priv)
                return uplink_priv->post_act;
        }
 
-       return priv->fs->tc->post_act;
+       return tc->post_act;
 }
 
 struct mlx5_flow_handle *
@@ -607,11 +609,12 @@ int mlx5e_get_flow_namespace(struct mlx5e_tc_flow *flow)
 static struct mod_hdr_tbl *
 get_mod_hdr_table(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
 
        return mlx5e_get_flow_namespace(flow) == MLX5_FLOW_NAMESPACE_FDB ?
                &esw->offloads.mod_hdr :
-               &priv->fs->tc->mod_hdr;
+               &tc->mod_hdr;
 }
 
 static int mlx5e_attach_mod_hdr(struct mlx5e_priv *priv,
@@ -810,6 +813,7 @@ static int mlx5e_hairpin_rss_init(struct mlx5e_hairpin *hp)
 {
        struct mlx5e_priv *priv = hp->func_priv;
        struct ttc_params ttc_params;
+       struct mlx5_ttc_table *ttc;
        int err;
 
        err = mlx5e_hairpin_create_indirect_rqt(hp);
@@ -827,9 +831,10 @@ static int mlx5e_hairpin_rss_init(struct mlx5e_hairpin *hp)
                goto err_create_ttc_table;
        }
 
+       ttc = mlx5e_fs_get_ttc(priv->fs, false);
        netdev_dbg(priv->netdev, "add hairpin: using %d channels rss ttc table id %x\n",
                   hp->num_channels,
-                  mlx5_get_ttc_flow_table(priv->fs->ttc)->id);
+                  mlx5_get_ttc_flow_table(ttc)->id);
 
        return 0;
 
@@ -916,10 +921,11 @@ static inline u32 hash_hairpin_info(u16 peer_vhca_id, u8 prio)
 static struct mlx5e_hairpin_entry *mlx5e_hairpin_get(struct mlx5e_priv *priv,
                                                     u16 peer_vhca_id, u8 prio)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5e_hairpin_entry *hpe;
        u32 hash_key = hash_hairpin_info(peer_vhca_id, prio);
 
-       hash_for_each_possible(priv->fs->tc->hairpin_tbl, hpe,
+       hash_for_each_possible(tc->hairpin_tbl, hpe,
                               hairpin_hlist, hash_key) {
                if (hpe->peer_vhca_id == peer_vhca_id && hpe->prio == prio) {
                        refcount_inc(&hpe->refcnt);
@@ -933,11 +939,12 @@ static struct mlx5e_hairpin_entry *mlx5e_hairpin_get(struct mlx5e_priv *priv,
 static void mlx5e_hairpin_put(struct mlx5e_priv *priv,
                              struct mlx5e_hairpin_entry *hpe)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        /* no more hairpin flows for us, release the hairpin pair */
-       if (!refcount_dec_and_mutex_lock(&hpe->refcnt, &priv->fs->tc->hairpin_tbl_lock))
+       if (!refcount_dec_and_mutex_lock(&hpe->refcnt, &tc->hairpin_tbl_lock))
                return;
        hash_del(&hpe->hairpin_hlist);
-       mutex_unlock(&priv->fs->tc->hairpin_tbl_lock);
+       mutex_unlock(&tc->hairpin_tbl_lock);
 
        if (!IS_ERR_OR_NULL(hpe->hp)) {
                netdev_dbg(priv->netdev, "del hairpin: peer %s\n",
@@ -993,6 +1000,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
                                  struct mlx5e_tc_flow_parse_attr *parse_attr,
                                  struct netlink_ext_ack *extack)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        int peer_ifindex = parse_attr->mirred_ifindex[0];
        struct mlx5_hairpin_params params;
        struct mlx5_core_dev *peer_mdev;
@@ -1021,10 +1029,10 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
        if (err)
                return err;
 
-       mutex_lock(&priv->fs->tc->hairpin_tbl_lock);
+       mutex_lock(&tc->hairpin_tbl_lock);
        hpe = mlx5e_hairpin_get(priv, peer_id, match_prio);
        if (hpe) {
-               mutex_unlock(&priv->fs->tc->hairpin_tbl_lock);
+               mutex_unlock(&tc->hairpin_tbl_lock);
                wait_for_completion(&hpe->res_ready);
 
                if (IS_ERR(hpe->hp)) {
@@ -1036,7 +1044,7 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
 
        hpe = kzalloc(sizeof(*hpe), GFP_KERNEL);
        if (!hpe) {
-               mutex_unlock(&priv->fs->tc->hairpin_tbl_lock);
+               mutex_unlock(&tc->hairpin_tbl_lock);
                return -ENOMEM;
        }
 
@@ -1048,9 +1056,9 @@ static int mlx5e_hairpin_flow_add(struct mlx5e_priv *priv,
        refcount_set(&hpe->refcnt, 1);
        init_completion(&hpe->res_ready);
 
-       hash_add(priv->fs->tc->hairpin_tbl, &hpe->hairpin_hlist,
+       hash_add(tc->hairpin_tbl, &hpe->hairpin_hlist,
                 hash_hairpin_info(peer_id, match_prio));
-       mutex_unlock(&priv->fs->tc->hairpin_tbl_lock);
+       mutex_unlock(&tc->hairpin_tbl_lock);
 
        params.log_data_size = 16;
        params.log_data_size = min_t(u8, params.log_data_size,
@@ -1126,8 +1134,9 @@ mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
                             struct mlx5_flow_attr *attr)
 {
        struct mlx5_flow_context *flow_context = &spec->flow_context;
+       struct mlx5e_vlan_table *vlan = mlx5e_fs_get_vlan(priv->fs);
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_nic_flow_attr *nic_attr = attr->nic_attr;
-       struct mlx5e_tc_table *tc = priv->fs->tc;
        struct mlx5_flow_destination dest[2] = {};
        struct mlx5_fs_chains *nic_chains;
        struct mlx5_flow_act flow_act = {
@@ -1163,7 +1172,7 @@ mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
                        if (IS_ERR(dest[dest_ix].ft))
                                return ERR_CAST(dest[dest_ix].ft);
                } else {
-                       dest[dest_ix].ft = mlx5e_vlan_get_flowtable(priv->fs->vlan);
+                       dest[dest_ix].ft = mlx5e_vlan_get_flowtable(vlan);
                }
                dest_ix++;
        }
@@ -1191,7 +1200,7 @@ mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
                        mutex_unlock(&tc->t_lock);
                        netdev_err(priv->netdev,
                                   "Failed to create tc offload table\n");
-                       rule = ERR_CAST(priv->fs->tc->t);
+                       rule = ERR_CAST(tc->t);
                        goto err_ft_get;
                }
        }
@@ -1293,8 +1302,10 @@ void mlx5e_del_offloaded_nic_rule(struct mlx5e_priv *priv,
                                  struct mlx5_flow_handle *rule,
                                  struct mlx5_flow_attr *attr)
 {
-       struct mlx5_fs_chains *nic_chains = mlx5e_nic_chains(priv->fs->tc);
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
+       struct mlx5_fs_chains *nic_chains;
 
+       nic_chains = mlx5e_nic_chains(tc);
        mlx5_del_flow_rules(rule);
 
        if (attr->chain || attr->prio)
@@ -1309,8 +1320,8 @@ void mlx5e_del_offloaded_nic_rule(struct mlx5e_priv *priv,
 static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
                                  struct mlx5e_tc_flow *flow)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_flow_attr *attr = flow->attr;
-       struct mlx5e_tc_table *tc = priv->fs->tc;
 
        flow_flag_clear(flow, OFFLOADED);
 
@@ -1322,13 +1333,13 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
        /* Remove root table if no rules are left to avoid
         * extra steering hops.
         */
-       mutex_lock(&priv->fs->tc->t_lock);
+       mutex_lock(&tc->t_lock);
        if (!mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD)) &&
            !IS_ERR_OR_NULL(tc->t)) {
                mlx5_chains_put_table(mlx5e_nic_chains(tc), 0, 1, MLX5E_TC_FT_LEVEL);
-               priv->fs->tc->t = NULL;
+               tc->t = NULL;
        }
-       mutex_unlock(&priv->fs->tc->t_lock);
+       mutex_unlock(&tc->t_lock);
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                mlx5e_detach_mod_hdr(priv, flow);
@@ -1494,8 +1505,11 @@ bool mlx5e_tc_is_vf_tunnel(struct net_device *out_dev, struct net_device *route_
        route_priv = netdev_priv(route_dev);
        route_mdev = route_priv->mdev;
 
-       if (out_mdev->coredev_type != MLX5_COREDEV_PF ||
-           route_mdev->coredev_type != MLX5_COREDEV_VF)
+       if (out_mdev->coredev_type != MLX5_COREDEV_PF)
+               return false;
+
+       if (route_mdev->coredev_type != MLX5_COREDEV_VF &&
+           route_mdev->coredev_type != MLX5_COREDEV_SF)
                return false;
 
        return mlx5e_same_hw_devs(out_priv, route_priv);
@@ -4058,13 +4072,14 @@ static const struct rhashtable_params tc_ht_params = {
 static struct rhashtable *get_tc_ht(struct mlx5e_priv *priv,
                                    unsigned long flags)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5e_rep_priv *rpriv;
 
        if (flags & MLX5_TC_FLAG(ESW_OFFLOAD)) {
                rpriv = priv->ppriv;
                return &rpriv->tc_ht;
        } else /* NIC offload */
-               return &priv->fs->tc->ht;
+               return &tc->ht;
 }
 
 static bool is_peer_flow_needed(struct mlx5e_tc_flow *flow)
@@ -4772,6 +4787,7 @@ void mlx5e_tc_stats_matchall(struct mlx5e_priv *priv,
 static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
                                              struct mlx5e_priv *peer_priv)
 {
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_core_dev *peer_mdev = peer_priv->mdev;
        struct mlx5e_hairpin_entry *hpe, *tmp;
        LIST_HEAD(init_wait_list);
@@ -4783,11 +4799,11 @@ static void mlx5e_tc_hairpin_update_dead_peer(struct mlx5e_priv *priv,
 
        peer_vhca_id = MLX5_CAP_GEN(peer_mdev, vhca_id);
 
-       mutex_lock(&priv->fs->tc->hairpin_tbl_lock);
-       hash_for_each(priv->fs->tc->hairpin_tbl, bkt, hpe, hairpin_hlist)
+       mutex_lock(&tc->hairpin_tbl_lock);
+       hash_for_each(tc->hairpin_tbl, bkt, hpe, hairpin_hlist)
                if (refcount_inc_not_zero(&hpe->refcnt))
                        list_add(&hpe->dead_peer_wait_list, &init_wait_list);
-       mutex_unlock(&priv->fs->tc->hairpin_tbl_lock);
+       mutex_unlock(&tc->hairpin_tbl_lock);
 
        list_for_each_entry_safe(hpe, tmp, &init_wait_list, dead_peer_wait_list) {
                wait_for_completion(&hpe->res_ready);
@@ -4841,7 +4857,8 @@ static int mlx5e_tc_nic_get_ft_size(struct mlx5_core_dev *dev)
 
 static int mlx5e_tc_nic_create_miss_table(struct mlx5e_priv *priv)
 {
-       struct mlx5_flow_table **ft = &priv->fs->tc->miss_t;
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
+       struct mlx5_flow_table **ft = &tc->miss_t;
        struct mlx5_flow_table_attr ft_attr = {};
        struct mlx5_flow_namespace *ns;
        int err = 0;
@@ -4863,12 +4880,14 @@ static int mlx5e_tc_nic_create_miss_table(struct mlx5e_priv *priv)
 
 static void mlx5e_tc_nic_destroy_miss_table(struct mlx5e_priv *priv)
 {
-       mlx5_destroy_flow_table(priv->fs->tc->miss_t);
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
+
+       mlx5_destroy_flow_table(tc->miss_t);
 }
 
 int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
 {
-       struct mlx5e_tc_table *tc = priv->fs->tc;
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
        struct mlx5_core_dev *dev = priv->mdev;
        struct mapping_ctx *chains_mapping;
        struct mlx5_chains_attr attr = {};
@@ -4909,7 +4928,7 @@ int mlx5e_tc_nic_init(struct mlx5e_priv *priv)
        attr.ns = MLX5_FLOW_NAMESPACE_KERNEL;
        attr.max_ft_sz = mlx5e_tc_nic_get_ft_size(dev);
        attr.max_grp_num = MLX5E_TC_TABLE_NUM_GROUPS;
-       attr.default_ft = priv->fs->tc->miss_t;
+       attr.default_ft = tc->miss_t;
        attr.mapping = chains_mapping;
 
        tc->chains = mlx5_chains_create(dev, &attr);
@@ -4958,7 +4977,7 @@ static void _mlx5e_tc_del_flow(void *ptr, void *arg)
 
 void mlx5e_tc_nic_cleanup(struct mlx5e_priv *priv)
 {
-       struct mlx5e_tc_table *tc = priv->fs->tc;
+       struct mlx5e_tc_table *tc = mlx5e_fs_get_tc(priv->fs);
 
        if (tc->netdevice_nb.notifier_call)
                unregister_netdevice_notifier_dev_net(priv->netdev,
@@ -5163,13 +5182,13 @@ bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe,
 #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
        u32 chain = 0, chain_tag, reg_b, zone_restore_id;
        struct mlx5e_priv *priv = netdev_priv(skb->dev);
-       struct mlx5e_tc_table *tc = priv->fs->tc;
        struct mlx5_mapped_obj mapped_obj;
        struct tc_skb_ext *tc_skb_ext;
+       struct mlx5e_tc_table *tc;
        int err;
 
        reg_b = be32_to_cpu(cqe->ft_metadata);
-
+       tc = mlx5e_fs_get_tc(priv->fs);
        chain_tag = reg_b & MLX5E_TC_TABLE_CHAIN_TAG_MASK;
 
        err = mapping_find(tc->mapping, chain_tag, &mapped_obj);
index 6ce1ab6..4824131 100644 (file)
@@ -54,6 +54,7 @@
                            ESW_FLOW_ATTR_SZ :\
                            NIC_FLOW_ATTR_SZ)
 
+struct mlx5_fs_chains *mlx5e_nic_chains(struct mlx5e_tc_table *tc);
 int mlx5e_tc_num_filters(struct mlx5e_priv *priv, unsigned long flags);
 
 struct mlx5e_tc_update_priv {
index 0abef71..c9a9115 100644 (file)
@@ -78,12 +78,16 @@ mlx5_esw_indir_table_needed(struct mlx5_eswitch *esw,
                            struct mlx5_core_dev *dest_mdev)
 {
        struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
+       bool vf_sf_vport;
+
+       vf_sf_vport = mlx5_eswitch_is_vf_vport(esw, vport_num) ||
+                     mlx5_esw_is_sf_vport(esw, vport_num);
 
        /* Use indirect table for all IP traffic from UL to VF with vport
         * destination when source rewrite flag is set.
         */
        return esw_attr->in_rep->vport == MLX5_VPORT_UPLINK &&
-               mlx5_eswitch_is_vf_vport(esw, vport_num) &&
+               vf_sf_vport &&
                esw->dev == dest_mdev &&
                attr->ip_version &&
                attr->flags & MLX5_ATTR_FLAG_SRC_REWRITE;
index 6aa5804..c59107f 100644 (file)
@@ -1360,7 +1360,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
        if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
                struct devlink *devlink = priv_to_devlink(esw->dev);
 
-               esw_offloads_del_send_to_vport_meta_rules(esw);
                devl_rate_nodes_destroy(devlink);
        }
 
index 87ce5a2..f68dc2d 100644 (file)
@@ -244,6 +244,8 @@ struct mlx5_esw_offload {
 
        struct mlx5_flow_table *ft_offloads;
        struct mlx5_flow_group *vport_rx_group;
+       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 mutex peer_mutex;
@@ -344,7 +346,10 @@ void esw_offloads_disable(struct mlx5_eswitch *esw);
 int esw_offloads_enable(struct mlx5_eswitch *esw);
 void esw_offloads_cleanup_reps(struct mlx5_eswitch *esw);
 int esw_offloads_init_reps(struct mlx5_eswitch *esw);
-void esw_offloads_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw);
+
+struct mlx5_flow_handle *
+mlx5_eswitch_add_send_to_vport_meta_rule(struct mlx5_eswitch *esw, u16 vport_num);
+void mlx5_eswitch_del_send_to_vport_meta_rule(struct mlx5_flow_handle *rule);
 
 bool mlx5_esw_vport_match_metadata_supported(const struct mlx5_eswitch *esw);
 int mlx5_esw_offloads_vport_metadata_set(struct mlx5_eswitch *esw, bool enable);
index a9f4c65..c98c6af 100644 (file)
@@ -70,6 +70,8 @@
 #define MLX5_ESW_VPORT_TBL_SIZE 128
 #define MLX5_ESW_VPORT_TBL_NUM_GROUPS  4
 
+#define MLX5_ESW_FT_OFFLOADS_DROP_RULE (1)
+
 static const struct esw_vport_tbl_namespace mlx5_esw_vport_tbl_mirror_ns = {
        .max_fte = MLX5_ESW_VPORT_TBL_SIZE,
        .max_num_groups = MLX5_ESW_VPORT_TBL_NUM_GROUPS,
@@ -1058,52 +1060,23 @@ void mlx5_eswitch_del_send_to_vport_rule(struct mlx5_flow_handle *rule)
        mlx5_del_flow_rules(rule);
 }
 
-static void mlx5_eswitch_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
-{
-       struct mlx5_flow_handle **flows = esw->fdb_table.offloads.send_to_vport_meta_rules;
-       int i = 0, num_vfs = esw->esw_funcs.num_vfs;
-
-       if (!num_vfs || !flows)
-               return;
-
-       for (i = 0; i < num_vfs; i++)
-               mlx5_del_flow_rules(flows[i]);
-
-       kvfree(flows);
-       /* If changing eswitch mode from switchdev to legacy, but num_vfs is not 0,
-        * meta rules could be freed again. So set it to NULL.
-        */
-       esw->fdb_table.offloads.send_to_vport_meta_rules = NULL;
-}
-
-void esw_offloads_del_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
+void mlx5_eswitch_del_send_to_vport_meta_rule(struct mlx5_flow_handle *rule)
 {
-       mlx5_eswitch_del_send_to_vport_meta_rules(esw);
+       if (rule)
+               mlx5_del_flow_rules(rule);
 }
 
-static int
-mlx5_eswitch_add_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
+struct mlx5_flow_handle *
+mlx5_eswitch_add_send_to_vport_meta_rule(struct mlx5_eswitch *esw, u16 vport_num)
 {
        struct mlx5_flow_destination dest = {};
        struct mlx5_flow_act flow_act = {0};
-       int num_vfs, rule_idx = 0, err = 0;
        struct mlx5_flow_handle *flow_rule;
-       struct mlx5_flow_handle **flows;
        struct mlx5_flow_spec *spec;
-       struct mlx5_vport *vport;
-       unsigned long i;
-       u16 vport_num;
-
-       num_vfs = esw->esw_funcs.num_vfs;
-       flows = kvcalloc(num_vfs, sizeof(*flows), GFP_KERNEL);
-       if (!flows)
-               return -ENOMEM;
 
        spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
-       if (!spec) {
-               err = -ENOMEM;
-               goto alloc_err;
-       }
+       if (!spec)
+               return ERR_PTR(-ENOMEM);
 
        MLX5_SET(fte_match_param, spec->match_criteria,
                 misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask());
@@ -1116,34 +1089,18 @@ mlx5_eswitch_add_send_to_vport_meta_rules(struct mlx5_eswitch *esw)
        dest.type = MLX5_FLOW_DESTINATION_TYPE_VPORT;
        flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
 
-       mlx5_esw_for_each_vf_vport(esw, i, vport, num_vfs) {
-               vport_num = vport->vport;
-               MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_0,
-                        mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
-               dest.vport.num = vport_num;
-
-               flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
-                                               spec, &flow_act, &dest, 1);
-               if (IS_ERR(flow_rule)) {
-                       err = PTR_ERR(flow_rule);
-                       esw_warn(esw->dev, "FDB: Failed to add send to vport meta rule idx %d, err %ld\n",
-                                rule_idx, PTR_ERR(flow_rule));
-                       goto rule_err;
-               }
-               flows[rule_idx++] = flow_rule;
-       }
+       MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.metadata_reg_c_0,
+                mlx5_eswitch_get_vport_metadata_for_match(esw, vport_num));
+       dest.vport.num = vport_num;
 
-       esw->fdb_table.offloads.send_to_vport_meta_rules = flows;
-       kvfree(spec);
-       return 0;
+       flow_rule = mlx5_add_flow_rules(esw->fdb_table.offloads.slow_fdb,
+                                       spec, &flow_act, &dest, 1);
+       if (IS_ERR(flow_rule))
+               esw_warn(esw->dev, "FDB: Failed to add send to vport meta rule vport %d, err %ld\n",
+                        vport_num, PTR_ERR(flow_rule));
 
-rule_err:
-       while (--rule_idx >= 0)
-               mlx5_del_flow_rules(flows[rule_idx]);
        kvfree(spec);
-alloc_err:
-       kvfree(flows);
-       return err;
+       return flow_rule;
 }
 
 static bool mlx5_eswitch_reg_c1_loopback_supported(struct mlx5_eswitch *esw)
@@ -1668,18 +1625,200 @@ esw_chains_destroy(struct mlx5_eswitch *esw, struct mlx5_fs_chains *chains)
 
 #endif
 
+static int
+esw_create_send_to_vport_group(struct mlx5_eswitch *esw,
+                              struct mlx5_flow_table *fdb,
+                              u32 *flow_group_in,
+                              int *ix)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_group *g;
+       void *match_criteria;
+       int count, err = 0;
+
+       memset(flow_group_in, 0, inlen);
+
+       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_sqn);
+       MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
+       if (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,
+                        source_eswitch_owner_vhca_id_valid, 1);
+       }
+
+       /* See comment at table_size calculation */
+       count = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ);
+       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, *ix + count - 1);
+       *ix += count;
+
+       g = mlx5_create_flow_group(fdb, flow_group_in);
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               esw_warn(esw->dev, "Failed to create send-to-vport flow group err(%d)\n", err);
+               goto out;
+       }
+       esw->fdb_table.offloads.send_to_vport_grp = g;
+
+out:
+       return err;
+}
+
+static int
+esw_create_meta_send_to_vport_group(struct mlx5_eswitch *esw,
+                                   struct mlx5_flow_table *fdb,
+                                   u32 *flow_group_in,
+                                   int *ix)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_group *g;
+       void *match_criteria;
+       int err = 0;
+
+       if (!esw_src_port_rewrite_supported(esw))
+               return 0;
+
+       memset(flow_group_in, 0, inlen);
+
+       MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
+                MLX5_MATCH_MISC_PARAMETERS_2);
+
+       match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
+
+       MLX5_SET(fte_match_param, match_criteria,
+                misc_parameters_2.metadata_reg_c_0,
+                mlx5_eswitch_get_vport_metadata_mask());
+       MLX5_SET(fte_match_param, match_criteria,
+                misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
+
+       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;
+
+       g = mlx5_create_flow_group(fdb, flow_group_in);
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               esw_warn(esw->dev,
+                        "Failed to create send-to-vport meta flow group err(%d)\n", err);
+               goto send_vport_meta_err;
+       }
+       esw->fdb_table.offloads.send_to_vport_meta_grp = g;
+
+       return 0;
+
+send_vport_meta_err:
+       return err;
+}
+
+static int
+esw_create_peer_esw_miss_group(struct mlx5_eswitch *esw,
+                              struct mlx5_flow_table *fdb,
+                              u32 *flow_group_in,
+                              int *ix)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_group *g;
+       void *match_criteria;
+       int err = 0;
+
+       if (!MLX5_CAP_ESW(esw->dev, merged_eswitch))
+               return 0;
+
+       memset(flow_group_in, 0, inlen);
+
+       esw_set_flow_group_source_port(esw, flow_group_in);
+
+       if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
+               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_eswitch_owner_vhca_id);
+
+               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, *ix);
+       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
+                *ix + esw->total_vports - 1);
+       *ix += esw->total_vports;
+
+       g = mlx5_create_flow_group(fdb, flow_group_in);
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               esw_warn(esw->dev, "Failed to create peer miss flow group err(%d)\n", err);
+               goto out;
+       }
+       esw->fdb_table.offloads.peer_miss_grp = g;
+
+out:
+       return err;
+}
+
+static int
+esw_create_miss_group(struct mlx5_eswitch *esw,
+                     struct mlx5_flow_table *fdb,
+                     u32 *flow_group_in,
+                     int *ix)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_group *g;
+       void *match_criteria;
+       int err = 0;
+       u8 *dmac;
+
+       memset(flow_group_in, 0, inlen);
+
+       MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
+                MLX5_MATCH_OUTER_HEADERS);
+       match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
+                                     match_criteria);
+       dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
+                           outer_headers.dmac_47_16);
+       dmac[0] = 0x01;
+
+       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 + MLX5_ESW_MISS_FLOWS);
+
+       g = mlx5_create_flow_group(fdb, flow_group_in);
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               esw_warn(esw->dev, "Failed to create miss flow group err(%d)\n", err);
+               goto miss_err;
+       }
+       esw->fdb_table.offloads.miss_grp = g;
+
+       err = esw_add_fdb_miss_rule(esw);
+       if (err)
+               goto miss_rule_err;
+
+       return 0;
+
+miss_rule_err:
+       mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
+miss_err:
+       return err;
+}
+
 static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
 {
        int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
        struct mlx5_flow_table_attr ft_attr = {};
-       int num_vfs, table_size, ix, err = 0;
        struct mlx5_core_dev *dev = esw->dev;
        struct mlx5_flow_namespace *root_ns;
        struct mlx5_flow_table *fdb = NULL;
+       int table_size, ix = 0, err = 0;
        u32 flags = 0, *flow_group_in;
-       struct mlx5_flow_group *g;
-       void *match_criteria;
-       u8 *dmac;
 
        esw_debug(esw->dev, "Create offloads FDB Tables\n");
 
@@ -1713,7 +1852,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) +
-               MLX5_ESW_MISS_FLOWS + esw->total_vports + esw->esw_funcs.num_vfs;
+                    esw->total_vports * 2 + 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.
@@ -1754,139 +1893,29 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw)
                goto fdb_chains_err;
        }
 
-       /* create send-to-vport group */
-       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_sqn);
-       MLX5_SET_TO_ONES(fte_match_param, match_criteria, misc_parameters.source_port);
-       if (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,
-                        source_eswitch_owner_vhca_id_valid, 1);
-       }
-
-       /* See comment above table_size calculation */
-       ix = MLX5_MAX_PORTS * (esw->total_vports * MAX_SQ_NVPORTS + MAX_PF_SQ);
-       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, ix - 1);
-
-       g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR(g)) {
-               err = PTR_ERR(g);
-               esw_warn(dev, "Failed to create send-to-vport flow group err(%d)\n", err);
+       err = esw_create_send_to_vport_group(esw, fdb, flow_group_in, &ix);
+       if (err)
                goto send_vport_err;
-       }
-       esw->fdb_table.offloads.send_to_vport_grp = g;
-
-       if (esw_src_port_rewrite_supported(esw)) {
-               /* meta send to vport */
-               memset(flow_group_in, 0, inlen);
-               MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
-                        MLX5_MATCH_MISC_PARAMETERS_2);
-
-               match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria);
-
-               MLX5_SET(fte_match_param, match_criteria,
-                        misc_parameters_2.metadata_reg_c_0,
-                        mlx5_eswitch_get_vport_metadata_mask());
-               MLX5_SET(fte_match_param, match_criteria,
-                        misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK);
-
-               num_vfs = esw->esw_funcs.num_vfs;
-               if (num_vfs) {
-                       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 + num_vfs - 1);
-                       ix += num_vfs;
-
-                       g = mlx5_create_flow_group(fdb, flow_group_in);
-                       if (IS_ERR(g)) {
-                               err = PTR_ERR(g);
-                               esw_warn(dev, "Failed to create send-to-vport meta flow group err(%d)\n",
-                                        err);
-                               goto send_vport_meta_err;
-                       }
-                       esw->fdb_table.offloads.send_to_vport_meta_grp = g;
-
-                       err = mlx5_eswitch_add_send_to_vport_meta_rules(esw);
-                       if (err)
-                               goto meta_rule_err;
-               }
-       }
-
-       if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) {
-               /* create peer esw miss group */
-               memset(flow_group_in, 0, inlen);
-
-               esw_set_flow_group_source_port(esw, flow_group_in);
-
-               if (!mlx5_eswitch_vport_match_metadata_enabled(esw)) {
-                       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_eswitch_owner_vhca_id);
-
-                       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, ix);
-               MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index,
-                        ix + esw->total_vports - 1);
-               ix += esw->total_vports;
-
-               g = mlx5_create_flow_group(fdb, flow_group_in);
-               if (IS_ERR(g)) {
-                       err = PTR_ERR(g);
-                       esw_warn(dev, "Failed to create peer miss flow group err(%d)\n", err);
-                       goto peer_miss_err;
-               }
-               esw->fdb_table.offloads.peer_miss_grp = g;
-       }
-
-       /* create miss group */
-       memset(flow_group_in, 0, inlen);
-       MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable,
-                MLX5_MATCH_OUTER_HEADERS);
-       match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in,
-                                     match_criteria);
-       dmac = MLX5_ADDR_OF(fte_match_param, match_criteria,
-                           outer_headers.dmac_47_16);
-       dmac[0] = 0x01;
 
-       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 + MLX5_ESW_MISS_FLOWS);
+       err = esw_create_meta_send_to_vport_group(esw, fdb, flow_group_in, &ix);
+       if (err)
+               goto send_vport_meta_err;
 
-       g = mlx5_create_flow_group(fdb, flow_group_in);
-       if (IS_ERR(g)) {
-               err = PTR_ERR(g);
-               esw_warn(dev, "Failed to create miss flow group err(%d)\n", err);
-               goto miss_err;
-       }
-       esw->fdb_table.offloads.miss_grp = g;
+       err = esw_create_peer_esw_miss_group(esw, fdb, flow_group_in, &ix);
+       if (err)
+               goto peer_miss_err;
 
-       err = esw_add_fdb_miss_rule(esw);
+       err = esw_create_miss_group(esw, fdb, flow_group_in, &ix);
        if (err)
-               goto miss_rule_err;
+               goto miss_err;
 
        kvfree(flow_group_in);
        return 0;
 
-miss_rule_err:
-       mlx5_destroy_flow_group(esw->fdb_table.offloads.miss_grp);
 miss_err:
        if (MLX5_CAP_ESW(esw->dev, merged_eswitch))
                mlx5_destroy_flow_group(esw->fdb_table.offloads.peer_miss_grp);
 peer_miss_err:
-       mlx5_eswitch_del_send_to_vport_meta_rules(esw);
-meta_rule_err:
        if (esw->fdb_table.offloads.send_to_vport_meta_grp)
                mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
 send_vport_meta_err:
@@ -1913,7 +1942,6 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
        esw_debug(esw->dev, "Destroy offloads FDB Tables\n");
        mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_multi);
        mlx5_del_flow_rules(esw->fdb_table.offloads.miss_rule_uni);
-       mlx5_eswitch_del_send_to_vport_meta_rules(esw);
        mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_grp);
        if (esw->fdb_table.offloads.send_to_vport_meta_grp)
                mlx5_destroy_flow_group(esw->fdb_table.offloads.send_to_vport_meta_grp);
@@ -1931,7 +1959,7 @@ static void esw_destroy_offloads_fdb_tables(struct mlx5_eswitch *esw)
        atomic64_set(&esw->user_count, 0);
 }
 
-static int esw_get_offloads_ft_size(struct mlx5_eswitch *esw)
+static int esw_get_nr_ft_offloads_steering_src_ports(struct mlx5_eswitch *esw)
 {
        int nvports;
 
@@ -1956,7 +1984,8 @@ static int esw_create_offloads_table(struct mlx5_eswitch *esw)
                return -EOPNOTSUPP;
        }
 
-       ft_attr.max_fte = esw_get_offloads_ft_size(esw);
+       ft_attr.max_fte = esw_get_nr_ft_offloads_steering_src_ports(esw) +
+                         MLX5_ESW_FT_OFFLOADS_DROP_RULE;
        ft_attr.prio = 1;
 
        ft_offloads = mlx5_create_flow_table(ns, &ft_attr);
@@ -1985,7 +2014,7 @@ static int esw_create_vport_rx_group(struct mlx5_eswitch *esw)
        int nvports;
        int err = 0;
 
-       nvports = esw_get_offloads_ft_size(esw);
+       nvports = esw_get_nr_ft_offloads_steering_src_ports(esw);
        flow_group_in = kvzalloc(inlen, GFP_KERNEL);
        if (!flow_group_in)
                return -ENOMEM;
@@ -2015,6 +2044,52 @@ static void esw_destroy_vport_rx_group(struct mlx5_eswitch *esw)
        mlx5_destroy_flow_group(esw->offloads.vport_rx_group);
 }
 
+static int esw_create_vport_rx_drop_rule_index(struct mlx5_eswitch *esw)
+{
+       /* ft_offloads table is enlarged by MLX5_ESW_FT_OFFLOADS_DROP_RULE (1)
+        * for the drop rule, which is placed at the end of the table.
+        * So return the total of vport and int_port as rule index.
+        */
+       return esw_get_nr_ft_offloads_steering_src_ports(esw);
+}
+
+static int esw_create_vport_rx_drop_group(struct mlx5_eswitch *esw)
+{
+       int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
+       struct mlx5_flow_group *g;
+       u32 *flow_group_in;
+       int flow_index;
+       int err = 0;
+
+       flow_index = esw_create_vport_rx_drop_rule_index(esw);
+
+       flow_group_in = kvzalloc(inlen, GFP_KERNEL);
+       if (!flow_group_in)
+               return -ENOMEM;
+
+       MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, flow_index);
+       MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, flow_index);
+
+       g = mlx5_create_flow_group(esw->offloads.ft_offloads, flow_group_in);
+
+       if (IS_ERR(g)) {
+               err = PTR_ERR(g);
+               mlx5_core_warn(esw->dev, "Failed to create vport rx drop group err %d\n", err);
+               goto out;
+       }
+
+       esw->offloads.vport_rx_drop_group = g;
+out:
+       kvfree(flow_group_in);
+       return err;
+}
+
+static void esw_destroy_vport_rx_drop_group(struct mlx5_eswitch *esw)
+{
+       if (esw->offloads.vport_rx_drop_group)
+               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)
@@ -2063,6 +2138,32 @@ out:
        return flow_rule;
 }
 
+static int esw_create_vport_rx_drop_rule(struct mlx5_eswitch *esw)
+{
+       struct mlx5_flow_act flow_act = {};
+       struct mlx5_flow_handle *flow_rule;
+
+       flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP;
+       flow_rule = mlx5_add_flow_rules(esw->offloads.ft_offloads, NULL,
+                                       &flow_act, NULL, 0);
+       if (IS_ERR(flow_rule)) {
+               esw_warn(esw->dev,
+                        "fs offloads: Failed to add vport rx drop rule err %ld\n",
+                        PTR_ERR(flow_rule));
+               return PTR_ERR(flow_rule);
+       }
+
+       esw->offloads.vport_rx_drop_rule = flow_rule;
+
+       return 0;
+}
+
+static void esw_destroy_vport_rx_drop_rule(struct mlx5_eswitch *esw)
+{
+       if (esw->offloads.vport_rx_drop_rule)
+               mlx5_del_flow_rules(esw->offloads.vport_rx_drop_rule);
+}
+
 static int mlx5_eswitch_inline_mode_get(struct mlx5_eswitch *esw, u8 *mode)
 {
        u8 prev_mlx5_mode, mlx5_mode = MLX5_INLINE_MODE_L2;
@@ -3063,8 +3164,20 @@ static int esw_offloads_steering_init(struct mlx5_eswitch *esw)
        if (err)
                goto create_fg_err;
 
+       err = esw_create_vport_rx_drop_group(esw);
+       if (err)
+               goto create_rx_drop_fg_err;
+
+       err = esw_create_vport_rx_drop_rule(esw);
+       if (err)
+               goto create_rx_drop_rule_err;
+
        return 0;
 
+create_rx_drop_rule_err:
+       esw_destroy_vport_rx_drop_group(esw);
+create_rx_drop_fg_err:
+       esw_destroy_vport_rx_group(esw);
 create_fg_err:
        esw_destroy_offloads_fdb_tables(esw);
 create_fdb_err:
@@ -3082,6 +3195,8 @@ create_indir_err:
 
 static void esw_offloads_steering_cleanup(struct mlx5_eswitch *esw)
 {
+       esw_destroy_vport_rx_drop_rule(esw);
+       esw_destroy_vport_rx_drop_group(esw);
        esw_destroy_vport_rx_group(esw);
        esw_destroy_offloads_fdb_tables(esw);
        esw_destroy_restore_table(esw);
index ac3757b..c247cca 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "en.h"
 #include "ipoib.h"
+#include "en/fs_ethtool.h"
 
 static void mlx5i_get_drvinfo(struct net_device *dev,
                              struct ethtool_drvinfo *drvinfo)
@@ -39,7 +40,7 @@ static void mlx5i_get_drvinfo(struct net_device *dev,
        struct mlx5e_priv *priv = mlx5i_epriv(dev);
 
        mlx5e_ethtool_get_drvinfo(priv, drvinfo);
-       strlcpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
+       strscpy(drvinfo->driver, KBUILD_MODNAME "[ib_ipoib]",
                sizeof(drvinfo->driver));
 }
 
index c02b7b0..35f797c 100644 (file)
@@ -35,6 +35,7 @@
 #include "en.h"
 #include "en/params.h"
 #include "ipoib.h"
+#include "en/fs_ethtool.h"
 
 #define IB_DEFAULT_Q_KEY   0xb1b
 #define MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE 9
@@ -320,43 +321,47 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
 
 static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 {
+       struct mlx5_flow_namespace *ns =
+               mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_KERNEL);
        int err;
 
-       priv->fs->ns = mlx5_get_flow_namespace(priv->mdev,
-                                              MLX5_FLOW_NAMESPACE_KERNEL);
 
-       if (!priv->fs->ns)
+       if (!ns)
                return -EINVAL;
 
-       err = mlx5e_arfs_create_tables(priv);
+       mlx5e_fs_set_ns(priv->fs, ns, false);
+       err = mlx5e_arfs_create_tables(priv->fs, priv->rx_res,
+                                      !!(priv->netdev->hw_features & NETIF_F_NTUPLE));
        if (err) {
                netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
                           err);
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv);
+       err = mlx5e_create_ttc_table(priv->fs, priv->rx_res);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
                goto err_destroy_arfs_tables;
        }
 
-       mlx5e_ethtool_init_steering(priv);
+       mlx5e_ethtool_init_steering(priv->fs);
 
        return 0;
 
 err_destroy_arfs_tables:
-       mlx5e_arfs_destroy_tables(priv);
+       mlx5e_arfs_destroy_tables(priv->fs,
+                                 !!(priv->netdev->hw_features & NETIF_F_NTUPLE));
 
        return err;
 }
 
 static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv)
 {
-       mlx5e_destroy_ttc_table(priv);
-       mlx5e_arfs_destroy_tables(priv);
-       mlx5e_ethtool_cleanup_steering(priv);
+       mlx5e_destroy_ttc_table(priv->fs);
+       mlx5e_arfs_destroy_tables(priv->fs,
+                                 !!(priv->netdev->hw_features & NETIF_F_NTUPLE));
+       mlx5e_ethtool_cleanup_steering(priv->fs);
 }
 
 static int mlx5i_init_rx(struct mlx5e_priv *priv)
index 5fdf9b7..5a1027b 100644 (file)
@@ -75,6 +75,7 @@ struct mlxbf_gige {
        struct net_device *netdev;
        struct platform_device *pdev;
        void __iomem *mdio_io;
+       void __iomem *clk_io;
        struct mii_bus *mdiobus;
        spinlock_t lock;      /* for packet processing indices */
        u16 rx_q_entries;
@@ -137,7 +138,8 @@ enum mlxbf_gige_res {
        MLXBF_GIGE_RES_MDIO9,
        MLXBF_GIGE_RES_GPIO0,
        MLXBF_GIGE_RES_LLU,
-       MLXBF_GIGE_RES_PLU
+       MLXBF_GIGE_RES_PLU,
+       MLXBF_GIGE_RES_CLK
 };
 
 /* Version of register data returned by mlxbf_gige_get_regs() */
index 2e6c1b7..85155cd 100644 (file)
 #include <linux/property.h>
 
 #include "mlxbf_gige.h"
+#include "mlxbf_gige_regs.h"
 
 #define MLXBF_GIGE_MDIO_GW_OFFSET      0x0
 #define MLXBF_GIGE_MDIO_CFG_OFFSET     0x4
 
+#define MLXBF_GIGE_MDIO_FREQ_REFERENCE 156250000ULL
+#define MLXBF_GIGE_MDIO_COREPLL_CONST  16384ULL
+#define MLXBF_GIGE_MDC_CLK_NS          400
+#define MLXBF_GIGE_MDIO_PLL_I1CLK_REG1 0x4
+#define MLXBF_GIGE_MDIO_PLL_I1CLK_REG2 0x8
+#define MLXBF_GIGE_MDIO_CORE_F_SHIFT   0
+#define MLXBF_GIGE_MDIO_CORE_F_MASK    GENMASK(25, 0)
+#define MLXBF_GIGE_MDIO_CORE_R_SHIFT   26
+#define MLXBF_GIGE_MDIO_CORE_R_MASK    GENMASK(31, 26)
+#define MLXBF_GIGE_MDIO_CORE_OD_SHIFT  0
+#define MLXBF_GIGE_MDIO_CORE_OD_MASK   GENMASK(3, 0)
+
 /* Support clause 22 */
 #define MLXBF_GIGE_MDIO_CL22_ST1       0x1
 #define MLXBF_GIGE_MDIO_CL22_WRITE     0x1
 #define MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK          GENMASK(23, 16)
 #define MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK         GENMASK(31, 24)
 
+#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
+                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
+
+#define MLXBF_GIGE_BF2_COREPLL_ADDR 0x02800c30
+#define MLXBF_GIGE_BF2_COREPLL_SIZE 0x0000000c
+
+static struct resource corepll_params[] = {
+       [MLXBF_GIGE_VERSION_BF2] = {
+               .start = MLXBF_GIGE_BF2_COREPLL_ADDR,
+               .end = MLXBF_GIGE_BF2_COREPLL_ADDR + MLXBF_GIGE_BF2_COREPLL_SIZE - 1,
+               .name = "COREPLL_RES"
+       },
+};
+
+/* Returns core clock i1clk in Hz */
+static u64 calculate_i1clk(struct mlxbf_gige *priv)
+{
+       u8 core_od, core_r;
+       u64 freq_output;
+       u32 reg1, reg2;
+       u32 core_f;
+
+       reg1 = readl(priv->clk_io + MLXBF_GIGE_MDIO_PLL_I1CLK_REG1);
+       reg2 = readl(priv->clk_io + MLXBF_GIGE_MDIO_PLL_I1CLK_REG2);
+
+       core_f = (reg1 & MLXBF_GIGE_MDIO_CORE_F_MASK) >>
+               MLXBF_GIGE_MDIO_CORE_F_SHIFT;
+       core_r = (reg1 & MLXBF_GIGE_MDIO_CORE_R_MASK) >>
+               MLXBF_GIGE_MDIO_CORE_R_SHIFT;
+       core_od = (reg2 & MLXBF_GIGE_MDIO_CORE_OD_MASK) >>
+               MLXBF_GIGE_MDIO_CORE_OD_SHIFT;
+
+       /* Compute PLL output frequency as follow:
+        *
+        *                                     CORE_F / 16384
+        * freq_output = freq_reference * ----------------------------
+        *                              (CORE_R + 1) * (CORE_OD + 1)
+        */
+       freq_output = div_u64((MLXBF_GIGE_MDIO_FREQ_REFERENCE * core_f),
+                             MLXBF_GIGE_MDIO_COREPLL_CONST);
+       freq_output = div_u64(freq_output, (core_r + 1) * (core_od + 1));
+
+       return freq_output;
+}
+
 /* Formula for encoding the MDIO period. The encoded value is
  * passed to the MDIO config register.
  *
- * mdc_clk = 2*(val + 1)*i1clk
+ * mdc_clk = 2*(val + 1)*(core clock in sec)
  *
- * 400 ns = 2*(val + 1)*(((1/430)*1000) ns)
+ * i1clk is in Hz:
+ * 400 ns = 2*(val + 1)*(1/i1clk)
  *
- * val = (((400 * 430 / 1000) / 2) - 1)
+ * val = (((400/10^9) / (1/i1clk) / 2) - 1)
+ * val = (400/2 * i1clk)/10^9 - 1
  */
-#define MLXBF_GIGE_I1CLK_MHZ           430
-#define MLXBF_GIGE_MDC_CLK_NS          400
+static u8 mdio_period_map(struct mlxbf_gige *priv)
+{
+       u8 mdio_period;
+       u64 i1clk;
 
-#define MLXBF_GIGE_MDIO_PERIOD (((MLXBF_GIGE_MDC_CLK_NS * MLXBF_GIGE_I1CLK_MHZ / 1000) / 2) - 1)
+       i1clk = calculate_i1clk(priv);
 
-#define MLXBF_GIGE_MDIO_CFG_VAL (FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_MODE_MASK, 1) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO3_3_MASK, 1) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_FULL_DRIVE_MASK, 1) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, \
-                                           MLXBF_GIGE_MDIO_PERIOD) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_IN_SAMP_MASK, 6) | \
-                                FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDIO_OUT_SAMP_MASK, 13))
+       mdio_period = div_u64((MLXBF_GIGE_MDC_CLK_NS >> 1) * i1clk, 1000000000) - 1;
+
+       return mdio_period;
+}
 
 static u32 mlxbf_gige_mdio_create_cmd(u16 data, int phy_add,
                                      int phy_reg, u32 opcode)
@@ -124,9 +186,9 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
                                 int phy_reg, u16 val)
 {
        struct mlxbf_gige *priv = bus->priv;
+       u32 temp;
        u32 cmd;
        int ret;
-       u32 temp;
 
        if (phy_reg & MII_ADDR_C45)
                return -EOPNOTSUPP;
@@ -144,18 +206,44 @@ static int mlxbf_gige_mdio_write(struct mii_bus *bus, int phy_add,
        return ret;
 }
 
+static void mlxbf_gige_mdio_cfg(struct mlxbf_gige *priv)
+{
+       u8 mdio_period;
+       u32 val;
+
+       mdio_period = mdio_period_map(priv);
+
+       val = MLXBF_GIGE_MDIO_CFG_VAL;
+       val |= FIELD_PREP(MLXBF_GIGE_MDIO_CFG_MDC_PERIOD_MASK, mdio_period);
+       writel(val, priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
+}
+
 int mlxbf_gige_mdio_probe(struct platform_device *pdev, struct mlxbf_gige *priv)
 {
        struct device *dev = &pdev->dev;
+       struct resource *res;
        int ret;
 
        priv->mdio_io = devm_platform_ioremap_resource(pdev, MLXBF_GIGE_RES_MDIO9);
        if (IS_ERR(priv->mdio_io))
                return PTR_ERR(priv->mdio_io);
 
-       /* Configure mdio parameters */
-       writel(MLXBF_GIGE_MDIO_CFG_VAL,
-              priv->mdio_io + MLXBF_GIGE_MDIO_CFG_OFFSET);
+       /* clk resource shared with other drivers so cannot use
+        * devm_platform_ioremap_resource
+        */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_CLK);
+       if (!res) {
+               /* For backward compatibility with older ACPI tables, also keep
+                * CLK resource internal to the driver.
+                */
+               res = &corepll_params[MLXBF_GIGE_VERSION_BF2];
+       }
+
+       priv->clk_io = devm_ioremap(dev, res->start, resource_size(res));
+       if (IS_ERR(priv->clk_io))
+               return PTR_ERR(priv->clk_io);
+
+       mlxbf_gige_mdio_cfg(priv);
 
        priv->mdiobus = devm_mdiobus_alloc(dev);
        if (!priv->mdiobus) {
index 5fb33c9..7be3a79 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef __MLXBF_GIGE_REGS_H__
 #define __MLXBF_GIGE_REGS_H__
 
+#define MLXBF_GIGE_VERSION                            0x0000
+#define MLXBF_GIGE_VERSION_BF2                        0x0
 #define MLXBF_GIGE_STATUS                             0x0010
 #define MLXBF_GIGE_STATUS_READY                       BIT(0)
 #define MLXBF_GIGE_INT_STATUS                         0x0028
index 60232fb..09bef04 100644 (file)
@@ -703,6 +703,9 @@ MLXSW_ITEM32(cmd_mbox, config_profile, max_vepa_channels, 0x10, 0, 8);
 
 /* cmd_mbox_config_profile_max_lag
  * Maximum number of LAG IDs requested.
+ * Reserved when Spectrum-1/2/3, supported from Spectrum-4 and above.
+ * For Spectrum-4, firmware sets 128 for values between 1-128 and 256 for values
+ * between 129-256.
  */
 MLXSW_ITEM32(cmd_mbox, config_profile, max_lag, 0x14, 0, 16);
 
index 75553eb..e2a985e 100644 (file)
@@ -70,6 +70,8 @@ struct mlxsw_core {
        struct workqueue_struct *emad_wq;
        struct list_head rx_listener_list;
        struct list_head event_listener_list;
+       struct list_head irq_event_handler_list;
+       struct mutex irq_event_handler_lock; /* Locks access to handlers list */
        struct {
                atomic64_t tid;
                struct list_head trans_list;
@@ -184,6 +186,23 @@ unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core)
 }
 EXPORT_SYMBOL(mlxsw_core_max_ports);
 
+int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag)
+{
+       struct mlxsw_driver *driver = mlxsw_core->driver;
+
+       if (driver->profile->used_max_lag) {
+               *p_max_lag = driver->profile->max_lag;
+               return 0;
+       }
+
+       if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG))
+               return -EIO;
+
+       *p_max_lag = MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG);
+       return 0;
+}
+EXPORT_SYMBOL(mlxsw_core_max_lag);
+
 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core)
 {
        return mlxsw_core->driver_priv;
@@ -633,7 +652,7 @@ static void mlxsw_emad_process_string_tlv(const struct sk_buff *skb,
                return;
 
        string = mlxsw_emad_string_tlv_string_data(string_tlv);
-       strlcpy(trans->emad_err_string, string,
+       strscpy(trans->emad_err_string, string,
                MLXSW_EMAD_STRING_TLV_STRING_LEN);
 }
 
@@ -1305,21 +1324,6 @@ mlxsw_devlink_sb_pool_set(struct devlink *devlink,
                                         extack);
 }
 
-static int mlxsw_devlink_port_type_set(struct devlink_port *devlink_port,
-                                      enum devlink_port_type port_type)
-{
-       struct mlxsw_core *mlxsw_core = devlink_priv(devlink_port->devlink);
-       struct mlxsw_driver *mlxsw_driver = mlxsw_core->driver;
-       struct mlxsw_core_port *mlxsw_core_port = __dl_port(devlink_port);
-
-       if (!mlxsw_driver->port_type_set)
-               return -EOPNOTSUPP;
-
-       return mlxsw_driver->port_type_set(mlxsw_core,
-                                          mlxsw_core_port->local_port,
-                                          port_type);
-}
-
 static int mlxsw_devlink_sb_port_pool_get(struct devlink_port *devlink_port,
                                          unsigned int sb_index, u16 pool_index,
                                          u32 *p_threshold)
@@ -1650,7 +1654,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_type_set                  = mlxsw_devlink_port_type_set,
        .port_split                     = mlxsw_devlink_port_split,
        .port_unsplit                   = mlxsw_devlink_port_unsplit,
        .sb_pool_get                    = mlxsw_devlink_sb_pool_get,
@@ -2090,6 +2093,18 @@ static void mlxsw_core_health_fini(struct mlxsw_core *mlxsw_core)
        devlink_health_reporter_destroy(mlxsw_core->health.fw_fatal);
 }
 
+static void mlxsw_core_irq_event_handler_init(struct mlxsw_core *mlxsw_core)
+{
+       INIT_LIST_HEAD(&mlxsw_core->irq_event_handler_list);
+       mutex_init(&mlxsw_core->irq_event_handler_lock);
+}
+
+static void mlxsw_core_irq_event_handler_fini(struct mlxsw_core *mlxsw_core)
+{
+       mutex_destroy(&mlxsw_core->irq_event_handler_lock);
+       WARN_ON(!list_empty(&mlxsw_core->irq_event_handler_list));
+}
+
 static int
 __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
                                 const struct mlxsw_bus *mlxsw_bus,
@@ -2101,6 +2116,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
        struct mlxsw_core *mlxsw_core;
        struct mlxsw_driver *mlxsw_driver;
        size_t alloc_size;
+       u16 max_lag;
        int err;
 
        mlxsw_driver = mlxsw_core_driver_get(device_kind);
@@ -2125,6 +2141,7 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
        mlxsw_core->bus = mlxsw_bus;
        mlxsw_core->bus_priv = bus_priv;
        mlxsw_core->bus_info = mlxsw_bus_info;
+       mlxsw_core_irq_event_handler_init(mlxsw_core);
 
        err = mlxsw_bus->init(bus_priv, mlxsw_core, mlxsw_driver->profile,
                              &mlxsw_core->res);
@@ -2141,10 +2158,9 @@ __mlxsw_core_bus_device_register(const struct mlxsw_bus_info *mlxsw_bus_info,
        if (err)
                goto err_ports_init;
 
-       if (MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG) &&
-           MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
-               alloc_size = sizeof(*mlxsw_core->lag.mapping) *
-                       MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG) *
+       err = mlxsw_core_max_lag(mlxsw_core, &max_lag);
+       if (!err && MLXSW_CORE_RES_VALID(mlxsw_core, MAX_LAG_MEMBERS)) {
+               alloc_size = sizeof(*mlxsw_core->lag.mapping) * max_lag *
                        MLXSW_CORE_RES_GET(mlxsw_core, MAX_LAG_MEMBERS);
                mlxsw_core->lag.mapping = kzalloc(alloc_size, GFP_KERNEL);
                if (!mlxsw_core->lag.mapping) {
@@ -2233,6 +2249,7 @@ err_ports_init:
 err_register_resources:
        mlxsw_bus->fini(bus_priv);
 err_bus_init:
+       mlxsw_core_irq_event_handler_fini(mlxsw_core);
        if (!reload) {
                devl_unlock(devlink);
                devlink_free(devlink);
@@ -2302,6 +2319,7 @@ void mlxsw_core_bus_device_unregister(struct mlxsw_core *mlxsw_core,
        if (!reload)
                devl_resources_unregister(devlink);
        mlxsw_core->bus->fini(mlxsw_core->bus_priv);
+       mlxsw_core_irq_event_handler_fini(mlxsw_core);
        if (!reload) {
                devl_unlock(devlink);
                devlink_free(devlink);
@@ -2772,6 +2790,57 @@ int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list)
 }
 EXPORT_SYMBOL(mlxsw_reg_trans_bulk_wait);
 
+struct mlxsw_core_irq_event_handler_item {
+       struct list_head list;
+       void (*cb)(struct mlxsw_core *mlxsw_core);
+};
+
+int mlxsw_core_irq_event_handler_register(struct mlxsw_core *mlxsw_core,
+                                         mlxsw_irq_event_cb_t cb)
+{
+       struct mlxsw_core_irq_event_handler_item *item;
+
+       item = kzalloc(sizeof(*item), GFP_KERNEL);
+       if (!item)
+               return -ENOMEM;
+       item->cb = cb;
+       mutex_lock(&mlxsw_core->irq_event_handler_lock);
+       list_add_tail(&item->list, &mlxsw_core->irq_event_handler_list);
+       mutex_unlock(&mlxsw_core->irq_event_handler_lock);
+       return 0;
+}
+EXPORT_SYMBOL(mlxsw_core_irq_event_handler_register);
+
+void mlxsw_core_irq_event_handler_unregister(struct mlxsw_core *mlxsw_core,
+                                            mlxsw_irq_event_cb_t cb)
+{
+       struct mlxsw_core_irq_event_handler_item *item, *tmp;
+
+       mutex_lock(&mlxsw_core->irq_event_handler_lock);
+       list_for_each_entry_safe(item, tmp,
+                                &mlxsw_core->irq_event_handler_list, list) {
+               if (item->cb == cb) {
+                       list_del(&item->list);
+                       kfree(item);
+               }
+       }
+       mutex_unlock(&mlxsw_core->irq_event_handler_lock);
+}
+EXPORT_SYMBOL(mlxsw_core_irq_event_handler_unregister);
+
+void mlxsw_core_irq_event_handlers_call(struct mlxsw_core *mlxsw_core)
+{
+       struct mlxsw_core_irq_event_handler_item *item;
+
+       mutex_lock(&mlxsw_core->irq_event_handler_lock);
+       list_for_each_entry(item, &mlxsw_core->irq_event_handler_list, list) {
+               if (item->cb)
+                       item->cb(mlxsw_core);
+       }
+       mutex_unlock(&mlxsw_core->irq_event_handler_lock);
+}
+EXPORT_SYMBOL(mlxsw_core_irq_event_handlers_call);
+
 static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core,
                                     const struct mlxsw_reg_info *reg,
                                     char *payload,
@@ -3115,18 +3184,6 @@ void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port,
 }
 EXPORT_SYMBOL(mlxsw_core_port_eth_set);
 
-void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port,
-                           void *port_driver_priv)
-{
-       struct mlxsw_core_port *mlxsw_core_port =
-                                       &mlxsw_core->ports[local_port];
-       struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
-
-       mlxsw_core_port->port_driver_priv = port_driver_priv;
-       devlink_port_type_ib_set(devlink_port, NULL);
-}
-EXPORT_SYMBOL(mlxsw_core_port_ib_set);
-
 void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port,
                           void *port_driver_priv)
 {
@@ -3139,18 +3196,6 @@ void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port,
 }
 EXPORT_SYMBOL(mlxsw_core_port_clear);
 
-enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
-                                               u16 local_port)
-{
-       struct mlxsw_core_port *mlxsw_core_port =
-                                       &mlxsw_core->ports[local_port];
-       struct devlink_port *devlink_port = &mlxsw_core_port->devlink_port;
-
-       return devlink_port->type;
-}
-EXPORT_SYMBOL(mlxsw_core_port_type_get);
-
-
 struct devlink_port *
 mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
                                 u16 local_port)
index 02d9cc2..ca0c3d2 100644 (file)
@@ -35,6 +35,8 @@ struct mlxsw_fw_rev;
 
 unsigned int mlxsw_core_max_ports(const struct mlxsw_core *mlxsw_core);
 
+int mlxsw_core_max_lag(struct mlxsw_core *mlxsw_core, u16 *p_max_lag);
+
 void *mlxsw_core_driver_priv(struct mlxsw_core *mlxsw_core);
 
 struct mlxsw_linecards *mlxsw_core_linecards(struct mlxsw_core *mlxsw_core);
@@ -215,6 +217,14 @@ int mlxsw_reg_trans_write(struct mlxsw_core *mlxsw_core,
                          mlxsw_reg_trans_cb_t *cb, unsigned long cb_priv);
 int mlxsw_reg_trans_bulk_wait(struct list_head *bulk_list);
 
+typedef void mlxsw_irq_event_cb_t(struct mlxsw_core *mlxsw_core);
+
+int mlxsw_core_irq_event_handler_register(struct mlxsw_core *mlxsw_core,
+                                         mlxsw_irq_event_cb_t cb);
+void mlxsw_core_irq_event_handler_unregister(struct mlxsw_core *mlxsw_core,
+                                            mlxsw_irq_event_cb_t cb);
+void mlxsw_core_irq_event_handlers_call(struct mlxsw_core *mlxsw_core);
+
 int mlxsw_reg_query(struct mlxsw_core *mlxsw_core,
                    const struct mlxsw_reg_info *reg, char *payload);
 int mlxsw_reg_write(struct mlxsw_core *mlxsw_core,
@@ -256,12 +266,8 @@ int mlxsw_core_cpu_port_init(struct mlxsw_core *mlxsw_core,
 void mlxsw_core_cpu_port_fini(struct mlxsw_core *mlxsw_core);
 void mlxsw_core_port_eth_set(struct mlxsw_core *mlxsw_core, u16 local_port,
                             void *port_driver_priv, struct net_device *dev);
-void mlxsw_core_port_ib_set(struct mlxsw_core *mlxsw_core, u16 local_port,
-                           void *port_driver_priv);
 void mlxsw_core_port_clear(struct mlxsw_core *mlxsw_core, u16 local_port,
                           void *port_driver_priv);
-enum devlink_port_type mlxsw_core_port_type_get(struct mlxsw_core *mlxsw_core,
-                                               u16 local_port);
 struct devlink_port *
 mlxsw_core_port_devlink_port_get(struct mlxsw_core *mlxsw_core,
                                 u16 local_port);
@@ -291,6 +297,7 @@ struct mlxsw_swid_config {
 
 struct mlxsw_config_profile {
        u16     used_max_vepa_channels:1,
+               used_max_lag:1,
                used_max_mid:1,
                used_max_pgt:1,
                used_max_system_port:1,
@@ -306,6 +313,7 @@ struct mlxsw_config_profile {
                used_kvd_sizes:1,
                used_cqe_time_stamp_type:1;
        u8      max_vepa_channels;
+       u16     max_lag;
        u16     max_mid;
        u16     max_pgt;
        u16     max_system_port;
@@ -341,8 +349,6 @@ struct mlxsw_driver {
                    const struct mlxsw_bus_info *mlxsw_bus_info,
                    struct netlink_ext_ack *extack);
        void (*fini)(struct mlxsw_core *mlxsw_core);
-       int (*port_type_set)(struct mlxsw_core *mlxsw_core, u16 local_port,
-                            enum devlink_port_type new_type);
        int (*port_split)(struct mlxsw_core *mlxsw_core, u16 local_port,
                          unsigned int count, struct netlink_ext_ack *extack);
        int (*port_unsplit)(struct mlxsw_core *mlxsw_core, u16 local_port,
index ca59f0b..83d2dc9 100644 (file)
@@ -785,6 +785,21 @@ static int mlxsw_linecard_status_get_and_process(struct mlxsw_core *mlxsw_core,
        return mlxsw_linecard_status_process(linecards, linecard, mddq_pl);
 }
 
+static void mlxsw_linecards_irq_event_handler(struct mlxsw_core *mlxsw_core)
+{
+       struct mlxsw_linecards *linecards = mlxsw_core_linecards(mlxsw_core);
+       int i;
+
+       /* Handle change of line card active state. */
+       for (i = 0; i < linecards->count; i++) {
+               struct mlxsw_linecard *linecard = mlxsw_linecard_get(linecards,
+                                                                    i + 1);
+
+               mlxsw_linecard_status_get_and_process(mlxsw_core, linecards,
+                                                     linecard);
+       }
+}
+
 static const char * const mlxsw_linecard_status_event_type_name[] = {
        [MLXSW_LINECARD_STATUS_EVENT_TYPE_PROVISION] = "provision",
        [MLXSW_LINECARD_STATUS_EVENT_TYPE_UNPROVISION] = "unprovision",
@@ -1238,7 +1253,6 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
 {
        struct devlink_linecard *devlink_linecard;
        struct mlxsw_linecard *linecard;
-       int err;
 
        linecard = mlxsw_linecard_get(linecards, slot_index);
        linecard->slot_index = slot_index;
@@ -1248,17 +1262,45 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
        devlink_linecard = devlink_linecard_create(priv_to_devlink(mlxsw_core),
                                                   slot_index, &mlxsw_linecard_ops,
                                                   linecard);
-       if (IS_ERR(devlink_linecard)) {
-               err = PTR_ERR(devlink_linecard);
-               goto err_devlink_linecard_create;
-       }
+       if (IS_ERR(devlink_linecard))
+               return PTR_ERR(devlink_linecard);
+
        linecard->devlink_linecard = devlink_linecard;
        INIT_DELAYED_WORK(&linecard->status_event_to_dw,
                          &mlxsw_linecard_status_event_to_work);
 
+       return 0;
+}
+
+static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core,
+                               struct mlxsw_linecards *linecards,
+                               u8 slot_index)
+{
+       struct mlxsw_linecard *linecard;
+
+       linecard = mlxsw_linecard_get(linecards, slot_index);
+       cancel_delayed_work_sync(&linecard->status_event_to_dw);
+       /* Make sure all scheduled events are processed */
+       mlxsw_core_flush_owq();
+       if (linecard->active)
+               mlxsw_linecard_active_clear(linecard);
+       mlxsw_linecard_bdev_del(linecard);
+       devlink_linecard_destroy(linecard->devlink_linecard);
+       mutex_destroy(&linecard->lock);
+}
+
+static int
+mlxsw_linecard_event_delivery_init(struct mlxsw_core *mlxsw_core,
+                                  struct mlxsw_linecards *linecards,
+                                  u8 slot_index)
+{
+       struct mlxsw_linecard *linecard;
+       int err;
+
+       linecard = mlxsw_linecard_get(linecards, slot_index);
        err = mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, true);
        if (err)
-               goto err_event_delivery_set;
+               return err;
 
        err = mlxsw_linecard_status_get_and_process(mlxsw_core, linecards,
                                                    linecard);
@@ -1269,29 +1311,18 @@ static int mlxsw_linecard_init(struct mlxsw_core *mlxsw_core,
 
 err_status_get_and_process:
        mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false);
-err_event_delivery_set:
-       devlink_linecard_destroy(linecard->devlink_linecard);
-err_devlink_linecard_create:
-       mutex_destroy(&linecard->lock);
        return err;
 }
 
-static void mlxsw_linecard_fini(struct mlxsw_core *mlxsw_core,
-                               struct mlxsw_linecards *linecards,
-                               u8 slot_index)
+static void
+mlxsw_linecard_event_delivery_fini(struct mlxsw_core *mlxsw_core,
+                                  struct mlxsw_linecards *linecards,
+                                  u8 slot_index)
 {
        struct mlxsw_linecard *linecard;
 
        linecard = mlxsw_linecard_get(linecards, slot_index);
        mlxsw_linecard_event_delivery_set(mlxsw_core, linecard, false);
-       cancel_delayed_work_sync(&linecard->status_event_to_dw);
-       /* Make sure all scheduled events are processed */
-       mlxsw_core_flush_owq();
-       if (linecard->active)
-               mlxsw_linecard_active_clear(linecard);
-       mlxsw_linecard_bdev_del(linecard);
-       devlink_linecard_destroy(linecard->devlink_linecard);
-       mutex_destroy(&linecard->lock);
 }
 
 /*       LINECARDS INI BUNDLE FILE
@@ -1505,6 +1536,11 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
        if (err)
                goto err_traps_register;
 
+       err = mlxsw_core_irq_event_handler_register(mlxsw_core,
+                                                   mlxsw_linecards_irq_event_handler);
+       if (err)
+               goto err_irq_event_handler_register;
+
        mlxsw_core_linecards_set(mlxsw_core, linecards);
 
        for (i = 0; i < linecards->count; i++) {
@@ -1513,11 +1549,25 @@ int mlxsw_linecards_init(struct mlxsw_core *mlxsw_core,
                        goto err_linecard_init;
        }
 
+       for (i = 0; i < linecards->count; i++) {
+               err = mlxsw_linecard_event_delivery_init(mlxsw_core, linecards,
+                                                        i + 1);
+               if (err)
+                       goto err_linecard_event_delivery_init;
+       }
+
        return 0;
 
+err_linecard_event_delivery_init:
+       for (i--; i >= 0; i--)
+               mlxsw_linecard_event_delivery_fini(mlxsw_core, linecards, i + 1);
+       i = linecards->count;
 err_linecard_init:
        for (i--; i >= 0; i--)
                mlxsw_linecard_fini(mlxsw_core, linecards, i + 1);
+       mlxsw_core_irq_event_handler_unregister(mlxsw_core,
+                                               mlxsw_linecards_irq_event_handler);
+err_irq_event_handler_register:
        mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener,
                                    ARRAY_SIZE(mlxsw_linecard_listener),
                                    mlxsw_core);
@@ -1535,8 +1585,12 @@ void mlxsw_linecards_fini(struct mlxsw_core *mlxsw_core)
 
        if (!linecards)
                return;
+       for (i = 0; i < linecards->count; i++)
+               mlxsw_linecard_event_delivery_fini(mlxsw_core, linecards, i + 1);
        for (i = 0; i < linecards->count; i++)
                mlxsw_linecard_fini(mlxsw_core, linecards, i + 1);
+       mlxsw_core_irq_event_handler_unregister(mlxsw_core,
+                                               mlxsw_linecards_irq_event_handler);
        mlxsw_core_traps_unregister(mlxsw_core, mlxsw_linecard_listener,
                                    ARRAY_SIZE(mlxsw_linecard_listener),
                                    mlxsw_core);
index ce843ea..716c73e 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mutex.h>
 #include <linux/module.h>
 #include <linux/mod_devicetable.h>
+#include <linux/platform_data/mlxreg.h>
 #include <linux/slab.h>
 
 #include "cmd.h"
 #define MLXSW_I2C_TIMEOUT_MSECS                5000
 #define MLXSW_I2C_MAX_DATA_SIZE                256
 
+/* Driver can be initialized by kernel platform driver or from the user
+ * space. In the first case IRQ line number is passed through the platform
+ * data, otherwise default IRQ line is to be used. Default IRQ is relevant
+ * only for specific I2C slave address, allowing 3.4 MHz I2C path to the chip
+ * (special hardware feature for I2C acceleration).
+ */
+#define MLXSW_I2C_DEFAULT_IRQ          17
+#define MLXSW_FAST_I2C_SLAVE           0x37
+
 /**
  * struct mlxsw_i2c - device private data:
  * @cmd: command attributes;
@@ -63,6 +73,9 @@
  * @core: switch core pointer;
  * @bus_info: bus info block;
  * @block_size: maximum block size allowed to pass to under layer;
+ * @pdata: device platform data;
+ * @irq_work: interrupts work item;
+ * @irq: IRQ line number;
  */
 struct mlxsw_i2c {
        struct {
@@ -76,6 +89,9 @@ struct mlxsw_i2c {
        struct mlxsw_core *core;
        struct mlxsw_bus_info bus_info;
        u16 block_size;
+       struct mlxreg_core_hotplug_platform_data *pdata;
+       struct work_struct irq_work;
+       int irq;
 };
 
 #define MLXSW_I2C_READ_MSG(_client, _addr_buf, _buf, _len) {   \
@@ -546,6 +562,67 @@ static void mlxsw_i2c_fini(void *bus_priv)
        mlxsw_i2c->core = NULL;
 }
 
+static void mlxsw_i2c_work_handler(struct work_struct *work)
+{
+       struct mlxsw_i2c *mlxsw_i2c;
+
+       mlxsw_i2c = container_of(work, struct mlxsw_i2c, irq_work);
+       mlxsw_core_irq_event_handlers_call(mlxsw_i2c->core);
+}
+
+static irqreturn_t mlxsw_i2c_irq_handler(int irq, void *dev)
+{
+       struct mlxsw_i2c *mlxsw_i2c = dev;
+
+       mlxsw_core_schedule_work(&mlxsw_i2c->irq_work);
+
+       /* Interrupt handler shares IRQ line with 'main' interrupt handler.
+        * Return here IRQ_NONE, while main handler will return IRQ_HANDLED.
+        */
+       return IRQ_NONE;
+}
+
+static int mlxsw_i2c_irq_init(struct mlxsw_i2c *mlxsw_i2c, u8 addr)
+{
+       int err;
+
+       /* Initialize interrupt handler if system hotplug driver is reachable,
+        * otherwise interrupt line is not enabled and interrupts will not be
+        * raised to CPU. Also request_irq() call will be not valid.
+        */
+       if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG))
+               return 0;
+
+       /* Set default interrupt line. */
+       if (mlxsw_i2c->pdata && mlxsw_i2c->pdata->irq)
+               mlxsw_i2c->irq = mlxsw_i2c->pdata->irq;
+       else if (addr == MLXSW_FAST_I2C_SLAVE)
+               mlxsw_i2c->irq = MLXSW_I2C_DEFAULT_IRQ;
+
+       if (!mlxsw_i2c->irq)
+               return 0;
+
+       INIT_WORK(&mlxsw_i2c->irq_work, mlxsw_i2c_work_handler);
+       err = request_irq(mlxsw_i2c->irq, mlxsw_i2c_irq_handler,
+                         IRQF_TRIGGER_FALLING | IRQF_SHARED, "mlxsw-i2c",
+                         mlxsw_i2c);
+       if (err) {
+               dev_err(mlxsw_i2c->bus_info.dev, "Failed to request irq: %d\n",
+                       err);
+               return err;
+       }
+
+       return 0;
+}
+
+static void mlxsw_i2c_irq_fini(struct mlxsw_i2c *mlxsw_i2c)
+{
+       if (!IS_REACHABLE(CONFIG_MLXREG_HOTPLUG) || !mlxsw_i2c->irq)
+               return;
+       cancel_work_sync(&mlxsw_i2c->irq_work);
+       free_irq(mlxsw_i2c->irq, mlxsw_i2c);
+}
+
 static const struct mlxsw_bus mlxsw_i2c_bus = {
        .kind                   = "i2c",
        .init                   = mlxsw_i2c_init,
@@ -638,17 +715,24 @@ static int mlxsw_i2c_probe(struct i2c_client *client,
        mlxsw_i2c->bus_info.dev = &client->dev;
        mlxsw_i2c->bus_info.low_frequency = true;
        mlxsw_i2c->dev = &client->dev;
+       mlxsw_i2c->pdata = client->dev.platform_data;
+
+       err = mlxsw_i2c_irq_init(mlxsw_i2c, client->addr);
+       if (err)
+               goto errout;
 
        err = mlxsw_core_bus_device_register(&mlxsw_i2c->bus_info,
                                             &mlxsw_i2c_bus, mlxsw_i2c, false,
                                             NULL, NULL);
        if (err) {
                dev_err(&client->dev, "Fail to register core bus\n");
-               return err;
+               goto err_bus_device_register;
        }
 
        return 0;
 
+err_bus_device_register:
+       mlxsw_i2c_irq_fini(mlxsw_i2c);
 errout:
        mutex_destroy(&mlxsw_i2c->cmd.lock);
        i2c_set_clientdata(client, NULL);
@@ -661,6 +745,7 @@ static int mlxsw_i2c_remove(struct i2c_client *client)
        struct mlxsw_i2c *mlxsw_i2c = i2c_get_clientdata(client);
 
        mlxsw_core_bus_device_unregister(mlxsw_i2c->core, false);
+       mlxsw_i2c_irq_fini(mlxsw_i2c);
        mutex_destroy(&mlxsw_i2c->cmd.lock);
 
        return 0;
index bb1cd4b..55b3c42 100644 (file)
@@ -26,20 +26,29 @@ static const struct mlxsw_fw_rev mlxsw_m_fw_rev = {
 
 struct mlxsw_m_port;
 
+struct mlxsw_m_line_card {
+       bool active;
+       int module_to_port[];
+};
+
 struct mlxsw_m {
        struct mlxsw_m_port **ports;
-       int *module_to_port;
        struct mlxsw_core *core;
        const struct mlxsw_bus_info *bus_info;
        u8 base_mac[ETH_ALEN];
        u8 max_ports;
+       u8 max_modules_per_slot; /* Maximum number of modules per-slot. */
+       u8 num_of_slots; /* Including the main board. */
+       struct mlxsw_m_line_card **line_cards;
 };
 
 struct mlxsw_m_port {
        struct net_device *dev;
        struct mlxsw_m *mlxsw_m;
        u16 local_port;
+       u8 slot_index;
        u8 module;
+       u8 module_offset;
 };
 
 static int mlxsw_m_base_mac_get(struct mlxsw_m *mlxsw_m)
@@ -94,14 +103,14 @@ static void mlxsw_m_module_get_drvinfo(struct net_device *dev,
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(dev);
        struct mlxsw_m *mlxsw_m = mlxsw_m_port->mlxsw_m;
 
-       strlcpy(drvinfo->driver, mlxsw_m->bus_info->device_kind,
+       strscpy(drvinfo->driver, mlxsw_m->bus_info->device_kind,
                sizeof(drvinfo->driver));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                 "%d.%d.%d",
                 mlxsw_m->bus_info->fw_rev.major,
                 mlxsw_m->bus_info->fw_rev.minor,
                 mlxsw_m->bus_info->fw_rev.subminor);
-       strlcpy(drvinfo->bus_info, mlxsw_m->bus_info->device_name,
+       strscpy(drvinfo->bus_info, mlxsw_m->bus_info->device_name,
                sizeof(drvinfo->bus_info));
 }
 
@@ -111,8 +120,9 @@ static int mlxsw_m_get_module_info(struct net_device *netdev,
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
        struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
 
-       return mlxsw_env_get_module_info(netdev, core, 0, mlxsw_m_port->module,
-                                        modinfo);
+       return mlxsw_env_get_module_info(netdev, core,
+                                        mlxsw_m_port->slot_index,
+                                        mlxsw_m_port->module, modinfo);
 }
 
 static int
@@ -122,7 +132,8 @@ mlxsw_m_get_module_eeprom(struct net_device *netdev, struct ethtool_eeprom *ee,
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
        struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
 
-       return mlxsw_env_get_module_eeprom(netdev, core, 0,
+       return mlxsw_env_get_module_eeprom(netdev, core,
+                                          mlxsw_m_port->slot_index,
                                           mlxsw_m_port->module, ee, data);
 }
 
@@ -134,7 +145,8 @@ mlxsw_m_get_module_eeprom_by_page(struct net_device *netdev,
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
        struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
 
-       return mlxsw_env_get_module_eeprom_by_page(core, 0,
+       return mlxsw_env_get_module_eeprom_by_page(core,
+                                                  mlxsw_m_port->slot_index,
                                                   mlxsw_m_port->module,
                                                   page, extack);
 }
@@ -144,7 +156,8 @@ static int mlxsw_m_reset(struct net_device *netdev, u32 *flags)
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
        struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
 
-       return mlxsw_env_reset_module(netdev, core, 0, mlxsw_m_port->module,
+       return mlxsw_env_reset_module(netdev, core, mlxsw_m_port->slot_index,
+                                     mlxsw_m_port->module,
                                      flags);
 }
 
@@ -156,7 +169,8 @@ mlxsw_m_get_module_power_mode(struct net_device *netdev,
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
        struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
 
-       return mlxsw_env_get_module_power_mode(core, 0, mlxsw_m_port->module,
+       return mlxsw_env_get_module_power_mode(core, mlxsw_m_port->slot_index,
+                                              mlxsw_m_port->module,
                                               params, extack);
 }
 
@@ -168,7 +182,8 @@ mlxsw_m_set_module_power_mode(struct net_device *netdev,
        struct mlxsw_m_port *mlxsw_m_port = netdev_priv(netdev);
        struct mlxsw_core *core = mlxsw_m_port->mlxsw_m->core;
 
-       return mlxsw_env_set_module_power_mode(core, 0, mlxsw_m_port->module,
+       return mlxsw_env_set_module_power_mode(core, mlxsw_m_port->slot_index,
+                                              mlxsw_m_port->module,
                                               params->policy, extack);
 }
 
@@ -184,7 +199,7 @@ static const struct ethtool_ops mlxsw_m_port_ethtool_ops = {
 
 static int
 mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port,
-                            u8 *p_module, u8 *p_width)
+                            u8 *p_module, u8 *p_width, u8 *p_slot_index)
 {
        char pmlp_pl[MLXSW_REG_PMLP_LEN];
        int err;
@@ -195,6 +210,7 @@ mlxsw_m_port_module_info_get(struct mlxsw_m *mlxsw_m, u16 local_port,
                return err;
        *p_module = mlxsw_reg_pmlp_module_get(pmlp_pl, 0);
        *p_width = mlxsw_reg_pmlp_width_get(pmlp_pl);
+       *p_slot_index = mlxsw_reg_pmlp_slot_index_get(pmlp_pl, 0);
 
        return 0;
 }
@@ -212,18 +228,25 @@ mlxsw_m_port_dev_addr_get(struct mlxsw_m_port *mlxsw_m_port)
        if (err)
                return err;
        mlxsw_reg_ppad_mac_memcpy_from(ppad_pl, addr);
-       eth_hw_addr_gen(mlxsw_m_port->dev, addr, mlxsw_m_port->module + 1);
+       eth_hw_addr_gen(mlxsw_m_port->dev, addr, mlxsw_m_port->module + 1 +
+                       mlxsw_m_port->module_offset);
        return 0;
 }
 
+static bool mlxsw_m_port_created(struct mlxsw_m *mlxsw_m, u16 local_port)
+{
+       return mlxsw_m->ports[local_port];
+}
+
 static int
-mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module)
+mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 slot_index,
+                   u8 module)
 {
        struct mlxsw_m_port *mlxsw_m_port;
        struct net_device *dev;
        int err;
 
-       err = mlxsw_core_port_init(mlxsw_m->core, local_port, 0,
+       err = mlxsw_core_port_init(mlxsw_m->core, local_port, slot_index,
                                   module + 1, false, 0, false,
                                   0, mlxsw_m->base_mac,
                                   sizeof(mlxsw_m->base_mac));
@@ -246,6 +269,15 @@ mlxsw_m_port_create(struct mlxsw_m *mlxsw_m, u16 local_port, u8 module)
        mlxsw_m_port->mlxsw_m = mlxsw_m;
        mlxsw_m_port->local_port = local_port;
        mlxsw_m_port->module = module;
+       mlxsw_m_port->slot_index = slot_index;
+       /* Add module offset for line card. Offset for main board iz zero.
+        * For line card in slot #n offset is calculated as (#n - 1)
+        * multiplied by maximum modules number, which could be found on a line
+        * card.
+        */
+       mlxsw_m_port->module_offset = mlxsw_m_port->slot_index ?
+                                     (mlxsw_m_port->slot_index - 1) *
+                                     mlxsw_m->max_modules_per_slot : 0;
 
        dev->netdev_ops = &mlxsw_m_port_netdev_ops;
        dev->ethtool_ops = &mlxsw_m_port_ethtool_ops;
@@ -291,19 +323,29 @@ static void mlxsw_m_port_remove(struct mlxsw_m *mlxsw_m, u16 local_port)
        mlxsw_core_port_fini(mlxsw_m->core, local_port);
 }
 
+static int*
+mlxsw_m_port_mapping_get(struct mlxsw_m *mlxsw_m, u8 slot_index, u8 module)
+{
+       return &mlxsw_m->line_cards[slot_index]->module_to_port[module];
+}
+
 static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port,
                                   u8 *last_module)
 {
        unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
-       u8 module, width;
+       u8 module, width, slot_index;
+       int *module_to_port;
        int err;
 
        /* Fill out to local port mapping array */
        err = mlxsw_m_port_module_info_get(mlxsw_m, local_port, &module,
-                                          &width);
+                                          &width, &slot_index);
        if (err)
                return err;
 
+       /* Skip if line card has been already configured */
+       if (mlxsw_m->line_cards[slot_index]->active)
+               return 0;
        if (!width)
                return 0;
        /* Skip, if port belongs to the cluster */
@@ -313,91 +355,220 @@ static int mlxsw_m_port_module_map(struct mlxsw_m *mlxsw_m, u16 local_port,
 
        if (WARN_ON_ONCE(module >= max_ports))
                return -EINVAL;
-       mlxsw_env_module_port_map(mlxsw_m->core, 0, module);
-       mlxsw_m->module_to_port[module] = ++mlxsw_m->max_ports;
+       mlxsw_env_module_port_map(mlxsw_m->core, slot_index, module);
+       module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, module);
+       *module_to_port = local_port;
 
        return 0;
 }
 
-static void mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 module)
+static void
+mlxsw_m_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index, u8 module)
 {
-       mlxsw_m->module_to_port[module] = -1;
-       mlxsw_env_module_port_unmap(mlxsw_m->core, 0, module);
+       int *module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index,
+                                                      module);
+       *module_to_port = -1;
+       mlxsw_env_module_port_unmap(mlxsw_m->core, slot_index, module);
 }
 
-static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
+static int mlxsw_m_linecards_init(struct mlxsw_m *mlxsw_m)
 {
        unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
-       u8 last_module = max_ports;
-       int i;
-       int err;
+       char mgpir_pl[MLXSW_REG_MGPIR_LEN];
+       u8 num_of_modules;
+       int i, j, err;
+
+       mlxsw_reg_mgpir_pack(mgpir_pl, 0);
+       err = mlxsw_reg_query(mlxsw_m->core, MLXSW_REG(mgpir), mgpir_pl);
+       if (err)
+               return err;
+
+       mlxsw_reg_mgpir_unpack(mgpir_pl, NULL, NULL, NULL, &num_of_modules,
+                              &mlxsw_m->num_of_slots);
+       /* If the system is modular, get the maximum number of modules per-slot.
+        * Otherwise, get the maximum number of modules on the main board.
+        */
+       if (mlxsw_m->num_of_slots)
+               mlxsw_m->max_modules_per_slot =
+                       mlxsw_reg_mgpir_max_modules_per_slot_get(mgpir_pl);
+       else
+               mlxsw_m->max_modules_per_slot = num_of_modules;
+       /* Add slot for main board. */
+       mlxsw_m->num_of_slots += 1;
 
        mlxsw_m->ports = kcalloc(max_ports, sizeof(*mlxsw_m->ports),
                                 GFP_KERNEL);
        if (!mlxsw_m->ports)
                return -ENOMEM;
 
-       mlxsw_m->module_to_port = kmalloc_array(max_ports, sizeof(int),
-                                               GFP_KERNEL);
-       if (!mlxsw_m->module_to_port) {
+       mlxsw_m->line_cards = kcalloc(mlxsw_m->num_of_slots,
+                                     sizeof(*mlxsw_m->line_cards),
+                                     GFP_KERNEL);
+       if (!mlxsw_m->line_cards) {
                err = -ENOMEM;
-               goto err_module_to_port_alloc;
+               goto err_kcalloc;
        }
 
-       /* Invalidate the entries of module to local port mapping array */
-       for (i = 0; i < max_ports; i++)
-               mlxsw_m->module_to_port[i] = -1;
+       for (i = 0; i < mlxsw_m->num_of_slots; i++) {
+               mlxsw_m->line_cards[i] =
+                       kzalloc(struct_size(mlxsw_m->line_cards[i],
+                                           module_to_port,
+                                           mlxsw_m->max_modules_per_slot),
+                               GFP_KERNEL);
+               if (!mlxsw_m->line_cards[i]) {
+                       err = -ENOMEM;
+                       goto err_kmalloc_array;
+               }
 
-       /* Fill out module to local port mapping array */
-       for (i = 1; i < max_ports; i++) {
-               err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module);
-               if (err)
-                       goto err_module_to_port_map;
+               /* Invalidate the entries of module to local port mapping array. */
+               for (j = 0; j < mlxsw_m->max_modules_per_slot; j++)
+                       mlxsw_m->line_cards[i]->module_to_port[j] = -1;
        }
 
-       /* Create port objects for each valid entry */
-       for (i = 0; i < mlxsw_m->max_ports; i++) {
-               if (mlxsw_m->module_to_port[i] > 0) {
-                       err = mlxsw_m_port_create(mlxsw_m,
-                                                 mlxsw_m->module_to_port[i],
-                                                 i);
+       return 0;
+
+err_kmalloc_array:
+       for (i--; i >= 0; i--)
+               kfree(mlxsw_m->line_cards[i]);
+err_kcalloc:
+       kfree(mlxsw_m->ports);
+       return err;
+}
+
+static void mlxsw_m_linecards_fini(struct mlxsw_m *mlxsw_m)
+{
+       int i = mlxsw_m->num_of_slots;
+
+       for (i--; i >= 0; i--)
+               kfree(mlxsw_m->line_cards[i]);
+       kfree(mlxsw_m->line_cards);
+       kfree(mlxsw_m->ports);
+}
+
+static void
+mlxsw_m_linecard_port_module_unmap(struct mlxsw_m *mlxsw_m, u8 slot_index)
+{
+       int i;
+
+       for (i = mlxsw_m->max_modules_per_slot - 1; i >= 0; i--) {
+               int *module_to_port;
+
+               module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i);
+               if (*module_to_port > 0)
+                       mlxsw_m_port_module_unmap(mlxsw_m, slot_index, i);
+       }
+}
+
+static int
+mlxsw_m_linecard_ports_create(struct mlxsw_m *mlxsw_m, u8 slot_index)
+{
+       int *module_to_port;
+       int i, err;
+
+       for (i = 0; i < mlxsw_m->max_modules_per_slot; i++) {
+               module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i);
+               if (*module_to_port > 0) {
+                       err = mlxsw_m_port_create(mlxsw_m, *module_to_port,
+                                                 slot_index, i);
                        if (err)
-                               goto err_module_to_port_create;
+                               goto err_port_create;
+                       /* Mark slot as active */
+                       if (!mlxsw_m->line_cards[slot_index]->active)
+                               mlxsw_m->line_cards[slot_index]->active = true;
                }
        }
-
        return 0;
 
-err_module_to_port_create:
+err_port_create:
        for (i--; i >= 0; i--) {
-               if (mlxsw_m->module_to_port[i] > 0)
-                       mlxsw_m_port_remove(mlxsw_m,
-                                           mlxsw_m->module_to_port[i]);
+               module_to_port = mlxsw_m_port_mapping_get(mlxsw_m, slot_index, i);
+               if (*module_to_port > 0 &&
+                   mlxsw_m_port_created(mlxsw_m, *module_to_port)) {
+                       mlxsw_m_port_remove(mlxsw_m, *module_to_port);
+                       /* Mark slot as inactive */
+                       if (mlxsw_m->line_cards[slot_index]->active)
+                               mlxsw_m->line_cards[slot_index]->active = false;
+               }
        }
-       i = max_ports;
-err_module_to_port_map:
-       for (i--; i > 0; i--)
-               mlxsw_m_port_module_unmap(mlxsw_m, i);
-       kfree(mlxsw_m->module_to_port);
-err_module_to_port_alloc:
-       kfree(mlxsw_m->ports);
        return err;
 }
 
-static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
+static void
+mlxsw_m_linecard_ports_remove(struct mlxsw_m *mlxsw_m, u8 slot_index)
 {
        int i;
 
-       for (i = 0; i < mlxsw_m->max_ports; i++) {
-               if (mlxsw_m->module_to_port[i] > 0) {
-                       mlxsw_m_port_remove(mlxsw_m,
-                                           mlxsw_m->module_to_port[i]);
-                       mlxsw_m_port_module_unmap(mlxsw_m, i);
+       for (i = 0; i < mlxsw_m->max_modules_per_slot; i++) {
+               int *module_to_port = mlxsw_m_port_mapping_get(mlxsw_m,
+                                                              slot_index, i);
+
+               if (*module_to_port > 0 &&
+                   mlxsw_m_port_created(mlxsw_m, *module_to_port)) {
+                       mlxsw_m_port_remove(mlxsw_m, *module_to_port);
+                       mlxsw_m_port_module_unmap(mlxsw_m, slot_index, i);
                }
        }
+}
 
-       kfree(mlxsw_m->module_to_port);
-       kfree(mlxsw_m->ports);
+static int mlxsw_m_ports_module_map(struct mlxsw_m *mlxsw_m)
+{
+       unsigned int max_ports = mlxsw_core_max_ports(mlxsw_m->core);
+       u8 last_module = max_ports;
+       int i, err;
+
+       for (i = 1; i < max_ports; i++) {
+               err = mlxsw_m_port_module_map(mlxsw_m, i, &last_module);
+               if (err)
+                       return err;
+       }
+
+       return 0;
+}
+
+static int mlxsw_m_ports_create(struct mlxsw_m *mlxsw_m)
+{
+       int err;
+
+       /* Fill out module to local port mapping array */
+       err = mlxsw_m_ports_module_map(mlxsw_m);
+       if (err)
+               goto err_ports_module_map;
+
+       /* Create port objects for each valid entry */
+       err = mlxsw_m_linecard_ports_create(mlxsw_m, 0);
+       if (err)
+               goto err_linecard_ports_create;
+
+       return 0;
+
+err_linecard_ports_create:
+err_ports_module_map:
+       mlxsw_m_linecard_port_module_unmap(mlxsw_m, 0);
+
+       return err;
+}
+
+static void mlxsw_m_ports_remove(struct mlxsw_m *mlxsw_m)
+{
+       mlxsw_m_linecard_ports_remove(mlxsw_m, 0);
+}
+
+static void
+mlxsw_m_ports_remove_selected(struct mlxsw_core *mlxsw_core,
+                             bool (*selector)(void *priv, u16 local_port),
+                             void *priv)
+{
+       struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
+       struct mlxsw_linecard *linecard_priv = priv;
+       struct mlxsw_m_line_card *linecard;
+
+       linecard = mlxsw_m->line_cards[linecard_priv->slot_index];
+
+       if (WARN_ON(!linecard->active))
+               return;
+
+       mlxsw_m_linecard_ports_remove(mlxsw_m, linecard_priv->slot_index);
+       linecard->active = false;
 }
 
 static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m)
@@ -418,6 +589,60 @@ static int mlxsw_m_fw_rev_validate(struct mlxsw_m *mlxsw_m)
        return -EINVAL;
 }
 
+static void
+mlxsw_m_got_active(struct mlxsw_core *mlxsw_core, u8 slot_index, void *priv)
+{
+       struct mlxsw_m_line_card *linecard;
+       struct mlxsw_m *mlxsw_m = priv;
+       int err;
+
+       linecard = mlxsw_m->line_cards[slot_index];
+       /* Skip if line card has been already configured during init */
+       if (linecard->active)
+               return;
+
+       /* Fill out module to local port mapping array */
+       err = mlxsw_m_ports_module_map(mlxsw_m);
+       if (err)
+               goto err_ports_module_map;
+
+       /* Create port objects for each valid entry */
+       err = mlxsw_m_linecard_ports_create(mlxsw_m, slot_index);
+       if (err) {
+               dev_err(mlxsw_m->bus_info->dev, "Failed to create port for line card at slot %d\n",
+                       slot_index);
+               goto err_linecard_ports_create;
+       }
+
+       linecard->active = true;
+
+       return;
+
+err_linecard_ports_create:
+err_ports_module_map:
+       mlxsw_m_linecard_port_module_unmap(mlxsw_m, slot_index);
+}
+
+static void
+mlxsw_m_got_inactive(struct mlxsw_core *mlxsw_core, u8 slot_index, void *priv)
+{
+       struct mlxsw_m_line_card *linecard;
+       struct mlxsw_m *mlxsw_m = priv;
+
+       linecard = mlxsw_m->line_cards[slot_index];
+
+       if (WARN_ON(!linecard->active))
+               return;
+
+       mlxsw_m_linecard_ports_remove(mlxsw_m, slot_index);
+       linecard->active = false;
+}
+
+static struct mlxsw_linecards_event_ops mlxsw_m_event_ops = {
+       .got_active = mlxsw_m_got_active,
+       .got_inactive = mlxsw_m_got_inactive,
+};
+
 static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
                        const struct mlxsw_bus_info *mlxsw_bus_info,
                        struct netlink_ext_ack *extack)
@@ -438,13 +663,33 @@ static int mlxsw_m_init(struct mlxsw_core *mlxsw_core,
                return err;
        }
 
+       err = mlxsw_m_linecards_init(mlxsw_m);
+       if (err) {
+               dev_err(mlxsw_m->bus_info->dev, "Failed to create line cards\n");
+               return err;
+       }
+
+       err = mlxsw_linecards_event_ops_register(mlxsw_core,
+                                                &mlxsw_m_event_ops, mlxsw_m);
+       if (err) {
+               dev_err(mlxsw_m->bus_info->dev, "Failed to register line cards operations\n");
+               goto linecards_event_ops_register;
+       }
+
        err = mlxsw_m_ports_create(mlxsw_m);
        if (err) {
                dev_err(mlxsw_m->bus_info->dev, "Failed to create ports\n");
-               return err;
+               goto err_ports_create;
        }
 
        return 0;
+
+err_ports_create:
+       mlxsw_linecards_event_ops_unregister(mlxsw_core,
+                                            &mlxsw_m_event_ops, mlxsw_m);
+linecards_event_ops_register:
+       mlxsw_m_linecards_fini(mlxsw_m);
+       return err;
 }
 
 static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core)
@@ -452,6 +697,9 @@ static void mlxsw_m_fini(struct mlxsw_core *mlxsw_core)
        struct mlxsw_m *mlxsw_m = mlxsw_core_driver_priv(mlxsw_core);
 
        mlxsw_m_ports_remove(mlxsw_m);
+       mlxsw_linecards_event_ops_unregister(mlxsw_core,
+                                            &mlxsw_m_event_ops, mlxsw_m);
+       mlxsw_m_linecards_fini(mlxsw_m);
 }
 
 static const struct mlxsw_config_profile mlxsw_m_config_profile;
@@ -461,6 +709,7 @@ static struct mlxsw_driver mlxsw_m_driver = {
        .priv_size              = sizeof(struct mlxsw_m),
        .init                   = mlxsw_m_init,
        .fini                   = mlxsw_m_fini,
+       .ports_remove_selected  = mlxsw_m_ports_remove_selected,
        .profile                = &mlxsw_m_config_profile,
 };
 
index 50527ad..c968309 100644 (file)
@@ -1187,6 +1187,11 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox,
                mlxsw_cmd_mbox_config_profile_max_vepa_channels_set(
                        mbox, profile->max_vepa_channels);
        }
+       if (profile->used_max_lag) {
+               mlxsw_cmd_mbox_config_profile_set_max_lag_set(mbox, 1);
+               mlxsw_cmd_mbox_config_profile_max_lag_set(mbox,
+                                                         profile->max_lag);
+       }
        if (profile->used_max_mid) {
                mlxsw_cmd_mbox_config_profile_set_max_mid_set(
                        mbox, 1);
index f27bdec..d71d7f9 100644 (file)
@@ -4729,25 +4729,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_cap, 0x08, 0, 32);
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_cap, 0x0C, 0, 32);
 
-/* reg_ptys_ib_link_width_cap
- * IB port supported widths.
- * Access: RO
- */
-MLXSW_ITEM32(reg, ptys, ib_link_width_cap, 0x10, 16, 16);
-
-#define MLXSW_REG_PTYS_IB_SPEED_SDR    BIT(0)
-#define MLXSW_REG_PTYS_IB_SPEED_DDR    BIT(1)
-#define MLXSW_REG_PTYS_IB_SPEED_QDR    BIT(2)
-#define MLXSW_REG_PTYS_IB_SPEED_FDR10  BIT(3)
-#define MLXSW_REG_PTYS_IB_SPEED_FDR    BIT(4)
-#define MLXSW_REG_PTYS_IB_SPEED_EDR    BIT(5)
-
-/* reg_ptys_ib_proto_cap
- * IB port supported speeds and protocols.
- * Access: RO
- */
-MLXSW_ITEM32(reg, ptys, ib_proto_cap, 0x10, 0, 16);
-
 /* reg_ptys_ext_eth_proto_admin
  * Extended speed and protocol to set port to.
  * Access: RW
@@ -4760,18 +4741,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_admin, 0x14, 0, 32);
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_admin, 0x18, 0, 32);
 
-/* reg_ptys_ib_link_width_admin
- * IB width to set port to.
- * Access: RW
- */
-MLXSW_ITEM32(reg, ptys, ib_link_width_admin, 0x1C, 16, 16);
-
-/* reg_ptys_ib_proto_admin
- * IB speeds and protocols to set port to.
- * Access: RW
- */
-MLXSW_ITEM32(reg, ptys, ib_proto_admin, 0x1C, 0, 16);
-
 /* reg_ptys_ext_eth_proto_oper
  * The extended current speed and protocol configured for the port.
  * Access: RO
@@ -4784,18 +4753,6 @@ MLXSW_ITEM32(reg, ptys, ext_eth_proto_oper, 0x20, 0, 32);
  */
 MLXSW_ITEM32(reg, ptys, eth_proto_oper, 0x24, 0, 32);
 
-/* reg_ptys_ib_link_width_oper
- * The current IB width to set port to.
- * Access: RO
- */
-MLXSW_ITEM32(reg, ptys, ib_link_width_oper, 0x28, 16, 16);
-
-/* reg_ptys_ib_proto_oper
- * The current IB speed and protocol.
- * Access: RO
- */
-MLXSW_ITEM32(reg, ptys, ib_proto_oper, 0x28, 0, 16);
-
 enum mlxsw_reg_ptys_connector_type {
        MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR,
        MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE,
@@ -4866,33 +4823,6 @@ static inline void mlxsw_reg_ptys_ext_eth_unpack(char *payload,
                        mlxsw_reg_ptys_ext_eth_proto_oper_get(payload);
 }
 
-static inline void mlxsw_reg_ptys_ib_pack(char *payload, u16 local_port,
-                                         u16 proto_admin, u16 link_width)
-{
-       MLXSW_REG_ZERO(ptys, payload);
-       mlxsw_reg_ptys_local_port_set(payload, local_port);
-       mlxsw_reg_ptys_proto_mask_set(payload, MLXSW_REG_PTYS_PROTO_MASK_IB);
-       mlxsw_reg_ptys_ib_proto_admin_set(payload, proto_admin);
-       mlxsw_reg_ptys_ib_link_width_admin_set(payload, link_width);
-}
-
-static inline void mlxsw_reg_ptys_ib_unpack(char *payload, u16 *p_ib_proto_cap,
-                                           u16 *p_ib_link_width_cap,
-                                           u16 *p_ib_proto_oper,
-                                           u16 *p_ib_link_width_oper)
-{
-       if (p_ib_proto_cap)
-               *p_ib_proto_cap = mlxsw_reg_ptys_ib_proto_cap_get(payload);
-       if (p_ib_link_width_cap)
-               *p_ib_link_width_cap =
-                       mlxsw_reg_ptys_ib_link_width_cap_get(payload);
-       if (p_ib_proto_oper)
-               *p_ib_proto_oper = mlxsw_reg_ptys_ib_proto_oper_get(payload);
-       if (p_ib_link_width_oper)
-               *p_ib_link_width_oper =
-                       mlxsw_reg_ptys_ib_link_width_oper_get(payload);
-}
-
 /* PPAD - Port Physical Address Register
  * -------------------------------------
  * The PPAD register configures the per port physical MAC address.
@@ -5666,27 +5596,6 @@ static inline void mlxsw_reg_ppcnt_pack(char *payload, u16 local_port,
        mlxsw_reg_ppcnt_prio_tc_set(payload, prio_tc);
 }
 
-/* PLIB - Port Local to InfiniBand Port
- * ------------------------------------
- * The PLIB register performs mapping from Local Port into InfiniBand Port.
- */
-#define MLXSW_REG_PLIB_ID 0x500A
-#define MLXSW_REG_PLIB_LEN 0x10
-
-MLXSW_REG_DEFINE(plib, MLXSW_REG_PLIB_ID, MLXSW_REG_PLIB_LEN);
-
-/* reg_plib_local_port
- * Local port number.
- * Access: Index
- */
-MLXSW_ITEM32_LP(reg, plib, 0x00, 16, 0x00, 12);
-
-/* reg_plib_ib_port
- * InfiniBand port remapping for local_port.
- * Access: RW
- */
-MLXSW_ITEM32(reg, plib, ib_port, 0x00, 0, 8);
-
 /* PPTB - Port Prio To Buffer Register
  * -----------------------------------
  * Configures the switch priority to buffer table.
@@ -12962,7 +12871,6 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
        MLXSW_REG(paos),
        MLXSW_REG(pfcc),
        MLXSW_REG(ppcnt),
-       MLXSW_REG(plib),
        MLXSW_REG(pptb),
        MLXSW_REG(pbmc),
        MLXSW_REG(pspa),
index 30c7b0e..5bcf5bc 100644 (file)
@@ -2691,6 +2691,7 @@ static void mlxsw_sp_traps_fini(struct mlxsw_sp *mlxsw_sp)
 static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
 {
        char slcr_pl[MLXSW_REG_SLCR_LEN];
+       u16 max_lag;
        u32 seed;
        int err;
 
@@ -2709,12 +2710,14 @@ static int mlxsw_sp_lag_init(struct mlxsw_sp *mlxsw_sp)
        if (err)
                return err;
 
-       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG) ||
-           !MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
+       err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag);
+       if (err)
+               return err;
+
+       if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MAX_LAG_MEMBERS))
                return -EIO;
 
-       mlxsw_sp->lags = kcalloc(MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG),
-                                sizeof(struct mlxsw_sp_upper),
+       mlxsw_sp->lags = kcalloc(max_lag, sizeof(struct mlxsw_sp_upper),
                                 GFP_KERNEL);
        if (!mlxsw_sp->lags)
                return -ENOMEM;
@@ -3509,6 +3512,33 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = {
        .cqe_time_stamp_type            = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC,
 };
 
+/* Reduce number of LAGs from full capacity (256) to the maximum supported LAGs
+ * in Spectrum-2/3, to avoid regression in number of free entries in the PGT
+ * table.
+ */
+#define MLXSW_SP4_CONFIG_PROFILE_MAX_LAG 128
+
+static const struct mlxsw_config_profile mlxsw_sp4_config_profile = {
+       .used_max_lag                   = 1,
+       .max_lag                        = MLXSW_SP4_CONFIG_PROFILE_MAX_LAG,
+       .used_flood_mode                = 1,
+       .flood_mode                     = MLXSW_CMD_MBOX_CONFIG_PROFILE_FLOOD_MODE_CONTROLLED,
+       .used_max_ib_mc                 = 1,
+       .max_ib_mc                      = 0,
+       .used_max_pkey                  = 1,
+       .max_pkey                       = 0,
+       .used_ubridge                   = 1,
+       .ubridge                        = 1,
+       .swid_config                    = {
+               {
+                       .used_type      = 1,
+                       .type           = MLXSW_PORT_SWID_TYPE_ETH,
+               }
+       },
+       .used_cqe_time_stamp_type       = 1,
+       .cqe_time_stamp_type            = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC,
+};
+
 static void
 mlxsw_sp_resource_size_params_prepare(struct mlxsw_core *mlxsw_core,
                                      struct devlink_resource_size_params *kvd_size_params,
@@ -4039,7 +4069,7 @@ static struct mlxsw_driver mlxsw_sp4_driver = {
        .params_unregister              = mlxsw_sp2_params_unregister,
        .ptp_transmitted                = mlxsw_sp_ptp_transmitted,
        .txhdr_len                      = MLXSW_TXHDR_LEN,
-       .profile                        = &mlxsw_sp2_config_profile,
+       .profile                        = &mlxsw_sp4_config_profile,
        .sdq_supports_cqe_v2            = true,
 };
 
@@ -4263,10 +4293,13 @@ static int mlxsw_sp_lag_index_get(struct mlxsw_sp *mlxsw_sp,
 {
        struct mlxsw_sp_upper *lag;
        int free_lag_id = -1;
-       u64 max_lag;
-       int i;
+       u16 max_lag;
+       int err, i;
+
+       err = mlxsw_core_max_lag(mlxsw_sp->core, &max_lag);
+       if (err)
+               return err;
 
-       max_lag = MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_LAG);
        for (i = 0; i < max_lag; i++) {
                lag = mlxsw_sp_lag_get(mlxsw_sp, i);
                if (lag->ref_count) {
index 915dffb..dcd79d7 100644 (file)
@@ -14,16 +14,16 @@ static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
        struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
        struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
 
-       strlcpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind,
+       strscpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, mlxsw_sp_driver_version,
+       strscpy(drvinfo->version, mlxsw_sp_driver_version,
                sizeof(drvinfo->version));
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                 "%d.%d.%d",
                 mlxsw_sp->bus_info->fw_rev.major,
                 mlxsw_sp->bus_info->fw_rev.minor,
                 mlxsw_sp->bus_info->fw_rev.subminor);
-       strlcpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name,
+       strscpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name,
                sizeof(drvinfo->bus_info));
 }
 
index 39904da..b3472fb 100644 (file)
@@ -423,7 +423,8 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
 
        parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
        ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
-                           0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0);
+                           0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0,
+                           0);
 
        rt = ip_route_output_key(tun->net, &fl4);
        if (IS_ERR(rt))
index 691206f..ec8457e 100644 (file)
@@ -703,9 +703,9 @@ static const struct net_device_ops ks8851_netdev_ops = {
 static void ks8851_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *di)
 {
-       strlcpy(di->driver, "KS8851", sizeof(di->driver));
-       strlcpy(di->version, "1.00", sizeof(di->version));
-       strlcpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info));
+       strscpy(di->driver, "KS8851", sizeof(di->driver));
+       strscpy(di->version, "1.00", sizeof(di->version));
+       strscpy(di->bus_info, dev_name(dev->dev.parent), sizeof(di->bus_info));
 }
 
 static u32 ks8851_get_msglevel(struct net_device *dev)
index 82d55fc..70bc725 100644 (file)
@@ -413,7 +413,8 @@ static int ks8851_probe_spi(struct spi_device *spi)
 
        spi->bits_per_word = 8;
 
-       ks = netdev_priv(netdev);
+       kss = netdev_priv(netdev);
+       ks = &kss->ks8851;
 
        ks->lock = ks8851_lock_spi;
        ks->unlock = ks8851_unlock_spi;
@@ -433,8 +434,6 @@ static int ks8851_probe_spi(struct spi_device *spi)
                 IRQ_RXPSI)     /* RX process stop */
        ks->rc_ier = STD_IRQ;
 
-       kss = to_ks8851_spi(ks);
-
        kss->spidev = spi;
        mutex_init(&kss->lock);
        INIT_WORK(&kss->tx_work, ks8851_tx_work);
index 2b3eb5e..4685200 100644 (file)
@@ -5998,9 +5998,9 @@ static void netdev_get_drvinfo(struct net_device *dev,
        struct dev_priv *priv = netdev_priv(dev);
        struct dev_info *hw_priv = priv->adapter;
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(hw_priv->pdev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(hw_priv->pdev),
                sizeof(info->bus_info));
 }
 
index 559ad94..176efbe 100644 (file)
@@ -1467,9 +1467,9 @@ static void enc28j60_restart_work_handler(struct work_struct *work)
 static void
 enc28j60_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info,
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info,
                dev_name(dev->dev.parent), sizeof(info->bus_info));
 }
 
index dc1840c..d7c8aa7 100644 (file)
@@ -925,9 +925,9 @@ static void encx24j600_get_regs(struct net_device *dev,
 static void encx24j600_get_drvinfo(struct net_device *dev,
                                   struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(dev->dev.parent),
                sizeof(info->bus_info));
 }
 
index b1c74e6..c739d60 100644 (file)
@@ -579,8 +579,8 @@ static void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
 {
        struct lan743x_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info,
+       strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+       strscpy(info->bus_info,
                pci_name(adapter->pdev), sizeof(info->bus_info));
 }
 
index 4241ff0..49e1464 100644 (file)
@@ -4,6 +4,7 @@ config LAN966X_SWITCH
        depends on HAS_IOMEM
        depends on OF
        depends on NET_SWITCHDEV
+       depends on BRIDGE || BRIDGE=n
        select PHYLINK
        select PACKING
        help
index fd2e0eb..0c22c86 100644 (file)
@@ -8,4 +8,4 @@ obj-$(CONFIG_LAN966X_SWITCH) += lan966x-switch.o
 lan966x-switch-objs  := lan966x_main.o lan966x_phylink.o lan966x_port.o \
                        lan966x_mac.o lan966x_ethtool.o lan966x_switchdev.o \
                        lan966x_vlan.o lan966x_fdb.o lan966x_mdb.o \
-                       lan966x_ptp.o lan966x_fdma.o
+                       lan966x_ptp.o lan966x_fdma.o lan966x_lag.o
index da5ca71..2ea263e 100644 (file)
@@ -8,6 +8,7 @@ struct lan966x_fdb_event_work {
        struct work_struct work;
        struct switchdev_notifier_fdb_info fdb_info;
        struct net_device *dev;
+       struct net_device *orig_dev;
        struct lan966x *lan966x;
        unsigned long event;
 };
@@ -127,75 +128,119 @@ void lan966x_fdb_deinit(struct lan966x *lan966x)
        lan966x_fdb_purge_entries(lan966x);
 }
 
-static void lan966x_fdb_event_work(struct work_struct *work)
+void lan966x_fdb_flush_workqueue(struct lan966x *lan966x)
+{
+       flush_workqueue(lan966x->fdb_work);
+}
+
+static void lan966x_fdb_port_event_work(struct lan966x_fdb_event_work *fdb_work)
 {
-       struct lan966x_fdb_event_work *fdb_work =
-               container_of(work, struct lan966x_fdb_event_work, work);
        struct switchdev_notifier_fdb_info *fdb_info;
-       struct net_device *dev = fdb_work->dev;
        struct lan966x_port *port;
        struct lan966x *lan966x;
-       int ret;
 
-       fdb_info = &fdb_work->fdb_info;
        lan966x = fdb_work->lan966x;
+       port = netdev_priv(fdb_work->orig_dev);
+       fdb_info = &fdb_work->fdb_info;
 
-       if (lan966x_netdevice_check(dev)) {
-               port = netdev_priv(dev);
+       switch (fdb_work->event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE:
+               if (!fdb_info->added_by_user)
+                       break;
+               lan966x_mac_add_entry(lan966x, port, fdb_info->addr,
+                                     fdb_info->vid);
+               break;
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               if (!fdb_info->added_by_user)
+                       break;
+               lan966x_mac_del_entry(lan966x, fdb_info->addr,
+                                     fdb_info->vid);
+               break;
+       }
+}
+
+static void lan966x_fdb_bridge_event_work(struct lan966x_fdb_event_work *fdb_work)
+{
+       struct switchdev_notifier_fdb_info *fdb_info;
+       struct lan966x *lan966x;
+       int ret;
 
-               switch (fdb_work->event) {
-               case SWITCHDEV_FDB_ADD_TO_DEVICE:
-                       if (!fdb_info->added_by_user)
-                               break;
-                       lan966x_mac_add_entry(lan966x, port, fdb_info->addr,
-                                             fdb_info->vid);
+       lan966x = fdb_work->lan966x;
+       fdb_info = &fdb_work->fdb_info;
+
+       /* In case the bridge is called */
+       switch (fdb_work->event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE:
+               /* If there is no front port in this vlan, there is no
+                * point to copy the frame to CPU because it would be
+                * just dropped at later point. So add it only if
+                * there is a port but it is required to store the fdb
+                * entry for later point when a port actually gets in
+                * the vlan.
+                */
+               lan966x_fdb_add_entry(lan966x, fdb_info);
+               if (!lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x,
+                                                          fdb_info->vid))
                        break;
-               case SWITCHDEV_FDB_DEL_TO_DEVICE:
-                       if (!fdb_info->added_by_user)
-                               break;
-                       lan966x_mac_del_entry(lan966x, fdb_info->addr,
-                                             fdb_info->vid);
+
+               lan966x_mac_cpu_learn(lan966x, fdb_info->addr,
+                                     fdb_info->vid);
+               break;
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               ret = lan966x_fdb_del_entry(lan966x, fdb_info);
+               if (!lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x,
+                                                          fdb_info->vid))
                        break;
-               }
-       } else {
-               if (!netif_is_bridge_master(dev))
-                       goto out;
-
-               /* In case the bridge is called */
-               switch (fdb_work->event) {
-               case SWITCHDEV_FDB_ADD_TO_DEVICE:
-                       /* If there is no front port in this vlan, there is no
-                        * point to copy the frame to CPU because it would be
-                        * just dropped at later point. So add it only if
-                        * there is a port but it is required to store the fdb
-                        * entry for later point when a port actually gets in
-                        * the vlan.
-                        */
-                       lan966x_fdb_add_entry(lan966x, fdb_info);
-                       if (!lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x,
-                                                                  fdb_info->vid))
-                               break;
-
-                       lan966x_mac_cpu_learn(lan966x, fdb_info->addr,
-                                             fdb_info->vid);
+
+               if (ret)
+                       lan966x_mac_cpu_forget(lan966x, fdb_info->addr,
+                                              fdb_info->vid);
+               break;
+       }
+}
+
+static void lan966x_fdb_lag_event_work(struct lan966x_fdb_event_work *fdb_work)
+{
+       struct switchdev_notifier_fdb_info *fdb_info;
+       struct lan966x_port *port;
+       struct lan966x *lan966x;
+
+       if (!lan966x_lag_first_port(fdb_work->orig_dev, fdb_work->dev))
+               return;
+
+       lan966x = fdb_work->lan966x;
+       port = netdev_priv(fdb_work->dev);
+       fdb_info = &fdb_work->fdb_info;
+
+       switch (fdb_work->event) {
+       case SWITCHDEV_FDB_ADD_TO_DEVICE:
+               if (!fdb_info->added_by_user)
                        break;
-               case SWITCHDEV_FDB_DEL_TO_DEVICE:
-                       ret = lan966x_fdb_del_entry(lan966x, fdb_info);
-                       if (!lan966x_vlan_cpu_member_cpu_vlan_mask(lan966x,
-                                                                  fdb_info->vid))
-                               break;
-
-                       if (ret)
-                               lan966x_mac_cpu_forget(lan966x, fdb_info->addr,
-                                                      fdb_info->vid);
+               lan966x_mac_add_entry(lan966x, port, fdb_info->addr,
+                                     fdb_info->vid);
+               break;
+       case SWITCHDEV_FDB_DEL_TO_DEVICE:
+               if (!fdb_info->added_by_user)
                        break;
-               }
+               lan966x_mac_del_entry(lan966x, fdb_info->addr, fdb_info->vid);
+               break;
        }
+}
+
+static void lan966x_fdb_event_work(struct work_struct *work)
+{
+       struct lan966x_fdb_event_work *fdb_work =
+               container_of(work, struct lan966x_fdb_event_work, work);
+
+       if (lan966x_netdevice_check(fdb_work->orig_dev))
+               lan966x_fdb_port_event_work(fdb_work);
+       else if (netif_is_bridge_master(fdb_work->orig_dev))
+               lan966x_fdb_bridge_event_work(fdb_work);
+       else if (netif_is_lag_master(fdb_work->orig_dev))
+               lan966x_fdb_lag_event_work(fdb_work);
 
-out:
        kfree(fdb_work->fdb_info.addr);
        kfree(fdb_work);
-       dev_put(dev);
 }
 
 int lan966x_handle_fdb(struct net_device *dev,
@@ -221,7 +266,8 @@ int lan966x_handle_fdb(struct net_device *dev,
                if (!fdb_work)
                        return -ENOMEM;
 
-               fdb_work->dev = orig_dev;
+               fdb_work->dev = dev;
+               fdb_work->orig_dev = orig_dev;
                fdb_work->lan966x = lan966x;
                fdb_work->event = event;
                INIT_WORK(&fdb_work->work, lan966x_fdb_event_work);
@@ -231,7 +277,6 @@ int lan966x_handle_fdb(struct net_device *dev,
                        goto err_addr_alloc;
 
                ether_addr_copy((u8 *)fdb_work->fdb_info.addr, fdb_info->addr);
-               dev_hold(orig_dev);
 
                queue_work(lan966x->fdb_work, &fdb_work->work);
                break;
index 6dea7f8..51f8a08 100644 (file)
@@ -425,7 +425,8 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
        lan966x_ifh_get_src_port(skb->data, &src_port);
        lan966x_ifh_get_timestamp(skb->data, &timestamp);
 
-       WARN_ON(src_port >= lan966x->num_phys_ports);
+       if (WARN_ON(src_port >= lan966x->num_phys_ports))
+               goto free_skb;
 
        skb->dev = lan966x->ports[src_port]->dev;
        skb_pull(skb, IFH_LEN * sizeof(u32));
@@ -449,6 +450,8 @@ static struct sk_buff *lan966x_fdma_rx_get_frame(struct lan966x_rx *rx)
 
        return skb;
 
+free_skb:
+       kfree_skb(skb);
 unmap_page:
        dma_unmap_page(lan966x->dev, (dma_addr_t)db->dataptr,
                       FDMA_DCB_STATUS_BLOCKL(db->status),
diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c b/drivers/net/ethernet/microchip/lan966x/lan966x_lag.c
new file mode 100644 (file)
index 0000000..41fa252
--- /dev/null
@@ -0,0 +1,363 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <linux/if_bridge.h>
+
+#include "lan966x_main.h"
+
+static void lan966x_lag_set_aggr_pgids(struct lan966x *lan966x)
+{
+       u32 visited = GENMASK(lan966x->num_phys_ports - 1, 0);
+       int p, lag, i;
+
+       /* Reset destination and aggregation PGIDS */
+       for (p = 0; p < lan966x->num_phys_ports; ++p)
+               lan_wr(ANA_PGID_PGID_SET(BIT(p)),
+                      lan966x, ANA_PGID(p));
+
+       for (p = PGID_AGGR; p < PGID_SRC; ++p)
+               lan_wr(ANA_PGID_PGID_SET(visited),
+                      lan966x, ANA_PGID(p));
+
+       /* The visited ports bitmask holds the list of ports offloading any
+        * bonding interface. Initially we mark all these ports as unvisited,
+        * then every time we visit a port in this bitmask, we know that it is
+        * the lowest numbered port, i.e. the one whose logical ID == physical
+        * port ID == LAG ID. So we mark as visited all further ports in the
+        * bitmask that are offloading the same bonding interface. This way,
+        * we set up the aggregation PGIDs only once per bonding interface.
+        */
+       for (p = 0; p < lan966x->num_phys_ports; ++p) {
+               struct lan966x_port *port = lan966x->ports[p];
+
+               if (!port || !port->bond)
+                       continue;
+
+               visited &= ~BIT(p);
+       }
+
+       /* Now, set PGIDs for each active LAG */
+       for (lag = 0; lag < lan966x->num_phys_ports; ++lag) {
+               struct net_device *bond = lan966x->ports[lag]->bond;
+               int num_active_ports = 0;
+               unsigned long bond_mask;
+               u8 aggr_idx[16];
+
+               if (!bond || (visited & BIT(lag)))
+                       continue;
+
+               bond_mask = lan966x_lag_get_mask(lan966x, bond);
+
+               for_each_set_bit(p, &bond_mask, lan966x->num_phys_ports) {
+                       struct lan966x_port *port = lan966x->ports[p];
+
+                       lan_wr(ANA_PGID_PGID_SET(bond_mask),
+                              lan966x, ANA_PGID(p));
+                       if (port->lag_tx_active)
+                               aggr_idx[num_active_ports++] = p;
+               }
+
+               for (i = PGID_AGGR; i < PGID_SRC; ++i) {
+                       u32 ac;
+
+                       ac = lan_rd(lan966x, ANA_PGID(i));
+                       ac &= ~bond_mask;
+                       /* Don't do division by zero if there was no active
+                        * port. Just make all aggregation codes zero.
+                        */
+                       if (num_active_ports)
+                               ac |= BIT(aggr_idx[i % num_active_ports]);
+                       lan_wr(ANA_PGID_PGID_SET(ac),
+                              lan966x, ANA_PGID(i));
+               }
+
+               /* Mark all ports in the same LAG as visited to avoid applying
+                * the same config again.
+                */
+               for (p = lag; p < lan966x->num_phys_ports; p++) {
+                       struct lan966x_port *port = lan966x->ports[p];
+
+                       if (!port)
+                               continue;
+
+                       if (port->bond == bond)
+                               visited |= BIT(p);
+               }
+       }
+}
+
+static void lan966x_lag_set_port_ids(struct lan966x *lan966x)
+{
+       struct lan966x_port *port;
+       u32 bond_mask;
+       u32 lag_id;
+       int p;
+
+       for (p = 0; p < lan966x->num_phys_ports; ++p) {
+               port = lan966x->ports[p];
+               if (!port)
+                       continue;
+
+               lag_id = port->chip_port;
+
+               bond_mask = lan966x_lag_get_mask(lan966x, port->bond);
+               if (bond_mask)
+                       lag_id = __ffs(bond_mask);
+
+               lan_rmw(ANA_PORT_CFG_PORTID_VAL_SET(lag_id),
+                       ANA_PORT_CFG_PORTID_VAL,
+                       lan966x, ANA_PORT_CFG(port->chip_port));
+       }
+}
+
+static void lan966x_lag_update_ids(struct lan966x *lan966x)
+{
+       lan966x_lag_set_port_ids(lan966x);
+       lan966x_update_fwd_mask(lan966x);
+       lan966x_lag_set_aggr_pgids(lan966x);
+}
+
+int lan966x_lag_port_join(struct lan966x_port *port,
+                         struct net_device *brport_dev,
+                         struct net_device *bond,
+                         struct netlink_ext_ack *extack)
+{
+       struct lan966x *lan966x = port->lan966x;
+       struct net_device *dev = port->dev;
+       u32 lag_id = -1;
+       u32 bond_mask;
+       int err;
+
+       bond_mask = lan966x_lag_get_mask(lan966x, bond);
+       if (bond_mask)
+               lag_id = __ffs(bond_mask);
+
+       port->bond = bond;
+       lan966x_lag_update_ids(lan966x);
+
+       err = switchdev_bridge_port_offload(brport_dev, dev, port,
+                                           &lan966x_switchdev_nb,
+                                           &lan966x_switchdev_blocking_nb,
+                                           false, extack);
+       if (err)
+               goto out;
+
+       lan966x_port_stp_state_set(port, br_port_get_stp_state(brport_dev));
+
+       if (lan966x_lag_first_port(port->bond, port->dev) &&
+           lag_id != -1)
+               lan966x_mac_lag_replace_port_entry(lan966x,
+                                                  lan966x->ports[lag_id],
+                                                  port);
+
+       return 0;
+
+out:
+       port->bond = NULL;
+       lan966x_lag_update_ids(lan966x);
+
+       return err;
+}
+
+void lan966x_lag_port_leave(struct lan966x_port *port, struct net_device *bond)
+{
+       struct lan966x *lan966x = port->lan966x;
+       u32 bond_mask;
+       u32 lag_id;
+
+       if (lan966x_lag_first_port(port->bond, port->dev)) {
+               bond_mask = lan966x_lag_get_mask(lan966x, port->bond);
+               bond_mask &= ~BIT(port->chip_port);
+               if (bond_mask) {
+                       lag_id = __ffs(bond_mask);
+                       lan966x_mac_lag_replace_port_entry(lan966x, port,
+                                                          lan966x->ports[lag_id]);
+               } else {
+                       lan966x_mac_lag_remove_port_entry(lan966x, port);
+               }
+       }
+
+       port->bond = NULL;
+       lan966x_lag_update_ids(lan966x);
+       lan966x_port_stp_state_set(port, BR_STATE_FORWARDING);
+}
+
+static bool lan966x_lag_port_check_hash_types(struct lan966x *lan966x,
+                                             enum netdev_lag_hash hash_type)
+{
+       int p;
+
+       for (p = 0; p < lan966x->num_phys_ports; ++p) {
+               struct lan966x_port *port = lan966x->ports[p];
+
+               if (!port || !port->bond)
+                       continue;
+
+               if (port->hash_type != hash_type)
+                       return false;
+       }
+
+       return true;
+}
+
+int lan966x_lag_port_prechangeupper(struct net_device *dev,
+                                   struct netdev_notifier_changeupper_info *info)
+{
+       struct lan966x_port *port = netdev_priv(dev);
+       struct lan966x *lan966x = port->lan966x;
+       struct netdev_lag_upper_info *lui;
+       struct netlink_ext_ack *extack;
+
+       extack = netdev_notifier_info_to_extack(&info->info);
+       lui = info->upper_info;
+       if (!lui) {
+               port->hash_type = NETDEV_LAG_HASH_NONE;
+               return NOTIFY_DONE;
+       }
+
+       if (lui->tx_type != NETDEV_LAG_TX_TYPE_HASH) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "LAG device using unsupported Tx type");
+               return -EINVAL;
+       }
+
+       if (!lan966x_lag_port_check_hash_types(lan966x, lui->hash_type)) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "LAG devices can have only the same hash_type");
+               return -EINVAL;
+       }
+
+       switch (lui->hash_type) {
+       case NETDEV_LAG_HASH_L2:
+               lan_wr(ANA_AGGR_CFG_AC_DMAC_ENA_SET(1) |
+                      ANA_AGGR_CFG_AC_SMAC_ENA_SET(1),
+                      lan966x, ANA_AGGR_CFG);
+               break;
+       case NETDEV_LAG_HASH_L34:
+               lan_wr(ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA_SET(1) |
+                      ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_SET(1) |
+                      ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA_SET(1),
+                      lan966x, ANA_AGGR_CFG);
+               break;
+       case NETDEV_LAG_HASH_L23:
+               lan_wr(ANA_AGGR_CFG_AC_DMAC_ENA_SET(1) |
+                      ANA_AGGR_CFG_AC_SMAC_ENA_SET(1) |
+                      ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA_SET(1) |
+                      ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_SET(1),
+                      lan966x, ANA_AGGR_CFG);
+               break;
+       default:
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "LAG device using unsupported hash type");
+               return -EINVAL;
+       }
+
+       port->hash_type = lui->hash_type;
+
+       return NOTIFY_OK;
+}
+
+int lan966x_lag_port_changelowerstate(struct net_device *dev,
+                                     struct netdev_notifier_changelowerstate_info *info)
+{
+       struct netdev_lag_lower_state_info *lag = info->lower_state_info;
+       struct lan966x_port *port = netdev_priv(dev);
+       struct lan966x *lan966x = port->lan966x;
+       bool is_active;
+
+       if (!port->bond)
+               return NOTIFY_DONE;
+
+       is_active = lag->link_up && lag->tx_enabled;
+       if (port->lag_tx_active == is_active)
+               return NOTIFY_DONE;
+
+       port->lag_tx_active = is_active;
+       lan966x_lag_set_aggr_pgids(lan966x);
+
+       return NOTIFY_OK;
+}
+
+int lan966x_lag_netdev_prechangeupper(struct net_device *dev,
+                                     struct netdev_notifier_changeupper_info *info)
+{
+       struct lan966x_port *port;
+       struct net_device *lower;
+       struct list_head *iter;
+       int err;
+
+       netdev_for_each_lower_dev(dev, lower, iter) {
+               if (!lan966x_netdevice_check(lower))
+                       continue;
+
+               port = netdev_priv(lower);
+               if (port->bond != dev)
+                       continue;
+
+               err = lan966x_port_prechangeupper(lower, dev, info);
+               if (err)
+                       return err;
+       }
+
+       return NOTIFY_DONE;
+}
+
+int lan966x_lag_netdev_changeupper(struct net_device *dev,
+                                  struct netdev_notifier_changeupper_info *info)
+{
+       struct lan966x_port *port;
+       struct net_device *lower;
+       struct list_head *iter;
+       int err;
+
+       netdev_for_each_lower_dev(dev, lower, iter) {
+               if (!lan966x_netdevice_check(lower))
+                       continue;
+
+               port = netdev_priv(lower);
+               if (port->bond != dev)
+                       continue;
+
+               err = lan966x_port_changeupper(lower, dev, info);
+               if (err)
+                       return err;
+       }
+
+       return NOTIFY_DONE;
+}
+
+bool lan966x_lag_first_port(struct net_device *lag, struct net_device *dev)
+{
+       struct lan966x_port *port = netdev_priv(dev);
+       struct lan966x *lan966x = port->lan966x;
+       unsigned long bond_mask;
+
+       if (port->bond != lag)
+               return false;
+
+       bond_mask = lan966x_lag_get_mask(lan966x, lag);
+       if (bond_mask && port->chip_port == __ffs(bond_mask))
+               return true;
+
+       return false;
+}
+
+u32 lan966x_lag_get_mask(struct lan966x *lan966x, struct net_device *bond)
+{
+       struct lan966x_port *port;
+       u32 mask = 0;
+       int p;
+
+       if (!bond)
+               return mask;
+
+       for (p = 0; p < lan966x->num_phys_ports; p++) {
+               port = lan966x->ports[p];
+               if (!port)
+                       continue;
+
+               if (port->bond == bond)
+                       mask |= BIT(p);
+       }
+
+       return mask;
+}
index 5893770..baa3a30 100644 (file)
@@ -22,6 +22,7 @@ struct lan966x_mac_entry {
        u16 vid;
        u16 port_index;
        int row;
+       bool lag;
 };
 
 struct lan966x_mac_raw_entry {
@@ -69,15 +70,14 @@ static void lan966x_mac_select(struct lan966x *lan966x,
        lan_wr(mach, lan966x, ANA_MACHDATA);
 }
 
-static int __lan966x_mac_learn(struct lan966x *lan966x, int pgid,
-                              bool cpu_copy,
-                              const unsigned char mac[ETH_ALEN],
-                              unsigned int vid,
-                              enum macaccess_entry_type type)
+static int __lan966x_mac_learn_locked(struct lan966x *lan966x, int pgid,
+                                     bool cpu_copy,
+                                     const unsigned char mac[ETH_ALEN],
+                                     unsigned int vid,
+                                     enum macaccess_entry_type type)
 {
-       int ret;
+       lockdep_assert_held(&lan966x->mac_lock);
 
-       spin_lock(&lan966x->mac_lock);
        lan966x_mac_select(lan966x, mac, vid);
 
        /* Issue a write command */
@@ -89,7 +89,19 @@ static int __lan966x_mac_learn(struct lan966x *lan966x, int pgid,
               ANA_MACACCESS_MAC_TABLE_CMD_SET(MACACCESS_CMD_LEARN),
               lan966x, ANA_MACACCESS);
 
-       ret = lan966x_mac_wait_for_completion(lan966x);
+       return lan966x_mac_wait_for_completion(lan966x);
+}
+
+static int __lan966x_mac_learn(struct lan966x *lan966x, int pgid,
+                              bool cpu_copy,
+                              const unsigned char mac[ETH_ALEN],
+                              unsigned int vid,
+                              enum macaccess_entry_type type)
+{
+       int ret;
+
+       spin_lock(&lan966x->mac_lock);
+       ret = __lan966x_mac_learn_locked(lan966x, pgid, cpu_copy, mac, vid, type);
        spin_unlock(&lan966x->mac_lock);
 
        return ret;
@@ -119,6 +131,16 @@ int lan966x_mac_learn(struct lan966x *lan966x, int port,
        return __lan966x_mac_learn(lan966x, port, false, mac, vid, type);
 }
 
+static int lan966x_mac_learn_locked(struct lan966x *lan966x, int port,
+                                   const unsigned char mac[ETH_ALEN],
+                                   unsigned int vid,
+                                   enum macaccess_entry_type type)
+{
+       WARN_ON(type != ENTRYTYPE_NORMAL && type != ENTRYTYPE_LOCKED);
+
+       return __lan966x_mac_learn_locked(lan966x, port, false, mac, vid, type);
+}
+
 static int lan966x_mac_forget_locked(struct lan966x *lan966x,
                                     const unsigned char mac[ETH_ALEN],
                                     unsigned int vid,
@@ -178,8 +200,9 @@ void lan966x_mac_init(struct lan966x *lan966x)
        INIT_LIST_HEAD(&lan966x->mac_entries);
 }
 
-static struct lan966x_mac_entry *lan966x_mac_alloc_entry(const unsigned char *mac,
-                                                        u16 vid, u16 port_index)
+static struct lan966x_mac_entry *lan966x_mac_alloc_entry(struct lan966x_port *port,
+                                                        const unsigned char *mac,
+                                                        u16 vid)
 {
        struct lan966x_mac_entry *mac_entry;
 
@@ -189,8 +212,9 @@ static struct lan966x_mac_entry *lan966x_mac_alloc_entry(const unsigned char *ma
 
        memcpy(mac_entry->mac, mac, ETH_ALEN);
        mac_entry->vid = vid;
-       mac_entry->port_index = port_index;
+       mac_entry->port_index = port->chip_port;
        mac_entry->row = LAN966X_MAC_INVALID_ROW;
+       mac_entry->lag = port->bond ? true : false;
        return mac_entry;
 }
 
@@ -269,7 +293,7 @@ int lan966x_mac_add_entry(struct lan966x *lan966x, struct lan966x_port *port,
                goto mac_learn;
        }
 
-       mac_entry = lan966x_mac_alloc_entry(addr, vid, port->chip_port);
+       mac_entry = lan966x_mac_alloc_entry(port, addr, vid);
        if (!mac_entry) {
                spin_unlock(&lan966x->mac_lock);
                return -ENOMEM;
@@ -278,7 +302,8 @@ int lan966x_mac_add_entry(struct lan966x *lan966x, struct lan966x_port *port,
        list_add_tail(&mac_entry->list, &lan966x->mac_entries);
        spin_unlock(&lan966x->mac_lock);
 
-       lan966x_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, addr, vid, port->dev);
+       lan966x_fdb_call_notifiers(SWITCHDEV_FDB_OFFLOADED, addr, vid,
+                                  port->bond ?: port->dev);
 
 mac_learn:
        lan966x_mac_learn(lan966x, port->chip_port, addr, vid, ENTRYTYPE_LOCKED);
@@ -309,6 +334,50 @@ int lan966x_mac_del_entry(struct lan966x *lan966x, const unsigned char *addr,
        return 0;
 }
 
+void lan966x_mac_lag_replace_port_entry(struct lan966x *lan966x,
+                                       struct lan966x_port *src,
+                                       struct lan966x_port *dst)
+{
+       struct lan966x_mac_entry *mac_entry;
+
+       spin_lock(&lan966x->mac_lock);
+       list_for_each_entry(mac_entry, &lan966x->mac_entries, list) {
+               if (mac_entry->port_index == src->chip_port &&
+                   mac_entry->lag) {
+                       lan966x_mac_forget_locked(lan966x, mac_entry->mac,
+                                                 mac_entry->vid,
+                                                 ENTRYTYPE_LOCKED);
+
+                       lan966x_mac_learn_locked(lan966x, dst->chip_port,
+                                                mac_entry->mac, mac_entry->vid,
+                                                ENTRYTYPE_LOCKED);
+                       mac_entry->port_index = dst->chip_port;
+               }
+       }
+       spin_unlock(&lan966x->mac_lock);
+}
+
+void lan966x_mac_lag_remove_port_entry(struct lan966x *lan966x,
+                                      struct lan966x_port *src)
+{
+       struct lan966x_mac_entry *mac_entry, *tmp;
+
+       spin_lock(&lan966x->mac_lock);
+       list_for_each_entry_safe(mac_entry, tmp, &lan966x->mac_entries,
+                                list) {
+               if (mac_entry->port_index == src->chip_port &&
+                   mac_entry->lag) {
+                       lan966x_mac_forget_locked(lan966x, mac_entry->mac,
+                                                 mac_entry->vid,
+                                                 ENTRYTYPE_LOCKED);
+
+                       list_del(&mac_entry->list);
+                       kfree(mac_entry);
+               }
+       }
+       spin_unlock(&lan966x->mac_lock);
+}
+
 void lan966x_mac_purge_entries(struct lan966x *lan966x)
 {
        struct lan966x_mac_entry *mac_entry, *tmp;
@@ -354,6 +423,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
        struct lan966x_mac_entry *mac_entry, *tmp;
        unsigned char mac[ETH_ALEN] __aligned(2);
        struct list_head mac_deleted_entries;
+       struct lan966x_port *port;
        u32 dest_idx;
        u32 column;
        u16 vid;
@@ -406,9 +476,10 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
                /* Notify the bridge that the entry doesn't exist
                 * anymore in the HW
                 */
+               port = lan966x->ports[mac_entry->port_index];
                lan966x_mac_notifiers(SWITCHDEV_FDB_DEL_TO_BRIDGE,
                                      mac_entry->mac, mac_entry->vid,
-                                     lan966x->ports[mac_entry->port_index]->dev);
+                                     port->bond ?: port->dev);
                list_del(&mac_entry->list);
                kfree(mac_entry);
        }
@@ -440,7 +511,8 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
                        continue;
                }
 
-               mac_entry = lan966x_mac_alloc_entry(mac, vid, dest_idx);
+               port = lan966x->ports[dest_idx];
+               mac_entry = lan966x_mac_alloc_entry(port, mac, vid);
                if (!mac_entry) {
                        spin_unlock(&lan966x->mac_lock);
                        return;
@@ -451,7 +523,7 @@ static void lan966x_mac_irq_process(struct lan966x *lan966x, u32 row,
                spin_unlock(&lan966x->mac_lock);
 
                lan966x_mac_notifiers(SWITCHDEV_FDB_ADD_TO_BRIDGE,
-                                     mac, vid, lan966x->ports[dest_idx]->dev);
+                                     mac, vid, port->bond ?: port->dev);
        }
 }
 
index d928b75..e2c77f9 100644 (file)
@@ -778,6 +778,8 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
                  port->phylink_config.supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_QSGMII,
                  port->phylink_config.supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_QUSGMII,
+                 port->phylink_config.supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_1000BASEX,
                  port->phylink_config.supported_interfaces);
        __set_bit(PHY_INTERFACE_MODE_2500BASEX,
@@ -969,7 +971,8 @@ static int lan966x_reset_switch(struct lan966x *lan966x)
        int val = 0;
        int ret;
 
-       switch_reset = devm_reset_control_get_shared(lan966x->dev, "switch");
+       switch_reset = devm_reset_control_get_optional_shared(lan966x->dev,
+                                                             "switch");
        if (IS_ERR(switch_reset))
                return dev_err_probe(lan966x->dev, PTR_ERR(switch_reset),
                                     "Could not obtain switch reset");
index 2787055..6135d31 100644 (file)
@@ -292,11 +292,17 @@ struct lan966x_port {
        u8 ptp_cmd;
        u16 ts_id;
        struct sk_buff_head tx_skbs;
+
+       struct net_device *bond;
+       bool lag_tx_active;
+       enum netdev_lag_hash hash_type;
 };
 
 extern const struct phylink_mac_ops lan966x_phylink_mac_ops;
 extern const struct phylink_pcs_ops lan966x_phylink_pcs_ops;
 extern const struct ethtool_ops lan966x_ethtool_ops;
+extern struct notifier_block lan966x_switchdev_nb __read_mostly;
+extern struct notifier_block lan966x_switchdev_blocking_nb __read_mostly;
 
 bool lan966x_netdevice_check(const struct net_device *dev);
 
@@ -345,6 +351,11 @@ int lan966x_mac_add_entry(struct lan966x *lan966x,
                          struct lan966x_port *port,
                          const unsigned char *addr,
                          u16 vid);
+void lan966x_mac_lag_replace_port_entry(struct lan966x *lan966x,
+                                       struct lan966x_port *src,
+                                       struct lan966x_port *dst);
+void lan966x_mac_lag_remove_port_entry(struct lan966x *lan966x,
+                                      struct lan966x_port *src);
 void lan966x_mac_purge_entries(struct lan966x *lan966x);
 irqreturn_t lan966x_mac_irq_handler(struct lan966x *lan966x);
 
@@ -369,6 +380,7 @@ void lan966x_fdb_write_entries(struct lan966x *lan966x, u16 vid);
 void lan966x_fdb_erase_entries(struct lan966x *lan966x, u16 vid);
 int lan966x_fdb_init(struct lan966x *lan966x);
 void lan966x_fdb_deinit(struct lan966x *lan966x);
+void lan966x_fdb_flush_workqueue(struct lan966x *lan966x);
 int lan966x_handle_fdb(struct net_device *dev,
                       struct net_device *orig_dev,
                       unsigned long event, const void *ctx,
@@ -406,6 +418,33 @@ int lan966x_fdma_init(struct lan966x *lan966x);
 void lan966x_fdma_deinit(struct lan966x *lan966x);
 irqreturn_t lan966x_fdma_irq_handler(int irq, void *args);
 
+int lan966x_lag_port_join(struct lan966x_port *port,
+                         struct net_device *brport_dev,
+                         struct net_device *bond,
+                         struct netlink_ext_ack *extack);
+void lan966x_lag_port_leave(struct lan966x_port *port, struct net_device *bond);
+int lan966x_lag_port_prechangeupper(struct net_device *dev,
+                                   struct netdev_notifier_changeupper_info *info);
+int lan966x_lag_port_changelowerstate(struct net_device *dev,
+                                     struct netdev_notifier_changelowerstate_info *info);
+int lan966x_lag_netdev_prechangeupper(struct net_device *dev,
+                                     struct netdev_notifier_changeupper_info *info);
+int lan966x_lag_netdev_changeupper(struct net_device *dev,
+                                  struct netdev_notifier_changeupper_info *info);
+bool lan966x_lag_first_port(struct net_device *lag, struct net_device *dev);
+u32 lan966x_lag_get_mask(struct lan966x *lan966x, struct net_device *bond);
+
+int lan966x_port_changeupper(struct net_device *dev,
+                            struct net_device *brport_dev,
+                            struct netdev_notifier_changeupper_info *info);
+int lan966x_port_prechangeupper(struct net_device *dev,
+                               struct net_device *brport_dev,
+                               struct netdev_notifier_changeupper_info *info);
+void lan966x_port_stp_state_set(struct lan966x_port *port, u8 state);
+void lan966x_port_ageing_set(struct lan966x_port *port,
+                            unsigned long ageing_clock_t);
+void lan966x_update_fwd_mask(struct lan966x *lan966x);
+
 static inline void __iomem *lan_addr(void __iomem *base[],
                                     int id, int tinst, int tcnt,
                                     int gbase, int ginst,
index 38a7e95..87f3d3a 100644 (file)
@@ -28,11 +28,12 @@ static int lan966x_phylink_mac_prepare(struct phylink_config *config,
                                       phy_interface_t iface)
 {
        struct lan966x_port *port = netdev_priv(to_net_dev(config->dev));
+       phy_interface_t serdes_mode = iface;
        int err;
 
        if (port->serdes) {
                err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET,
-                                      iface);
+                                      serdes_mode);
                if (err) {
                        netdev_err(to_net_dev(config->dev),
                                   "Could not set mode of SerDes\n");
index f141644..bbf42fc 100644 (file)
@@ -168,7 +168,7 @@ static void lan966x_port_link_up(struct lan966x_port *port)
        /* Also the GIGA_MODE_ENA(1) needs to be set regardless of the
         * port speed for QSGMII ports.
         */
-       if (config->portmode == PHY_INTERFACE_MODE_QSGMII)
+       if (phy_interface_num_ports(config->portmode) == 4)
                mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);
 
        lan_wr(config->duplex | mode,
@@ -331,10 +331,14 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
        struct lan966x *lan966x = port->lan966x;
        bool inband_aneg = false;
        bool outband;
+       bool full_preamble = false;
+
+       if (config->portmode == PHY_INTERFACE_MODE_QUSGMII)
+               full_preamble = true;
 
        if (config->inband) {
                if (config->portmode == PHY_INTERFACE_MODE_SGMII ||
-                   config->portmode == PHY_INTERFACE_MODE_QSGMII)
+                   phy_interface_num_ports(config->portmode) == 4)
                        inband_aneg = true; /* Cisco-SGMII in-band-aneg */
                else if (config->portmode == PHY_INTERFACE_MODE_1000BASEX &&
                         config->autoneg)
@@ -345,9 +349,15 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
                outband = true;
        }
 
-       /* Disable or enable inband */
-       lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband),
-               DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA,
+       /* Disable or enable inband.
+        * For QUSGMII, we rely on the preamble to transmit data such as
+        * timestamps, therefore force full preamble transmission, and prevent
+        * premable shortening
+        */
+       lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband) |
+               DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_SET(full_preamble),
+               DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA |
+               DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA,
                lan966x, DEV_PCS1G_MODE_CFG(port->chip_port));
 
        /* Enable PCS */
@@ -396,7 +406,7 @@ void lan966x_port_init(struct lan966x_port *port)
        if (lan966x->fdma)
                lan966x_fdma_netdev_init(lan966x, port->dev);
 
-       if (config->portmode != PHY_INTERFACE_MODE_QSGMII)
+       if (phy_interface_num_ports(config->portmode) != 4)
                return;
 
        lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(0) |
index 8265ad8..f2d83fc 100644 (file)
@@ -363,6 +363,51 @@ enum lan966x_target {
 #define ANA_PFC_CFG_FC_LINK_SPEED_GET(x)\
        FIELD_GET(ANA_PFC_CFG_FC_LINK_SPEED, x)
 
+/*      ANA:COMMON:AGGR_CFG */
+#define ANA_AGGR_CFG              __REG(TARGET_ANA, 0, 1, 31232, 0, 1, 552, 0, 0, 1, 4)
+
+#define ANA_AGGR_CFG_AC_RND_ENA                  BIT(6)
+#define ANA_AGGR_CFG_AC_RND_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_RND_ENA, x)
+#define ANA_AGGR_CFG_AC_RND_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_RND_ENA, x)
+
+#define ANA_AGGR_CFG_AC_DMAC_ENA                 BIT(5)
+#define ANA_AGGR_CFG_AC_DMAC_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_DMAC_ENA, x)
+#define ANA_AGGR_CFG_AC_DMAC_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_DMAC_ENA, x)
+
+#define ANA_AGGR_CFG_AC_SMAC_ENA                 BIT(4)
+#define ANA_AGGR_CFG_AC_SMAC_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_SMAC_ENA, x)
+#define ANA_AGGR_CFG_AC_SMAC_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_SMAC_ENA, x)
+
+#define ANA_AGGR_CFG_AC_IP6_FLOW_LBL_ENA         BIT(3)
+#define ANA_AGGR_CFG_AC_IP6_FLOW_LBL_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_IP6_FLOW_LBL_ENA, x)
+#define ANA_AGGR_CFG_AC_IP6_FLOW_LBL_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_IP6_FLOW_LBL_ENA, x)
+
+#define ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA           BIT(2)
+#define ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA, x)
+#define ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_IP6_TCPUDP_ENA, x)
+
+#define ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA           BIT(1)
+#define ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA, x)
+#define ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_IP4_SIPDIP_ENA, x)
+
+#define ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA           BIT(0)
+#define ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_SET(x)\
+       FIELD_PREP(ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA, x)
+#define ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA_GET(x)\
+       FIELD_GET(ANA_AGGR_CFG_AC_IP4_TCPUDP_ENA, x)
+
 /*      CHIP_TOP:CUPHY_CFG:CUPHY_PORT_CFG */
 #define CHIP_TOP_CUPHY_PORT_CFG(r) __REG(TARGET_CHIP_TOP, 0, 1, 16, 0, 1, 20, 8, r, 2, 4)
 
@@ -504,6 +549,12 @@ enum lan966x_target {
 #define DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_GET(x)\
        FIELD_GET(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA, x)
 
+#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA        BIT(1)
+#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_SET(x)\
+       FIELD_PREP(DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA, x)
+#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_GET(x)\
+       FIELD_GET(DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA, x)
+
 /*      DEV:PCS1G_CFG_STATUS:PCS1G_SD_CFG */
 #define DEV_PCS1G_SD_CFG(t)       __REG(TARGET_DEV, t, 8, 72, 0, 1, 68, 8, 0, 1, 4)
 
index df2bee6..1c88120 100644 (file)
@@ -6,8 +6,6 @@
 #include "lan966x_main.h"
 
 static struct notifier_block lan966x_netdevice_nb __read_mostly;
-static struct notifier_block lan966x_switchdev_nb __read_mostly;
-static struct notifier_block lan966x_switchdev_blocking_nb __read_mostly;
 
 static void lan966x_port_set_mcast_ip_flood(struct lan966x_port *port,
                                            u32 pgid_ip)
@@ -132,7 +130,7 @@ static int lan966x_port_pre_bridge_flags(struct lan966x_port *port,
        return 0;
 }
 
-static void lan966x_update_fwd_mask(struct lan966x *lan966x)
+void lan966x_update_fwd_mask(struct lan966x *lan966x)
 {
        int i;
 
@@ -140,9 +138,14 @@ static void lan966x_update_fwd_mask(struct lan966x *lan966x)
                struct lan966x_port *port = lan966x->ports[i];
                unsigned long mask = 0;
 
-               if (port && lan966x->bridge_fwd_mask & BIT(i))
+               if (port && lan966x->bridge_fwd_mask & BIT(i)) {
                        mask = lan966x->bridge_fwd_mask & ~BIT(i);
 
+                       if (port->bond)
+                               mask &= ~lan966x_lag_get_mask(lan966x,
+                                                             port->bond);
+               }
+
                mask |= BIT(CPU_PORT);
 
                lan_wr(ANA_PGID_PGID_SET(mask),
@@ -150,7 +153,7 @@ static void lan966x_update_fwd_mask(struct lan966x *lan966x)
        }
 }
 
-static void lan966x_port_stp_state_set(struct lan966x_port *port, u8 state)
+void lan966x_port_stp_state_set(struct lan966x_port *port, u8 state)
 {
        struct lan966x *lan966x = port->lan966x;
        bool learn_ena = false;
@@ -171,8 +174,8 @@ static void lan966x_port_stp_state_set(struct lan966x_port *port, u8 state)
        lan966x_update_fwd_mask(lan966x);
 }
 
-static void lan966x_port_ageing_set(struct lan966x_port *port,
-                                   unsigned long ageing_clock_t)
+void lan966x_port_ageing_set(struct lan966x_port *port,
+                            unsigned long ageing_clock_t)
 {
        unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock_t);
        u32 ageing_time = jiffies_to_msecs(ageing_jiffies) / 1000;
@@ -241,6 +244,7 @@ static int lan966x_port_attr_set(struct net_device *dev, const void *ctx,
 }
 
 static int lan966x_port_bridge_join(struct lan966x_port *port,
+                                   struct net_device *brport_dev,
                                    struct net_device *bridge,
                                    struct netlink_ext_ack *extack)
 {
@@ -258,7 +262,7 @@ static int lan966x_port_bridge_join(struct lan966x_port *port,
                }
        }
 
-       err = switchdev_bridge_port_offload(dev, dev, port,
+       err = switchdev_bridge_port_offload(brport_dev, dev, port,
                                            &lan966x_switchdev_nb,
                                            &lan966x_switchdev_blocking_nb,
                                            false, extack);
@@ -295,8 +299,9 @@ static void lan966x_port_bridge_leave(struct lan966x_port *port,
        lan966x_vlan_port_apply(port);
 }
 
-static int lan966x_port_changeupper(struct net_device *dev,
-                                   struct netdev_notifier_changeupper_info *info)
+int lan966x_port_changeupper(struct net_device *dev,
+                            struct net_device *brport_dev,
+                            struct netdev_notifier_changeupper_info *info)
 {
        struct lan966x_port *port = netdev_priv(dev);
        struct netlink_ext_ack *extack;
@@ -306,44 +311,68 @@ static int lan966x_port_changeupper(struct net_device *dev,
 
        if (netif_is_bridge_master(info->upper_dev)) {
                if (info->linking)
-                       err = lan966x_port_bridge_join(port, info->upper_dev,
+                       err = lan966x_port_bridge_join(port, brport_dev,
+                                                      info->upper_dev,
                                                       extack);
                else
                        lan966x_port_bridge_leave(port, info->upper_dev);
        }
 
+       if (netif_is_lag_master(info->upper_dev)) {
+               if (info->linking)
+                       err = lan966x_lag_port_join(port, info->upper_dev,
+                                                   info->upper_dev,
+                                                   extack);
+               else
+                       lan966x_lag_port_leave(port, info->upper_dev);
+       }
+
        return err;
 }
 
-static int lan966x_port_prechangeupper(struct net_device *dev,
-                                      struct netdev_notifier_changeupper_info *info)
+int lan966x_port_prechangeupper(struct net_device *dev,
+                               struct net_device *brport_dev,
+                               struct netdev_notifier_changeupper_info *info)
 {
        struct lan966x_port *port = netdev_priv(dev);
+       int err = NOTIFY_DONE;
 
-       if (netif_is_bridge_master(info->upper_dev) && !info->linking)
-               switchdev_bridge_port_unoffload(port->dev, port,
-                                               NULL, NULL);
+       if (netif_is_bridge_master(info->upper_dev) && !info->linking) {
+               switchdev_bridge_port_unoffload(port->dev, port, NULL, NULL);
+               lan966x_fdb_flush_workqueue(port->lan966x);
+       }
 
-       return NOTIFY_DONE;
+       if (netif_is_lag_master(info->upper_dev)) {
+               err = lan966x_lag_port_prechangeupper(dev, info);
+               if (err || info->linking)
+                       return err;
+
+               switchdev_bridge_port_unoffload(brport_dev, port, NULL, NULL);
+               lan966x_fdb_flush_workqueue(port->lan966x);
+       }
+
+       return err;
 }
 
-static int lan966x_foreign_bridging_check(struct net_device *bridge,
+static int lan966x_foreign_bridging_check(struct net_device *upper,
+                                         bool *has_foreign,
+                                         bool *seen_lan966x,
                                          struct netlink_ext_ack *extack)
 {
        struct lan966x *lan966x = NULL;
-       bool has_foreign = false;
        struct net_device *dev;
        struct list_head *iter;
 
-       if (!netif_is_bridge_master(bridge))
+       if (!netif_is_bridge_master(upper) &&
+           !netif_is_lag_master(upper))
                return 0;
 
-       netdev_for_each_lower_dev(bridge, dev, iter) {
+       netdev_for_each_lower_dev(upper, dev, iter) {
                if (lan966x_netdevice_check(dev)) {
                        struct lan966x_port *port = netdev_priv(dev);
 
                        if (lan966x) {
-                               /* Bridge already has at least one port of a
+                               /* Upper already has at least one port of a
                                 * lan966x switch inside it, check that it's
                                 * the same instance of the driver.
                                 */
@@ -354,15 +383,24 @@ static int lan966x_foreign_bridging_check(struct net_device *bridge,
                                }
                        } else {
                                /* This is the first lan966x port inside this
-                                * bridge
+                                * upper device
                                 */
                                lan966x = port->lan966x;
+                               *seen_lan966x = true;
                        }
+               } else if (netif_is_lag_master(dev)) {
+                       /* Allow to have bond interfaces that have only lan966x
+                        * devices
+                        */
+                       if (lan966x_foreign_bridging_check(dev, has_foreign,
+                                                          seen_lan966x,
+                                                          extack))
+                               return -EINVAL;
                } else {
-                       has_foreign = true;
+                       *has_foreign = true;
                }
 
-               if (lan966x && has_foreign) {
+               if (*seen_lan966x && *has_foreign) {
                        NL_SET_ERR_MSG_MOD(extack,
                                           "Bridging lan966x ports with foreign interfaces disallowed");
                        return -EINVAL;
@@ -375,7 +413,12 @@ static int lan966x_foreign_bridging_check(struct net_device *bridge,
 static int lan966x_bridge_check(struct net_device *dev,
                                struct netdev_notifier_changeupper_info *info)
 {
+       bool has_foreign = false;
+       bool seen_lan966x = false;
+
        return lan966x_foreign_bridging_check(info->upper_dev,
+                                             &has_foreign,
+                                             &seen_lan966x,
                                              info->info.extack);
 }
 
@@ -386,21 +429,44 @@ static int lan966x_netdevice_port_event(struct net_device *dev,
        int err = 0;
 
        if (!lan966x_netdevice_check(dev)) {
-               if (event == NETDEV_CHANGEUPPER)
-                       return lan966x_bridge_check(dev, ptr);
+               switch (event) {
+               case NETDEV_CHANGEUPPER:
+               case NETDEV_PRECHANGEUPPER:
+                       err = lan966x_bridge_check(dev, ptr);
+                       if (err)
+                               return err;
+
+                       if (netif_is_lag_master(dev)) {
+                               if (event == NETDEV_CHANGEUPPER)
+                                       err = lan966x_lag_netdev_changeupper(dev,
+                                                                            ptr);
+                               else
+                                       err = lan966x_lag_netdev_prechangeupper(dev,
+                                                                               ptr);
+
+                               return err;
+                       }
+                       break;
+               default:
+                       return 0;
+               }
+
                return 0;
        }
 
        switch (event) {
        case NETDEV_PRECHANGEUPPER:
-               err = lan966x_port_prechangeupper(dev, ptr);
+               err = lan966x_port_prechangeupper(dev, dev, ptr);
                break;
        case NETDEV_CHANGEUPPER:
                err = lan966x_bridge_check(dev, ptr);
                if (err)
                        return err;
 
-               err = lan966x_port_changeupper(dev, ptr);
+               err = lan966x_port_changeupper(dev, dev, ptr);
+               break;
+       case NETDEV_CHANGELOWERSTATE:
+               err = lan966x_lag_port_changelowerstate(dev, ptr);
                break;
        }
 
@@ -418,19 +484,23 @@ static int lan966x_netdevice_event(struct notifier_block *nb,
        return notifier_from_errno(ret);
 }
 
-/* We don't offload uppers such as LAG as bridge ports, so every device except
- * the bridge itself is foreign.
- */
 static bool lan966x_foreign_dev_check(const struct net_device *dev,
                                      const struct net_device *foreign_dev)
 {
        struct lan966x_port *port = netdev_priv(dev);
        struct lan966x *lan966x = port->lan966x;
+       int i;
 
        if (netif_is_bridge_master(foreign_dev))
                if (lan966x->bridge == foreign_dev)
                        return false;
 
+       if (netif_is_lag_master(foreign_dev))
+               for (i = 0; i < lan966x->num_phys_ports; ++i)
+                       if (lan966x->ports[i] &&
+                           lan966x->ports[i]->bond == foreign_dev)
+                               return false;
+
        return true;
 }
 
@@ -571,11 +641,11 @@ static struct notifier_block lan966x_netdevice_nb __read_mostly = {
        .notifier_call = lan966x_netdevice_event,
 };
 
-static struct notifier_block lan966x_switchdev_nb __read_mostly = {
+struct notifier_block lan966x_switchdev_nb __read_mostly = {
        .notifier_call = lan966x_switchdev_event,
 };
 
-static struct notifier_block lan966x_switchdev_blocking_nb __read_mostly = {
+struct notifier_block lan966x_switchdev_blocking_nb __read_mostly = {
        .notifier_call = lan966x_switchdev_blocking_event,
 };
 
index 01be7bd..bbe4173 100644 (file)
@@ -277,6 +277,7 @@ static int sparx5_create_port(struct sparx5 *sparx5,
        spx5_port->custom_etype = 0x8880; /* Vitesse */
        spx5_port->phylink_pcs.poll = true;
        spx5_port->phylink_pcs.ops = &sparx5_phylink_pcs_ops;
+       spx5_port->is_mrouter = false;
        sparx5->ports[config->portno] = spx5_port;
 
        err = sparx5_port_init(sparx5, spx5_port, &config->conf);
@@ -661,6 +662,9 @@ static int sparx5_start(struct sparx5 *sparx5)
        queue_delayed_work(sparx5->mact_queue, &sparx5->mact_work,
                           SPX5_MACT_PULL_DELAY);
 
+       mutex_init(&sparx5->mdb_lock);
+       INIT_LIST_HEAD(&sparx5->mdb_entries);
+
        err = sparx5_register_netdevs(sparx5);
        if (err)
                return err;
index b197129..9b4395b 100644 (file)
@@ -190,6 +190,7 @@ struct sparx5_port {
        u8 ptp_cmd;
        u16 ts_id;
        struct sk_buff_head tx_skbs;
+       bool is_mrouter;
 };
 
 enum sparx5_core_clockfreq {
@@ -215,6 +216,15 @@ struct sparx5_skb_cb {
        unsigned long jiffies;
 };
 
+struct sparx5_mdb_entry {
+       struct list_head list;
+       DECLARE_BITMAP(port_mask, SPX5_PORTS);
+       unsigned char addr[ETH_ALEN];
+       bool cpu_copy;
+       u16 vid;
+       u16 pgid_idx;
+};
+
 #define SPARX5_PTP_TIMEOUT             msecs_to_jiffies(10)
 #define SPARX5_SKB_CB(skb) \
        ((struct sparx5_skb_cb *)((skb)->cb))
@@ -256,6 +266,10 @@ struct sparx5 {
        struct list_head mact_entries;
        /* mac table list (mact_entries) mutex */
        struct mutex mact_lock;
+       /* SW MDB table */
+       struct list_head mdb_entries;
+       /* mdb list mutex */
+       struct mutex mdb_lock;
        struct delayed_work mact_work;
        struct workqueue_struct *mact_queue;
        /* Board specifics */
@@ -325,6 +339,7 @@ void sparx5_mact_init(struct sparx5 *sparx5);
 
 /* sparx5_vlan.c */
 void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable);
+void sparx5_pgid_clear(struct sparx5 *spx5, int pgid);
 void sparx5_pgid_read_mask(struct sparx5 *sparx5, int pgid, u32 portmask[3]);
 void sparx5_update_fwd(struct sparx5 *sparx5);
 void sparx5_vlan_init(struct sparx5 *sparx5);
index 304f84a..21844be 100644 (file)
@@ -113,6 +113,8 @@ static void sparx5_xtr_grp(struct sparx5 *sparx5, u8 grp, bool byte_swap)
                        /* This assumes STATUS_WORD_POS == 1, Status
                         * just after last data
                         */
+                       if (!byte_swap)
+                               val = ntohl((__force __be32)val);
                        byte_cnt -= (4 - XTR_VALID_BYTES(val));
                        eof_flag = true;
                        break;
index ec07f7d..4af85d1 100644 (file)
@@ -29,14 +29,23 @@ static int sparx5_port_attr_pre_bridge_flags(struct sparx5_port *port,
        return 0;
 }
 
+static void sparx5_port_update_mcast_ip_flood(struct sparx5_port *port, bool flood_flag)
+{
+       bool should_flood = flood_flag || port->is_mrouter;
+       int pgid;
+
+       for (pgid = PGID_IPV4_MC_DATA; pgid <= PGID_IPV6_MC_CTRL; pgid++)
+               sparx5_pgid_update_mask(port, pgid, should_flood);
+}
+
 static void sparx5_port_attr_bridge_flags(struct sparx5_port *port,
                                          struct switchdev_brport_flags flags)
 {
-       int pgid;
+       if (flags.mask & BR_MCAST_FLOOD) {
+               sparx5_pgid_update_mask(port, PGID_MC_FLOOD, !!(flags.val & BR_MCAST_FLOOD));
+               sparx5_port_update_mcast_ip_flood(port, !!(flags.val & BR_MCAST_FLOOD));
+       }
 
-       if (flags.mask & BR_MCAST_FLOOD)
-               for (pgid = PGID_MC_FLOOD; pgid <= PGID_IPV6_MC_CTRL; pgid++)
-                       sparx5_pgid_update_mask(port, pgid, !!(flags.val & BR_MCAST_FLOOD));
        if (flags.mask & BR_FLOOD)
                sparx5_pgid_update_mask(port, PGID_UC_FLOOD, !!(flags.val & BR_FLOOD));
        if (flags.mask & BR_BCAST_FLOOD)
@@ -82,6 +91,37 @@ static void sparx5_port_attr_ageing_set(struct sparx5_port *port,
        sparx5_set_ageing(port->sparx5, ageing_time);
 }
 
+static void sparx5_port_attr_mrouter_set(struct sparx5_port *port,
+                                        struct net_device *orig_dev,
+                                        bool enable)
+{
+       struct sparx5 *sparx5 = port->sparx5;
+       struct sparx5_mdb_entry *e;
+       bool flood_flag;
+
+       if ((enable && port->is_mrouter) || (!enable && !port->is_mrouter))
+               return;
+
+       /* Add/del mrouter port on all active mdb entries in HW.
+        * Don't change entry port mask, since that represents
+        * ports that actually joined that group.
+        */
+       mutex_lock(&sparx5->mdb_lock);
+       list_for_each_entry(e, &sparx5->mdb_entries, list) {
+               if (!test_bit(port->portno, e->port_mask) &&
+                   ether_addr_is_ip_mcast(e->addr))
+                       sparx5_pgid_update_mask(port, e->pgid_idx, enable);
+       }
+       mutex_unlock(&sparx5->mdb_lock);
+
+       /* Enable/disable flooding depending on if port is mrouter port
+        * or if mcast flood is enabled.
+        */
+       port->is_mrouter = enable;
+       flood_flag = br_port_flag_is_set(port->ndev, BR_MCAST_FLOOD);
+       sparx5_port_update_mcast_ip_flood(port, flood_flag);
+}
+
 static int sparx5_port_attr_set(struct net_device *dev, const void *ctx,
                                const struct switchdev_attr *attr,
                                struct netlink_ext_ack *extack)
@@ -110,6 +150,11 @@ static int sparx5_port_attr_set(struct net_device *dev, const void *ctx,
                port->vlan_aware = attr->u.vlan_filtering;
                sparx5_vlan_port_apply(port->sparx5, port);
                break;
+       case SWITCHDEV_ATTR_ID_PORT_MROUTER:
+               sparx5_port_attr_mrouter_set(port,
+                                            attr->orig_dev,
+                                            attr->u.mrouter);
+               break;
        default:
                return -EOPNOTSUPP;
        }
@@ -386,16 +431,95 @@ static int sparx5_handle_port_vlan_add(struct net_device *dev,
                                  v->flags & BRIDGE_VLAN_INFO_UNTAGGED);
 }
 
+static int sparx5_alloc_mdb_entry(struct sparx5 *sparx5,
+                                 const unsigned char *addr,
+                                 u16 vid,
+                                 struct sparx5_mdb_entry **entry_out)
+{
+       struct sparx5_mdb_entry *entry;
+       u16 pgid_idx;
+       int err;
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry)
+               return -ENOMEM;
+
+       err = sparx5_pgid_alloc_mcast(sparx5, &pgid_idx);
+       if (err) {
+               kfree(entry);
+               return err;
+       }
+
+       memcpy(entry->addr, addr, ETH_ALEN);
+       entry->vid = vid;
+       entry->pgid_idx = pgid_idx;
+
+       mutex_lock(&sparx5->mdb_lock);
+       list_add_tail(&entry->list, &sparx5->mdb_entries);
+       mutex_unlock(&sparx5->mdb_lock);
+
+       *entry_out = entry;
+       return 0;
+}
+
+static void sparx5_free_mdb_entry(struct sparx5 *sparx5,
+                                 const unsigned char *addr,
+                                 u16 vid)
+{
+       struct sparx5_mdb_entry *entry, *tmp;
+
+       mutex_lock(&sparx5->mdb_lock);
+       list_for_each_entry_safe(entry, tmp, &sparx5->mdb_entries, list) {
+               if ((vid == 0 || entry->vid == vid) &&
+                   ether_addr_equal(addr, entry->addr)) {
+                       list_del(&entry->list);
+
+                       sparx5_pgid_free(sparx5, entry->pgid_idx);
+                       kfree(entry);
+                       goto out;
+               }
+       }
+
+out:
+       mutex_unlock(&sparx5->mdb_lock);
+}
+
+static struct sparx5_mdb_entry *sparx5_mdb_get_entry(struct sparx5 *sparx5,
+                                                    const unsigned char *addr,
+                                                    u16 vid)
+{
+       struct sparx5_mdb_entry *e, *found = NULL;
+
+       mutex_lock(&sparx5->mdb_lock);
+       list_for_each_entry(e, &sparx5->mdb_entries, list) {
+               if (ether_addr_equal(e->addr, addr) && e->vid == vid) {
+                       found = e;
+                       goto out;
+               }
+       }
+
+out:
+       mutex_unlock(&sparx5->mdb_lock);
+       return found;
+}
+
+static void sparx5_cpu_copy_ena(struct sparx5 *spx5, u16 pgid, bool enable)
+{
+       spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(enable),
+                ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5,
+                ANA_AC_PGID_MISC_CFG(pgid));
+}
+
 static int sparx5_handle_port_mdb_add(struct net_device *dev,
                                      struct notifier_block *nb,
                                      const struct switchdev_obj_port_mdb *v)
 {
        struct sparx5_port *port = netdev_priv(dev);
        struct sparx5 *spx5 = port->sparx5;
-       u16 pgid_idx, vid;
-       u32 mact_entry;
-       bool is_host;
-       int res, err;
+       struct sparx5_mdb_entry *entry;
+       bool is_host, is_new;
+       int err, i;
+       u16 vid;
 
        if (!sparx5_netdevice_check(dev))
                return -EOPNOTSUPP;
@@ -410,66 +534,36 @@ static int sparx5_handle_port_mdb_add(struct net_device *dev,
        else
                vid = v->vid;
 
-       res = sparx5_mact_find(spx5, v->addr, vid, &mact_entry);
-
-       if (res == 0) {
-               pgid_idx = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(mact_entry);
-
-               /* MC_IDX starts after the port masks in the PGID table */
-               pgid_idx += SPX5_PORTS;
-
-               if (is_host)
-                       spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1),
-                                ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5,
-                                ANA_AC_PGID_MISC_CFG(pgid_idx));
-               else
-                       sparx5_pgid_update_mask(port, pgid_idx, true);
-
-       } else {
-               err = sparx5_pgid_alloc_mcast(spx5, &pgid_idx);
-               if (err) {
-                       netdev_warn(dev, "multicast pgid table full\n");
+       is_new = false;
+       entry = sparx5_mdb_get_entry(spx5, v->addr, vid);
+       if (!entry) {
+               err = sparx5_alloc_mdb_entry(spx5, v->addr, vid, &entry);
+               is_new = true;
+               if (err)
                        return err;
-               }
-
-               if (is_host)
-                       spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(1),
-                                ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5,
-                                ANA_AC_PGID_MISC_CFG(pgid_idx));
-               else
-                       sparx5_pgid_update_mask(port, pgid_idx, true);
-
-               err = sparx5_mact_learn(spx5, pgid_idx, v->addr, vid);
-
-               if (err) {
-                       netdev_warn(dev, "could not learn mac address %pM\n", v->addr);
-                       sparx5_pgid_free(spx5, pgid_idx);
-                       sparx5_pgid_update_mask(port, pgid_idx, false);
-                       return err;
-               }
        }
 
-       return 0;
-}
+       mutex_lock(&spx5->mdb_lock);
+
+       /* Add any mrouter ports to the new entry */
+       if (is_new && ether_addr_is_ip_mcast(v->addr))
+               for (i = 0; i < SPX5_PORTS; i++)
+                       if (spx5->ports[i] && spx5->ports[i]->is_mrouter)
+                               sparx5_pgid_update_mask(spx5->ports[i],
+                                                       entry->pgid_idx,
+                                                       true);
+
+       if (is_host && !entry->cpu_copy) {
+               sparx5_cpu_copy_ena(spx5, entry->pgid_idx, true);
+               entry->cpu_copy = true;
+       } else if (!is_host) {
+               sparx5_pgid_update_mask(port, entry->pgid_idx, true);
+               set_bit(port->portno, entry->port_mask);
+       }
+       mutex_unlock(&spx5->mdb_lock);
 
-static int sparx5_mdb_del_entry(struct net_device *dev,
-                               struct sparx5 *spx5,
-                               const unsigned char mac[ETH_ALEN],
-                               const u16 vid,
-                               u16 pgid_idx)
-{
-       int err;
+       sparx5_mact_learn(spx5, entry->pgid_idx, entry->addr, entry->vid);
 
-       err = sparx5_mact_forget(spx5, mac, vid);
-       if (err) {
-               netdev_warn(dev, "could not forget mac address %pM", mac);
-               return err;
-       }
-       err = sparx5_pgid_free(spx5, pgid_idx);
-       if (err) {
-               netdev_err(dev, "attempted to free already freed pgid\n");
-               return err;
-       }
        return 0;
 }
 
@@ -479,42 +573,45 @@ static int sparx5_handle_port_mdb_del(struct net_device *dev,
 {
        struct sparx5_port *port = netdev_priv(dev);
        struct sparx5 *spx5 = port->sparx5;
-       u16 pgid_idx, vid;
-       u32 mact_entry, res, pgid_entry[3], misc_cfg;
-       bool host_ena;
+       struct sparx5_mdb_entry *entry;
+       bool is_host;
+       u16 vid;
 
        if (!sparx5_netdevice_check(dev))
                return -EOPNOTSUPP;
 
+       is_host = netif_is_bridge_master(v->obj.orig_dev);
+
        if (!br_vlan_enabled(spx5->hw_bridge_dev))
                vid = 1;
        else
                vid = v->vid;
 
-       res = sparx5_mact_find(spx5, v->addr, vid, &mact_entry);
-
-       if (res == 0) {
-               pgid_idx = LRN_MAC_ACCESS_CFG_2_MAC_ENTRY_ADDR_GET(mact_entry);
-
-               /* MC_IDX starts after the port masks in the PGID table */
-               pgid_idx += SPX5_PORTS;
-
-               if (netif_is_bridge_master(v->obj.orig_dev))
-                       spx5_rmw(ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_SET(0),
-                                ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA, spx5,
-                                ANA_AC_PGID_MISC_CFG(pgid_idx));
-               else
-                       sparx5_pgid_update_mask(port, pgid_idx, false);
+       entry = sparx5_mdb_get_entry(spx5, v->addr, vid);
+       if (!entry)
+               return 0;
 
-               misc_cfg = spx5_rd(spx5, ANA_AC_PGID_MISC_CFG(pgid_idx));
-               host_ena = ANA_AC_PGID_MISC_CFG_PGID_CPU_COPY_ENA_GET(misc_cfg);
+       mutex_lock(&spx5->mdb_lock);
+       if (is_host && entry->cpu_copy) {
+               sparx5_cpu_copy_ena(spx5, entry->pgid_idx, false);
+               entry->cpu_copy = false;
+       } else if (!is_host) {
+               clear_bit(port->portno, entry->port_mask);
 
-               sparx5_pgid_read_mask(spx5, pgid_idx, pgid_entry);
-               if (bitmap_empty((unsigned long *)pgid_entry, SPX5_PORTS) && !host_ena)
-                       /* No ports or CPU are in MC group. Remove entry */
-                       return sparx5_mdb_del_entry(dev, spx5, v->addr, vid, pgid_idx);
+               /* Port not mrouter port or addr is L2 mcast, remove port from mask. */
+               if (!port->is_mrouter || !ether_addr_is_ip_mcast(v->addr))
+                       sparx5_pgid_update_mask(port, entry->pgid_idx, false);
+       }
+       mutex_unlock(&spx5->mdb_lock);
+
+       if (bitmap_empty(entry->port_mask, SPX5_PORTS) && !entry->cpu_copy) {
+                /* Clear pgid in case mrouter ports exists
+                 * that are not part of the group.
+                 */
+               sparx5_pgid_clear(spx5, entry->pgid_idx);
+               sparx5_mact_forget(spx5, entry->addr, entry->vid);
+               sparx5_free_mdb_entry(spx5, entry->addr, entry->vid);
        }
-
        return 0;
 }
 
index 37e4ac9..34f954b 100644 (file)
@@ -138,6 +138,13 @@ void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable)
        }
 }
 
+void sparx5_pgid_clear(struct sparx5 *spx5, int pgid)
+{
+       spx5_wr(0, spx5, ANA_AC_PGID_CFG(pgid));
+       spx5_wr(0, spx5, ANA_AC_PGID_CFG1(pgid));
+       spx5_wr(0, spx5, ANA_AC_PGID_CFG2(pgid));
+}
+
 void sparx5_pgid_read_mask(struct sparx5 *spx5, int pgid, u32 portmask[3])
 {
        portmask[0] = spx5_rd(spx5, ANA_AC_PGID_CFG(pgid));
index 306026e..dddaffd 100644 (file)
@@ -2064,6 +2064,16 @@ static int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond)
        return __ffs(bond_mask);
 }
 
+/* Returns the mask of user ports assigned to this DSA tag_8021q CPU port.
+ * Note that when CPU ports are in a LAG, the user ports are assigned to the
+ * 'primary' CPU port, the one whose physical port number gives the logical
+ * port number of the LAG.
+ *
+ * We leave PGID_SRC poorly configured for the 'secondary' CPU port in the LAG
+ * (to which no user port is assigned), but it appears that forwarding from
+ * this secondary CPU port looks at the PGID_SRC associated with the logical
+ * port ID that it's assigned to, which *is* configured properly.
+ */
 static u32 ocelot_dsa_8021q_cpu_assigned_ports(struct ocelot *ocelot,
                                               struct ocelot_port *cpu)
 {
@@ -2080,9 +2090,15 @@ static u32 ocelot_dsa_8021q_cpu_assigned_ports(struct ocelot *ocelot,
                        mask |= BIT(port);
        }
 
+       if (cpu->bond)
+               mask &= ~ocelot_get_bond_mask(ocelot, cpu->bond);
+
        return mask;
 }
 
+/* Returns the DSA tag_8021q CPU port that the given port is assigned to,
+ * or the bit mask of CPU ports if said CPU port is in a LAG.
+ */
 u32 ocelot_port_assigned_dsa_8021q_cpu_mask(struct ocelot *ocelot, int port)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
@@ -2091,6 +2107,9 @@ u32 ocelot_port_assigned_dsa_8021q_cpu_mask(struct ocelot *ocelot, int port)
        if (!cpu_port)
                return 0;
 
+       if (cpu_port->bond)
+               return ocelot_get_bond_mask(ocelot, cpu_port->bond);
+
        return BIT(cpu_port->index);
 }
 EXPORT_SYMBOL_GPL(ocelot_port_assigned_dsa_8021q_cpu_mask);
@@ -2214,61 +2233,61 @@ static void ocelot_update_pgid_cpu(struct ocelot *ocelot)
        ocelot_write_rix(ocelot, pgid_cpu, ANA_PGID_PGID, PGID_CPU);
 }
 
-void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port,
-                                     int cpu)
+void ocelot_port_setup_dsa_8021q_cpu(struct ocelot *ocelot, int cpu)
 {
        struct ocelot_port *cpu_port = ocelot->ports[cpu];
        u16 vid;
 
        mutex_lock(&ocelot->fwd_domain_lock);
 
-       ocelot->ports[port]->dsa_8021q_cpu = cpu_port;
-
-       if (!cpu_port->is_dsa_8021q_cpu) {
-               cpu_port->is_dsa_8021q_cpu = true;
-
-               for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
-                       ocelot_vlan_member_add(ocelot, cpu, vid, true);
+       cpu_port->is_dsa_8021q_cpu = true;
 
-               ocelot_update_pgid_cpu(ocelot);
-       }
+       for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
+               ocelot_vlan_member_add(ocelot, cpu, vid, true);
 
-       ocelot_apply_bridge_fwd_mask(ocelot, true);
+       ocelot_update_pgid_cpu(ocelot);
 
        mutex_unlock(&ocelot->fwd_domain_lock);
 }
-EXPORT_SYMBOL_GPL(ocelot_port_assign_dsa_8021q_cpu);
+EXPORT_SYMBOL_GPL(ocelot_port_setup_dsa_8021q_cpu);
 
-void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port)
+void ocelot_port_teardown_dsa_8021q_cpu(struct ocelot *ocelot, int cpu)
 {
-       struct ocelot_port *cpu_port = ocelot->ports[port]->dsa_8021q_cpu;
-       bool keep = false;
+       struct ocelot_port *cpu_port = ocelot->ports[cpu];
        u16 vid;
-       int p;
 
        mutex_lock(&ocelot->fwd_domain_lock);
 
-       ocelot->ports[port]->dsa_8021q_cpu = NULL;
+       cpu_port->is_dsa_8021q_cpu = false;
 
-       for (p = 0; p < ocelot->num_phys_ports; p++) {
-               if (!ocelot->ports[p])
-                       continue;
+       for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
+               ocelot_vlan_member_del(ocelot, cpu_port->index, vid);
 
-               if (ocelot->ports[p]->dsa_8021q_cpu == cpu_port) {
-                       keep = true;
-                       break;
-               }
-       }
+       ocelot_update_pgid_cpu(ocelot);
 
-       if (!keep) {
-               cpu_port->is_dsa_8021q_cpu = false;
+       mutex_unlock(&ocelot->fwd_domain_lock);
+}
+EXPORT_SYMBOL_GPL(ocelot_port_teardown_dsa_8021q_cpu);
+
+void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port,
+                                     int cpu)
+{
+       struct ocelot_port *cpu_port = ocelot->ports[cpu];
 
-               for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
-                       ocelot_vlan_member_del(ocelot, cpu_port->index, vid);
+       mutex_lock(&ocelot->fwd_domain_lock);
 
-               ocelot_update_pgid_cpu(ocelot);
-       }
+       ocelot->ports[port]->dsa_8021q_cpu = cpu_port;
+       ocelot_apply_bridge_fwd_mask(ocelot, true);
+
+       mutex_unlock(&ocelot->fwd_domain_lock);
+}
+EXPORT_SYMBOL_GPL(ocelot_port_assign_dsa_8021q_cpu);
 
+void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port)
+{
+       mutex_lock(&ocelot->fwd_domain_lock);
+
+       ocelot->ports[port]->dsa_8021q_cpu = NULL;
        ocelot_apply_bridge_fwd_mask(ocelot, true);
 
        mutex_unlock(&ocelot->fwd_domain_lock);
index 971dde8..9063e2e 100644 (file)
@@ -1647,10 +1647,10 @@ myri10ge_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
 {
        struct myri10ge_priv *mgp = netdev_priv(netdev);
 
-       strlcpy(info->driver, "myri10ge", sizeof(info->driver));
-       strlcpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
-       strlcpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
-       strlcpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, "myri10ge", sizeof(info->driver));
+       strscpy(info->version, MYRI10GE_VERSION_STR, sizeof(info->version));
+       strscpy(info->fw_version, mgp->fw_version, sizeof(info->fw_version));
+       strscpy(info->bus_info, pci_name(mgp->pdev), sizeof(info->bus_info));
 }
 
 static int myri10ge_get_coalesce(struct net_device *netdev,
index 9aae7f1..518b664 100644 (file)
@@ -2564,9 +2564,9 @@ static void set_rx_mode(struct net_device *dev)
 static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct netdev_private *np = netdev_priv(dev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int get_regs_len(struct net_device *dev)
index 49ea130..9985868 100644 (file)
@@ -1351,9 +1351,9 @@ static int ns83820_set_link_ksettings(struct net_device *ndev,
 static void ns83820_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info)
 {
        struct ns83820 *dev = PRIV(ndev);
-       strlcpy(info->driver, "ns83820", sizeof(info->driver));
-       strlcpy(info->version, VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(dev->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, "ns83820", sizeof(info->driver));
+       strscpy(info->version, VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(dev->pci_dev), sizeof(info->bus_info));
 }
 
 static u32 ns83820_get_link(struct net_device *ndev)
index 30f955e..d8a77b0 100644 (file)
@@ -5348,9 +5348,9 @@ static void s2io_ethtool_gdrvinfo(struct net_device *dev,
 {
        struct s2io_nic *sp = netdev_priv(dev);
 
-       strlcpy(info->driver, s2io_driver_name, sizeof(info->driver));
-       strlcpy(info->version, s2io_driver_version, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, s2io_driver_name, sizeof(info->driver));
+       strscpy(info->version, s2io_driver_version, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(sp->pdev), sizeof(info->bus_info));
 }
 
 /**
index 83c9715..3ab3e45 100644 (file)
@@ -1301,9 +1301,14 @@ static bool offload_pre_check(struct flow_cls_offload *flow)
 {
        struct flow_rule *rule = flow_cls_offload_flow_rule(flow);
        struct flow_dissector *dissector = rule->match.dissector;
+       struct flow_match_ct ct;
 
-       if (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT))
-               return false;
+       if (dissector->used_keys & BIT(FLOW_DISSECTOR_KEY_CT)) {
+               flow_rule_match_ct(rule, &ct);
+               /* Allow special case where CT match is all 0 */
+               if (memchr_inv(ct.key, 0, sizeof(*ct.key)))
+                       return false;
+       }
 
        if (flow->common.chain_index)
                return false;
index 4e5df9f..7b92026 100644 (file)
@@ -127,10 +127,11 @@ static int nfp_policer_validate(const struct flow_action *action,
                return -EOPNOTSUPP;
        }
 
-       if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
+       if (act->police.notexceed.act_id != FLOW_ACTION_CONTINUE &&
+           act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
            act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
                NL_SET_ERR_MSG_MOD(extack,
-                                  "Offload not supported when conform action is not pipe or ok");
+                                  "Offload not supported when conform action is not continue, pipe or ok");
                return -EOPNOTSUPP;
        }
 
index f56ca11..6805af1 100644 (file)
@@ -65,6 +65,7 @@ struct nfp_dumpspec {
  * @num_vfs:           Number of SR-IOV VFs enabled
  * @fw_loaded:         Is the firmware loaded?
  * @unload_fw_on_remove:Do we need to unload firmware on driver removal?
+ * @sp_indiff:         Is the firmware indifferent to physical port speed?
  * @ctrl_vnic:         Pointer to the control vNIC if available
  * @mip:               MIP handle
  * @rtbl:              RTsym table
@@ -114,6 +115,7 @@ struct nfp_pf {
 
        bool fw_loaded;
        bool unload_fw_on_remove;
+       bool sp_indiff;
 
        struct nfp_net *ctrl_vnic;
 
@@ -190,4 +192,7 @@ int nfp_shared_buf_pool_set(struct nfp_pf *pf, unsigned int sb,
 
 int nfp_devlink_params_register(struct nfp_pf *pf);
 void nfp_devlink_params_unregister(struct nfp_pf *pf);
+
+unsigned int nfp_net_lr2speed(unsigned int linkrate);
+unsigned int nfp_net_speed2lr(unsigned int speed);
 #endif /* NFP_MAIN_H */
index cf4d6f1..469c393 100644 (file)
@@ -474,19 +474,22 @@ static void nfp_net_read_link_status(struct nfp_net *nn)
 {
        unsigned long flags;
        bool link_up;
-       u32 sts;
+       u16 sts;
 
        spin_lock_irqsave(&nn->link_status_lock, flags);
 
-       sts = nn_readl(nn, NFP_NET_CFG_STS);
+       sts = nn_readw(nn, NFP_NET_CFG_STS);
        link_up = !!(sts & NFP_NET_CFG_STS_LINK);
 
        if (nn->link_up == link_up)
                goto out;
 
        nn->link_up = link_up;
-       if (nn->port)
+       if (nn->port) {
                set_bit(NFP_PORT_CHANGED, &nn->port->flags);
+               if (nn->port->link_cb)
+                       nn->port->link_cb(nn->port);
+       }
 
        if (nn->link_up) {
                netif_carrier_on(nn->dp.netdev);
@@ -1630,21 +1633,21 @@ static void nfp_net_stat64(struct net_device *netdev,
                unsigned int start;
 
                do {
-                       start = u64_stats_fetch_begin(&r_vec->rx_sync);
+                       start = u64_stats_fetch_begin_irq(&r_vec->rx_sync);
                        data[0] = r_vec->rx_pkts;
                        data[1] = r_vec->rx_bytes;
                        data[2] = r_vec->rx_drops;
-               } while (u64_stats_fetch_retry(&r_vec->rx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&r_vec->rx_sync, start));
                stats->rx_packets += data[0];
                stats->rx_bytes += data[1];
                stats->rx_dropped += data[2];
 
                do {
-                       start = u64_stats_fetch_begin(&r_vec->tx_sync);
+                       start = u64_stats_fetch_begin_irq(&r_vec->tx_sync);
                        data[0] = r_vec->tx_pkts;
                        data[1] = r_vec->tx_bytes;
                        data[2] = r_vec->tx_errors;
-               } while (u64_stats_fetch_retry(&r_vec->tx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&r_vec->tx_sync, start));
                stats->tx_packets += data[0];
                stats->tx_bytes += data[1];
                stats->tx_errors += data[2];
index c3a7631..d81bd86 100644 (file)
@@ -148,6 +148,14 @@ int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
                                                          true))
                                return -EINVAL;
                        break;
+               case NFP_NET_CFG_TLV_TYPE_SP_INDIFF:
+                       if (length) {
+                               dev_err(dev, "Unexpected len of SP_INDIFF TLV:%u\n", length);
+                               return -EINVAL;
+                       }
+
+                       caps->sp_indiff = true;
+                       break;
                default:
                        if (!FIELD_GET(NFP_NET_CFG_TLV_HEADER_REQUIRED, hdr))
                                break;
index ac05ec3..1d53f72 100644 (file)
 #define   NFP_NET_CFG_STS_LINK_RATE_40G                  5
 #define   NFP_NET_CFG_STS_LINK_RATE_50G                  6
 #define   NFP_NET_CFG_STS_LINK_RATE_100G         7
+/* NSP Link rate is a 16-bit word. It's determined by NSP and
+ * written to CFG BAR by NFP driver.
+ */
+#define NFP_NET_CFG_STS_NSP_LINK_RATE  0x0036
 #define NFP_NET_CFG_CAP                        0x0038
 #define NFP_NET_CFG_MAX_TXRINGS                0x003c
 #define NFP_NET_CFG_MAX_RXRINGS                0x0040
  * %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN:
  * Same as %NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS, but crypto TLS does stream scan
  * RX sync, rather than kernel-assisted sync.
+ *
+ * %NFP_NET_CFG_TLV_TYPE_SP_INDIFF:
+ * Empty, indicate the firmware is indifferent to port speed. Then no need to
+ * reload driver and firmware when port speed is changed.
  */
 #define NFP_NET_CFG_TLV_TYPE_UNKNOWN           0
 #define NFP_NET_CFG_TLV_TYPE_RESERVED          1
 #define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS                11 /* see crypto/fw.h */
 #define NFP_NET_CFG_TLV_TYPE_VNIC_STATS                12
 #define NFP_NET_CFG_TLV_TYPE_CRYPTO_OPS_RX_SCAN        13
+#define NFP_NET_CFG_TLV_TYPE_SP_INDIFF         14
 
 struct device;
 
@@ -515,6 +524,7 @@ struct device;
  * @vnic_stats_off:    offset of vNIC stats area
  * @vnic_stats_cnt:    number of vNIC stats
  * @tls_resync_ss:     TLS resync will be performed via stream scan
+ * @sp_indiff:         Firmware is indifferent to port speed
  */
 struct nfp_net_tlv_caps {
        u32 me_freq_mhz;
@@ -527,6 +537,7 @@ struct nfp_net_tlv_caps {
        unsigned int vnic_stats_off;
        unsigned int vnic_stats_cnt;
        unsigned int tls_resync_ss:1;
+       unsigned int sp_indiff:1;
 };
 
 int nfp_net_tlv_caps_parse(struct device *dev, u8 __iomem *ctrl_mem,
index eeb1455..db58532 100644 (file)
@@ -205,7 +205,7 @@ nfp_get_drvinfo(struct nfp_app *app, struct pci_dev *pdev,
 {
        char nsp_version[ETHTOOL_FWVERS_LEN] = {};
 
-       strlcpy(drvinfo->driver, dev_driver_string(&pdev->dev),
+       strscpy(drvinfo->driver, dev_driver_string(&pdev->dev),
                sizeof(drvinfo->driver));
        nfp_net_get_nspinfo(app, nsp_version);
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
@@ -222,7 +222,7 @@ nfp_net_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
        snprintf(vnic_version, sizeof(vnic_version), "%d.%d.%d.%d",
                 nn->fw_ver.extend, nn->fw_ver.class,
                 nn->fw_ver.major, nn->fw_ver.minor);
-       strlcpy(drvinfo->bus_info, pci_name(nn->pdev),
+       strscpy(drvinfo->bus_info, pci_name(nn->pdev),
                sizeof(drvinfo->bus_info));
 
        nfp_get_drvinfo(nn->app, nn->pdev, vnic_version, drvinfo);
@@ -233,7 +233,7 @@ nfp_app_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 {
        struct nfp_app *app = nfp_app_from_netdev(netdev);
 
-       strlcpy(drvinfo->bus_info, pci_name(app->pdev),
+       strscpy(drvinfo->bus_info, pci_name(app->pdev),
                sizeof(drvinfo->bus_info));
        nfp_get_drvinfo(app, app->pdev, "*", drvinfo);
 }
@@ -273,20 +273,11 @@ static int
 nfp_net_get_link_ksettings(struct net_device *netdev,
                           struct ethtool_link_ksettings *cmd)
 {
-       static const u32 ls_to_ethtool[] = {
-               [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
-               [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = SPEED_UNKNOWN,
-               [NFP_NET_CFG_STS_LINK_RATE_1G]          = SPEED_1000,
-               [NFP_NET_CFG_STS_LINK_RATE_10G]         = SPEED_10000,
-               [NFP_NET_CFG_STS_LINK_RATE_25G]         = SPEED_25000,
-               [NFP_NET_CFG_STS_LINK_RATE_40G]         = SPEED_40000,
-               [NFP_NET_CFG_STS_LINK_RATE_50G]         = SPEED_50000,
-               [NFP_NET_CFG_STS_LINK_RATE_100G]        = SPEED_100000,
-       };
        struct nfp_eth_table_port *eth_port;
        struct nfp_port *port;
        struct nfp_net *nn;
-       u32 sts, ls;
+       unsigned int speed;
+       u16 sts;
 
        /* Init to unknowns */
        ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
@@ -319,18 +310,15 @@ nfp_net_get_link_ksettings(struct net_device *netdev,
                return -EOPNOTSUPP;
        nn = netdev_priv(netdev);
 
-       sts = nn_readl(nn, NFP_NET_CFG_STS);
-
-       ls = FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts);
-       if (ls == NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED)
+       sts = nn_readw(nn, NFP_NET_CFG_STS);
+       speed = nfp_net_lr2speed(FIELD_GET(NFP_NET_CFG_STS_LINK_RATE, sts));
+       if (!speed)
                return -EOPNOTSUPP;
 
-       if (ls == NFP_NET_CFG_STS_LINK_RATE_UNKNOWN ||
-           ls >= ARRAY_SIZE(ls_to_ethtool))
-               return 0;
-
-       cmd->base.speed = ls_to_ethtool[ls];
-       cmd->base.duplex = DUPLEX_FULL;
+       if (speed != SPEED_UNKNOWN) {
+               cmd->base.speed = speed;
+               cmd->base.duplex = DUPLEX_FULL;
+       }
 
        return 0;
 }
@@ -649,7 +637,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
                unsigned int start;
 
                do {
-                       start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync);
+                       start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].rx_sync);
                        data[0] = nn->r_vecs[i].rx_pkts;
                        tmp[0] = nn->r_vecs[i].hw_csum_rx_ok;
                        tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok;
@@ -657,10 +645,10 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
                        tmp[3] = nn->r_vecs[i].hw_csum_rx_error;
                        tmp[4] = nn->r_vecs[i].rx_replace_buf_alloc_fail;
                        tmp[5] = nn->r_vecs[i].hw_tls_rx;
-               } while (u64_stats_fetch_retry(&nn->r_vecs[i].rx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].rx_sync, start));
 
                do {
-                       start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync);
+                       start = u64_stats_fetch_begin_irq(&nn->r_vecs[i].tx_sync);
                        data[1] = nn->r_vecs[i].tx_pkts;
                        data[2] = nn->r_vecs[i].tx_busy;
                        tmp[6] = nn->r_vecs[i].hw_csum_tx;
@@ -670,7 +658,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data)
                        tmp[10] = nn->r_vecs[i].hw_tls_tx;
                        tmp[11] = nn->r_vecs[i].tls_tx_fallback;
                        tmp[12] = nn->r_vecs[i].tls_tx_no_fallback;
-               } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start));
+               } while (u64_stats_fetch_retry_irq(&nn->r_vecs[i].tx_sync, start));
 
                data += NN_RVEC_PER_Q_STATS;
 
@@ -1676,6 +1664,160 @@ static int nfp_net_set_phys_id(struct net_device *netdev,
        return err;
 }
 
+#define NFP_EEPROM_LEN ETH_ALEN
+
+static int
+nfp_net_get_eeprom_len(struct net_device *netdev)
+{
+       struct nfp_eth_table_port *eth_port;
+       struct nfp_port *port;
+
+       port = nfp_port_from_netdev(netdev);
+       eth_port = __nfp_port_get_eth_port(port);
+       if (!eth_port)
+               return 0;
+
+       return NFP_EEPROM_LEN;
+}
+
+static int
+nfp_net_get_nsp_hwindex(struct net_device *netdev,
+                       struct nfp_nsp **nspptr,
+                       u32 *index)
+{
+       struct nfp_eth_table_port *eth_port;
+       struct nfp_port *port;
+       struct nfp_nsp *nsp;
+       int err;
+
+       port = nfp_port_from_netdev(netdev);
+       eth_port = __nfp_port_get_eth_port(port);
+       if (!eth_port)
+               return -EOPNOTSUPP;
+
+       nsp = nfp_nsp_open(port->app->cpp);
+       if (IS_ERR(nsp)) {
+               err = PTR_ERR(nsp);
+               netdev_err(netdev, "Failed to access the NSP: %d\n", err);
+               return err;
+       }
+
+       if (!nfp_nsp_has_hwinfo_lookup(nsp)) {
+               netdev_err(netdev, "NSP doesn't support PF MAC generation\n");
+               nfp_nsp_close(nsp);
+               return -EOPNOTSUPP;
+       }
+
+       *nspptr = nsp;
+       *index = eth_port->eth_index;
+
+       return 0;
+}
+
+static int
+nfp_net_get_port_mac_by_hwinfo(struct net_device *netdev,
+                              u8 *mac_addr)
+{
+       char hwinfo[32] = {};
+       struct nfp_nsp *nsp;
+       u32 index;
+       int err;
+
+       err = nfp_net_get_nsp_hwindex(netdev, &nsp, &index);
+       if (err)
+               return err;
+
+       snprintf(hwinfo, sizeof(hwinfo), "eth%u.mac", index);
+       err = nfp_nsp_hwinfo_lookup(nsp, hwinfo, sizeof(hwinfo));
+       nfp_nsp_close(nsp);
+       if (err) {
+               netdev_err(netdev, "Reading persistent MAC address failed: %d\n",
+                          err);
+               return -EOPNOTSUPP;
+       }
+
+       if (sscanf(hwinfo, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+                  &mac_addr[0], &mac_addr[1], &mac_addr[2],
+                  &mac_addr[3], &mac_addr[4], &mac_addr[5]) != 6) {
+               netdev_err(netdev, "Can't parse persistent MAC address (%s)\n",
+                          hwinfo);
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int
+nfp_net_set_port_mac_by_hwinfo(struct net_device *netdev,
+                              u8 *mac_addr)
+{
+       char hwinfo[32] = {};
+       struct nfp_nsp *nsp;
+       u32 index;
+       int err;
+
+       err = nfp_net_get_nsp_hwindex(netdev, &nsp, &index);
+       if (err)
+               return err;
+
+       snprintf(hwinfo, sizeof(hwinfo),
+                "eth%u.mac=%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+                index, mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
+                mac_addr[4], mac_addr[5]);
+
+       err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo));
+       nfp_nsp_close(nsp);
+       if (err) {
+               netdev_err(netdev, "HWinfo set failed: %d, hwinfo: %s\n",
+                          err, hwinfo);
+               return -EOPNOTSUPP;
+       }
+
+       return 0;
+}
+
+static int
+nfp_net_get_eeprom(struct net_device *netdev,
+                  struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+       struct nfp_net *nn = netdev_priv(netdev);
+       u8 buf[NFP_EEPROM_LEN] = {};
+
+       if (eeprom->len == 0)
+               return -EINVAL;
+
+       if (nfp_net_get_port_mac_by_hwinfo(netdev, buf))
+               return -EOPNOTSUPP;
+
+       eeprom->magic = nn->pdev->vendor | (nn->pdev->device << 16);
+       memcpy(bytes, buf + eeprom->offset, eeprom->len);
+
+       return 0;
+}
+
+static int
+nfp_net_set_eeprom(struct net_device *netdev,
+                  struct ethtool_eeprom *eeprom, u8 *bytes)
+{
+       struct nfp_net *nn = netdev_priv(netdev);
+       u8 buf[NFP_EEPROM_LEN] = {};
+
+       if (eeprom->len == 0)
+               return -EINVAL;
+
+       if (eeprom->magic != (nn->pdev->vendor | nn->pdev->device << 16))
+               return -EINVAL;
+
+       if (nfp_net_get_port_mac_by_hwinfo(netdev, buf))
+               return -EOPNOTSUPP;
+
+       memcpy(buf + eeprom->offset, bytes, eeprom->len);
+       if (nfp_net_set_port_mac_by_hwinfo(netdev, buf))
+               return -EOPNOTSUPP;
+
+       return 0;
+}
+
 static const struct ethtool_ops nfp_net_ethtool_ops = {
        .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
                                     ETHTOOL_COALESCE_MAX_FRAMES |
@@ -1699,6 +1841,9 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
        .set_dump               = nfp_app_set_dump,
        .get_dump_flag          = nfp_app_get_dump_flag,
        .get_dump_data          = nfp_app_get_dump_data,
+       .get_eeprom_len         = nfp_net_get_eeprom_len,
+       .get_eeprom             = nfp_net_get_eeprom,
+       .set_eeprom             = nfp_net_set_eeprom,
        .get_module_info        = nfp_port_get_module_info,
        .get_module_eeprom      = nfp_port_get_module_eeprom,
        .get_coalesce           = nfp_net_get_coalesce,
index ca4e056..e2d4c48 100644 (file)
@@ -202,7 +202,11 @@ nfp_net_pf_alloc_vnics(struct nfp_pf *pf, void __iomem *ctrl_bar,
                        goto err_free_prev;
                }
 
+               if (nn->port)
+                       nn->port->link_cb = nfp_net_refresh_port_table;
+
                ctrl_bar += NFP_PF_CSR_SLICE_SIZE;
+               pf->sp_indiff |= nn->tlv_caps.sp_indiff;
 
                /* Kill the vNIC if app init marked it as invalid */
                if (nn->port && nn->port->type == NFP_PORT_INVALID)
@@ -304,6 +308,37 @@ err_prev_deinit:
        return err;
 }
 
+static int nfp_net_pf_cfg_nsp(struct nfp_pf *pf, bool sp_indiff)
+{
+       struct nfp_nsp *nsp;
+       char hwinfo[32];
+       int err;
+
+       nsp = nfp_nsp_open(pf->cpp);
+       if (IS_ERR(nsp)) {
+               err = PTR_ERR(nsp);
+               return err;
+       }
+
+       snprintf(hwinfo, sizeof(hwinfo), "sp_indiff=%d", sp_indiff);
+       err = nfp_nsp_hwinfo_set(nsp, hwinfo, sizeof(hwinfo));
+       if (err)
+               nfp_warn(pf->cpp, "HWinfo(sp_indiff=%d) set failed: %d\n", sp_indiff, err);
+
+       nfp_nsp_close(nsp);
+       return err;
+}
+
+static int nfp_net_pf_init_nsp(struct nfp_pf *pf)
+{
+       return nfp_net_pf_cfg_nsp(pf, pf->sp_indiff);
+}
+
+static void nfp_net_pf_clean_nsp(struct nfp_pf *pf)
+{
+       (void)nfp_net_pf_cfg_nsp(pf, false);
+}
+
 static int
 nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
 {
@@ -315,6 +350,8 @@ nfp_net_pf_app_init(struct nfp_pf *pf, u8 __iomem *qc_bar, unsigned int stride)
        if (IS_ERR(pf->app))
                return PTR_ERR(pf->app);
 
+       pf->sp_indiff |= pf->app->type->id == NFP_APP_FLOWER_NIC;
+
        devl_lock(devlink);
        err = nfp_app_init(pf->app);
        devl_unlock(devlink);
@@ -523,6 +560,57 @@ err_unmap_ctrl:
        return err;
 }
 
+static const unsigned int lr_to_speed[] = {
+       [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = 0,
+       [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = SPEED_UNKNOWN,
+       [NFP_NET_CFG_STS_LINK_RATE_1G]          = SPEED_1000,
+       [NFP_NET_CFG_STS_LINK_RATE_10G]         = SPEED_10000,
+       [NFP_NET_CFG_STS_LINK_RATE_25G]         = SPEED_25000,
+       [NFP_NET_CFG_STS_LINK_RATE_40G]         = SPEED_40000,
+       [NFP_NET_CFG_STS_LINK_RATE_50G]         = SPEED_50000,
+       [NFP_NET_CFG_STS_LINK_RATE_100G]        = SPEED_100000,
+};
+
+unsigned int nfp_net_lr2speed(unsigned int linkrate)
+{
+       if (linkrate < ARRAY_SIZE(lr_to_speed))
+               return lr_to_speed[linkrate];
+
+       return SPEED_UNKNOWN;
+}
+
+unsigned int nfp_net_speed2lr(unsigned int speed)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(lr_to_speed); i++) {
+               if (speed == lr_to_speed[i])
+                       return i;
+       }
+
+       return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;
+}
+
+static void nfp_net_notify_port_speed(struct nfp_port *port)
+{
+       struct net_device *netdev = port->netdev;
+       struct nfp_net *nn;
+       u16 sts;
+
+       if (!nfp_netdev_is_nfp_net(netdev))
+               return;
+
+       nn = netdev_priv(netdev);
+       sts = nn_readw(nn, NFP_NET_CFG_STS);
+
+       if (!(sts & NFP_NET_CFG_STS_LINK)) {
+               nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);
+               return;
+       }
+
+       nn_writew(nn, NFP_NET_CFG_STS_NSP_LINK_RATE, nfp_net_speed2lr(port->eth_port->speed));
+}
+
 static int
 nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
                        struct nfp_eth_table *eth_table)
@@ -544,6 +632,7 @@ nfp_net_eth_port_update(struct nfp_cpp *cpp, struct nfp_port *port,
        }
 
        memcpy(port->eth_port, eth_port, sizeof(*eth_port));
+       nfp_net_notify_port_speed(port);
 
        return 0;
 }
@@ -725,10 +814,14 @@ int nfp_net_pci_probe(struct nfp_pf *pf)
        if (err)
                goto err_clean_ddir;
 
-       err = nfp_net_pf_alloc_irqs(pf);
+       err = nfp_net_pf_init_nsp(pf);
        if (err)
                goto err_free_vnics;
 
+       err = nfp_net_pf_alloc_irqs(pf);
+       if (err)
+               goto err_clean_nsp;
+
        err = nfp_net_pf_app_start(pf);
        if (err)
                goto err_free_irqs;
@@ -746,6 +839,8 @@ err_stop_app:
        nfp_net_pf_app_stop(pf);
 err_free_irqs:
        nfp_net_pf_free_irqs(pf);
+err_clean_nsp:
+       nfp_net_pf_clean_nsp(pf);
 err_free_vnics:
        nfp_net_pf_free_vnics(pf);
 err_clean_ddir:
@@ -776,6 +871,7 @@ void nfp_net_pci_remove(struct nfp_pf *pf)
                nfp_net_pf_free_vnic(pf, nn);
        }
 
+       nfp_net_pf_clean_nsp(pf);
        nfp_net_pf_app_stop(pf);
        /* stop app first, to avoid double free of ctrl vNIC's ddir */
        nfp_net_debugfs_dir_clean(&pf->ddir);
index d1ebe6c..6793cdf 100644 (file)
@@ -46,6 +46,7 @@ enum nfp_port_flags {
  * @tc_offload_cnt:    number of active TC offloads, how offloads are counted
  *                     is not defined, use as a boolean
  * @app:       backpointer to the app structure
+ * @link_cb:   callback when link status changed
  * @dl_port:   devlink port structure
  * @eth_id:    for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
  * @eth_forced:        for %NFP_PORT_PHYS_PORT port is forced UP or DOWN, don't change
@@ -66,6 +67,7 @@ struct nfp_port {
        unsigned long tc_offload_cnt;
 
        struct nfp_app *app;
+       void (*link_cb)(struct nfp_port *port);
 
        struct devlink_port dl_port;
 
index edd3000..4cc3879 100644 (file)
@@ -507,6 +507,7 @@ int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsigned int idx, bool state)
        if (nfp_nsp_get_abi_ver_minor(nsp) < 32) {
                nfp_err(nfp_nsp_cpp(nsp),
                        "set id mode operation not supported, please update flash\n");
+               nfp_eth_config_cleanup_end(nsp);
                return -EOPNOTSUPP;
        }
 
index 4b3482c..cf2929f 100644 (file)
@@ -990,8 +990,8 @@ static const struct net_device_ops nixge_netdev_ops = {
 static void nixge_ethtools_get_drvinfo(struct net_device *ndev,
                                       struct ethtool_drvinfo *ed)
 {
-       strlcpy(ed->driver, "nixge", sizeof(ed->driver));
-       strlcpy(ed->bus_info, "platform", sizeof(ed->bus_info));
+       strscpy(ed->driver, "nixge", sizeof(ed->driver));
+       strscpy(ed->bus_info, "platform", sizeof(ed->bus_info));
 }
 
 static int
index 5116bad..7c0675c 100644 (file)
@@ -4291,9 +4291,9 @@ static void nv_do_stats_poll(struct timer_list *t)
 static void nv_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct fe_priv *np = netdev_priv(dev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, FORCEDETH_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, FORCEDETH_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static void nv_get_wol(struct net_device *dev, struct ethtool_wolinfo *wolinfo)
index f606d75..1a4a272 100644 (file)
@@ -1184,9 +1184,9 @@ static int lpc_eth_open(struct net_device *ndev)
 static void lpc_eth_ethtool_getdrvinfo(struct net_device *ndev,
        struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, MODNAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+       strscpy(info->driver, MODNAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(ndev->dev.parent),
                sizeof(info->bus_info));
 }
 
index 84cc79e..541b8bc 100644 (file)
@@ -169,9 +169,9 @@ static void pch_gbe_get_drvinfo(struct net_device *netdev,
 {
        struct pch_gbe_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, pch_driver_version, sizeof(drvinfo->version));
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 9c40832..1cc0010 100644 (file)
@@ -1819,9 +1819,9 @@ static void hamachi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
 {
        struct hamachi_private *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int hamachi_get_link_ksettings(struct net_device *dev,
index 0365002..640ac01 100644 (file)
@@ -1340,9 +1340,9 @@ static void yellowfin_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
 {
        struct yellowfin_private *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops ethtool_ops = {
index 3c4a84e..8c4cb91 100644 (file)
@@ -65,9 +65,9 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        u32 fw_minor = 0;
        u32 fw_build = 0;
 
-       strlcpy(drvinfo->driver, netxen_nic_driver_name,
+       strscpy(drvinfo->driver, netxen_nic_driver_name,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID,
+       strscpy(drvinfo->version, NETXEN_NIC_LINUX_VERSIONID,
                sizeof(drvinfo->version));
        fw_major = NXRD32(adapter, NETXEN_FW_VERSION_MAJOR);
        fw_minor = NXRD32(adapter, NETXEN_FW_VERSION_MINOR);
@@ -75,7 +75,7 @@ netxen_nic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                "%d.%d.%d", fw_major, fw_minor, fw_build);
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index d701ecd..2661c48 100644 (file)
@@ -1119,7 +1119,7 @@ static int qed_int_deassertion(struct qed_hwfn  *p_hwfn,
                                                snprintf(bit_name, 30,
                                                         p_aeu->bit_name, num);
                                        else
-                                               strlcpy(bit_name,
+                                               strscpy(bit_name,
                                                        p_aeu->bit_name, 30);
 
                                        /* We now need to pass bitmask in its
index 97a7ab0..8034d81 100644 (file)
@@ -624,7 +624,7 @@ static void qede_get_drvinfo(struct net_device *ndev,
        struct qede_dev *edev = netdev_priv(ndev);
        char mbi[ETHTOOL_FWVERS_LEN];
 
-       strlcpy(info->driver, "qede", sizeof(info->driver));
+       strscpy(info->driver, "qede", sizeof(info->driver));
 
        snprintf(storm, ETHTOOL_FWVERS_LEN, "%d.%d.%d.%d",
                 edev->dev_info.common.fw_major,
@@ -661,7 +661,7 @@ static void qede_get_drvinfo(struct net_device *ndev,
                         "mfw %s", mfw);
        }
 
-       strlcpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
+       strscpy(info->bus_info, pci_name(edev->pdev), sizeof(info->bus_info));
 }
 
 static void qede_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
index f56b679..3c1bfff 100644 (file)
@@ -1214,7 +1214,7 @@ static int __qede_probe(struct pci_dev *pdev, u32 dp_module, u8 dp_level,
        /* Start the Slowpath-process */
        memset(&sp_params, 0, sizeof(sp_params));
        sp_params.int_mode = QED_INT_MODE_MSIX;
-       strlcpy(sp_params.name, "qede LAN", QED_DRV_VER_STR_SIZE);
+       strscpy(sp_params.name, "qede LAN", QED_DRV_VER_STR_SIZE);
        rc = qed_ops->common->slowpath_start(cdev, &sp_params);
        if (rc) {
                pr_notice("Cannot start slowpath\n");
index 06f4d9a..31e3ab1 100644 (file)
@@ -1736,10 +1736,10 @@ static void ql_get_drvinfo(struct net_device *ndev,
                           struct ethtool_drvinfo *drvinfo)
 {
        struct ql3_adapter *qdev = netdev_priv(ndev);
-       strlcpy(drvinfo->driver, ql3xxx_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, ql3xxx_driver_version,
+       strscpy(drvinfo->driver, ql3xxx_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, ql3xxx_driver_version,
                sizeof(drvinfo->version));
-       strlcpy(drvinfo->bus_info, pci_name(qdev->pdev),
+       strscpy(drvinfo->bus_info, pci_name(qdev->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 54a2d65..1ee491f 100644 (file)
@@ -277,10 +277,10 @@ qlcnic_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo)
        snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
                "%d.%d.%d", fw_major, fw_minor, fw_build);
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
-       strlcpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
+       strscpy(drvinfo->driver, qlcnic_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, QLCNIC_LINUX_VERSIONID,
                sizeof(drvinfo->version));
 }
 
index 792ce9a..f62c395 100644 (file)
@@ -164,10 +164,10 @@ qcaspi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *p)
 {
        struct qcaspi *qca = netdev_priv(dev);
 
-       strlcpy(p->driver, QCASPI_DRV_NAME, sizeof(p->driver));
-       strlcpy(p->version, QCASPI_DRV_VERSION, sizeof(p->version));
-       strlcpy(p->fw_version, "QCA7000", sizeof(p->fw_version));
-       strlcpy(p->bus_info, dev_name(&qca->spi_dev->dev),
+       strscpy(p->driver, QCASPI_DRV_NAME, sizeof(p->driver));
+       strscpy(p->version, QCASPI_DRV_VERSION, sizeof(p->version));
+       strscpy(p->fw_version, "QCA7000", sizeof(p->fw_version));
+       strscpy(p->bus_info, dev_name(&qca->spi_dev->dev),
                sizeof(p->bus_info));
 }
 
index a6bf7d5..1aac2c3 100644 (file)
@@ -939,9 +939,9 @@ static void netdev_get_drvinfo(struct net_device *dev,
 {
        struct r6040_private *rp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(rp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(rp->pdev), sizeof(info->bus_info));
 }
 
 static const struct ethtool_ops netdev_ethtool_ops = {
index e0feeec..f5786d7 100644 (file)
@@ -1382,9 +1382,9 @@ static void cp_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *info
 {
        struct cp_private *cp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(cp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(cp->pdev), sizeof(info->bus_info));
 }
 
 static void cp_get_ringparam(struct net_device *dev,
index 15b40fd..ab424b5 100644 (file)
@@ -2380,9 +2380,9 @@ static int rtl8139_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
 static void rtl8139_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct rtl8139_private *tp = netdev_priv(dev);
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
 }
 
 static int rtl8139_get_link_ksettings(struct net_device *dev,
index 8da4b66..36d3826 100644 (file)
@@ -51,20 +51,20 @@ enum mac_version {
        RTL_GIGA_MAC_VER_38,
        RTL_GIGA_MAC_VER_39,
        RTL_GIGA_MAC_VER_40,
-       RTL_GIGA_MAC_VER_41,
+       /* support for RTL_GIGA_MAC_VER_41 has been removed */
        RTL_GIGA_MAC_VER_42,
        RTL_GIGA_MAC_VER_43,
        RTL_GIGA_MAC_VER_44,
-       RTL_GIGA_MAC_VER_45,
+       /* support for RTL_GIGA_MAC_VER_45 has been removed */
        RTL_GIGA_MAC_VER_46,
-       RTL_GIGA_MAC_VER_47,
+       /* support for RTL_GIGA_MAC_VER_47 has been removed */
        RTL_GIGA_MAC_VER_48,
-       RTL_GIGA_MAC_VER_49,
-       RTL_GIGA_MAC_VER_50,
+       /* support for RTL_GIGA_MAC_VER_49 has been removed */
+       /* support for RTL_GIGA_MAC_VER_50 has been removed */
        RTL_GIGA_MAC_VER_51,
        RTL_GIGA_MAC_VER_52,
        RTL_GIGA_MAC_VER_53,
-       RTL_GIGA_MAC_VER_60,
+       /* support for RTL_GIGA_MAC_VER_60 has been removed */
        RTL_GIGA_MAC_VER_61,
        RTL_GIGA_MAC_VER_63,
        RTL_GIGA_MAC_NONE
index 1b7fdb4..7d2f005 100644 (file)
 #define FIRMWARE_8106E_2       "rtl_nic/rtl8106e-2.fw"
 #define FIRMWARE_8168G_2       "rtl_nic/rtl8168g-2.fw"
 #define FIRMWARE_8168G_3       "rtl_nic/rtl8168g-3.fw"
-#define FIRMWARE_8168H_1       "rtl_nic/rtl8168h-1.fw"
 #define FIRMWARE_8168H_2       "rtl_nic/rtl8168h-2.fw"
 #define FIRMWARE_8168FP_3      "rtl_nic/rtl8168fp-3.fw"
-#define FIRMWARE_8107E_1       "rtl_nic/rtl8107e-1.fw"
 #define FIRMWARE_8107E_2       "rtl_nic/rtl8107e-2.fw"
 #define FIRMWARE_8125A_3       "rtl_nic/rtl8125a-3.fw"
 #define FIRMWARE_8125B_2       "rtl_nic/rtl8125b-2.fw"
@@ -131,20 +129,14 @@ static const struct {
        [RTL_GIGA_MAC_VER_38] = {"RTL8411",             FIRMWARE_8411_1 },
        [RTL_GIGA_MAC_VER_39] = {"RTL8106e",            FIRMWARE_8106E_1},
        [RTL_GIGA_MAC_VER_40] = {"RTL8168g/8111g",      FIRMWARE_8168G_2},
-       [RTL_GIGA_MAC_VER_41] = {"RTL8168g/8111g"                       },
        [RTL_GIGA_MAC_VER_42] = {"RTL8168gu/8111gu",    FIRMWARE_8168G_3},
        [RTL_GIGA_MAC_VER_43] = {"RTL8106eus",          FIRMWARE_8106E_2},
        [RTL_GIGA_MAC_VER_44] = {"RTL8411b",            FIRMWARE_8411_2 },
-       [RTL_GIGA_MAC_VER_45] = {"RTL8168h/8111h",      FIRMWARE_8168H_1},
        [RTL_GIGA_MAC_VER_46] = {"RTL8168h/8111h",      FIRMWARE_8168H_2},
-       [RTL_GIGA_MAC_VER_47] = {"RTL8107e",            FIRMWARE_8107E_1},
        [RTL_GIGA_MAC_VER_48] = {"RTL8107e",            FIRMWARE_8107E_2},
-       [RTL_GIGA_MAC_VER_49] = {"RTL8168ep/8111ep"                     },
-       [RTL_GIGA_MAC_VER_50] = {"RTL8168ep/8111ep"                     },
        [RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep"                     },
        [RTL_GIGA_MAC_VER_52] = {"RTL8168fp/RTL8117",  FIRMWARE_8168FP_3},
        [RTL_GIGA_MAC_VER_53] = {"RTL8168fp/RTL8117",                   },
-       [RTL_GIGA_MAC_VER_60] = {"RTL8125A"                             },
        [RTL_GIGA_MAC_VER_61] = {"RTL8125A",            FIRMWARE_8125A_3},
        /* reserve 62 for CFG_METHOD_4 in the vendor driver */
        [RTL_GIGA_MAC_VER_63] = {"RTL8125B",            FIRMWARE_8125B_2},
@@ -658,10 +650,8 @@ MODULE_FIRMWARE(FIRMWARE_8106E_1);
 MODULE_FIRMWARE(FIRMWARE_8106E_2);
 MODULE_FIRMWARE(FIRMWARE_8168G_2);
 MODULE_FIRMWARE(FIRMWARE_8168G_3);
-MODULE_FIRMWARE(FIRMWARE_8168H_1);
 MODULE_FIRMWARE(FIRMWARE_8168H_2);
 MODULE_FIRMWARE(FIRMWARE_8168FP_3);
-MODULE_FIRMWARE(FIRMWARE_8107E_1);
 MODULE_FIRMWARE(FIRMWARE_8107E_2);
 MODULE_FIRMWARE(FIRMWARE_8125A_3);
 MODULE_FIRMWARE(FIRMWARE_8125B_2);
@@ -689,7 +679,7 @@ static void rtl_pci_commit(struct rtl8169_private *tp)
 
 static bool rtl_is_8125(struct rtl8169_private *tp)
 {
-       return tp->mac_version >= RTL_GIGA_MAC_VER_60;
+       return tp->mac_version >= RTL_GIGA_MAC_VER_61;
 }
 
 static bool rtl_is_8168evl_up(struct rtl8169_private *tp)
@@ -892,8 +882,6 @@ static void rtl8168g_phy_suspend_quirk(struct rtl8169_private *tp, int value)
 {
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_40:
-       case RTL_GIGA_MAC_VER_41:
-       case RTL_GIGA_MAC_VER_49:
                if (value & BMCR_RESET || !(value & BMCR_PDOWN))
                        rtl_eri_set_bits(tp, 0x1a8, 0xfc000000);
                else
@@ -1207,7 +1195,7 @@ static enum rtl_dash_type rtl_check_dash(struct rtl8169_private *tp)
        case RTL_GIGA_MAC_VER_28:
        case RTL_GIGA_MAC_VER_31:
                return r8168dp_check_dash(tp) ? RTL_DASH_DP : RTL_DASH_NONE;
-       case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_53:
+       case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
                return r8168ep_check_dash(tp) ? RTL_DASH_EP : RTL_DASH_NONE;
        default:
                return RTL_DASH_NONE;
@@ -1423,11 +1411,11 @@ static void rtl8169_get_drvinfo(struct net_device *dev,
        struct rtl8169_private *tp = netdev_priv(dev);
        struct rtl_fw *rtl_fw = tp->rtl_fw;
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
        BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
        if (rtl_fw)
-               strlcpy(info->fw_version, rtl_fw->version,
+               strscpy(info->fw_version, rtl_fw->version,
                        sizeof(info->fw_version));
 }
 
@@ -2088,8 +2076,6 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
        if (ver != RTL_GIGA_MAC_NONE && !gmii) {
                if (ver == RTL_GIGA_MAC_VER_42)
                        ver = RTL_GIGA_MAC_VER_43;
-               else if (ver == RTL_GIGA_MAC_VER_45)
-                       ver = RTL_GIGA_MAC_VER_47;
                else if (ver == RTL_GIGA_MAC_VER_46)
                        ver = RTL_GIGA_MAC_VER_48;
        }
@@ -2271,7 +2257,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
        case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_53:
                RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
                break;
-       case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_63:
+       case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
                RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
                break;
        default:
@@ -2455,7 +2441,7 @@ static void rtl_wait_txrx_fifo_empty(struct rtl8169_private *tp)
                rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42);
                rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
                break;
-       case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_61:
+       case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61:
                rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
                break;
        case RTL_GIGA_MAC_VER_63:
@@ -2700,8 +2686,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
                RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
 
                switch (tp->mac_version) {
-               case RTL_GIGA_MAC_VER_45 ... RTL_GIGA_MAC_VER_48:
-               case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_63:
+               case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+               case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
                        /* reset ephy tx/rx disable timer */
                        r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
                        /* chip can trigger L1.2 */
@@ -2712,8 +2698,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
                }
        } else {
                switch (tp->mac_version) {
-               case RTL_GIGA_MAC_VER_45 ... RTL_GIGA_MAC_VER_48:
-               case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_63:
+               case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
+               case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
                        r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
                        break;
                default:
@@ -3288,45 +3274,6 @@ static void rtl_hw_start_8168ep(struct rtl8169_private *tp)
        rtl_pcie_state_l2l3_disable(tp);
 }
 
-static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
-{
-       static const struct ephy_info e_info_8168ep_1[] = {
-               { 0x00, 0xffff, 0x10ab },
-               { 0x06, 0xffff, 0xf030 },
-               { 0x08, 0xffff, 0x2006 },
-               { 0x0d, 0xffff, 0x1666 },
-               { 0x0c, 0x3ff0, 0x0000 }
-       };
-
-       /* disable aspm and clock request before access ephy */
-       rtl_hw_aspm_clkreq_enable(tp, false);
-       rtl_ephy_init(tp, e_info_8168ep_1);
-
-       rtl_hw_start_8168ep(tp);
-
-       rtl_hw_aspm_clkreq_enable(tp, true);
-}
-
-static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
-{
-       static const struct ephy_info e_info_8168ep_2[] = {
-               { 0x00, 0xffff, 0x10a3 },
-               { 0x19, 0xffff, 0xfc00 },
-               { 0x1e, 0xffff, 0x20ea }
-       };
-
-       /* disable aspm and clock request before access ephy */
-       rtl_hw_aspm_clkreq_enable(tp, false);
-       rtl_ephy_init(tp, e_info_8168ep_2);
-
-       rtl_hw_start_8168ep(tp);
-
-       RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
-       RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
-
-       rtl_hw_aspm_clkreq_enable(tp, true);
-}
-
 static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
 {
        static const struct ephy_info e_info_8168ep_3[] = {
@@ -3625,46 +3572,6 @@ static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
        udelay(10);
 }
 
-static void rtl_hw_start_8125a_1(struct rtl8169_private *tp)
-{
-       static const struct ephy_info e_info_8125a_1[] = {
-               { 0x01, 0xffff, 0xa812 },
-               { 0x09, 0xffff, 0x520c },
-               { 0x04, 0xffff, 0xd000 },
-               { 0x0d, 0xffff, 0xf702 },
-               { 0x0a, 0xffff, 0x8653 },
-               { 0x06, 0xffff, 0x001e },
-               { 0x08, 0xffff, 0x3595 },
-               { 0x20, 0xffff, 0x9455 },
-               { 0x21, 0xffff, 0x99ff },
-               { 0x02, 0xffff, 0x6046 },
-               { 0x29, 0xffff, 0xfe00 },
-               { 0x23, 0xffff, 0xab62 },
-
-               { 0x41, 0xffff, 0xa80c },
-               { 0x49, 0xffff, 0x520c },
-               { 0x44, 0xffff, 0xd000 },
-               { 0x4d, 0xffff, 0xf702 },
-               { 0x4a, 0xffff, 0x8653 },
-               { 0x46, 0xffff, 0x001e },
-               { 0x48, 0xffff, 0x3595 },
-               { 0x60, 0xffff, 0x9455 },
-               { 0x61, 0xffff, 0x99ff },
-               { 0x42, 0xffff, 0x6046 },
-               { 0x69, 0xffff, 0xfe00 },
-               { 0x63, 0xffff, 0xab62 },
-       };
-
-       rtl_set_def_aspm_entry_latency(tp);
-
-       /* disable aspm and clock request before access ephy */
-       rtl_hw_aspm_clkreq_enable(tp, false);
-       rtl_ephy_init(tp, e_info_8125a_1);
-
-       rtl_hw_start_8125_common(tp);
-       rtl_hw_aspm_clkreq_enable(tp, true);
-}
-
 static void rtl_hw_start_8125a_2(struct rtl8169_private *tp)
 {
        static const struct ephy_info e_info_8125a_2[] = {
@@ -3748,20 +3655,14 @@ static void rtl_hw_config(struct rtl8169_private *tp)
                [RTL_GIGA_MAC_VER_38] = rtl_hw_start_8411,
                [RTL_GIGA_MAC_VER_39] = rtl_hw_start_8106,
                [RTL_GIGA_MAC_VER_40] = rtl_hw_start_8168g_1,
-               [RTL_GIGA_MAC_VER_41] = rtl_hw_start_8168g_1,
                [RTL_GIGA_MAC_VER_42] = rtl_hw_start_8168g_2,
                [RTL_GIGA_MAC_VER_43] = rtl_hw_start_8168g_2,
                [RTL_GIGA_MAC_VER_44] = rtl_hw_start_8411_2,
-               [RTL_GIGA_MAC_VER_45] = rtl_hw_start_8168h_1,
                [RTL_GIGA_MAC_VER_46] = rtl_hw_start_8168h_1,
-               [RTL_GIGA_MAC_VER_47] = rtl_hw_start_8168h_1,
                [RTL_GIGA_MAC_VER_48] = rtl_hw_start_8168h_1,
-               [RTL_GIGA_MAC_VER_49] = rtl_hw_start_8168ep_1,
-               [RTL_GIGA_MAC_VER_50] = rtl_hw_start_8168ep_2,
                [RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3,
                [RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117,
                [RTL_GIGA_MAC_VER_53] = rtl_hw_start_8117,
-               [RTL_GIGA_MAC_VER_60] = rtl_hw_start_8125a_1,
                [RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
                [RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
        };
@@ -4156,7 +4057,6 @@ static unsigned int rtl_quirk_packet_padto(struct rtl8169_private *tp,
 
        switch (tp->mac_version) {
        case RTL_GIGA_MAC_VER_34:
-       case RTL_GIGA_MAC_VER_60:
        case RTL_GIGA_MAC_VER_61:
        case RTL_GIGA_MAC_VER_63:
                padto = max_t(unsigned int, padto, ETH_ZLEN);
@@ -5194,13 +5094,13 @@ static void rtl_hw_init_8125(struct rtl8169_private *tp)
 static void rtl_hw_initialize(struct rtl8169_private *tp)
 {
        switch (tp->mac_version) {
-       case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_53:
+       case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
                rtl8168ep_stop_cmac(tp);
                fallthrough;
        case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
                rtl_hw_init_8168g(tp);
                break;
-       case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_63:
+       case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_63:
                rtl_hw_init_8125(tp);
                break;
        default:
@@ -5291,7 +5191,7 @@ done:
 /* register is set if system vendor successfully tested ASPM 1.2 */
 static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
 {
-       if (tp->mac_version >= RTL_GIGA_MAC_VER_60 &&
+       if (tp->mac_version >= RTL_GIGA_MAC_VER_61 &&
            r8168_mac_ocp_read(tp, 0xc0b2) & 0xf)
                return true;
 
@@ -5378,7 +5278,7 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
         */
        if (rtl_aspm_is_safe(tp))
                rc = 0;
-       else if (tp->mac_version >= RTL_GIGA_MAC_VER_45)
+       else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
                rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
        else
                rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
index 15c295f..8c04cc5 100644 (file)
@@ -793,71 +793,6 @@ static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp,
        rtl8168g_config_eee_phy(phydev);
 }
 
-static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp,
-                                    struct phy_device *phydev)
-{
-       u16 dout_tapbin;
-       u32 data;
-
-       r8169_apply_firmware(tp);
-
-       /* CHN EST parameters adjust - giga master */
-       r8168g_phy_param(phydev, 0x809b, 0xf800, 0x8000);
-       r8168g_phy_param(phydev, 0x80a2, 0xff00, 0x8000);
-       r8168g_phy_param(phydev, 0x80a4, 0xff00, 0x8500);
-       r8168g_phy_param(phydev, 0x809c, 0xff00, 0xbd00);
-
-       /* CHN EST parameters adjust - giga slave */
-       r8168g_phy_param(phydev, 0x80ad, 0xf800, 0x7000);
-       r8168g_phy_param(phydev, 0x80b4, 0xff00, 0x5000);
-       r8168g_phy_param(phydev, 0x80ac, 0xff00, 0x4000);
-
-       /* CHN EST parameters adjust - fnet */
-       r8168g_phy_param(phydev, 0x808e, 0xff00, 0x1200);
-       r8168g_phy_param(phydev, 0x8090, 0xff00, 0xe500);
-       r8168g_phy_param(phydev, 0x8092, 0xff00, 0x9f00);
-
-       /* enable R-tune & PGA-retune function */
-       dout_tapbin = 0;
-       data = phy_read_paged(phydev, 0x0a46, 0x13);
-       data &= 3;
-       data <<= 2;
-       dout_tapbin |= data;
-       data = phy_read_paged(phydev, 0x0a46, 0x12);
-       data &= 0xc000;
-       data >>= 14;
-       dout_tapbin |= data;
-       dout_tapbin = ~(dout_tapbin ^ 0x08);
-       dout_tapbin <<= 12;
-       dout_tapbin &= 0xf000;
-
-       r8168g_phy_param(phydev, 0x827a, 0xf000, dout_tapbin);
-       r8168g_phy_param(phydev, 0x827b, 0xf000, dout_tapbin);
-       r8168g_phy_param(phydev, 0x827c, 0xf000, dout_tapbin);
-       r8168g_phy_param(phydev, 0x827d, 0xf000, dout_tapbin);
-       r8168g_phy_param(phydev, 0x0811, 0x0000, 0x0800);
-       phy_modify_paged(phydev, 0x0a42, 0x16, 0x0000, 0x0002);
-
-       rtl8168g_enable_gphy_10m(phydev);
-
-       /* SAR ADC performance */
-       phy_modify_paged(phydev, 0x0bca, 0x17, BIT(12) | BIT(13), BIT(14));
-
-       r8168g_phy_param(phydev, 0x803f, 0x3000, 0x0000);
-       r8168g_phy_param(phydev, 0x8047, 0x3000, 0x0000);
-       r8168g_phy_param(phydev, 0x804f, 0x3000, 0x0000);
-       r8168g_phy_param(phydev, 0x8057, 0x3000, 0x0000);
-       r8168g_phy_param(phydev, 0x805f, 0x3000, 0x0000);
-       r8168g_phy_param(phydev, 0x8067, 0x3000, 0x0000);
-       r8168g_phy_param(phydev, 0x806f, 0x3000, 0x0000);
-
-       /* disable phy pfm mode */
-       phy_modify_paged(phydev, 0x0a44, 0x11, BIT(7), 0);
-
-       rtl8168g_disable_aldps(phydev);
-       rtl8168h_config_eee_phy(phydev);
-}
-
 static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp,
                                     struct phy_device *phydev)
 {
@@ -895,27 +830,6 @@ static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp,
        rtl8168g_config_eee_phy(phydev);
 }
 
-static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp,
-                                     struct phy_device *phydev)
-{
-       /* Enable PHY auto speed down */
-       phy_modify_paged(phydev, 0x0a44, 0x11, 0, BIT(3) | BIT(2));
-
-       rtl8168g_phy_adjust_10m_aldps(phydev);
-
-       /* Enable EEE auto-fallback function */
-       phy_modify_paged(phydev, 0x0a4b, 0x11, 0, BIT(2));
-
-       /* Enable UC LPF tune function */
-       r8168g_phy_param(phydev, 0x8012, 0x0000, 0x8000);
-
-       /* set rg_sel_sdm_rate */
-       phy_modify_paged(phydev, 0x0c42, 0x11, BIT(13), BIT(14));
-
-       rtl8168g_disable_aldps(phydev);
-       rtl8168g_config_eee_phy(phydev);
-}
-
 static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp,
                                      struct phy_device *phydev)
 {
@@ -1081,44 +995,6 @@ static void rtl8125_legacy_force_mode(struct phy_device *phydev)
        phy_modify_paged(phydev, 0xa5b, 0x12, BIT(15), 0);
 }
 
-static void rtl8125a_1_hw_phy_config(struct rtl8169_private *tp,
-                                    struct phy_device *phydev)
-{
-       phy_modify_paged(phydev, 0xad4, 0x10, 0x03ff, 0x0084);
-       phy_modify_paged(phydev, 0xad4, 0x17, 0x0000, 0x0010);
-       phy_modify_paged(phydev, 0xad1, 0x13, 0x03ff, 0x0006);
-       phy_modify_paged(phydev, 0xad3, 0x11, 0x003f, 0x0006);
-       phy_modify_paged(phydev, 0xac0, 0x14, 0x0000, 0x1100);
-       phy_modify_paged(phydev, 0xac8, 0x15, 0xf000, 0x7000);
-       phy_modify_paged(phydev, 0xad1, 0x14, 0x0000, 0x0400);
-       phy_modify_paged(phydev, 0xad1, 0x15, 0x0000, 0x03ff);
-       phy_modify_paged(phydev, 0xad1, 0x16, 0x0000, 0x03ff);
-
-       r8168g_phy_param(phydev, 0x80ea, 0xff00, 0xc400);
-       r8168g_phy_param(phydev, 0x80eb, 0x0700, 0x0300);
-       r8168g_phy_param(phydev, 0x80f8, 0xff00, 0x1c00);
-       r8168g_phy_param(phydev, 0x80f1, 0xff00, 0x3000);
-       r8168g_phy_param(phydev, 0x80fe, 0xff00, 0xa500);
-       r8168g_phy_param(phydev, 0x8102, 0xff00, 0x5000);
-       r8168g_phy_param(phydev, 0x8105, 0xff00, 0x3300);
-       r8168g_phy_param(phydev, 0x8100, 0xff00, 0x7000);
-       r8168g_phy_param(phydev, 0x8104, 0xff00, 0xf000);
-       r8168g_phy_param(phydev, 0x8106, 0xff00, 0x6500);
-       r8168g_phy_param(phydev, 0x80dc, 0xff00, 0xed00);
-       r8168g_phy_param(phydev, 0x80df, 0x0000, 0x0100);
-       r8168g_phy_param(phydev, 0x80e1, 0x0100, 0x0000);
-
-       phy_modify_paged(phydev, 0xbf0, 0x13, 0x003f, 0x0038);
-       r8168g_phy_param(phydev, 0x819f, 0xffff, 0xd0b6);
-
-       phy_write_paged(phydev, 0xbc3, 0x12, 0x5555);
-       phy_modify_paged(phydev, 0xbf0, 0x15, 0x0e00, 0x0a00);
-       phy_modify_paged(phydev, 0xa5c, 0x10, 0x0400, 0x0000);
-       rtl8168g_enable_gphy_10m(phydev);
-
-       rtl8125a_config_eee_phy(phydev);
-}
-
 static void rtl8125a_2_hw_phy_config(struct rtl8169_private *tp,
                                     struct phy_device *phydev)
 {
@@ -1266,20 +1142,14 @@ void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
                [RTL_GIGA_MAC_VER_38] = rtl8411_hw_phy_config,
                [RTL_GIGA_MAC_VER_39] = rtl8106e_hw_phy_config,
                [RTL_GIGA_MAC_VER_40] = rtl8168g_1_hw_phy_config,
-               [RTL_GIGA_MAC_VER_41] = NULL,
                [RTL_GIGA_MAC_VER_42] = rtl8168g_2_hw_phy_config,
                [RTL_GIGA_MAC_VER_43] = rtl8168g_2_hw_phy_config,
                [RTL_GIGA_MAC_VER_44] = rtl8168g_2_hw_phy_config,
-               [RTL_GIGA_MAC_VER_45] = rtl8168h_1_hw_phy_config,
                [RTL_GIGA_MAC_VER_46] = rtl8168h_2_hw_phy_config,
-               [RTL_GIGA_MAC_VER_47] = rtl8168h_1_hw_phy_config,
                [RTL_GIGA_MAC_VER_48] = rtl8168h_2_hw_phy_config,
-               [RTL_GIGA_MAC_VER_49] = rtl8168ep_1_hw_phy_config,
-               [RTL_GIGA_MAC_VER_50] = rtl8168ep_2_hw_phy_config,
                [RTL_GIGA_MAC_VER_51] = rtl8168ep_2_hw_phy_config,
                [RTL_GIGA_MAC_VER_52] = rtl8117_hw_phy_config,
                [RTL_GIGA_MAC_VER_53] = rtl8117_hw_phy_config,
-               [RTL_GIGA_MAC_VER_60] = rtl8125a_1_hw_phy_config,
                [RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config,
                [RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config,
        };
index fc83ec2..9e7b627 100644 (file)
@@ -2226,8 +2226,8 @@ rocker_port_set_link_ksettings(struct net_device *dev,
 static void rocker_port_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, rocker_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, rocker_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
 }
 
 static struct rocker_port_stats {
index bc70c6a..58cf7cc 100644 (file)
@@ -1273,7 +1273,7 @@ static int ofdpa_port_ipv4_neigh(struct ofdpa_port *ofdpa_port,
        bool removing;
        int err = 0;
 
-       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
        if (!entry)
                return -ENOMEM;
 
index 98edb01..8ba017e 100644 (file)
@@ -175,8 +175,8 @@ static int sxgbe_set_eee(struct net_device *dev,
 static void sxgbe_getdrvinfo(struct net_device *dev,
                             struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static u32 sxgbe_getmsglevel(struct net_device *dev)
index 153d68e..abed618 100644 (file)
@@ -778,7 +778,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
                return;
 
        if (efx_dev_registered(efx)) {
-               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+               strscpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
                efx_fini_mcdi_logging(efx);
                device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
                unregister_netdev(efx->net_dev);
index a929a1a..c2224e4 100644 (file)
@@ -996,7 +996,7 @@ int efx_init_struct(struct efx_nic *efx, struct pci_dev *pci_dev)
        efx->pci_dev = pci_dev;
        efx->msg_enable = debug;
        efx->state = STATE_UNINIT;
-       strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
+       strscpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
 
        efx->rx_prefix_size = efx->type->rx_prefix_size;
        efx->rx_ip_align =
index bc840ed..a8cbcee 100644 (file)
@@ -106,10 +106,10 @@ void efx_ethtool_get_drvinfo(struct net_device *net_dev,
 {
        struct efx_nic *efx = efx_netdev_priv(net_dev);
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
        efx_mcdi_print_fwver(efx, info->fw_version,
                             sizeof(info->fw_version));
-       strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
+       strscpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
 u32 efx_ethtool_get_msglevel(struct net_device *net_dev)
@@ -468,7 +468,7 @@ void efx_ethtool_get_strings(struct net_device *net_dev,
                strings += (efx->type->describe_stats(efx, strings) *
                            ETH_GSTRING_LEN);
                for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++)
-                       strlcpy(strings + i * ETH_GSTRING_LEN,
+                       strscpy(strings + i * ETH_GSTRING_LEN,
                                efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
                strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
                strings += (efx_describe_per_queue_stats(efx, strings) *
index a63f40b..f18418e 100644 (file)
@@ -2329,7 +2329,7 @@ static void ef4_unregister_netdev(struct ef4_nic *efx)
        BUG_ON(netdev_priv(efx->net_dev) != efx);
 
        if (ef4_dev_registered(efx)) {
-               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+               strscpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
                device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
                unregister_netdev(efx->net_dev);
        }
@@ -2640,7 +2640,7 @@ static int ef4_init_struct(struct ef4_nic *efx,
        efx->pci_dev = pci_dev;
        efx->msg_enable = debug;
        efx->state = STATE_UNINIT;
-       strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
+       strscpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
 
        efx->net_dev = net_dev;
        efx->rx_prefix_size = efx->type->rx_prefix_size;
index 907254b..3976a33 100644 (file)
@@ -162,9 +162,9 @@ static void ef4_ethtool_get_drvinfo(struct net_device *net_dev,
 {
        struct ef4_nic *efx = netdev_priv(net_dev);
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->version, EF4_DRIVER_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->version, EF4_DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
 static int ef4_ethtool_get_regs_len(struct net_device *net_dev)
@@ -412,7 +412,7 @@ static void ef4_ethtool_get_strings(struct net_device *net_dev,
                strings += (efx->type->describe_stats(efx, strings) *
                            ETH_GSTRING_LEN);
                for (i = 0; i < EF4_ETHTOOL_SW_STAT_COUNT; i++)
-                       strlcpy(strings + i * ETH_GSTRING_LEN,
+                       strscpy(strings + i * ETH_GSTRING_LEN,
                                ef4_sw_stat_desc[i].name, ETH_GSTRING_LEN);
                strings += EF4_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
                strings += (ef4_describe_per_queue_stats(efx, strings) *
index 3324a62..7a1c933 100644 (file)
@@ -2387,7 +2387,7 @@ static int falcon_probe_nic(struct ef4_nic *efx)
        board->i2c_data.data = efx;
        board->i2c_adap.algo_data = &board->i2c_data;
        board->i2c_adap.dev.parent = &efx->pci_dev->dev;
-       strlcpy(board->i2c_adap.name, "SFC4000 GPIO",
+       strscpy(board->i2c_adap.name, "SFC4000 GPIO",
                sizeof(board->i2c_adap.name));
        rc = i2c_bit_add_bus(&board->i2c_adap);
        if (rc)
index 156da31..78c851b 100644 (file)
@@ -452,7 +452,7 @@ size_t ef4_nic_describe_stats(const struct ef4_hw_stat_desc *desc, size_t count,
        for_each_set_bit(index, mask, count) {
                if (desc[index].name) {
                        if (names) {
-                               strlcpy(names, desc[index].name,
+                               strscpy(names, desc[index].name,
                                        ETH_GSTRING_LEN);
                                names += ETH_GSTRING_LEN;
                        }
index 5954fcf..f5128db 100644 (file)
@@ -285,7 +285,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
 
-       strlcpy(attr->name, name, sizeof(attr->name));
+       strscpy(attr->name, name, sizeof(attr->name));
        attr->index = index;
        attr->type = type;
        if (type < ARRAY_SIZE(efx_mcdi_sensor_type))
index 22fbb0a..63e2394 100644 (file)
@@ -465,7 +465,7 @@ size_t efx_nic_describe_stats(const struct efx_hw_stat_desc *desc, size_t count,
        for_each_set_bit(index, mask, count) {
                if (desc[index].name) {
                        if (names) {
-                               strlcpy(names, desc[index].name,
+                               strscpy(names, desc[index].name,
                                        ETH_GSTRING_LEN);
                                names += ETH_GSTRING_LEN;
                        }
index 63d999e..10734e8 100644 (file)
@@ -775,7 +775,7 @@ static void efx_unregister_netdev(struct efx_nic *efx)
        BUG_ON(netdev_priv(efx->net_dev) != efx);
 
        if (efx_dev_registered(efx)) {
-               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+               strscpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
                efx_siena_fini_mcdi_logging(efx);
                device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
                unregister_netdev(efx->net_dev);
index 954daf4..1fd396b 100644 (file)
@@ -1006,7 +1006,7 @@ int efx_siena_init_struct(struct efx_nic *efx,
        efx->pci_dev = pci_dev;
        efx->msg_enable = debug;
        efx->state = STATE_UNINIT;
-       strlcpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
+       strscpy(efx->name, pci_name(pci_dev), sizeof(efx->name));
 
        efx->net_dev = net_dev;
        efx->rx_prefix_size = efx->type->rx_prefix_size;
index 0207d07..f590e87 100644 (file)
@@ -105,10 +105,10 @@ void efx_siena_ethtool_get_drvinfo(struct net_device *net_dev,
 {
        struct efx_nic *efx = netdev_priv(net_dev);
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
        efx_siena_mcdi_print_fwver(efx, info->fw_version,
                                   sizeof(info->fw_version));
-       strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
+       strscpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
 u32 efx_siena_ethtool_get_msglevel(struct net_device *net_dev)
@@ -467,7 +467,7 @@ void efx_siena_ethtool_get_strings(struct net_device *net_dev,
                strings += (efx->type->describe_stats(efx, strings) *
                            ETH_GSTRING_LEN);
                for (i = 0; i < EFX_ETHTOOL_SW_STAT_COUNT; i++)
-                       strlcpy(strings + i * ETH_GSTRING_LEN,
+                       strscpy(strings + i * ETH_GSTRING_LEN,
                                efx_sw_stat_desc[i].name, ETH_GSTRING_LEN);
                strings += EFX_ETHTOOL_SW_STAT_COUNT * ETH_GSTRING_LEN;
                strings += (efx_describe_per_queue_stats(efx, strings) *
index c7ea703..56a9c56 100644 (file)
@@ -285,7 +285,7 @@ efx_mcdi_mon_add_attr(struct efx_nic *efx, const char *name,
        struct efx_mcdi_mon *hwmon = efx_mcdi_mon(efx);
        struct efx_mcdi_mon_attribute *attr = &hwmon->attrs[hwmon->n_attrs];
 
-       strlcpy(attr->name, name, sizeof(attr->name));
+       strscpy(attr->name, name, sizeof(attr->name));
        attr->index = index;
        attr->type = type;
        if (type < ARRAY_SIZE(efx_mcdi_sensor_type))
index abf9a4a..0ea0433 100644 (file)
@@ -458,7 +458,7 @@ size_t efx_siena_describe_stats(const struct efx_hw_stat_desc *desc, size_t coun
        for_each_set_bit(index, mask, count) {
                if (desc[index].name) {
                        if (names) {
-                               strlcpy(names, desc[index].name,
+                               strscpy(names, desc[index].name,
                                        ETH_GSTRING_LEN);
                                names += ETH_GSTRING_LEN;
                        }
index e2d0098..8fc3f52 100644 (file)
@@ -1158,9 +1158,9 @@ static inline unsigned int ioc3_hash(const unsigned char *addr)
 static void ioc3_get_drvinfo(struct net_device *dev,
                             struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, IOC3_NAME, sizeof(info->driver));
-       strlcpy(info->version, IOC3_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(to_pci_dev(dev->dev.parent)),
+       strscpy(info->driver, IOC3_NAME, sizeof(info->driver));
+       strscpy(info->version, IOC3_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(to_pci_dev(dev->dev.parent)),
                sizeof(info->bus_info));
 }
 
index 216bb2d..dda4e48 100644 (file)
@@ -1769,9 +1769,9 @@ static void sis190_get_drvinfo(struct net_device *dev,
 {
        struct sis190_private *tp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(tp->pci_dev),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(tp->pci_dev),
                sizeof(info->bus_info));
 }
 
index 23a336c..cb7fec2 100644 (file)
@@ -2027,9 +2027,9 @@ static void sis900_get_drvinfo(struct net_device *net_dev,
 {
        struct sis900_private *sis_priv = netdev_priv(net_dev);
 
-       strlcpy(info->driver, SIS900_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->version, SIS900_DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(sis_priv->pci_dev),
+       strscpy(info->driver, SIS900_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->version, SIS900_DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(sis_priv->pci_dev),
                sizeof(info->bus_info));
 }
 
index 0329caf..83fe534 100644 (file)
@@ -1392,9 +1392,9 @@ static void netdev_get_drvinfo (struct net_device *dev, struct ethtool_drvinfo *
 {
        struct epic_private *np = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(np->pci_dev), sizeof(info->bus_info));
 }
 
 static int netdev_get_link_ksettings(struct net_device *dev,
index 24d66af..52ecfb4 100644 (file)
@@ -1509,9 +1509,9 @@ smc911x_ethtool_set_link_ksettings(struct net_device *dev,
 static void
 smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, CARDNAME, sizeof(info->driver));
-       strlcpy(info->version, version, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent),
+       strscpy(info->driver, CARDNAME, sizeof(info->driver));
+       strscpy(info->version, version, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(dev->dev.parent),
                sizeof(info->bus_info));
 }
 
index 37c822e..29bb19f 100644 (file)
@@ -1909,8 +1909,8 @@ static int check_if_running(struct net_device *dev)
 
 static void smc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static int smc_get_link_ksettings(struct net_device *dev,
index a31c159..35e99bf 100644 (file)
@@ -1588,9 +1588,9 @@ smc_ethtool_set_link_ksettings(struct net_device *dev,
 static void
 smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, CARDNAME, sizeof(info->driver));
-       strlcpy(info->version, version, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent),
+       strscpy(info->driver, CARDNAME, sizeof(info->driver));
+       strscpy(info->version, version, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(dev->dev.parent),
                sizeof(info->bus_info));
 }
 
index 3bf2021..a2e5119 100644 (file)
@@ -1037,6 +1037,8 @@ static int smsc911x_mii_probe(struct net_device *dev)
                return ret;
        }
 
+       /* Indicate that the MAC is responsible for managing PHY PM */
+       phydev->mac_managed_pm = true;
        phy_attached_info(phydev);
 
        phy_set_max_speed(phydev, SPEED_100);
@@ -1953,9 +1955,9 @@ static int smsc911x_set_mac_address(struct net_device *dev, void *p)
 static void smsc911x_ethtool_getdrvinfo(struct net_device *dev,
                                        struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver));
-       strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(dev->dev.parent),
+       strscpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver));
+       strscpy(info->version, SMSC_DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(dev->dev.parent),
                sizeof(info->bus_info));
 }
 
@@ -2587,6 +2589,8 @@ static int smsc911x_suspend(struct device *dev)
        if (netif_running(ndev)) {
                netif_stop_queue(ndev);
                netif_device_detach(ndev);
+               if (!device_may_wakeup(dev))
+                       phy_stop(ndev->phydev);
        }
 
        /* enable wake on LAN, energy detection and the external PME
@@ -2628,6 +2632,8 @@ static int smsc911x_resume(struct device *dev)
        if (netif_running(ndev)) {
                netif_device_attach(ndev);
                netif_start_queue(ndev);
+               if (!device_may_wakeup(dev))
+                       phy_start(ndev->phydev);
        }
 
        return 0;
index 0c68c7f..229180a 100644 (file)
@@ -215,10 +215,10 @@ static void smsc9420_ethtool_get_drvinfo(struct net_device *netdev,
 {
        struct smsc9420_pdata *pd = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->bus_info, pci_name(pd->pdev),
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->bus_info, pci_name(pd->pdev),
                sizeof(drvinfo->bus_info));
-       strlcpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
+       strscpy(drvinfo->version, DRV_VERSION, sizeof(drvinfo->version));
 }
 
 static u32 smsc9420_ethtool_get_msglevel(struct net_device *netdev)
index b0c5a44..85e62f5 100644 (file)
@@ -526,8 +526,8 @@ static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr)
 static void netsec_et_get_drvinfo(struct net_device *net_device,
                                  struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "netsec", sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(net_device->dev.parent),
+       strscpy(info->driver, "netsec", sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(net_device->dev.parent),
                sizeof(info->bus_info));
 }
 
index f0c8de2..ee341a3 100644 (file)
@@ -395,8 +395,8 @@ static void ave_ethtool_get_drvinfo(struct net_device *ndev,
 {
        struct device *dev = ndev->dev.parent;
 
-       strlcpy(info->driver, dev->driver->name, sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(dev), sizeof(info->bus_info));
+       strscpy(info->driver, dev->driver->name, sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(dev), sizeof(info->bus_info));
        ave_hw_read_version(ndev, info->fw_version, sizeof(info->fw_version));
 }
 
index 4f2b82a..7d3c7ca 100644 (file)
@@ -610,7 +610,6 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
        plat->int_snapshot_num = AUX_SNAPSHOT1;
        plat->ext_snapshot_num = AUX_SNAPSHOT0;
 
-       plat->has_crossts = true;
        plat->crosststamp = intel_crosststamp;
        plat->int_snapshot_en = 0;
 
index c469abc..15dea1f 100644 (file)
@@ -32,6 +32,8 @@ struct rk_gmac_ops {
        void (*set_to_rmii)(struct rk_priv_data *bsp_priv);
        void (*set_rgmii_speed)(struct rk_priv_data *bsp_priv, int speed);
        void (*set_rmii_speed)(struct rk_priv_data *bsp_priv, int speed);
+       void (*set_clock_selection)(struct rk_priv_data *bsp_priv, bool input,
+                                   bool enable);
        void (*integrated_phy_powerup)(struct rk_priv_data *bsp_priv);
        bool regs_valid;
        u32 regs[];
@@ -66,6 +68,7 @@ struct rk_priv_data {
        int rx_delay;
 
        struct regmap *grf;
+       struct regmap *php_grf;
 };
 
 #define HIWORD_UPDATE(val, mask, shift) \
@@ -1101,6 +1104,147 @@ static const struct rk_gmac_ops rk3568_ops = {
        },
 };
 
+/* sys_grf */
+#define RK3588_GRF_GMAC_CON7                   0X031c
+#define RK3588_GRF_GMAC_CON8                   0X0320
+#define RK3588_GRF_GMAC_CON9                   0X0324
+
+#define RK3588_GMAC_RXCLK_DLY_ENABLE(id)       GRF_BIT(2 * (id) + 3)
+#define RK3588_GMAC_RXCLK_DLY_DISABLE(id)      GRF_CLR_BIT(2 * (id) + 3)
+#define RK3588_GMAC_TXCLK_DLY_ENABLE(id)       GRF_BIT(2 * (id) + 2)
+#define RK3588_GMAC_TXCLK_DLY_DISABLE(id)      GRF_CLR_BIT(2 * (id) + 2)
+
+#define RK3588_GMAC_CLK_RX_DL_CFG(val)         HIWORD_UPDATE(val, 0xFF, 8)
+#define RK3588_GMAC_CLK_TX_DL_CFG(val)         HIWORD_UPDATE(val, 0xFF, 0)
+
+/* php_grf */
+#define RK3588_GRF_GMAC_CON0                   0X0008
+#define RK3588_GRF_CLK_CON1                    0X0070
+
+#define RK3588_GMAC_PHY_INTF_SEL_RGMII(id)     \
+       (GRF_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_CLR_BIT(5 + (id) * 6))
+#define RK3588_GMAC_PHY_INTF_SEL_RMII(id)      \
+       (GRF_CLR_BIT(3 + (id) * 6) | GRF_CLR_BIT(4 + (id) * 6) | GRF_BIT(5 + (id) * 6))
+
+#define RK3588_GMAC_CLK_RMII_MODE(id)          GRF_BIT(5 * (id))
+#define RK3588_GMAC_CLK_RGMII_MODE(id)         GRF_CLR_BIT(5 * (id))
+
+#define RK3588_GMAC_CLK_SELET_CRU(id)          GRF_BIT(5 * (id) + 4)
+#define RK3588_GMAC_CLK_SELET_IO(id)           GRF_CLR_BIT(5 * (id) + 4)
+
+#define RK3588_GMA_CLK_RMII_DIV2(id)           GRF_BIT(5 * (id) + 2)
+#define RK3588_GMA_CLK_RMII_DIV20(id)          GRF_CLR_BIT(5 * (id) + 2)
+
+#define RK3588_GMAC_CLK_RGMII_DIV1(id)         \
+                       (GRF_CLR_BIT(5 * (id) + 2) | GRF_CLR_BIT(5 * (id) + 3))
+#define RK3588_GMAC_CLK_RGMII_DIV5(id)         \
+                       (GRF_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
+#define RK3588_GMAC_CLK_RGMII_DIV50(id)                \
+                       (GRF_CLR_BIT(5 * (id) + 2) | GRF_BIT(5 * (id) + 3))
+
+#define RK3588_GMAC_CLK_RMII_GATE(id)          GRF_BIT(5 * (id) + 1)
+#define RK3588_GMAC_CLK_RMII_NOGATE(id)                GRF_CLR_BIT(5 * (id) + 1)
+
+static void rk3588_set_to_rgmii(struct rk_priv_data *bsp_priv,
+                               int tx_delay, int rx_delay)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+       u32 offset_con, id = bsp_priv->id;
+
+       if (IS_ERR(bsp_priv->grf) || IS_ERR(bsp_priv->php_grf)) {
+               dev_err(dev, "Missing rockchip,grf or rockchip,php_grf property\n");
+               return;
+       }
+
+       offset_con = bsp_priv->id == 1 ? RK3588_GRF_GMAC_CON9 :
+                                        RK3588_GRF_GMAC_CON8;
+
+       regmap_write(bsp_priv->php_grf, RK3588_GRF_GMAC_CON0,
+                    RK3588_GMAC_PHY_INTF_SEL_RGMII(id));
+
+       regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1,
+                    RK3588_GMAC_CLK_RGMII_MODE(id));
+
+       regmap_write(bsp_priv->grf, RK3588_GRF_GMAC_CON7,
+                    RK3588_GMAC_RXCLK_DLY_ENABLE(id) |
+                    RK3588_GMAC_TXCLK_DLY_ENABLE(id));
+
+       regmap_write(bsp_priv->grf, offset_con,
+                    RK3588_GMAC_CLK_RX_DL_CFG(rx_delay) |
+                    RK3588_GMAC_CLK_TX_DL_CFG(tx_delay));
+}
+
+static void rk3588_set_to_rmii(struct rk_priv_data *bsp_priv)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+
+       if (IS_ERR(bsp_priv->php_grf)) {
+               dev_err(dev, "%s: Missing rockchip,php_grf property\n", __func__);
+               return;
+       }
+
+       regmap_write(bsp_priv->php_grf, RK3588_GRF_GMAC_CON0,
+                    RK3588_GMAC_PHY_INTF_SEL_RMII(bsp_priv->id));
+
+       regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1,
+                    RK3588_GMAC_CLK_RMII_MODE(bsp_priv->id));
+}
+
+static void rk3588_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
+{
+       struct device *dev = &bsp_priv->pdev->dev;
+       unsigned int val = 0, id = bsp_priv->id;
+
+       switch (speed) {
+       case 10:
+               if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
+                       val = RK3588_GMA_CLK_RMII_DIV20(id);
+               else
+                       val = RK3588_GMAC_CLK_RGMII_DIV50(id);
+               break;
+       case 100:
+               if (bsp_priv->phy_iface == PHY_INTERFACE_MODE_RMII)
+                       val = RK3588_GMA_CLK_RMII_DIV2(id);
+               else
+                       val = RK3588_GMAC_CLK_RGMII_DIV5(id);
+               break;
+       case 1000:
+               if (bsp_priv->phy_iface != PHY_INTERFACE_MODE_RMII)
+                       val = RK3588_GMAC_CLK_RGMII_DIV1(id);
+               else
+                       goto err;
+               break;
+       default:
+               goto err;
+       }
+
+       regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1, val);
+
+       return;
+err:
+       dev_err(dev, "unknown speed value for GMAC speed=%d", speed);
+}
+
+static void rk3588_set_clock_selection(struct rk_priv_data *bsp_priv, bool input,
+                                      bool enable)
+{
+       unsigned int val = input ? RK3588_GMAC_CLK_SELET_IO(bsp_priv->id) :
+                                  RK3588_GMAC_CLK_SELET_CRU(bsp_priv->id);
+
+       val |= enable ? RK3588_GMAC_CLK_RMII_NOGATE(bsp_priv->id) :
+                       RK3588_GMAC_CLK_RMII_GATE(bsp_priv->id);
+
+       regmap_write(bsp_priv->php_grf, RK3588_GRF_CLK_CON1, val);
+}
+
+static const struct rk_gmac_ops rk3588_ops = {
+       .set_to_rgmii = rk3588_set_to_rgmii,
+       .set_to_rmii = rk3588_set_to_rmii,
+       .set_rgmii_speed = rk3588_set_gmac_speed,
+       .set_rmii_speed = rk3588_set_gmac_speed,
+       .set_clock_selection = rk3588_set_clock_selection,
+};
+
 #define RV1108_GRF_GMAC_CON0           0X0900
 
 /* RV1108_GRF_GMAC_CON0 */
@@ -1304,6 +1448,10 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
                        if (!IS_ERR(bsp_priv->clk_mac_speed))
                                clk_prepare_enable(bsp_priv->clk_mac_speed);
 
+                       if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
+                               bsp_priv->ops->set_clock_selection(bsp_priv,
+                                              bsp_priv->clock_input, true);
+
                        /**
                         * if (!IS_ERR(bsp_priv->clk_mac))
                         *      clk_prepare_enable(bsp_priv->clk_mac);
@@ -1330,6 +1478,10 @@ static int gmac_clk_enable(struct rk_priv_data *bsp_priv, bool enable)
                        clk_disable_unprepare(bsp_priv->mac_clk_tx);
 
                        clk_disable_unprepare(bsp_priv->clk_mac_speed);
+
+                       if (bsp_priv->ops && bsp_priv->ops->set_clock_selection)
+                               bsp_priv->ops->set_clock_selection(bsp_priv,
+                                             bsp_priv->clock_input, false);
                        /**
                         * if (!IS_ERR(bsp_priv->clk_mac))
                         *      clk_disable_unprepare(bsp_priv->clk_mac);
@@ -1444,6 +1596,8 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
 
        bsp_priv->grf = syscon_regmap_lookup_by_phandle(dev->of_node,
                                                        "rockchip,grf");
+       bsp_priv->php_grf = syscon_regmap_lookup_by_phandle(dev->of_node,
+                                                           "rockchip,php-grf");
 
        if (plat->phy_node) {
                bsp_priv->integrated_phy = of_property_read_bool(plat->phy_node,
@@ -1680,6 +1834,7 @@ static const struct of_device_id rk_gmac_dwmac_match[] = {
        { .compatible = "rockchip,rk3368-gmac", .data = &rk3368_ops },
        { .compatible = "rockchip,rk3399-gmac", .data = &rk3399_ops },
        { .compatible = "rockchip,rk3568-gmac", .data = &rk3568_ops },
+       { .compatible = "rockchip,rk3588-gmac", .data = &rk3588_ops },
        { .compatible = "rockchip,rv1108-gmac", .data = &rv1108_ops },
        { }
 };
index d6a44d5..f453b0d 100644 (file)
@@ -287,15 +287,15 @@ static void stmmac_ethtool_getdrvinfo(struct net_device *dev,
        struct stmmac_priv *priv = netdev_priv(dev);
 
        if (priv->plat->has_gmac || priv->plat->has_gmac4)
-               strlcpy(info->driver, GMAC_ETHTOOL_NAME, sizeof(info->driver));
+               strscpy(info->driver, GMAC_ETHTOOL_NAME, sizeof(info->driver));
        else if (priv->plat->has_xgmac)
-               strlcpy(info->driver, XGMAC_ETHTOOL_NAME, sizeof(info->driver));
+               strscpy(info->driver, XGMAC_ETHTOOL_NAME, sizeof(info->driver));
        else
-               strlcpy(info->driver, MAC100_ETHTOOL_NAME,
+               strscpy(info->driver, MAC100_ETHTOOL_NAME,
                        sizeof(info->driver));
 
        if (priv->plat->pdev) {
-               strlcpy(info->bus_info, pci_name(priv->plat->pdev),
+               strscpy(info->bus_info, pci_name(priv->plat->pdev),
                        sizeof(info->bus_info));
        }
 }
index 0b08b0e..19a3eb6 100644 (file)
@@ -4484,9 +4484,9 @@ static void cas_set_multicast(struct net_device *dev)
 static void cas_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
        struct cas *cp = netdev_priv(dev);
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(cp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(cp->pdev), sizeof(info->bus_info));
 }
 
 static int cas_get_link_ksettings(struct net_device *dev,
index 0cd8493..bc51a75 100644 (file)
@@ -63,8 +63,8 @@ static struct vio_version vsw_versions[] = {
 static void vsw_get_drvinfo(struct net_device *dev,
                            struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
 }
 
 static u32 vsw_get_msglevel(struct net_device *dev)
index df70df2..204a29e 100644 (file)
@@ -6798,12 +6798,12 @@ static void niu_get_drvinfo(struct net_device *dev,
        struct niu *np = netdev_priv(dev);
        struct niu_vpd *vpd = &np->vpd;
 
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
        snprintf(info->fw_version, sizeof(info->fw_version), "%d.%d",
                vpd->fcode_major, vpd->fcode_minor);
        if (np->parent->plat_type != PLAT_TYPE_NIU)
-               strlcpy(info->bus_info, pci_name(np->pdev),
+               strscpy(info->bus_info, pci_name(np->pdev),
                        sizeof(info->bus_info));
 }
 
index 531a6f4..34b9415 100644 (file)
@@ -1038,8 +1038,8 @@ static void bigmac_set_multicast(struct net_device *dev)
 /* Ethtool support... */
 static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "sunbmac", sizeof(info->driver));
-       strlcpy(info->version, "2.0", sizeof(info->version));
+       strscpy(info->driver, "sunbmac", sizeof(info->driver));
+       strscpy(info->version, "2.0", sizeof(info->version));
 }
 
 static u32 bigmac_get_link(struct net_device *dev)
index a14591b..6fb89c5 100644 (file)
@@ -2521,9 +2521,9 @@ static void gem_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
 {
        struct gem *gp = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(gp->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(gp->pdev), sizeof(info->bus_info));
 }
 
 static int gem_get_link_ksettings(struct net_device *dev,
index 8594ee8..1921054 100644 (file)
@@ -2467,11 +2467,11 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
 {
        struct happy_meal *hp = netdev_priv(dev);
 
-       strlcpy(info->driver, "sunhme", sizeof(info->driver));
-       strlcpy(info->version, "2.02", sizeof(info->version));
+       strscpy(info->driver, "sunhme", sizeof(info->driver));
+       strscpy(info->version, "2.02", sizeof(info->version));
        if (hp->happy_flags & HFLAG_PCI) {
                struct pci_dev *pdev = hp->happy_dev;
-               strlcpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info));
+               strscpy(info->bus_info, pci_name(pdev), sizeof(info->bus_info));
        }
 #ifdef CONFIG_SBUS
        else {
index efe0d33..6418fcc 100644 (file)
@@ -684,8 +684,8 @@ static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
        struct sunqe *qep = netdev_priv(dev);
        struct platform_device *op;
 
-       strlcpy(info->driver, "sunqe", sizeof(info->driver));
-       strlcpy(info->version, "3.0", sizeof(info->version));
+       strscpy(info->driver, "sunqe", sizeof(info->driver));
+       strscpy(info->version, "3.0", sizeof(info->version));
 
        op = qep->op;
        regs = of_get_property(op->dev.of_node, "reg", NULL);
index da81196..042b502 100644 (file)
@@ -60,8 +60,8 @@ static struct vio_version vnet_versions[] = {
 static void vnet_get_drvinfo(struct net_device *dev,
                             struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_MODULE_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_MODULE_VERSION, sizeof(info->version));
 }
 
 static u32 vnet_get_msglevel(struct net_device *dev)
index 5462066..38e478a 100644 (file)
@@ -62,7 +62,8 @@ static int spl2sw_ethernet_stop(struct net_device *ndev)
        return 0;
 }
 
-static int spl2sw_ethernet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+static netdev_tx_t spl2sw_ethernet_start_xmit(struct sk_buff *skb,
+                                             struct net_device *ndev)
 {
        struct spl2sw_mac *mac = netdev_priv(ndev);
        struct spl2sw_common *comm = mac->comm;
index 5c9b6c9..f8e1336 100644 (file)
@@ -54,8 +54,8 @@ static void xlgmac_default_config(struct xlgmac_pdata *pdata)
        pdata->phy_speed = SPEED_25000;
        pdata->sysclk_rate = XLGMAC_SYSCLOCK;
 
-       strlcpy(pdata->drv_name, XLGMAC_DRV_NAME, sizeof(pdata->drv_name));
-       strlcpy(pdata->drv_ver, XLGMAC_DRV_VERSION, sizeof(pdata->drv_ver));
+       strscpy(pdata->drv_name, XLGMAC_DRV_NAME, sizeof(pdata->drv_name));
+       strscpy(pdata->drv_ver, XLGMAC_DRV_VERSION, sizeof(pdata->drv_ver));
 }
 
 static void xlgmac_init_all_ops(struct xlgmac_pdata *pdata)
index 49f8c6b..e794da7 100644 (file)
@@ -102,9 +102,9 @@ static void xlgmac_ethtool_get_drvinfo(struct net_device *netdev,
        u32 ver = pdata->hw_feat.version;
        u32 snpsver, devid, userver;
 
-       strlcpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version));
-       strlcpy(drvinfo->bus_info, dev_name(pdata->dev),
+       strscpy(drvinfo->driver, pdata->drv_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, pdata->drv_ver, sizeof(drvinfo->version));
+       strscpy(drvinfo->bus_info, dev_name(pdata->dev),
                sizeof(drvinfo->bus_info));
        /* S|SNPSVER: Synopsys-defined Version
         * D|DEVID: Indicates the Device family
index 985073e..08ba658 100644 (file)
@@ -2133,10 +2133,10 @@ bdx_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 {
        struct bdx_priv *priv = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
-       strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(priv->pdev),
+       strscpy(drvinfo->driver, BDX_DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, BDX_DRV_VERSION, sizeof(drvinfo->version));
+       strscpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       strscpy(drvinfo->bus_info, pci_name(priv->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index fb30bc5..fce0666 100644 (file)
@@ -33,6 +33,7 @@ config TI_DAVINCI_MDIO
        tristate "TI DaVinci MDIO Support"
        depends on ARCH_DAVINCI || ARCH_OMAP2PLUS || ARCH_KEYSTONE || ARCH_K3 || COMPILE_TEST
        select PHYLIB
+       select MDIO_BITBANG
        help
          This driver supports TI's DaVinci MDIO module.
 
index abc1e42..c51e2af 100644 (file)
@@ -402,9 +402,9 @@ static void am65_cpsw_get_drvinfo(struct net_device *ndev,
 {
        struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
 
-       strlcpy(info->driver, dev_driver_string(common->dev),
+       strscpy(info->driver, dev_driver_string(common->dev),
                sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
+       strscpy(info->bus_info, dev_name(common->dev), sizeof(info->bus_info));
 }
 
 static u32 am65_cpsw_get_msglevel(struct net_device *ndev)
index f4a6b59..7ef5d82 100644 (file)
@@ -74,6 +74,9 @@
 #define AM65_CPSW_PORTN_REG_TS_VLAN_LTYPE_REG  0x318
 #define AM65_CPSW_PORTN_REG_TS_CTL_LTYPE2       0x31C
 
+#define AM65_CPSW_SGMII_CONTROL_REG            0x010
+#define AM65_CPSW_SGMII_CONTROL_MR_AN_ENABLE   BIT(0)
+
 #define AM65_CPSW_CTL_VLAN_AWARE               BIT(1)
 #define AM65_CPSW_CTL_P0_ENABLE                        BIT(2)
 #define AM65_CPSW_CTL_P0_TX_CRC_REMOVE         BIT(13)
@@ -590,11 +593,6 @@ static int am65_cpsw_nuss_ndo_slave_open(struct net_device *ndev)
        /* mac_sl should be configured via phy-link interface */
        am65_cpsw_sl_ctl_reset(port);
 
-       ret = phy_set_mode_ext(port->slave.ifphy, PHY_MODE_ETHERNET,
-                              port->slave.phy_if);
-       if (ret)
-               goto error_cleanup;
-
        ret = phylink_of_phy_connect(port->slave.phylink, port->slave.phy_node, 0);
        if (ret)
                goto error_cleanup;
@@ -1409,7 +1407,14 @@ static const struct net_device_ops am65_cpsw_nuss_netdev_ops = {
 static void am65_cpsw_nuss_mac_config(struct phylink_config *config, unsigned int mode,
                                      const struct phylink_link_state *state)
 {
-       /* Currently not used */
+       struct am65_cpsw_slave_data *slave = container_of(config, struct am65_cpsw_slave_data,
+                                                         phylink_config);
+       struct am65_cpsw_port *port = container_of(slave, struct am65_cpsw_port, slave);
+       struct am65_cpsw_common *common = port->common;
+
+       if (common->pdata.extra_modes & BIT(state->interface))
+               writel(AM65_CPSW_SGMII_CONTROL_MR_AN_ENABLE,
+                      port->sgmii_base + AM65_CPSW_SGMII_CONTROL_REG);
 }
 
 static void am65_cpsw_nuss_mac_link_down(struct phylink_config *config, unsigned int mode,
@@ -1847,6 +1852,8 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
                port->common = common;
                port->port_base = common->cpsw_base + AM65_CPSW_NU_PORTS_BASE +
                                  AM65_CPSW_NU_PORTS_OFFSET * (port_id);
+               if (common->pdata.extra_modes)
+                       port->sgmii_base = common->ss_base + AM65_CPSW_SGMII_BASE * (port_id);
                port->stat_base = common->cpsw_base + AM65_CPSW_NU_STATS_BASE +
                                  (AM65_CPSW_NU_STATS_PORT_OFFSET * port_id);
                port->name = of_get_property(port_np, "label", NULL);
@@ -1886,6 +1893,10 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
                        goto of_node_put;
                }
 
+               ret = phy_set_mode_ext(port->slave.ifphy, PHY_MODE_ETHERNET, port->slave.phy_if);
+               if (ret)
+                       goto of_node_put;
+
                ret = of_get_mac_address(port_np, port->slave.mac_addr);
                if (ret) {
                        am65_cpsw_am654_get_efuse_macid(port_np,
@@ -1981,7 +1992,18 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
        port->slave.phylink_config.type = PHYLINK_NETDEV;
        port->slave.phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;
 
-       phy_interface_set_rgmii(port->slave.phylink_config.supported_interfaces);
+       if (phy_interface_mode_is_rgmii(port->slave.phy_if)) {
+               phy_interface_set_rgmii(port->slave.phylink_config.supported_interfaces);
+       } else if (port->slave.phy_if == PHY_INTERFACE_MODE_RMII) {
+               __set_bit(PHY_INTERFACE_MODE_RMII,
+                         port->slave.phylink_config.supported_interfaces);
+       } else if (common->pdata.extra_modes & BIT(port->slave.phy_if)) {
+               __set_bit(PHY_INTERFACE_MODE_QSGMII,
+                         port->slave.phylink_config.supported_interfaces);
+       } else {
+               dev_err(dev, "selected phy-mode is not supported\n");
+               return -EOPNOTSUPP;
+       }
 
        phylink = phylink_create(&port->slave.phylink_config,
                                 of_node_to_fwnode(port->slave.phy_node),
@@ -2611,10 +2633,18 @@ static const struct am65_cpsw_pdata am64x_cpswxg_pdata = {
        .fdqring_mode = K3_RINGACC_RING_MODE_RING,
 };
 
+static const struct am65_cpsw_pdata j7200_cpswxg_pdata = {
+       .quirks = 0,
+       .ale_dev_id = "am64-cpswxg",
+       .fdqring_mode = K3_RINGACC_RING_MODE_RING,
+       .extra_modes = BIT(PHY_INTERFACE_MODE_QSGMII),
+};
+
 static const struct of_device_id am65_cpsw_nuss_of_mtable[] = {
        { .compatible = "ti,am654-cpsw-nuss", .data = &am65x_sr1_0},
        { .compatible = "ti,j721e-cpsw-nuss", .data = &j721e_pdata},
        { .compatible = "ti,am642-cpsw-nuss", .data = &am64x_cpswxg_pdata},
+       { .compatible = "ti,j7200-cpswxg-nuss", .data = &j7200_cpswxg_pdata},
        { /* sentinel */ },
 };
 MODULE_DEVICE_TABLE(of, am65_cpsw_nuss_of_mtable);
index ac94563..2c9850f 100644 (file)
@@ -46,6 +46,7 @@ struct am65_cpsw_port {
        const char                      *name;
        u32                             port_id;
        void __iomem                    *port_base;
+       void __iomem                    *sgmii_base;
        void __iomem                    *stat_base;
        void __iomem                    *fetch_ram_base;
        bool                            disabled;
@@ -88,6 +89,7 @@ struct am65_cpsw_rx_chn {
 
 struct am65_cpsw_pdata {
        u32     quirks;
+       u64     extra_modes;
        enum k3_ring_mode fdqring_mode;
        const char      *ale_dev_id;
 };
index bef5e68..ce92d33 100644 (file)
@@ -851,8 +851,8 @@ static int cpmac_set_ringparam(struct net_device *dev,
 static void cpmac_get_drvinfo(struct net_device *dev,
                              struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "cpmac", sizeof(info->driver));
-       strlcpy(info->version, CPMAC_VERSION, sizeof(info->version));
+       strscpy(info->driver, "cpmac", sizeof(info->driver));
+       strscpy(info->version, CPMAC_VERSION, sizeof(info->version));
        snprintf(info->bus_info, sizeof(info->bus_info), "%s", "cpmac");
 }
 
index ed66c4d..312250c 100644 (file)
@@ -1172,9 +1172,9 @@ static void cpsw_get_drvinfo(struct net_device *ndev,
        struct cpsw_common *cpsw = ndev_to_cpsw(ndev);
        struct platform_device  *pdev = to_platform_device(cpsw->dev);
 
-       strlcpy(info->driver, "cpsw", sizeof(info->driver));
-       strlcpy(info->version, "1.0", sizeof(info->version));
-       strlcpy(info->bus_info, pdev->name, sizeof(info->bus_info));
+       strscpy(info->driver, "cpsw", sizeof(info->driver));
+       strscpy(info->version, "1.0", sizeof(info->version));
+       strscpy(info->bus_info, pdev->name, sizeof(info->bus_info));
 }
 
 static int cpsw_set_pauseparam(struct net_device *ndev,
index 353e58b..007de15 100644 (file)
@@ -1146,9 +1146,9 @@ static void cpsw_get_drvinfo(struct net_device *ndev,
        struct platform_device *pdev;
 
        pdev = to_platform_device(cpsw->dev);
-       strlcpy(info->driver, "cpsw-switch", sizeof(info->driver));
-       strlcpy(info->version, "2.0", sizeof(info->version));
-       strlcpy(info->bus_info, pdev->name, sizeof(info->bus_info));
+       strscpy(info->driver, "cpsw-switch", sizeof(info->driver));
+       strscpy(info->version, "2.0", sizeof(info->version));
+       strscpy(info->bus_info, pdev->name, sizeof(info->bus_info));
 }
 
 static int cpsw_set_pauseparam(struct net_device *ndev,
index 2a3e4e8..0d6a099 100644 (file)
@@ -374,8 +374,8 @@ static char *emac_rxhost_errcodes[16] = {
 static void emac_get_drvinfo(struct net_device *ndev,
                             struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, emac_version_string, sizeof(info->driver));
-       strlcpy(info->version, EMAC_MODULE_VERSION, sizeof(info->version));
+       strscpy(info->driver, emac_version_string, sizeof(info->driver));
+       strscpy(info->version, EMAC_MODULE_VERSION, sizeof(info->version));
 }
 
 /**
index ea37726..946b975 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/of_device.h>
 #include <linux/of_mdio.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/sys_soc.h>
 
 /*
  * This timeout definition is a worst-case ultra defensive measure against
@@ -41,6 +43,7 @@
 
 struct davinci_mdio_of_param {
        int autosuspend_delay_ms;
+       bool manual_mode;
 };
 
 struct davinci_mdio_regs {
@@ -49,6 +52,15 @@ struct davinci_mdio_regs {
 #define CONTROL_IDLE           BIT(31)
 #define CONTROL_ENABLE         BIT(30)
 #define CONTROL_MAX_DIV                (0xffff)
+#define CONTROL_CLKDIV         GENMASK(15, 0)
+
+#define MDIO_MAN_MDCLK_O       BIT(2)
+#define MDIO_MAN_OE            BIT(1)
+#define MDIO_MAN_PIN           BIT(0)
+#define MDIO_MANUALMODE                BIT(31)
+
+#define MDIO_PIN               0
+
 
        u32     alive;
        u32     link;
@@ -59,7 +71,9 @@ struct davinci_mdio_regs {
        u32     userintmasked;
        u32     userintmaskset;
        u32     userintmaskclr;
-       u32     __reserved_1[20];
+       u32     manualif;
+       u32     poll;
+       u32     __reserved_1[18];
 
        struct {
                u32     access;
@@ -79,6 +93,7 @@ static const struct mdio_platform_data default_pdata = {
 
 struct davinci_mdio_data {
        struct mdio_platform_data pdata;
+       struct mdiobb_ctrl bb_ctrl;
        struct davinci_mdio_regs __iomem *regs;
        struct clk      *clk;
        struct device   *dev;
@@ -90,6 +105,7 @@ struct davinci_mdio_data {
         */
        bool            skip_scan;
        u32             clk_div;
+       bool            manual_mode;
 };
 
 static void davinci_mdio_init_clk(struct davinci_mdio_data *data)
@@ -128,9 +144,122 @@ static void davinci_mdio_enable(struct davinci_mdio_data *data)
        writel(data->clk_div | CONTROL_ENABLE, &data->regs->control);
 }
 
-static int davinci_mdio_reset(struct mii_bus *bus)
+static void davinci_mdio_disable(struct davinci_mdio_data *data)
+{
+       u32 reg;
+
+       /* Disable MDIO state machine */
+       reg = readl(&data->regs->control);
+
+       reg &= ~CONTROL_CLKDIV;
+       reg |= data->clk_div;
+
+       reg &= ~CONTROL_ENABLE;
+       writel(reg, &data->regs->control);
+}
+
+static void davinci_mdio_enable_manual_mode(struct davinci_mdio_data *data)
+{
+       u32 reg;
+       /* set manual mode */
+       reg = readl(&data->regs->poll);
+       reg |= MDIO_MANUALMODE;
+       writel(reg, &data->regs->poll);
+}
+
+static void davinci_set_mdc(struct mdiobb_ctrl *ctrl, int level)
+{
+       struct davinci_mdio_data *data;
+       u32 reg;
+
+       data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl);
+       reg = readl(&data->regs->manualif);
+
+       if (level)
+               reg |= MDIO_MAN_MDCLK_O;
+       else
+               reg &= ~MDIO_MAN_MDCLK_O;
+
+       writel(reg, &data->regs->manualif);
+}
+
+static void davinci_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output)
+{
+       struct davinci_mdio_data *data;
+       u32 reg;
+
+       data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl);
+       reg = readl(&data->regs->manualif);
+
+       if (output)
+               reg |= MDIO_MAN_OE;
+       else
+               reg &= ~MDIO_MAN_OE;
+
+       writel(reg, &data->regs->manualif);
+}
+
+static void  davinci_set_mdio_data(struct mdiobb_ctrl *ctrl, int value)
+{
+       struct davinci_mdio_data *data;
+       u32 reg;
+
+       data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl);
+       reg = readl(&data->regs->manualif);
+
+       if (value)
+               reg |= MDIO_MAN_PIN;
+       else
+               reg &= ~MDIO_MAN_PIN;
+
+       writel(reg, &data->regs->manualif);
+}
+
+static int davinci_get_mdio_data(struct mdiobb_ctrl *ctrl)
+{
+       struct davinci_mdio_data *data;
+       unsigned long reg;
+
+       data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl);
+       reg = readl(&data->regs->manualif);
+       return test_bit(MDIO_PIN, &reg);
+}
+
+static int davinci_mdiobb_read(struct mii_bus *bus, int phy, int reg)
+{
+       int ret;
+
+       ret = pm_runtime_resume_and_get(bus->parent);
+       if (ret < 0)
+               return ret;
+
+       ret = mdiobb_read(bus, phy, reg);
+
+       pm_runtime_mark_last_busy(bus->parent);
+       pm_runtime_put_autosuspend(bus->parent);
+
+       return ret;
+}
+
+static int davinci_mdiobb_write(struct mii_bus *bus, int phy, int reg,
+                               u16 val)
+{
+       int ret;
+
+       ret = pm_runtime_resume_and_get(bus->parent);
+       if (ret < 0)
+               return ret;
+
+       ret = mdiobb_write(bus, phy, reg, val);
+
+       pm_runtime_mark_last_busy(bus->parent);
+       pm_runtime_put_autosuspend(bus->parent);
+
+       return ret;
+}
+
+static int davinci_mdio_common_reset(struct davinci_mdio_data *data)
 {
-       struct davinci_mdio_data *data = bus->priv;
        u32 phy_mask, ver;
        int ret;
 
@@ -138,6 +267,11 @@ static int davinci_mdio_reset(struct mii_bus *bus)
        if (ret < 0)
                return ret;
 
+       if (data->manual_mode) {
+               davinci_mdio_disable(data);
+               davinci_mdio_enable_manual_mode(data);
+       }
+
        /* wait for scan logic to settle */
        msleep(PHY_MAX_ADDR * data->access_time);
 
@@ -171,6 +305,23 @@ done:
        return 0;
 }
 
+static int davinci_mdio_reset(struct mii_bus *bus)
+{
+       struct davinci_mdio_data *data = bus->priv;
+
+       return davinci_mdio_common_reset(data);
+}
+
+static int davinci_mdiobb_reset(struct mii_bus *bus)
+{
+       struct mdiobb_ctrl *ctrl = bus->priv;
+       struct davinci_mdio_data *data;
+
+       data = container_of(ctrl, struct davinci_mdio_data, bb_ctrl);
+
+       return davinci_mdio_common_reset(data);
+}
+
 /* wait until hardware is ready for another user access */
 static inline int wait_for_user_access(struct davinci_mdio_data *data)
 {
@@ -318,6 +469,28 @@ static int davinci_mdio_probe_dt(struct mdio_platform_data *data,
        return 0;
 }
 
+struct k3_mdio_soc_data {
+       bool manual_mode;
+};
+
+static const struct k3_mdio_soc_data am65_mdio_soc_data = {
+       .manual_mode = true,
+};
+
+static const struct soc_device_attribute k3_mdio_socinfo[] = {
+       { .family = "AM62X", .revision = "SR1.0", .data = &am65_mdio_soc_data },
+       { .family = "AM64X", .revision = "SR1.0", .data = &am65_mdio_soc_data },
+       { .family = "AM64X", .revision = "SR2.0", .data = &am65_mdio_soc_data },
+       { .family = "AM65X", .revision = "SR1.0", .data = &am65_mdio_soc_data },
+       { .family = "AM65X", .revision = "SR2.0", .data = &am65_mdio_soc_data },
+       { .family = "J7200", .revision = "SR1.0", .data = &am65_mdio_soc_data },
+       { .family = "J7200", .revision = "SR2.0", .data = &am65_mdio_soc_data },
+       { .family = "J721E", .revision = "SR1.0", .data = &am65_mdio_soc_data },
+       { .family = "J721E", .revision = "SR2.0", .data = &am65_mdio_soc_data },
+       { .family = "J721S2", .revision = "SR1.0", .data = &am65_mdio_soc_data},
+       { /* sentinel */ },
+};
+
 #if IS_ENABLED(CONFIG_OF)
 static const struct davinci_mdio_of_param of_cpsw_mdio_data = {
        .autosuspend_delay_ms = 100,
@@ -331,6 +504,14 @@ static const struct of_device_id davinci_mdio_of_mtable[] = {
 MODULE_DEVICE_TABLE(of, davinci_mdio_of_mtable);
 #endif
 
+static const struct mdiobb_ops davinci_mdiobb_ops = {
+       .owner = THIS_MODULE,
+       .set_mdc = davinci_set_mdc,
+       .set_mdio_dir = davinci_set_mdio_dir,
+       .set_mdio_data = davinci_set_mdio_data,
+       .get_mdio_data = davinci_get_mdio_data,
+};
+
 static int davinci_mdio_probe(struct platform_device *pdev)
 {
        struct mdio_platform_data *pdata = dev_get_platdata(&pdev->dev);
@@ -345,7 +526,26 @@ static int davinci_mdio_probe(struct platform_device *pdev)
        if (!data)
                return -ENOMEM;
 
-       data->bus = devm_mdiobus_alloc(dev);
+       data->manual_mode = false;
+       data->bb_ctrl.ops = &davinci_mdiobb_ops;
+
+       if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+               const struct soc_device_attribute *soc_match_data;
+
+               soc_match_data = soc_device_match(k3_mdio_socinfo);
+               if (soc_match_data && soc_match_data->data) {
+                       const struct k3_mdio_soc_data *socdata =
+                                               soc_match_data->data;
+
+                       data->manual_mode = socdata->manual_mode;
+               }
+       }
+
+       if (data->manual_mode)
+               data->bus = alloc_mdio_bitbang(&data->bb_ctrl);
+       else
+               data->bus = devm_mdiobus_alloc(dev);
+
        if (!data->bus) {
                dev_err(dev, "failed to alloc mii bus\n");
                return -ENOMEM;
@@ -371,11 +571,20 @@ static int davinci_mdio_probe(struct platform_device *pdev)
        }
 
        data->bus->name         = dev_name(dev);
-       data->bus->read         = davinci_mdio_read;
-       data->bus->write        = davinci_mdio_write;
-       data->bus->reset        = davinci_mdio_reset;
+
+       if (data->manual_mode) {
+               data->bus->read         = davinci_mdiobb_read;
+               data->bus->write        = davinci_mdiobb_write;
+               data->bus->reset        = davinci_mdiobb_reset;
+
+               dev_info(dev, "Configuring MDIO in manual mode\n");
+       } else {
+               data->bus->read         = davinci_mdio_read;
+               data->bus->write        = davinci_mdio_write;
+               data->bus->reset        = davinci_mdio_reset;
+               data->bus->priv         = data;
+       }
        data->bus->parent       = dev;
-       data->bus->priv         = data;
 
        data->clk = devm_clk_get(dev, "fck");
        if (IS_ERR(data->clk)) {
@@ -433,9 +642,13 @@ static int davinci_mdio_remove(struct platform_device *pdev)
 {
        struct davinci_mdio_data *data = platform_get_drvdata(pdev);
 
-       if (data->bus)
+       if (data->bus) {
                mdiobus_unregister(data->bus);
 
+               if (data->manual_mode)
+                       free_mdio_bitbang(data->bus);
+       }
+
        pm_runtime_dont_use_autosuspend(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
 
@@ -452,7 +665,9 @@ static int davinci_mdio_runtime_suspend(struct device *dev)
        ctrl = readl(&data->regs->control);
        ctrl &= ~CONTROL_ENABLE;
        writel(ctrl, &data->regs->control);
-       wait_for_idle(data);
+
+       if (!data->manual_mode)
+               wait_for_idle(data);
 
        return 0;
 }
@@ -461,7 +676,12 @@ static int davinci_mdio_runtime_resume(struct device *dev)
 {
        struct davinci_mdio_data *data = dev_get_drvdata(dev);
 
-       davinci_mdio_enable(data);
+       if (data->manual_mode) {
+               davinci_mdio_disable(data);
+               davinci_mdio_enable_manual_mode(data);
+       } else {
+               davinci_mdio_enable(data);
+       }
        return 0;
 }
 #endif
index 741c42c..b3da76e 100644 (file)
@@ -762,12 +762,12 @@ static void tlan_get_drvinfo(struct net_device *dev,
 {
        struct tlan_priv *priv = netdev_priv(dev);
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
        if (priv->pci_dev)
-               strlcpy(info->bus_info, pci_name(priv->pci_dev),
+               strscpy(info->bus_info, pci_name(priv->pci_dev),
                        sizeof(info->bus_info));
        else
-               strlcpy(info->bus_info, "EISA", sizeof(info->bus_info));
+               strscpy(info->bus_info, "EISA", sizeof(info->bus_info));
 }
 
 static int tlan_get_eeprom_len(struct net_device *dev)
index 3dbfb1b..6e838e8 100644 (file)
@@ -1187,8 +1187,8 @@ int gelic_net_open(struct net_device *netdev)
 void gelic_net_get_drvinfo(struct net_device *netdev,
                           struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static int gelic_ether_get_link_ksettings(struct net_device *netdev,
index 93110db..fef9fd1 100644 (file)
@@ -63,12 +63,12 @@ spider_net_ethtool_get_drvinfo(struct net_device *netdev,
        card = netdev_priv(netdev);
 
        /* clear and fill out info */
-       strlcpy(drvinfo->driver, spider_net_driver_name,
+       strscpy(drvinfo->driver, spider_net_driver_name,
                sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, VERSION, sizeof(drvinfo->version));
-       strlcpy(drvinfo->fw_version, "no information",
+       strscpy(drvinfo->version, VERSION, sizeof(drvinfo->version));
+       strscpy(drvinfo->fw_version, "no information",
                sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, pci_name(card->pdev),
+       strscpy(drvinfo->bus_info, pci_name(card->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 47aab9c..b50be67 100644 (file)
@@ -1956,9 +1956,9 @@ static void tc35815_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *
 {
        struct tc35815_local *lp = netdev_priv(dev);
 
-       strlcpy(info->driver, MODNAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(lp->pci_dev), sizeof(info->bus_info));
+       strscpy(info->driver, MODNAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(lp->pci_dev), sizeof(info->bus_info));
 }
 
 static u32 tc35815_get_msglevel(struct net_device *dev)
index eb39a45..30a2f38 100644 (file)
@@ -762,6 +762,6 @@ static struct spi_driver mse102x_driver = {
 module_spi_driver(mse102x_driver);
 
 MODULE_DESCRIPTION("MSE102x Network driver");
-MODULE_AUTHOR("Stefan Wahren <stefan.wahren@in-tech.com>");
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@chargebyte.com>");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("spi:" DRV_NAME);
index 509c5e9..29cde0b 100644 (file)
@@ -2281,8 +2281,8 @@ static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *i
 {
        struct device *hwdev = dev->dev.parent;
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->bus_info, dev_name(hwdev), sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->bus_info, dev_name(hwdev), sizeof(info->bus_info));
 }
 
 static int netdev_get_link_ksettings(struct net_device *dev,
index ff0c102..5d710eb 100644 (file)
@@ -3419,13 +3419,13 @@ static void velocity_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo
 {
        struct velocity_info *vptr = netdev_priv(dev);
 
-       strlcpy(info->driver, VELOCITY_NAME, sizeof(info->driver));
-       strlcpy(info->version, VELOCITY_VERSION, sizeof(info->version));
+       strscpy(info->driver, VELOCITY_NAME, sizeof(info->driver));
+       strscpy(info->version, VELOCITY_VERSION, sizeof(info->version));
        if (vptr->pdev)
-               strlcpy(info->bus_info, pci_name(vptr->pdev),
+               strscpy(info->bus_info, pci_name(vptr->pdev),
                                                sizeof(info->bus_info));
        else
-               strlcpy(info->bus_info, "platform", sizeof(info->bus_info));
+               strscpy(info->bus_info, "platform", sizeof(info->bus_info));
 }
 
 static void velocity_ethtool_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
index b4a4fa0..f5d43d8 100644 (file)
@@ -16,6 +16,19 @@ config NET_VENDOR_WANGXUN
 
 if NET_VENDOR_WANGXUN
 
+config NGBE
+       tristate "Wangxun(R) GbE PCI Express adapters support"
+       depends on PCI
+       help
+         This driver supports Wangxun(R) GbE PCI Express family of
+         adapters.
+
+         More specific information on configuring the driver is in
+         <file:Documentation/networking/device_drivers/ethernet/wangxun/ngbe.rst>.
+
+         To compile this driver as a module, choose M here. The module
+         will be called ngbe.
+
 config TXGBE
        tristate "Wangxun(R) 10GbE PCI Express adapters support"
        depends on PCI
index c34db1b..ac3fb06 100644 (file)
@@ -4,3 +4,4 @@
 #
 
 obj-$(CONFIG_TXGBE) += txgbe/
+obj-$(CONFIG_NGBE) += ngbe/
diff --git a/drivers/net/ethernet/wangxun/ngbe/Makefile b/drivers/net/ethernet/wangxun/ngbe/Makefile
new file mode 100644 (file)
index 0000000..0baf759
--- /dev/null
@@ -0,0 +1,9 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd.
+#
+# Makefile for the Wangxun(R) GbE PCI Express ethernet driver
+#
+
+obj-$(CONFIG_NGBE) += ngbe.o
+
+ngbe-objs := ngbe_main.o
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe.h b/drivers/net/ethernet/wangxun/ngbe/ngbe.h
new file mode 100644 (file)
index 0000000..f5fa6e5
--- /dev/null
@@ -0,0 +1,24 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
+
+#ifndef _NGBE_H_
+#define _NGBE_H_
+
+#include "ngbe_type.h"
+
+#define NGBE_MAX_FDIR_INDICES          7
+
+#define NGBE_MAX_RX_QUEUES             (NGBE_MAX_FDIR_INDICES + 1)
+#define NGBE_MAX_TX_QUEUES             (NGBE_MAX_FDIR_INDICES + 1)
+
+/* board specific private data structure */
+struct ngbe_adapter {
+       u8 __iomem *io_addr;    /* Mainly for iounmap use */
+       /* OS defined structs */
+       struct net_device *netdev;
+       struct pci_dev *pdev;
+};
+
+extern char ngbe_driver_name[];
+
+#endif /* _NGBE_H_ */
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c b/drivers/net/ethernet/wangxun/ngbe/ngbe_main.c
new file mode 100644 (file)
index 0000000..7674cb6
--- /dev/null
@@ -0,0 +1,170 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/string.h>
+#include <linux/aer.h>
+#include <linux/etherdevice.h>
+
+#include "ngbe.h"
+char ngbe_driver_name[] = "ngbe";
+
+/* ngbe_pci_tbl - PCI Device ID Table
+ *
+ * { Vendor ID, Device ID, SubVendor ID, SubDevice ID,
+ *   Class, Class Mask, private data (not used) }
+ */
+static const struct pci_device_id ngbe_pci_tbl[] = {
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL_W), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A2), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A2S), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A4), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A4S), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL2), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL2S), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL4), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860AL4S), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860LC), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A1), 0},
+       { PCI_VDEVICE(WANGXUN, NGBE_DEV_ID_EM_WX1860A1L), 0},
+       /* required last entry */
+       { .device = 0 }
+};
+
+static void ngbe_dev_shutdown(struct pci_dev *pdev, bool *enable_wake)
+{
+       struct ngbe_adapter *adapter = pci_get_drvdata(pdev);
+       struct net_device *netdev = adapter->netdev;
+
+       netif_device_detach(netdev);
+
+       pci_disable_device(pdev);
+}
+
+static void ngbe_shutdown(struct pci_dev *pdev)
+{
+       bool wake;
+
+       ngbe_dev_shutdown(pdev, &wake);
+
+       if (system_state == SYSTEM_POWER_OFF) {
+               pci_wake_from_d3(pdev, wake);
+               pci_set_power_state(pdev, PCI_D3hot);
+       }
+}
+
+/**
+ * ngbe_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @ent: entry in ngbe_pci_tbl
+ *
+ * Returns 0 on success, negative on failure
+ *
+ * ngbe_probe initializes an adapter identified by a pci_dev structure.
+ * The OS initialization, configuring of the adapter private structure,
+ * and a hardware reset occur.
+ **/
+static int ngbe_probe(struct pci_dev *pdev,
+                     const struct pci_device_id __always_unused *ent)
+{
+       struct ngbe_adapter *adapter = NULL;
+       struct net_device *netdev;
+       int err;
+
+       err = pci_enable_device_mem(pdev);
+       if (err)
+               return err;
+
+       err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+       if (err) {
+               dev_err(&pdev->dev,
+                       "No usable DMA configuration, aborting\n");
+               goto err_pci_disable_dev;
+       }
+
+       err = pci_request_selected_regions(pdev,
+                                          pci_select_bars(pdev, IORESOURCE_MEM),
+                                          ngbe_driver_name);
+       if (err) {
+               dev_err(&pdev->dev,
+                       "pci_request_selected_regions failed %d\n", err);
+               goto err_pci_disable_dev;
+       }
+
+       pci_enable_pcie_error_reporting(pdev);
+       pci_set_master(pdev);
+
+       netdev = devm_alloc_etherdev_mqs(&pdev->dev,
+                                        sizeof(struct ngbe_adapter),
+                                        NGBE_MAX_TX_QUEUES,
+                                        NGBE_MAX_RX_QUEUES);
+       if (!netdev) {
+               err = -ENOMEM;
+               goto err_pci_release_regions;
+       }
+
+       SET_NETDEV_DEV(netdev, &pdev->dev);
+
+       adapter = netdev_priv(netdev);
+       adapter->netdev = netdev;
+       adapter->pdev = pdev;
+
+       adapter->io_addr = devm_ioremap(&pdev->dev,
+                                       pci_resource_start(pdev, 0),
+                                       pci_resource_len(pdev, 0));
+       if (!adapter->io_addr) {
+               err = -EIO;
+               goto err_pci_release_regions;
+       }
+
+       netdev->features |= NETIF_F_HIGHDMA;
+
+       pci_set_drvdata(pdev, adapter);
+
+       return 0;
+
+err_pci_release_regions:
+       pci_disable_pcie_error_reporting(pdev);
+       pci_release_selected_regions(pdev,
+                                    pci_select_bars(pdev, IORESOURCE_MEM));
+err_pci_disable_dev:
+       pci_disable_device(pdev);
+       return err;
+}
+
+/**
+ * ngbe_remove - Device Removal Routine
+ * @pdev: PCI device information struct
+ *
+ * ngbe_remove is called by the PCI subsystem to alert the driver
+ * that it should release a PCI device.  The could be caused by a
+ * Hot-Plug event, or because the driver is going to be removed from
+ * memory.
+ **/
+static void ngbe_remove(struct pci_dev *pdev)
+{
+       pci_release_selected_regions(pdev,
+                                    pci_select_bars(pdev, IORESOURCE_MEM));
+
+       pci_disable_pcie_error_reporting(pdev);
+
+       pci_disable_device(pdev);
+}
+
+static struct pci_driver ngbe_driver = {
+       .name     = ngbe_driver_name,
+       .id_table = ngbe_pci_tbl,
+       .probe    = ngbe_probe,
+       .remove   = ngbe_remove,
+       .shutdown = ngbe_shutdown,
+};
+
+module_pci_driver(ngbe_driver);
+
+MODULE_DEVICE_TABLE(pci, ngbe_pci_tbl);
+MODULE_AUTHOR("Beijing WangXun Technology Co., Ltd, <software@net-swift.com>");
+MODULE_DESCRIPTION("WangXun(R) Gigabit PCI Express Network Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h b/drivers/net/ethernet/wangxun/ngbe/ngbe_type.h
new file mode 100644 (file)
index 0000000..26e776c
--- /dev/null
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 - 2022 Beijing WangXun Technology Co., Ltd. */
+
+#ifndef _NGBE_TYPE_H_
+#define _NGBE_TYPE_H_
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+/************ NGBE_register.h ************/
+/* Vendor ID */
+#ifndef PCI_VENDOR_ID_WANGXUN
+#define PCI_VENDOR_ID_WANGXUN                  0x8088
+#endif
+
+/* Device IDs */
+#define NGBE_DEV_ID_EM_WX1860AL_W              0x0100
+#define NGBE_DEV_ID_EM_WX1860A2                        0x0101
+#define NGBE_DEV_ID_EM_WX1860A2S               0x0102
+#define NGBE_DEV_ID_EM_WX1860A4                        0x0103
+#define NGBE_DEV_ID_EM_WX1860A4S               0x0104
+#define NGBE_DEV_ID_EM_WX1860AL2               0x0105
+#define NGBE_DEV_ID_EM_WX1860AL2S              0x0106
+#define NGBE_DEV_ID_EM_WX1860AL4               0x0107
+#define NGBE_DEV_ID_EM_WX1860AL4S              0x0108
+#define NGBE_DEV_ID_EM_WX1860LC                        0x0109
+#define NGBE_DEV_ID_EM_WX1860A1                        0x010a
+#define NGBE_DEV_ID_EM_WX1860A1L               0x010b
+
+/* Subsystem ID */
+#define NGBE_SUBID_M88E1512_SFP                        0x0003
+#define NGBE_SUBID_OCP_CARD                    0x0040
+#define NGBE_SUBID_LY_M88E1512_SFP             0x0050
+#define NGBE_SUBID_M88E1512_RJ45               0x0051
+#define NGBE_SUBID_M88E1512_MIX                        0x0052
+#define NGBE_SUBID_YT8521S_SFP                 0x0060
+#define NGBE_SUBID_INTERNAL_YT8521S_SFP                0x0061
+#define NGBE_SUBID_YT8521S_SFP_GPIO            0x0062
+#define NGBE_SUBID_INTERNAL_YT8521S_SFP_GPIO   0x0064
+#define NGBE_SUBID_LY_YT8521S_SFP              0x0070
+#define NGBE_SUBID_RGMII_FPGA                  0x0080
+
+#define NGBE_OEM_MASK                          0x00FF
+
+#define NGBE_NCSI_SUP                          0x8000
+#define NGBE_NCSI_MASK                         0x8000
+#define NGBE_WOL_SUP                           0x4000
+#define NGBE_WOL_MASK                          0x4000
+
+#endif /* _NGBE_TYPE_H_ */
index acd7812..634946e 100644 (file)
@@ -719,9 +719,9 @@ static void w5100_hw_close(struct w5100_priv *priv)
 static void w5100_get_drvinfo(struct net_device *ndev,
                              struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(ndev->dev.parent),
                sizeof(info->bus_info));
 }
 
index 773f8c7..b0958fe 100644 (file)
@@ -282,9 +282,9 @@ static void w5300_hw_close(struct w5300_priv *priv)
 static void w5300_get_drvinfo(struct net_device *ndev,
                              struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, dev_name(ndev->dev.parent),
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, dev_name(ndev->dev.parent),
                sizeof(info->bus_info));
 }
 
index f2e2261..8ff4333 100644 (file)
@@ -402,6 +402,9 @@ struct axidma_bd {
  * @rx_bd_num: Size of RX buffer descriptor ring
  * @rx_bd_ci:  Stores the index of the Rx buffer descriptor in the ring being
  *             accessed currently.
+ * @rx_packets: RX packet count for statistics
+ * @rx_bytes:  RX byte count for statistics
+ * @rx_stat_sync: Synchronization object for RX stats
  * @napi_tx:   NAPI TX control structure
  * @tx_dma_cr:  Nominal content of TX DMA control register
  * @tx_bd_v:   Virtual address of the TX buffer descriptor ring
@@ -411,6 +414,9 @@ struct axidma_bd {
  *             complete. Only updated at runtime by TX NAPI poll.
  * @tx_bd_tail:        Stores the index of the next Tx buffer descriptor in the ring
  *              to be populated.
+ * @tx_packets: TX packet count for statistics
+ * @tx_bytes:  TX byte count for statistics
+ * @tx_stat_sync: Synchronization object for TX stats
  * @dma_err_task: Work structure to process Axi DMA errors
  * @tx_irq:    Axidma TX IRQ number
  * @rx_irq:    Axidma RX IRQ number
@@ -458,6 +464,9 @@ struct axienet_local {
        dma_addr_t rx_bd_p;
        u32 rx_bd_num;
        u32 rx_bd_ci;
+       u64_stats_t rx_packets;
+       u64_stats_t rx_bytes;
+       struct u64_stats_sync rx_stat_sync;
 
        struct napi_struct napi_tx;
        u32 tx_dma_cr;
@@ -466,6 +475,9 @@ struct axienet_local {
        u32 tx_bd_num;
        u32 tx_bd_ci;
        u32 tx_bd_tail;
+       u64_stats_t tx_packets;
+       u64_stats_t tx_bytes;
+       struct u64_stats_sync tx_stat_sync;
 
        struct work_struct dma_err_task;
 
index 1760930..9fde594 100644 (file)
@@ -752,8 +752,10 @@ static int axienet_tx_poll(struct napi_struct *napi, int budget)
                if (lp->tx_bd_ci >= lp->tx_bd_num)
                        lp->tx_bd_ci %= lp->tx_bd_num;
 
-               ndev->stats.tx_packets += packets;
-               ndev->stats.tx_bytes += size;
+               u64_stats_update_begin(&lp->tx_stat_sync);
+               u64_stats_add(&lp->tx_packets, packets);
+               u64_stats_add(&lp->tx_bytes, size);
+               u64_stats_update_end(&lp->tx_stat_sync);
 
                /* Matches barrier in axienet_start_xmit */
                smp_mb();
@@ -984,8 +986,10 @@ static int axienet_rx_poll(struct napi_struct *napi, int budget)
                cur_p = &lp->rx_bd_v[lp->rx_bd_ci];
        }
 
-       lp->ndev->stats.rx_packets += packets;
-       lp->ndev->stats.rx_bytes += size;
+       u64_stats_update_begin(&lp->rx_stat_sync);
+       u64_stats_add(&lp->rx_packets, packets);
+       u64_stats_add(&lp->rx_bytes, size);
+       u64_stats_update_end(&lp->rx_stat_sync);
 
        if (tail_p)
                axienet_dma_out_addr(lp, XAXIDMA_RX_TDESC_OFFSET, tail_p);
@@ -1292,10 +1296,32 @@ static int axienet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return phylink_mii_ioctl(lp->phylink, rq, cmd);
 }
 
+static void
+axienet_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
+{
+       struct axienet_local *lp = netdev_priv(dev);
+       unsigned int start;
+
+       netdev_stats_to_stats64(stats, &dev->stats);
+
+       do {
+               start = u64_stats_fetch_begin_irq(&lp->rx_stat_sync);
+               stats->rx_packets = u64_stats_read(&lp->rx_packets);
+               stats->rx_bytes = u64_stats_read(&lp->rx_bytes);
+       } while (u64_stats_fetch_retry_irq(&lp->rx_stat_sync, start));
+
+       do {
+               start = u64_stats_fetch_begin_irq(&lp->tx_stat_sync);
+               stats->tx_packets = u64_stats_read(&lp->tx_packets);
+               stats->tx_bytes = u64_stats_read(&lp->tx_bytes);
+       } while (u64_stats_fetch_retry_irq(&lp->tx_stat_sync, start));
+}
+
 static const struct net_device_ops axienet_netdev_ops = {
        .ndo_open = axienet_open,
        .ndo_stop = axienet_stop,
        .ndo_start_xmit = axienet_start_xmit,
+       .ndo_get_stats64 = axienet_get_stats64,
        .ndo_change_mtu = axienet_change_mtu,
        .ndo_set_mac_address = netdev_set_mac_address,
        .ndo_validate_addr = eth_validate_addr,
@@ -1317,8 +1343,8 @@ static const struct net_device_ops axienet_netdev_ops = {
 static void axienet_ethtools_get_drvinfo(struct net_device *ndev,
                                         struct ethtool_drvinfo *ed)
 {
-       strlcpy(ed->driver, DRIVER_NAME, sizeof(ed->driver));
-       strlcpy(ed->version, DRIVER_VERSION, sizeof(ed->version));
+       strscpy(ed->driver, DRIVER_NAME, sizeof(ed->driver));
+       strscpy(ed->version, DRIVER_VERSION, sizeof(ed->version));
 }
 
 /**
@@ -1850,6 +1876,9 @@ static int axienet_probe(struct platform_device *pdev)
        lp->rx_bd_num = RX_BD_NUM_DEFAULT;
        lp->tx_bd_num = TX_BD_NUM_DEFAULT;
 
+       u64_stats_init(&lp->rx_stat_sync);
+       u64_stats_init(&lp->tx_stat_sync);
+
        netif_napi_add(ndev, &lp->napi_rx, axienet_rx_poll, NAPI_POLL_WEIGHT);
        netif_napi_add(ndev, &lp->napi_tx, axienet_tx_poll, NAPI_POLL_WEIGHT);
 
index 016a9c4..05848ff 100644 (file)
@@ -1060,7 +1060,7 @@ static bool get_bool(struct platform_device *ofdev, const char *s)
 static void xemaclite_ethtools_get_drvinfo(struct net_device *ndev,
                                           struct ethtool_drvinfo *ed)
 {
-       strlcpy(ed->driver, DRIVER_NAME, sizeof(ed->driver));
+       strscpy(ed->driver, DRIVER_NAME, sizeof(ed->driver));
 }
 
 static const struct ethtool_ops xemaclite_ethtool_ops = {
index f9587e5..894e92e 100644 (file)
@@ -1402,7 +1402,7 @@ do_open(struct net_device *dev)
 static void netdev_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "xirc2ps_cs", sizeof(info->driver));
+       strscpy(info->driver, "xirc2ps_cs", sizeof(info->driver));
        snprintf(info->bus_info, sizeof(info->bus_info), "PCMCIA 0x%lx",
                 dev->base_addr);
 }
index 3591b9e..3b0c5f1 100644 (file)
@@ -841,7 +841,7 @@ static void eth_txdone_irq(void *unused)
        }
 }
 
-static int eth_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t eth_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct port *port = netdev_priv(dev);
        unsigned int txreadyq = port->plat->txreadyq;
@@ -999,11 +999,11 @@ static void ixp4xx_get_drvinfo(struct net_device *dev,
 {
        struct port *port = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
        snprintf(info->fw_version, sizeof(info->fw_version), "%u:%u:%u:%u",
                 port->firmware[0], port->firmware[1],
                 port->firmware[2], port->firmware[3]);
-       strlcpy(info->bus_info, "internal", sizeof(info->bus_info));
+       strscpy(info->bus_info, "internal", sizeof(info->bus_info));
 }
 
 static int ixp4xx_get_ts_info(struct net_device *dev,
index 746736c..19c9952 100644 (file)
@@ -151,11 +151,11 @@ static void fjes_get_drvinfo(struct net_device *netdev,
 
        plat_dev = adapter->plat_dev;
 
-       strlcpy(drvinfo->driver, fjes_driver_name, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, fjes_driver_version,
+       strscpy(drvinfo->driver, fjes_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, fjes_driver_version,
                sizeof(drvinfo->version));
 
-       strlcpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version));
+       strscpy(drvinfo->fw_version, "none", sizeof(drvinfo->fw_version));
        snprintf(drvinfo->bus_info, sizeof(drvinfo->bus_info),
                 "platform:%s", plat_dev->name);
 }
index 7962c37..f393e45 100644 (file)
@@ -503,12 +503,9 @@ static struct sk_buff *geneve_gro_receive(struct sock *sk,
 
        off_gnv = skb_gro_offset(skb);
        hlen = off_gnv + sizeof(*gh);
-       gh = skb_gro_header_fast(skb, off_gnv);
-       if (skb_gro_header_hard(skb, hlen)) {
-               gh = skb_gro_header_slow(skb, hlen, off_gnv);
-               if (unlikely(!gh))
-                       goto out;
-       }
+       gh = skb_gro_header(skb, hlen, off_gnv);
+       if (unlikely(!gh))
+               goto out;
 
        if (gh->ver != GENEVE_VER || gh->oam)
                goto out;
@@ -1200,8 +1197,8 @@ static const struct net_device_ops geneve_netdev_ops = {
 static void geneve_get_drvinfo(struct net_device *dev,
                               struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->version, GENEVE_NETDEV_VER, sizeof(drvinfo->version));
-       strlcpy(drvinfo->driver, "geneve", sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, GENEVE_NETDEV_VER, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, "geneve", sizeof(drvinfo->driver));
 }
 
 static const struct ethtool_ops geneve_ethtool_ops = {
index a208e2b..15c7dc8 100644 (file)
@@ -1859,6 +1859,7 @@ static struct genl_family gtp_genl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = gtp_genl_ops,
        .n_small_ops    = ARRAY_SIZE(gtp_genl_ops),
+       .resv_start_op  = GTP_CMD_ECHOREQ + 1,
        .mcgrps         = gtp_genl_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(gtp_genl_mcgrps),
 };
index 8297411..a6184d6 100644 (file)
@@ -600,7 +600,7 @@ static int hdlcdrv_siocdevprivate(struct net_device *dev, struct ifreq *ifr,
 
        case HDLCDRVCTL_DRIVERNAME:
                if (s->ops && s->ops->drvname) {
-                       strlcpy(bi.data.drivername, s->ops->drvname,
+                       strscpy(bi.data.drivername, s->ops->drvname,
                                sizeof(bi.data.drivername));
                        break;
                }
index 15ebd54..5f08482 100644 (file)
@@ -935,8 +935,8 @@ int netvsc_recv_callback(struct net_device *net,
 static void netvsc_get_drvinfo(struct net_device *net,
                               struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
 }
 
 static void netvsc_get_channels(struct net_device *net,
index 6afdf16..5cf218c 100644 (file)
@@ -1310,10 +1310,11 @@ static void adf7242_remove(struct spi_device *spi)
 
        debugfs_remove_recursive(lp->debugfs_root);
 
+       ieee802154_unregister_hw(lp->hw);
+
        cancel_delayed_work_sync(&lp->work);
        destroy_workqueue(lp->wqueue);
 
-       ieee802154_unregister_hw(lp->hw);
        mutex_destroy(&lp->bmux);
        ieee802154_free_hw(lp->hw);
 }
index 42c0b45..450b16a 100644 (file)
@@ -2293,7 +2293,7 @@ static int ca8210_set_csma_params(
  * @retries:  Number of retries
  *
  * Sets the number of times to retry a transmission if no acknowledgment was
- * was received from the other end when one was requested.
+ * received from the other end when one was requested.
  *
  * Return: 0 or linux error code
  */
index 1e1f40f..c69b87d 100644 (file)
@@ -504,6 +504,7 @@ cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
                goto err_tx;
 
        if (status & CC2520_STATUS_TX_UNDERFLOW) {
+               rc = -EINVAL;
                dev_err(&priv->spi->dev, "cc2520 tx underflow exception\n");
                goto err_tx;
        }
index 38c217b..2f0544d 100644 (file)
@@ -630,6 +630,7 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = hwsim_nl_ops,
        .n_small_ops = ARRAY_SIZE(hwsim_nl_ops),
+       .resv_start_op = MAC802154_HWSIM_CMD_NEW_EDGE + 1,
        .mcgrps = hwsim_mcgrps,
        .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
 };
index 23de5f6..1346870 100644 (file)
@@ -82,7 +82,14 @@ struct gsi_trans_pool {
 
 struct gsi_trans_info {
        atomic_t tre_avail;             /* TREs available for allocation */
-       struct gsi_trans_pool pool;     /* transaction pool */
+
+       u16 free_id;                    /* first free trans in array */
+       u16 allocated_id;               /* first allocated transaction */
+       u16 committed_id;               /* first committed transaction */
+       u16 pending_id;                 /* first pending transaction */
+       u16 completed_id;               /* first completed transaction */
+       u16 polled_id;                  /* first polled transaction */
+       struct gsi_trans *trans;        /* transaction array */
        struct gsi_trans **map;         /* TRE -> transaction map */
 
        struct gsi_trans_pool sg_pool;  /* scatterlist pool */
index 18e7e8c..4eef148 100644 (file)
@@ -252,6 +252,9 @@ static void gsi_trans_move_committed(struct gsi_trans *trans)
        list_move_tail(&trans->links, &trans_info->committed);
 
        spin_unlock_bh(&trans_info->spinlock);
+
+       /* This allocated transaction is now committed */
+       trans_info->allocated_id++;
 }
 
 /* Move transactions from the committed list to the pending list */
@@ -259,7 +262,9 @@ static void gsi_trans_move_pending(struct gsi_trans *trans)
 {
        struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
        struct gsi_trans_info *trans_info = &channel->trans_info;
+       u16 trans_index = trans - &trans_info->trans[0];
        struct list_head list;
+       u16 delta;
 
        spin_lock_bh(&trans_info->spinlock);
 
@@ -268,6 +273,10 @@ static void gsi_trans_move_pending(struct gsi_trans *trans)
        list_splice_tail(&list, &trans_info->pending);
 
        spin_unlock_bh(&trans_info->spinlock);
+
+       /* These committed transactions are now pending */
+       delta = trans_index - trans_info->committed_id + 1;
+       trans_info->committed_id += delta % channel->tre_count;
 }
 
 /* Move a transaction and all of its predecessors from the pending list
@@ -277,7 +286,9 @@ void gsi_trans_move_complete(struct gsi_trans *trans)
 {
        struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
        struct gsi_trans_info *trans_info = &channel->trans_info;
+       u16 trans_index = trans - trans_info->trans;
        struct list_head list;
+       u16 delta;
 
        spin_lock_bh(&trans_info->spinlock);
 
@@ -286,6 +297,11 @@ void gsi_trans_move_complete(struct gsi_trans *trans)
        list_splice_tail(&list, &trans_info->complete);
 
        spin_unlock_bh(&trans_info->spinlock);
+
+       /* These pending transactions are now completed */
+       delta = trans_index - trans_info->pending_id + 1;
+       delta %= channel->tre_count;
+       trans_info->pending_id += delta;
 }
 
 /* Move a transaction from the completed list to the polled list */
@@ -293,12 +309,23 @@ void gsi_trans_move_polled(struct gsi_trans *trans)
 {
        struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
        struct gsi_trans_info *trans_info = &channel->trans_info;
+       u16 trans_index;
 
        spin_lock_bh(&trans_info->spinlock);
 
        list_move_tail(&trans->links, &trans_info->polled);
 
+       trans = list_first_entry(&trans_info->polled,
+                                struct gsi_trans, links);
+
        spin_unlock_bh(&trans_info->spinlock);
+
+       /* This completed transaction is now polled */
+       trans_info->completed_id++;
+
+       WARN_ON(trans_info->polled_id == trans_info->completed_id);
+       trans_index = trans_info->polled_id % channel->tre_count;
+       WARN_ON(trans != &trans_info->trans[trans_index]);
 }
 
 /* Reserve some number of TREs on a channel.  Returns true if successful */
@@ -343,20 +370,22 @@ struct gsi_trans *gsi_channel_trans_alloc(struct gsi *gsi, u32 channel_id,
        struct gsi_channel *channel = &gsi->channel[channel_id];
        struct gsi_trans_info *trans_info;
        struct gsi_trans *trans;
+       u16 trans_index;
 
        if (WARN_ON(tre_count > channel->trans_tre_max))
                return NULL;
 
        trans_info = &channel->trans_info;
 
-       /* We reserve the TREs now, but consume them at commit time.
-        * If there aren't enough available, we're done.
-        */
+       /* If we can't reserve the TREs for the transaction, we're done */
        if (!gsi_trans_tre_reserve(trans_info, tre_count))
                return NULL;
 
-       /* Allocate and initialize non-zero fields in the transaction */
-       trans = gsi_trans_pool_alloc(&trans_info->pool, 1);
+       trans_index = trans_info->free_id % channel->tre_count;
+       trans = &trans_info->trans[trans_index];
+       memset(trans, 0, sizeof(*trans));
+
+       /* Initialize non-zero fields in the transaction */
        trans->gsi = gsi;
        trans->channel_id = channel_id;
        trans->rsvd_count = tre_count;
@@ -367,6 +396,10 @@ struct gsi_trans *gsi_channel_trans_alloc(struct gsi *gsi, u32 channel_id,
        sg_init_marker(trans->sgl, tre_count);
 
        trans->direction = direction;
+       refcount_set(&trans->refcount, 1);
+
+       /* This free transaction will now be allocated */
+       trans_info->free_id++;
 
        spin_lock_bh(&trans_info->spinlock);
 
@@ -374,16 +407,17 @@ struct gsi_trans *gsi_channel_trans_alloc(struct gsi *gsi, u32 channel_id,
 
        spin_unlock_bh(&trans_info->spinlock);
 
-       refcount_set(&trans->refcount, 1);
-
        return trans;
 }
 
 /* Free a previously-allocated transaction */
 void gsi_trans_free(struct gsi_trans *trans)
 {
+       struct gsi_channel *channel = &trans->gsi->channel[trans->channel_id];
        refcount_t *refcount = &trans->refcount;
        struct gsi_trans_info *trans_info;
+       struct gsi_trans *polled;
+       u16 trans_index;
        bool last;
 
        /* We must hold the lock to release the last reference */
@@ -399,13 +433,36 @@ void gsi_trans_free(struct gsi_trans *trans)
        if (last)
                list_del(&trans->links);
 
+       polled = list_first_entry_or_null(&trans_info->polled,
+                                         struct gsi_trans, links);
+
        spin_unlock_bh(&trans_info->spinlock);
 
        if (!last)
                return;
 
-       if (trans->used_count)
+       /* Unused transactions are allocated but never committed, pending,
+        * completed, or polled.
+        */
+       if (!trans->used_count) {
+               trans_info->allocated_id++;
+               trans_info->committed_id++;
+               trans_info->pending_id++;
+               trans_info->completed_id++;
+       } else {
                ipa_gsi_trans_release(trans);
+       }
+
+       /* This transaction is now free */
+       trans_info->polled_id++;
+
+       if (polled) {
+               trans_index = trans_info->polled_id % channel->tre_count;
+               WARN_ON(polled != &trans_info->trans[trans_index]);
+       } else {
+               WARN_ON(trans_info->polled_id !=
+                       trans_info->completed_id);
+       }
 
        /* Releasing the reserved TREs implicitly frees the sgl[] and
         * (if present) info[] arrays, plus the transaction itself.
@@ -736,10 +793,16 @@ int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id)
         * modulo that number to determine the next one that's free.
         * Transactions are allocated one at a time.
         */
-       ret = gsi_trans_pool_init(&trans_info->pool, sizeof(struct gsi_trans),
-                                 tre_max, 1);
-       if (ret)
+       trans_info->trans = kcalloc(tre_count, sizeof(*trans_info->trans),
+                                   GFP_KERNEL);
+       if (!trans_info->trans)
                return -ENOMEM;
+       trans_info->free_id = 0;        /* all modulo channel->tre_count */
+       trans_info->allocated_id = 0;
+       trans_info->committed_id = 0;
+       trans_info->pending_id = 0;
+       trans_info->completed_id = 0;
+       trans_info->polled_id = 0;
 
        /* A completion event contains a pointer to the TRE that caused
         * the event (which will be the last one used by the transaction).
@@ -777,7 +840,7 @@ int gsi_channel_trans_init(struct gsi *gsi, u32 channel_id)
 err_map_free:
        kfree(trans_info->map);
 err_trans_free:
-       gsi_trans_pool_exit(&trans_info->pool);
+       kfree(trans_info->trans);
 
        dev_err(gsi->dev, "error %d initializing channel %u transactions\n",
                ret, channel_id);
@@ -791,6 +854,6 @@ void gsi_channel_trans_exit(struct gsi_channel *channel)
        struct gsi_trans_info *trans_info = &channel->trans_info;
 
        gsi_trans_pool_exit(&trans_info->sg_pool);
-       gsi_trans_pool_exit(&trans_info->pool);
+       kfree(trans_info->trans);
        kfree(trans_info->map);
 }
index 49ba8a5..54c94a6 100644 (file)
@@ -408,8 +408,8 @@ static int ipvlan_ethtool_get_link_ksettings(struct net_device *dev,
 static void ipvlan_ethtool_get_drvinfo(struct net_device *dev,
                                       struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, IPVLAN_DRV, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, IPV_DRV_VER, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, IPVLAN_DRV, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, IPV_DRV_VER, sizeof(drvinfo->version));
 }
 
 static u32 ipvlan_ethtool_get_msglevel(struct net_device *dev)
index c6d271e..adf448a 100644 (file)
@@ -3404,6 +3404,7 @@ static struct genl_family macsec_fam __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = macsec_genl_ops,
        .n_small_ops    = ARRAY_SIZE(macsec_genl_ops),
+       .resv_start_op  = MACSEC_CMD_UPD_OFFLOAD + 1,
 };
 
 static netdev_tx_t macsec_start_xmit(struct sk_buff *skb,
index 1080d6e..713e335 100644 (file)
@@ -1043,8 +1043,8 @@ static int macvlan_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
 static void macvlan_ethtool_get_drvinfo(struct net_device *dev,
                                        struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, "macvlan", sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, "0.1", sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, "macvlan", sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, "0.1", sizeof(drvinfo->version));
 }
 
 static int macvlan_ethtool_get_link_ksettings(struct net_device *dev,
index 21a0435..7a28e08 100644 (file)
@@ -324,8 +324,8 @@ static const struct net_device_ops failover_dev_ops = {
 static void nfo_ethtool_get_drvinfo(struct net_device *dev,
                                    struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, FAILOVER_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, FAILOVER_VERSION, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, FAILOVER_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, FAILOVER_VERSION, sizeof(drvinfo->version));
 }
 
 static int nfo_ethtool_get_link_ksettings(struct net_device *dev,
index ddac61d..bdff9ac 100644 (file)
@@ -55,7 +55,7 @@ MODULE_PARM_DESC(oops_only, "Only log oops messages");
 #ifndef        MODULE
 static int __init option_setup(char *opt)
 {
-       strlcpy(config, opt, MAX_PARAM_LENGTH);
+       strscpy(config, opt, MAX_PARAM_LENGTH);
        return 1;
 }
 __setup("netconsole=", option_setup);
@@ -178,7 +178,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
                goto fail;
 
        nt->np.name = "netconsole";
-       strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
+       strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
        nt->np.local_port = 6665;
        nt->np.remote_port = 6666;
        eth_broadcast_addr(nt->np.remote_mac);
@@ -414,7 +414,7 @@ static ssize_t dev_name_store(struct config_item *item, const char *buf,
                return -EINVAL;
        }
 
-       strlcpy(nt->np.dev_name, buf, IFNAMSIZ);
+       strscpy(nt->np.dev_name, buf, IFNAMSIZ);
 
        /* Get rid of possible trailing newline from echo(1) */
        len = strnlen(nt->np.dev_name, IFNAMSIZ);
@@ -630,7 +630,7 @@ static struct config_item *make_netconsole_target(struct config_group *group,
                return ERR_PTR(-ENOMEM);
 
        nt->np.name = "netconsole";
-       strlcpy(nt->np.dev_name, "eth0", IFNAMSIZ);
+       strscpy(nt->np.dev_name, "eth0", IFNAMSIZ);
        nt->np.local_port = 6665;
        nt->np.remote_port = 6666;
        eth_broadcast_addr(nt->np.remote_mac);
@@ -708,7 +708,7 @@ restart:
                if (nt->np.dev == dev) {
                        switch (event) {
                        case NETDEV_CHANGENAME:
-                               strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
+                               strscpy(nt->np.dev_name, dev->name, IFNAMSIZ);
                                break;
                        case NETDEV_RELEASE:
                        case NETDEV_JOIN:
index e88f783..794fc0c 100644 (file)
@@ -965,7 +965,6 @@ static int nsim_dev_reload_up(struct devlink *devlink, enum devlink_reload_actio
                              struct netlink_ext_ack *extack)
 {
        struct nsim_dev *nsim_dev = devlink_priv(devlink);
-       int ret;
 
        if (nsim_dev->fail_reload) {
                /* For testing purposes, user set debugfs fail_reload
@@ -976,15 +975,25 @@ static int nsim_dev_reload_up(struct devlink *devlink, enum devlink_reload_actio
        }
 
        *actions_performed = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
-       ret = nsim_dev_reload_create(nsim_dev, extack);
-       return ret;
+
+       return nsim_dev_reload_create(nsim_dev, extack);
 }
 
 static int nsim_dev_info_get(struct devlink *devlink,
                             struct devlink_info_req *req,
                             struct netlink_ext_ack *extack)
 {
-       return devlink_info_driver_name_put(req, DRV_NAME);
+       int err;
+
+       err = devlink_info_driver_name_put(req, DRV_NAME);
+       if (err)
+               return err;
+       err = devlink_info_version_stored_put_ext(req, "fw.mgmt", "10.20.30",
+                                                 DEVLINK_INFO_VERSION_TYPE_COMPONENT);
+       if (err)
+               return err;
+       return devlink_info_version_running_put_ext(req, "fw.mgmt", "10.20.30",
+                                                   DEVLINK_INFO_VERSION_TYPE_COMPONENT);
 }
 
 #define NSIM_DEV_FLASH_SIZE 500000
@@ -1312,8 +1321,7 @@ nsim_dev_devlink_trap_drop_counter_get(struct devlink *devlink,
 static const struct devlink_ops nsim_dev_devlink_ops = {
        .eswitch_mode_set = nsim_devlink_eswitch_mode_set,
        .eswitch_mode_get = nsim_devlink_eswitch_mode_get,
-       .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT |
-                                        DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
+       .supported_flash_update_params = DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK,
        .reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT),
        .reload_down = nsim_dev_reload_down,
        .reload_up = nsim_dev_reload_up,
index e470e33..9a1a5b2 100644 (file)
@@ -67,10 +67,10 @@ nsim_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
        unsigned int start;
 
        do {
-               start = u64_stats_fetch_begin(&ns->syncp);
+               start = u64_stats_fetch_begin_irq(&ns->syncp);
                stats->tx_bytes = ns->tx_bytes;
                stats->tx_packets = ns->tx_packets;
-       } while (u64_stats_fetch_retry(&ns->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&ns->syncp, start));
 }
 
 static int
index 80bdc07..464d88c 100644 (file)
@@ -364,9 +364,9 @@ static void ntb_get_drvinfo(struct net_device *ndev,
 {
        struct ntb_netdev *dev = netdev_priv(ndev);
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->version, NTB_NETDEV_VER, sizeof(info->version));
-       strlcpy(info->bus_info, pci_name(dev->pdev), sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->version, NTB_NETDEV_VER, sizeof(info->version));
+       strscpy(info->bus_info, pci_name(dev->pdev), sizeof(info->bus_info));
 }
 
 static int ntb_get_link_ksettings(struct net_device *dev,
index ee374a8..1346375 100644 (file)
@@ -749,7 +749,7 @@ static void adin_get_strings(struct phy_device *phydev, u8 *data)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(adin_hw_stats); i++) {
-               strlcpy(&data[i * ETH_GSTRING_LEN],
+               strscpy(&data[i * ETH_GSTRING_LEN],
                        adin_hw_stats[i].string, ETH_GSTRING_LEN);
        }
 }
index 59fe356..11ebd59 100644 (file)
 #define AT803X_DEBUG_REG_HIB_CTRL              0x0b
 #define   AT803X_DEBUG_HIB_CTRL_SEL_RST_80U    BIT(10)
 #define   AT803X_DEBUG_HIB_CTRL_EN_ANY_CHANGE  BIT(13)
+#define   AT803X_DEBUG_HIB_CTRL_PS_HIB_EN      BIT(15)
 
 #define AT803X_DEBUG_REG_3C                    0x3C
 
 #define AT803X_KEEP_PLL_ENABLED                        BIT(0)
 #define AT803X_DISABLE_SMARTEEE                        BIT(1)
 
+/* disable hibernation mode */
+#define AT803X_DISABLE_HIBERNATION_MODE                BIT(2)
+
 /* ADC threshold */
 #define QCA808X_PHY_DEBUG_ADC_THRESHOLD                0x2c80
 #define QCA808X_ADC_THRESHOLD_MASK             GENMASK(7, 0)
@@ -730,6 +734,9 @@ static int at803x_parse_dt(struct phy_device *phydev)
        if (of_property_read_bool(node, "qca,disable-smarteee"))
                priv->flags |= AT803X_DISABLE_SMARTEEE;
 
+       if (of_property_read_bool(node, "qca,disable-hibernation-mode"))
+               priv->flags |= AT803X_DISABLE_HIBERNATION_MODE;
+
        if (!of_property_read_u32(node, "qca,smarteee-tw-us-1g", &tw)) {
                if (!tw || tw > 255) {
                        phydev_err(phydev, "invalid qca,smarteee-tw-us-1g\n");
@@ -999,6 +1006,20 @@ static int at8031_pll_config(struct phy_device *phydev)
                                             AT803X_DEBUG_PLL_ON, 0);
 }
 
+static int at803x_hibernation_mode_config(struct phy_device *phydev)
+{
+       struct at803x_priv *priv = phydev->priv;
+
+       /* The default after hardware reset is hibernation mode enabled. After
+        * software reset, the value is retained.
+        */
+       if (!(priv->flags & AT803X_DISABLE_HIBERNATION_MODE))
+               return 0;
+
+       return at803x_debug_reg_mask(phydev, AT803X_DEBUG_REG_HIB_CTRL,
+                                        AT803X_DEBUG_HIB_CTRL_PS_HIB_EN, 0);
+}
+
 static int at803x_config_init(struct phy_device *phydev)
 {
        struct at803x_priv *priv = phydev->priv;
@@ -1051,6 +1072,10 @@ static int at803x_config_init(struct phy_device *phydev)
        if (ret < 0)
                return ret;
 
+       ret = at803x_hibernation_mode_config(phydev);
+       if (ret < 0)
+               return ret;
+
        /* Ar803x extended next page bit is enabled by default. Cisco
         * multigig switches read this bit and attempt to negotiate 10Gbps
         * rates even if the next page bit is disabled. This is incorrect
index 287cccf..b2c0baa 100644 (file)
@@ -519,7 +519,7 @@ void bcm_phy_get_strings(struct phy_device *phydev, u8 *data)
        unsigned int i;
 
        for (i = 0; i < ARRAY_SIZE(bcm_phy_hw_stats); i++)
-               strlcpy(data + i * ETH_GSTRING_LEN,
+               strscpy(data + i * ETH_GSTRING_LEN,
                        bcm_phy_hw_stats[i].string, ETH_GSTRING_LEN);
 }
 EXPORT_SYMBOL_GPL(bcm_phy_get_strings);
index 31fbcdd..ad71c88 100644 (file)
@@ -766,6 +766,41 @@ static irqreturn_t brcm_fet_handle_interrupt(struct phy_device *phydev)
        return IRQ_HANDLED;
 }
 
+static int brcm_fet_suspend(struct phy_device *phydev)
+{
+       int reg, err, err2, brcmtest;
+
+       /* We cannot use a read/modify/write here otherwise the PHY continues
+        * to drive LEDs which defeats the purpose of low power mode.
+        */
+       err = phy_write(phydev, MII_BMCR, BMCR_PDOWN);
+       if (err < 0)
+               return err;
+
+       /* Enable shadow register access */
+       brcmtest = phy_read(phydev, MII_BRCM_FET_BRCMTEST);
+       if (brcmtest < 0)
+               return brcmtest;
+
+       reg = brcmtest | MII_BRCM_FET_BT_SRE;
+
+       err = phy_write(phydev, MII_BRCM_FET_BRCMTEST, reg);
+       if (err < 0)
+               return err;
+
+       /* Set standby mode */
+       err = phy_modify(phydev, MII_BRCM_FET_SHDW_AUXMODE4,
+                        MII_BRCM_FET_SHDW_AM4_STANDBY,
+                        MII_BRCM_FET_SHDW_AM4_STANDBY);
+
+       /* Disable shadow register access */
+       err2 = phy_write(phydev, MII_BRCM_FET_BRCMTEST, brcmtest);
+       if (!err)
+               err = err2;
+
+       return err;
+}
+
 static int bcm54xx_phy_probe(struct phy_device *phydev)
 {
        struct bcm54xx_phy_priv *priv;
@@ -1033,6 +1068,8 @@ static struct phy_driver broadcom_drivers[] = {
        .config_init    = brcm_fet_config_init,
        .config_intr    = brcm_fet_config_intr,
        .handle_interrupt = brcm_fet_handle_interrupt,
+       .suspend        = brcm_fet_suspend,
+       .resume         = brcm_fet_config_init,
 }, {
        .phy_id         = PHY_ID_BCM5241,
        .phy_id_mask    = 0xfffffff0,
@@ -1041,6 +1078,8 @@ static struct phy_driver broadcom_drivers[] = {
        .config_init    = brcm_fet_config_init,
        .config_intr    = brcm_fet_config_intr,
        .handle_interrupt = brcm_fet_handle_interrupt,
+       .suspend        = brcm_fet_suspend,
+       .resume         = brcm_fet_config_init,
 }, {
        .phy_id         = PHY_ID_BCM5395,
        .phy_id_mask    = 0xfffffff0,
index a714150..a3e8107 100644 (file)
@@ -1952,7 +1952,7 @@ static void marvell_get_strings(struct phy_device *phydev, u8 *data)
        int i;
 
        for (i = 0; i < count; i++) {
-               strlcpy(data + i * ETH_GSTRING_LEN,
+               strscpy(data + i * ETH_GSTRING_LEN,
                        marvell_hw_stats[i].string, ETH_GSTRING_LEN);
        }
 }
index e78d0bf..7b8c5c8 100644 (file)
@@ -1650,7 +1650,7 @@ static void kszphy_get_strings(struct phy_device *phydev, u8 *data)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(kszphy_hw_stats); i++) {
-               strlcpy(data + i * ETH_GSTRING_LEN,
+               strscpy(data + i * ETH_GSTRING_LEN,
                        kszphy_hw_stats[i].string, ETH_GSTRING_LEN);
        }
 }
@@ -2873,12 +2873,18 @@ static int lan8814_config_init(struct phy_device *phydev)
        return 0;
 }
 
+/* It is expected that there will not be any 'lan8814_take_coma_mode'
+ * function called in suspend. Because the GPIO line can be shared, so if one of
+ * the phys goes back in coma mode, then all the other PHYs will go, which is
+ * wrong.
+ */
 static int lan8814_release_coma_mode(struct phy_device *phydev)
 {
        struct gpio_desc *gpiod;
 
        gpiod = devm_gpiod_get_optional(&phydev->mdio.dev, "coma-mode",
-                                       GPIOD_OUT_HIGH_OPEN_DRAIN);
+                                       GPIOD_OUT_HIGH_OPEN_DRAIN |
+                                       GPIOD_FLAGS_BIT_NONEXCLUSIVE);
        if (IS_ERR(gpiod))
                return PTR_ERR(gpiod);
 
index 7e3017e..8a13b1a 100644 (file)
@@ -136,7 +136,7 @@ static void vsc85xx_get_strings(struct phy_device *phydev, u8 *data)
                return;
 
        for (i = 0; i < priv->nstats; i++)
-               strlcpy(data + i * ETH_GSTRING_LEN, priv->hw_stats[i].string,
+               strscpy(data + i * ETH_GSTRING_LEN, priv->hw_stats[i].string,
                        ETH_GSTRING_LEN);
 }
 
index 2a8195c..ec91e67 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/mdio.h>
 #include <linux/mii.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/phy.h>
 #include <linux/hwmon.h>
 #include <linux/bitfield.h>
 #define MII_CFG1                       18
 #define MII_CFG1_MASTER_SLAVE          BIT(15)
 #define MII_CFG1_AUTO_OP               BIT(14)
+#define MII_CFG1_INTERFACE_MODE_MASK   GENMASK(9, 8)
+#define MII_CFG1_MII_MODE                              (0x0 << 8)
+#define MII_CFG1_RMII_MODE_REFCLK_IN   BIT(8)
+#define MII_CFG1_RMII_MODE_REFCLK_OUT  BIT(9)
+#define MII_CFG1_REVMII_MODE                   GENMASK(9, 8)
 #define MII_CFG1_SLEEP_CONFIRM         BIT(6)
 #define MII_CFG1_LED_MODE_MASK         GENMASK(5, 4)
 #define MII_CFG1_LED_MODE_LINKUP       0
 #define MII_COMMCFG                    27
 #define MII_COMMCFG_AUTO_OP            BIT(15)
 
+/* Configure REF_CLK as input in RMII mode */
+#define TJA110X_RMII_MODE_REFCLK_IN       BIT(0)
+
 struct tja11xx_priv {
        char            *hwmon_name;
        struct device   *hwmon_dev;
        struct phy_device *phydev;
        struct work_struct phy_register_work;
+       u32 flags;
 };
 
 struct tja11xx_phy_stats {
@@ -251,8 +261,34 @@ do_test:
        return __genphy_config_aneg(phydev, changed);
 }
 
+static int tja11xx_get_interface_mode(struct phy_device *phydev)
+{
+       struct tja11xx_priv *priv = phydev->priv;
+       int mii_mode;
+
+       switch (phydev->interface) {
+       case PHY_INTERFACE_MODE_MII:
+               mii_mode = MII_CFG1_MII_MODE;
+               break;
+       case PHY_INTERFACE_MODE_REVMII:
+               mii_mode = MII_CFG1_REVMII_MODE;
+               break;
+       case PHY_INTERFACE_MODE_RMII:
+               if (priv->flags & TJA110X_RMII_MODE_REFCLK_IN)
+                       mii_mode = MII_CFG1_RMII_MODE_REFCLK_IN;
+               else
+                       mii_mode = MII_CFG1_RMII_MODE_REFCLK_OUT;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return mii_mode;
+}
+
 static int tja11xx_config_init(struct phy_device *phydev)
 {
+       u16 reg_mask, reg_val;
        int ret;
 
        ret = tja11xx_enable_reg_write(phydev);
@@ -265,15 +301,32 @@ static int tja11xx_config_init(struct phy_device *phydev)
 
        switch (phydev->phy_id & PHY_ID_MASK) {
        case PHY_ID_TJA1100:
-               ret = phy_modify(phydev, MII_CFG1,
-                                MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK |
-                                MII_CFG1_LED_ENABLE,
-                                MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_LINKUP |
-                                MII_CFG1_LED_ENABLE);
+               reg_mask = MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_MASK |
+                          MII_CFG1_LED_ENABLE;
+               reg_val = MII_CFG1_AUTO_OP | MII_CFG1_LED_MODE_LINKUP |
+                         MII_CFG1_LED_ENABLE;
+
+               reg_mask |= MII_CFG1_INTERFACE_MODE_MASK;
+               ret = tja11xx_get_interface_mode(phydev);
+               if (ret < 0)
+                       return ret;
+
+               reg_val |= (ret & 0xffff);
+               ret = phy_modify(phydev, MII_CFG1, reg_mask, reg_val);
                if (ret)
                        return ret;
                break;
        case PHY_ID_TJA1101:
+               reg_mask = MII_CFG1_INTERFACE_MODE_MASK;
+               ret = tja11xx_get_interface_mode(phydev);
+               if (ret < 0)
+                       return ret;
+
+               reg_val = ret & 0xffff;
+               ret = phy_modify(phydev, MII_CFG1, reg_mask, reg_val);
+               if (ret)
+                       return ret;
+               fallthrough;
        case PHY_ID_TJA1102:
                ret = phy_set_bits(phydev, MII_COMMCFG, MII_COMMCFG_AUTO_OP);
                if (ret)
@@ -458,16 +511,36 @@ static int tja11xx_hwmon_register(struct phy_device *phydev,
        return PTR_ERR_OR_ZERO(priv->hwmon_dev);
 }
 
+static int tja11xx_parse_dt(struct phy_device *phydev)
+{
+       struct device_node *node = phydev->mdio.dev.of_node;
+       struct tja11xx_priv *priv = phydev->priv;
+
+       if (!IS_ENABLED(CONFIG_OF_MDIO))
+               return 0;
+
+       if (of_property_read_bool(node, "nxp,rmii-refclk-in"))
+               priv->flags |= TJA110X_RMII_MODE_REFCLK_IN;
+
+       return 0;
+}
+
 static int tja11xx_probe(struct phy_device *phydev)
 {
        struct device *dev = &phydev->mdio.dev;
        struct tja11xx_priv *priv;
+       int ret;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
 
        priv->phydev = phydev;
+       phydev->priv = priv;
+
+       ret = tja11xx_parse_dt(phydev);
+       if (ret)
+               return ret;
 
        return tja11xx_hwmon_register(phydev, priv);
 }
index 1f2531a..f8ec12d 100644 (file)
@@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned int duplex)
 }
 EXPORT_SYMBOL_GPL(phy_duplex_to_str);
 
+/**
+ * phy_interface_num_ports - Return the number of links that can be carried by
+ *                          a given MAC-PHY physical link. Returns 0 if this is
+ *                          unknown, the number of links else.
+ *
+ * @interface: The interface mode we want to get the number of ports
+ */
+int phy_interface_num_ports(phy_interface_t interface)
+{
+       switch (interface) {
+       case PHY_INTERFACE_MODE_NA:
+               return 0;
+       case PHY_INTERFACE_MODE_INTERNAL:
+       case PHY_INTERFACE_MODE_MII:
+       case PHY_INTERFACE_MODE_GMII:
+       case PHY_INTERFACE_MODE_TBI:
+       case PHY_INTERFACE_MODE_REVMII:
+       case PHY_INTERFACE_MODE_RMII:
+       case PHY_INTERFACE_MODE_REVRMII:
+       case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
+       case PHY_INTERFACE_MODE_RTBI:
+       case PHY_INTERFACE_MODE_XGMII:
+       case PHY_INTERFACE_MODE_XLGMII:
+       case PHY_INTERFACE_MODE_MOCA:
+       case PHY_INTERFACE_MODE_TRGMII:
+       case PHY_INTERFACE_MODE_USXGMII:
+       case PHY_INTERFACE_MODE_SGMII:
+       case PHY_INTERFACE_MODE_SMII:
+       case PHY_INTERFACE_MODE_1000BASEX:
+       case PHY_INTERFACE_MODE_2500BASEX:
+       case PHY_INTERFACE_MODE_5GBASER:
+       case PHY_INTERFACE_MODE_10GBASER:
+       case PHY_INTERFACE_MODE_25GBASER:
+       case PHY_INTERFACE_MODE_10GKR:
+       case PHY_INTERFACE_MODE_100BASEX:
+       case PHY_INTERFACE_MODE_RXAUI:
+       case PHY_INTERFACE_MODE_XAUI:
+               return 1;
+       case PHY_INTERFACE_MODE_QSGMII:
+       case PHY_INTERFACE_MODE_QUSGMII:
+               return 4;
+       case PHY_INTERFACE_MODE_MAX:
+               WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");
+               return 0;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(phy_interface_num_ports);
+
 /* A mapping of all SUPPORTED settings to speed/duplex.  This table
  * must be grouped by speed and sorted in descending match priority
  * - iow, descending speed.
index 12ff276..2198f13 100644 (file)
@@ -370,7 +370,7 @@ int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
        if (!fixup)
                return -ENOMEM;
 
-       strlcpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
+       strscpy(fixup->bus_id, bus_id, sizeof(fixup->bus_id));
        fixup->phy_uid = phy_uid;
        fixup->phy_uid_mask = phy_uid_mask;
        fixup->run = run;
index 9bd6932..e487bde 100644 (file)
@@ -321,6 +321,7 @@ void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface,
        case PHY_INTERFACE_MODE_RGMII_ID:
        case PHY_INTERFACE_MODE_RGMII:
        case PHY_INTERFACE_MODE_QSGMII:
+       case PHY_INTERFACE_MODE_QUSGMII:
        case PHY_INTERFACE_MODE_SGMII:
        case PHY_INTERFACE_MODE_GMII:
                caps |= MAC_1000HD | MAC_1000FD;
@@ -632,6 +633,12 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
                switch (pl->link_config.interface) {
                case PHY_INTERFACE_MODE_SGMII:
                case PHY_INTERFACE_MODE_QSGMII:
+               case PHY_INTERFACE_MODE_QUSGMII:
+               case PHY_INTERFACE_MODE_RGMII:
+               case PHY_INTERFACE_MODE_RGMII_ID:
+               case PHY_INTERFACE_MODE_RGMII_RXID:
+               case PHY_INTERFACE_MODE_RGMII_TXID:
+               case PHY_INTERFACE_MODE_RTBI:
                        phylink_set(pl->supported, 10baseT_Half);
                        phylink_set(pl->supported, 10baseT_Full);
                        phylink_set(pl->supported, 100baseT_Half);
@@ -2929,6 +2936,7 @@ void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,
 
        case PHY_INTERFACE_MODE_SGMII:
        case PHY_INTERFACE_MODE_QSGMII:
+       case PHY_INTERFACE_MODE_QUSGMII:
                phylink_decode_sgmii_word(state, lpa);
                break;
 
index a5671ab..3d99fd6 100644 (file)
@@ -70,6 +70,7 @@
 #define RTLGEN_SPEED_MASK                      0x0630
 
 #define RTL_GENERIC_PHYID                      0x001cc800
+#define RTL_8211FVD_PHYID                      0x001cc878
 
 MODULE_DESCRIPTION("Realtek PHY driver");
 MODULE_AUTHOR("Johnson Leung");
@@ -78,6 +79,7 @@ MODULE_LICENSE("GPL");
 struct rtl821x_priv {
        u16 phycr1;
        u16 phycr2;
+       bool has_phycr2;
 };
 
 static int rtl821x_read_page(struct phy_device *phydev)
@@ -94,6 +96,7 @@ static int rtl821x_probe(struct phy_device *phydev)
 {
        struct device *dev = &phydev->mdio.dev;
        struct rtl821x_priv *priv;
+       u32 phy_id = phydev->drv->phy_id;
        int ret;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
@@ -108,13 +111,16 @@ static int rtl821x_probe(struct phy_device *phydev)
        if (of_property_read_bool(dev->of_node, "realtek,aldps-enable"))
                priv->phycr1 |= RTL8211F_ALDPS_PLL_OFF | RTL8211F_ALDPS_ENABLE | RTL8211F_ALDPS_XTAL_OFF;
 
-       ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2);
-       if (ret < 0)
-               return ret;
+       priv->has_phycr2 = !(phy_id == RTL_8211FVD_PHYID);
+       if (priv->has_phycr2) {
+               ret = phy_read_paged(phydev, 0xa43, RTL8211F_PHYCR2);
+               if (ret < 0)
+                       return ret;
 
-       priv->phycr2 = ret & RTL8211F_CLKOUT_EN;
-       if (of_property_read_bool(dev->of_node, "realtek,clkout-disable"))
-               priv->phycr2 &= ~RTL8211F_CLKOUT_EN;
+               priv->phycr2 = ret & RTL8211F_CLKOUT_EN;
+               if (of_property_read_bool(dev->of_node, "realtek,clkout-disable"))
+                       priv->phycr2 &= ~RTL8211F_CLKOUT_EN;
+       }
 
        phydev->priv = priv;
 
@@ -400,12 +406,14 @@ static int rtl8211f_config_init(struct phy_device *phydev)
                        val_rxdly ? "enabled" : "disabled");
        }
 
-       ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2,
-                              RTL8211F_CLKOUT_EN, priv->phycr2);
-       if (ret < 0) {
-               dev_err(dev, "clkout configuration failed: %pe\n",
-                       ERR_PTR(ret));
-               return ret;
+       if (priv->has_phycr2) {
+               ret = phy_modify_paged(phydev, 0xa43, RTL8211F_PHYCR2,
+                                      RTL8211F_CLKOUT_EN, priv->phycr2);
+               if (ret < 0) {
+                       dev_err(dev, "clkout configuration failed: %pe\n",
+                               ERR_PTR(ret));
+                       return ret;
+               }
        }
 
        return genphy_soft_reset(phydev);
@@ -923,6 +931,18 @@ static struct phy_driver realtek_drvs[] = {
                .resume         = rtl821x_resume,
                .read_page      = rtl821x_read_page,
                .write_page     = rtl821x_write_page,
+       }, {
+               PHY_ID_MATCH_EXACT(RTL_8211FVD_PHYID),
+               .name           = "RTL8211F-VD Gigabit Ethernet",
+               .probe          = rtl821x_probe,
+               .config_init    = &rtl8211f_config_init,
+               .read_status    = rtlgen_read_status,
+               .config_intr    = &rtl8211f_config_intr,
+               .handle_interrupt = rtl8211f_handle_interrupt,
+               .suspend        = genphy_suspend,
+               .resume         = rtl821x_resume,
+               .read_page      = rtl821x_read_page,
+               .write_page     = rtl821x_write_page,
        }, {
                .name           = "Generic FE-GE Realtek PHY",
                .match_phy_device = rtlgen_match_phy_device,
index 63f90fe..a12f7b5 100644 (file)
@@ -1195,90 +1195,45 @@ static const struct hwmon_ops sfp_hwmon_ops = {
        .read_string = sfp_hwmon_read_string,
 };
 
-static u32 sfp_hwmon_chip_config[] = {
-       HWMON_C_REGISTER_TZ,
-       0,
-};
-
-static const struct hwmon_channel_info sfp_hwmon_chip = {
-       .type = hwmon_chip,
-       .config = sfp_hwmon_chip_config,
-};
-
-static u32 sfp_hwmon_temp_config[] = {
-       HWMON_T_INPUT |
-       HWMON_T_MAX | HWMON_T_MIN |
-       HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM |
-       HWMON_T_CRIT | HWMON_T_LCRIT |
-       HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM |
-       HWMON_T_LABEL,
-       0,
-};
-
-static const struct hwmon_channel_info sfp_hwmon_temp_channel_info = {
-       .type = hwmon_temp,
-       .config = sfp_hwmon_temp_config,
-};
-
-static u32 sfp_hwmon_vcc_config[] = {
-       HWMON_I_INPUT |
-       HWMON_I_MAX | HWMON_I_MIN |
-       HWMON_I_MAX_ALARM | HWMON_I_MIN_ALARM |
-       HWMON_I_CRIT | HWMON_I_LCRIT |
-       HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM |
-       HWMON_I_LABEL,
-       0,
-};
-
-static const struct hwmon_channel_info sfp_hwmon_vcc_channel_info = {
-       .type = hwmon_in,
-       .config = sfp_hwmon_vcc_config,
-};
-
-static u32 sfp_hwmon_bias_config[] = {
-       HWMON_C_INPUT |
-       HWMON_C_MAX | HWMON_C_MIN |
-       HWMON_C_MAX_ALARM | HWMON_C_MIN_ALARM |
-       HWMON_C_CRIT | HWMON_C_LCRIT |
-       HWMON_C_CRIT_ALARM | HWMON_C_LCRIT_ALARM |
-       HWMON_C_LABEL,
-       0,
-};
-
-static const struct hwmon_channel_info sfp_hwmon_bias_channel_info = {
-       .type = hwmon_curr,
-       .config = sfp_hwmon_bias_config,
-};
-
-static u32 sfp_hwmon_power_config[] = {
-       /* Transmit power */
-       HWMON_P_INPUT |
-       HWMON_P_MAX | HWMON_P_MIN |
-       HWMON_P_MAX_ALARM | HWMON_P_MIN_ALARM |
-       HWMON_P_CRIT | HWMON_P_LCRIT |
-       HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM |
-       HWMON_P_LABEL,
-       /* Receive power */
-       HWMON_P_INPUT |
-       HWMON_P_MAX | HWMON_P_MIN |
-       HWMON_P_MAX_ALARM | HWMON_P_MIN_ALARM |
-       HWMON_P_CRIT | HWMON_P_LCRIT |
-       HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM |
-       HWMON_P_LABEL,
-       0,
-};
-
-static const struct hwmon_channel_info sfp_hwmon_power_channel_info = {
-       .type = hwmon_power,
-       .config = sfp_hwmon_power_config,
-};
-
 static const struct hwmon_channel_info *sfp_hwmon_info[] = {
-       &sfp_hwmon_chip,
-       &sfp_hwmon_vcc_channel_info,
-       &sfp_hwmon_temp_channel_info,
-       &sfp_hwmon_bias_channel_info,
-       &sfp_hwmon_power_channel_info,
+       HWMON_CHANNEL_INFO(chip,
+                          HWMON_C_REGISTER_TZ),
+       HWMON_CHANNEL_INFO(in,
+                          HWMON_I_INPUT |
+                          HWMON_I_MAX | HWMON_I_MIN |
+                          HWMON_I_MAX_ALARM | HWMON_I_MIN_ALARM |
+                          HWMON_I_CRIT | HWMON_I_LCRIT |
+                          HWMON_I_CRIT_ALARM | HWMON_I_LCRIT_ALARM |
+                          HWMON_I_LABEL),
+       HWMON_CHANNEL_INFO(temp,
+                          HWMON_T_INPUT |
+                          HWMON_T_MAX | HWMON_T_MIN |
+                          HWMON_T_MAX_ALARM | HWMON_T_MIN_ALARM |
+                          HWMON_T_CRIT | HWMON_T_LCRIT |
+                          HWMON_T_CRIT_ALARM | HWMON_T_LCRIT_ALARM |
+                          HWMON_T_LABEL),
+       HWMON_CHANNEL_INFO(curr,
+                          HWMON_C_INPUT |
+                          HWMON_C_MAX | HWMON_C_MIN |
+                          HWMON_C_MAX_ALARM | HWMON_C_MIN_ALARM |
+                          HWMON_C_CRIT | HWMON_C_LCRIT |
+                          HWMON_C_CRIT_ALARM | HWMON_C_LCRIT_ALARM |
+                          HWMON_C_LABEL),
+       HWMON_CHANNEL_INFO(power,
+                          /* Transmit power */
+                          HWMON_P_INPUT |
+                          HWMON_P_MAX | HWMON_P_MIN |
+                          HWMON_P_MAX_ALARM | HWMON_P_MIN_ALARM |
+                          HWMON_P_CRIT | HWMON_P_LCRIT |
+                          HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM |
+                          HWMON_P_LABEL,
+                          /* Receive power */
+                          HWMON_P_INPUT |
+                          HWMON_P_MAX | HWMON_P_MIN |
+                          HWMON_P_MAX_ALARM | HWMON_P_MIN_ALARM |
+                          HWMON_P_CRIT | HWMON_P_LCRIT |
+                          HWMON_P_CRIT_ALARM | HWMON_P_LCRIT_ALARM |
+                          HWMON_P_LABEL),
        NULL,
 };
 
index 69423b8..ac7481c 100644 (file)
@@ -46,7 +46,6 @@ static struct smsc_hw_stat smsc_hw_stats[] = {
 struct smsc_phy_priv {
        u16 intmask;
        bool energy_enable;
-       struct clk *refclk;
 };
 
 static int smsc_phy_ack_interrupt(struct phy_device *phydev)
@@ -285,20 +284,12 @@ static void smsc_get_stats(struct phy_device *phydev,
                data[i] = smsc_get_stat(phydev, i);
 }
 
-static void smsc_phy_remove(struct phy_device *phydev)
-{
-       struct smsc_phy_priv *priv = phydev->priv;
-
-       clk_disable_unprepare(priv->refclk);
-       clk_put(priv->refclk);
-}
-
 static int smsc_phy_probe(struct phy_device *phydev)
 {
        struct device *dev = &phydev->mdio.dev;
        struct device_node *of_node = dev->of_node;
        struct smsc_phy_priv *priv;
-       int ret;
+       struct clk *refclk;
 
        priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
        if (!priv)
@@ -312,22 +303,12 @@ static int smsc_phy_probe(struct phy_device *phydev)
        phydev->priv = priv;
 
        /* Make clk optional to keep DTB backward compatibility. */
-       priv->refclk = clk_get_optional(dev, NULL);
-       if (IS_ERR(priv->refclk))
-               return dev_err_probe(dev, PTR_ERR(priv->refclk),
+       refclk = devm_clk_get_optional_enabled(dev, NULL);
+       if (IS_ERR(refclk))
+               return dev_err_probe(dev, PTR_ERR(refclk),
                                     "Failed to request clock\n");
 
-       ret = clk_prepare_enable(priv->refclk);
-       if (ret)
-               return ret;
-
-       ret = clk_set_rate(priv->refclk, 50 * 1000 * 1000);
-       if (ret) {
-               clk_disable_unprepare(priv->refclk);
-               return ret;
-       }
-
-       return 0;
+       return clk_set_rate(refclk, 50 * 1000 * 1000);
 }
 
 static struct phy_driver smsc_phy_driver[] = {
@@ -429,7 +410,6 @@ static struct phy_driver smsc_phy_driver[] = {
        /* PHY_BASIC_FEATURES */
 
        .probe          = smsc_phy_probe,
-       .remove         = smsc_phy_remove,
 
        /* basic functions */
        .read_status    = lan87xx_read_status,
index 39e61e0..fbcb9d0 100644 (file)
@@ -443,10 +443,10 @@ static void rionet_get_drvinfo(struct net_device *ndev,
 {
        struct rionet_private *rnet = netdev_priv(ndev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
-       strlcpy(info->fw_version, "n/a", sizeof(info->fw_version));
-       strlcpy(info->bus_info, rnet->mport->name, sizeof(info->bus_info));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->fw_version, "n/a", sizeof(info->fw_version));
+       strscpy(info->bus_info, rnet->mport->name, sizeof(info->bus_info));
 }
 
 static u32 rionet_get_msglevel(struct net_device *ndev)
index aac133a..ab92416 100644 (file)
@@ -2070,8 +2070,8 @@ static const struct net_device_ops team_netdev_ops = {
 static void team_ethtool_get_drvinfo(struct net_device *dev,
                                     struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, DRV_NAME, sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
 }
 
 static int team_ethtool_get_link_ksettings(struct net_device *dev,
@@ -2840,6 +2840,7 @@ static struct genl_family team_nl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = team_nl_ops,
        .n_small_ops    = ARRAY_SIZE(team_nl_ops),
+       .resv_start_op  = TEAM_CMD_PORT_LIST_GET + 1,
        .mcgrps         = team_nl_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(team_nl_mcgrps),
 };
index ff5d0e9..c058eab 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Networking over Thunderbolt cable using Apple ThunderboltIP protocol
+ * Networking over Thunderbolt/USB4 cables using USB4NET protocol
+ * (formerly Apple ThunderboltIP).
  *
  * Copyright (C) 2017, Intel Corporation
  * Authors: Amir Levy <amir.jer.levy@intel.com>
@@ -30,6 +31,7 @@
 #define TBNET_RING_SIZE                256
 #define TBNET_LOGIN_RETRIES    60
 #define TBNET_LOGOUT_RETRIES   10
+#define TBNET_E2E              BIT(0)
 #define TBNET_MATCH_FRAGS_ID   BIT(1)
 #define TBNET_64K_FRAMES       BIT(2)
 #define TBNET_MAX_MTU          SZ_64K
@@ -209,6 +211,10 @@ static const uuid_t tbnet_svc_uuid =
 
 static struct tb_property_dir *tbnet_dir;
 
+static bool tbnet_e2e = true;
+module_param_named(e2e, tbnet_e2e, bool, 0444);
+MODULE_PARM_DESC(e2e, "USB4NET full end-to-end flow control (default: true)");
+
 static void tbnet_fill_header(struct thunderbolt_ip_header *hdr, u64 route,
        u8 sequence, const uuid_t *initiator_uuid, const uuid_t *target_uuid,
        enum thunderbolt_ip_type type, size_t size, u32 command_id)
@@ -612,18 +618,13 @@ static void tbnet_connected_work(struct work_struct *work)
                return;
        }
 
-       /* Both logins successful so enable the high-speed DMA paths and
-        * start the network device queue.
+       /* Both logins successful so enable the rings, high-speed DMA
+        * paths and start the network device queue.
+        *
+        * Note we enable the DMA paths last to make sure we have primed
+        * the Rx ring before any incoming packets are allowed to
+        * arrive.
         */
-       ret = tb_xdomain_enable_paths(net->xd, net->local_transmit_path,
-                                     net->rx_ring.ring->hop,
-                                     net->remote_transmit_path,
-                                     net->tx_ring.ring->hop);
-       if (ret) {
-               netdev_err(net->dev, "failed to enable DMA paths\n");
-               return;
-       }
-
        tb_ring_start(net->tx_ring.ring);
        tb_ring_start(net->rx_ring.ring);
 
@@ -635,10 +636,21 @@ static void tbnet_connected_work(struct work_struct *work)
        if (ret)
                goto err_free_rx_buffers;
 
+       ret = tb_xdomain_enable_paths(net->xd, net->local_transmit_path,
+                                     net->rx_ring.ring->hop,
+                                     net->remote_transmit_path,
+                                     net->tx_ring.ring->hop);
+       if (ret) {
+               netdev_err(net->dev, "failed to enable DMA paths\n");
+               goto err_free_tx_buffers;
+       }
+
        netif_carrier_on(net->dev);
        netif_start_queue(net->dev);
        return;
 
+err_free_tx_buffers:
+       tbnet_free_buffers(&net->tx_ring);
 err_free_rx_buffers:
        tbnet_free_buffers(&net->rx_ring);
 err_stop_rings:
@@ -867,6 +879,7 @@ static int tbnet_open(struct net_device *dev)
        struct tb_xdomain *xd = net->xd;
        u16 sof_mask, eof_mask;
        struct tb_ring *ring;
+       unsigned int flags;
        int hopid;
 
        netif_carrier_off(dev);
@@ -891,9 +904,14 @@ static int tbnet_open(struct net_device *dev)
        sof_mask = BIT(TBIP_PDF_FRAME_START);
        eof_mask = BIT(TBIP_PDF_FRAME_END);
 
-       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE,
-                               RING_FLAG_FRAME, 0, sof_mask, eof_mask,
-                               tbnet_start_poll, net);
+       flags = RING_FLAG_FRAME;
+       /* Only enable full E2E if the other end supports it too */
+       if (tbnet_e2e && net->svc->prtcstns & TBNET_E2E)
+               flags |= RING_FLAG_E2E;
+
+       ring = tb_ring_alloc_rx(xd->tb->nhi, -1, TBNET_RING_SIZE, flags,
+                               net->tx_ring.ring->hop, sof_mask,
+                               eof_mask, tbnet_start_poll, net);
        if (!ring) {
                netdev_err(dev, "failed to allocate Rx ring\n");
                tb_ring_free(net->tx_ring.ring);
@@ -1356,6 +1374,7 @@ static struct tb_service_driver tbnet_driver = {
 
 static int __init tbnet_init(void)
 {
+       unsigned int flags;
        int ret;
 
        tbnet_dir = tb_property_create_dir(&tbnet_dir_uuid);
@@ -1365,12 +1384,11 @@ static int __init tbnet_init(void)
        tb_property_add_immediate(tbnet_dir, "prtcid", 1);
        tb_property_add_immediate(tbnet_dir, "prtcvers", 1);
        tb_property_add_immediate(tbnet_dir, "prtcrevs", 1);
-       /* Currently only announce support for match frags ID (bit 1). Bit 0
-        * is reserved for full E2E flow control which we do not support at
-        * the moment.
-        */
-       tb_property_add_immediate(tbnet_dir, "prtcstns",
-                                 TBNET_MATCH_FRAGS_ID | TBNET_64K_FRAMES);
+
+       flags = TBNET_MATCH_FRAGS_ID | TBNET_64K_FRAMES;
+       if (tbnet_e2e)
+               flags |= TBNET_E2E;
+       tb_property_add_immediate(tbnet_dir, "prtcstns", flags);
 
        ret = tb_register_property_dir("network", tbnet_dir);
        if (ret) {
@@ -1393,5 +1411,5 @@ module_exit(tbnet_exit);
 MODULE_AUTHOR("Amir Levy <amir.jer.levy@intel.com>");
 MODULE_AUTHOR("Michael Jamet <michael.jamet@intel.com>");
 MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
-MODULE_DESCRIPTION("Thunderbolt network driver");
+MODULE_DESCRIPTION("Thunderbolt/USB4 network driver");
 MODULE_LICENSE("GPL v2");
index 259b2b8..3732e51 100644 (file)
@@ -3540,15 +3540,15 @@ static void tun_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info
 {
        struct tun_struct *tun = netdev_priv(dev);
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 
        switch (tun->flags & TUN_TYPE_MASK) {
        case IFF_TUN:
-               strlcpy(info->bus_info, "tun", sizeof(info->bus_info));
+               strscpy(info->bus_info, "tun", sizeof(info->bus_info));
                break;
        case IFF_TAP:
-               strlcpy(info->bus_info, "tap", sizeof(info->bus_info));
+               strscpy(info->bus_info, "tap", sizeof(info->bus_info));
                break;
        }
 }
index 76659c1..4402eed 100644 (file)
@@ -168,7 +168,7 @@ config USB_NET_AX8817X
        tristate "ASIX AX88xxx Based USB 2.0 Ethernet Adapters"
        depends on USB_USBNET
        select CRC32
-       select PHYLIB
+       select PHYLINK
        select AX88796B_PHY
        imply NET_SELFTESTS
        default y
index 3020e81..a017e9d 100644 (file)
@@ -201,7 +201,7 @@ static void aqc111_get_drvinfo(struct net_device *net,
 
        /* Inherit standard device info */
        usbnet_get_drvinfo(net, info);
-       strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+       strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
        snprintf(info->fw_version, sizeof(info->fw_version), "%u.%u.%u",
                 aqc111_data->fw_ver.major,
                 aqc111_data->fw_ver.minor,
index 21c1ca2..7416219 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/if_vlan.h>
 #include <linux/phy.h>
 #include <net/selftests.h>
+#include <linux/phylink.h>
 
 #define DRIVER_VERSION "22-Dec-2011"
 #define DRIVER_NAME "asix"
@@ -185,6 +186,8 @@ struct asix_common_private {
        struct mii_bus *mdio;
        struct phy_device *phydev;
        struct phy_device *phydev_int;
+       struct phylink *phylink;
+       struct phylink_config phylink_config;
        u16 phy_addr;
        bool embd_phy;
        u8 chipcode;
index 9ea91c3..72ffc89 100644 (file)
@@ -752,8 +752,8 @@ void asix_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *info)
 {
        /* Inherit standard device info */
        usbnet_get_drvinfo(net, info);
-       strlcpy(info->driver, DRIVER_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
+       strscpy(info->version, DRIVER_VERSION, sizeof(info->version));
 }
 
 int asix_set_mac_address(struct net_device *net, void *p)
index 5b5eb63..11f60d3 100644 (file)
@@ -303,6 +303,24 @@ static int ax88772_ethtool_get_sset_count(struct net_device *ndev, int sset)
        }
 }
 
+static void ax88772_ethtool_get_pauseparam(struct net_device *ndev,
+                                         struct ethtool_pauseparam *pause)
+{
+       struct usbnet *dev = netdev_priv(ndev);
+       struct asix_common_private *priv = dev->driver_priv;
+
+       phylink_ethtool_get_pauseparam(priv->phylink, pause);
+}
+
+static int ax88772_ethtool_set_pauseparam(struct net_device *ndev,
+                                        struct ethtool_pauseparam *pause)
+{
+       struct usbnet *dev = netdev_priv(ndev);
+       struct asix_common_private *priv = dev->driver_priv;
+
+       return phylink_ethtool_set_pauseparam(priv->phylink, pause);
+}
+
 static const struct ethtool_ops ax88772_ethtool_ops = {
        .get_drvinfo            = asix_get_drvinfo,
        .get_link               = usbnet_get_link,
@@ -319,6 +337,8 @@ static const struct ethtool_ops ax88772_ethtool_ops = {
        .self_test              = net_selftest,
        .get_strings            = ax88772_ethtool_get_strings,
        .get_sset_count         = ax88772_ethtool_get_sset_count,
+       .get_pauseparam         = ax88772_ethtool_get_pauseparam,
+       .set_pauseparam         = ax88772_ethtool_set_pauseparam,
 };
 
 static int ax88772_reset(struct usbnet *dev)
@@ -343,7 +363,7 @@ static int ax88772_reset(struct usbnet *dev)
        if (ret < 0)
                goto out;
 
-       phy_start(priv->phydev);
+       phylink_start(priv->phylink);
 
        return 0;
 
@@ -590,8 +610,11 @@ static void ax88772_suspend(struct usbnet *dev)
        struct asix_common_private *priv = dev->driver_priv;
        u16 medium;
 
-       if (netif_running(dev->net))
-               phy_stop(priv->phydev);
+       if (netif_running(dev->net)) {
+               rtnl_lock();
+               phylink_suspend(priv->phylink, false);
+               rtnl_unlock();
+       }
 
        /* Stop MAC operation */
        medium = asix_read_medium_status(dev, 1);
@@ -622,8 +645,11 @@ static void ax88772_resume(struct usbnet *dev)
                if (!priv->reset(dev, 1))
                        break;
 
-       if (netif_running(dev->net))
-               phy_start(priv->phydev);
+       if (netif_running(dev->net)) {
+               rtnl_lock();
+               phylink_resume(priv->phylink);
+               rtnl_unlock();
+       }
 }
 
 static int asix_resume(struct usb_interface *intf)
@@ -667,8 +693,7 @@ static int ax88772_init_phy(struct usbnet *dev)
                return -ENODEV;
        }
 
-       ret = phy_connect_direct(dev->net, priv->phydev, &asix_adjust_link,
-                                PHY_INTERFACE_MODE_INTERNAL);
+       ret = phylink_connect_phy(priv->phylink, priv->phydev);
        if (ret) {
                netdev_err(dev->net, "Could not connect PHY\n");
                return ret;
@@ -688,6 +713,9 @@ static int ax88772_init_phy(struct usbnet *dev)
         */
        priv->phydev_int = mdiobus_get_phy(priv->mdio, AX_EMBD_PHY_ADDR);
        if (!priv->phydev_int) {
+               rtnl_lock();
+               phylink_disconnect_phy(priv->phylink);
+               rtnl_unlock();
                netdev_err(dev->net, "Could not find internal PHY\n");
                return -ENODEV;
        }
@@ -698,6 +726,89 @@ static int ax88772_init_phy(struct usbnet *dev)
        return 0;
 }
 
+static void ax88772_mac_config(struct phylink_config *config, unsigned int mode,
+                             const struct phylink_link_state *state)
+{
+       /* Nothing to do */
+}
+
+static void ax88772_mac_link_down(struct phylink_config *config,
+                                unsigned int mode, phy_interface_t interface)
+{
+       struct usbnet *dev = netdev_priv(to_net_dev(config->dev));
+
+       asix_write_medium_mode(dev, 0, 0);
+       usbnet_link_change(dev, false, false);
+}
+
+static void ax88772_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 usbnet *dev = netdev_priv(to_net_dev(config->dev));
+       u16 m = AX_MEDIUM_AC | AX_MEDIUM_RE;
+
+       m |= duplex ? AX_MEDIUM_FD : 0;
+
+       switch (speed) {
+       case SPEED_100:
+               m |= AX_MEDIUM_PS;
+               break;
+       case SPEED_10:
+               break;
+       default:
+               return;
+       }
+
+       if (tx_pause)
+               m |= AX_MEDIUM_TFC;
+
+       if (rx_pause)
+               m |= AX_MEDIUM_RFC;
+
+       asix_write_medium_mode(dev, m, 0);
+       usbnet_link_change(dev, true, false);
+}
+
+static const struct phylink_mac_ops ax88772_phylink_mac_ops = {
+       .validate = phylink_generic_validate,
+       .mac_config = ax88772_mac_config,
+       .mac_link_down = ax88772_mac_link_down,
+       .mac_link_up = ax88772_mac_link_up,
+};
+
+static int ax88772_phylink_setup(struct usbnet *dev)
+{
+       struct asix_common_private *priv = dev->driver_priv;
+       phy_interface_t phy_if_mode;
+       struct phylink *phylink;
+
+       priv->phylink_config.dev = &dev->net->dev;
+       priv->phylink_config.type = PHYLINK_NETDEV;
+       priv->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
+               MAC_10 | MAC_100;
+
+       __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+                 priv->phylink_config.supported_interfaces);
+       __set_bit(PHY_INTERFACE_MODE_RMII,
+                 priv->phylink_config.supported_interfaces);
+
+       if (priv->embd_phy)
+               phy_if_mode = PHY_INTERFACE_MODE_INTERNAL;
+       else
+               phy_if_mode = PHY_INTERFACE_MODE_RMII;
+
+       phylink = phylink_create(&priv->phylink_config, dev->net->dev.fwnode,
+                                phy_if_mode, &ax88772_phylink_mac_ops);
+       if (IS_ERR(phylink))
+               return PTR_ERR(phylink);
+
+       priv->phylink = phylink;
+       return 0;
+}
+
 static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct asix_common_private *priv;
@@ -788,14 +899,22 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        if (ret)
                return ret;
 
-       return ax88772_init_phy(dev);
+       ret = ax88772_phylink_setup(dev);
+       if (ret)
+               return ret;
+
+       ret = ax88772_init_phy(dev);
+       if (ret)
+               phylink_destroy(priv->phylink);
+
+       return ret;
 }
 
 static int ax88772_stop(struct usbnet *dev)
 {
        struct asix_common_private *priv = dev->driver_priv;
 
-       phy_stop(priv->phydev);
+       phylink_stop(priv->phylink);
 
        return 0;
 }
@@ -804,7 +923,10 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
 {
        struct asix_common_private *priv = dev->driver_priv;
 
-       phy_disconnect(priv->phydev);
+       rtnl_lock();
+       phylink_disconnect_phy(priv->phylink);
+       rtnl_unlock();
+       phylink_destroy(priv->phylink);
        asix_rx_fixup_common_free(dev->driver_priv);
 }
 
index 8438934..ff439ef 100644 (file)
@@ -672,8 +672,8 @@ static void catc_get_drvinfo(struct net_device *dev,
                             struct ethtool_drvinfo *info)
 {
        struct catc *catc = netdev_priv(dev);
-       strlcpy(info->driver, driver_name, sizeof(info->driver));
-       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->driver, driver_name, sizeof(info->driver));
+       strscpy(info->version, DRIVER_VERSION, sizeof(info->version));
        usb_make_path(catc->usbdev, info->bus_info, sizeof(info->bus_info));
 }
 
index 2de09ad..e11f709 100644 (file)
@@ -777,6 +777,13 @@ static const struct usb_device_id  products[] = {
 },
 #endif
 
+/* Lenovo ThinkPad OneLink+ Dock (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3054, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* ThinkPad USB-C Dock (based on Realtek RTL8153) */
 {
        USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM,
index feb247e..81ca64d 100644 (file)
@@ -894,7 +894,7 @@ static void pegasus_get_drvinfo(struct net_device *dev,
 {
        pegasus_t *pegasus = netdev_priv(dev);
 
-       strlcpy(info->driver, driver_name, sizeof(info->driver));
+       strscpy(info->driver, driver_name, sizeof(info->driver));
        usb_make_path(pegasus->usb, info->bus_info, sizeof(info->bus_info));
 }
 
index d142ac8..a51d8de 100644 (file)
@@ -770,6 +770,8 @@ enum rtl8152_flags {
        RX_EPROTO,
 };
 
+#define DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB              0x721e
+#define DEVICE_ID_THINKPAD_ONELINK_PLUS_DOCK           0x3054
 #define DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2      0x3082
 #define DEVICE_ID_THINKPAD_USB_C_DONGLE                        0x720c
 #define DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2             0xa387
@@ -2726,22 +2728,26 @@ static void _rtl8152_set_rx_mode(struct net_device *netdev)
                ocp_data |= RCR_AM | RCR_AAP;
                mc_filter[1] = 0xffffffff;
                mc_filter[0] = 0xffffffff;
-       } else if ((netdev_mc_count(netdev) > multicast_filter_limit) ||
-                  (netdev->flags & IFF_ALLMULTI)) {
+       } else if ((netdev->flags & IFF_MULTICAST &&
+                               netdev_mc_count(netdev) > multicast_filter_limit) ||
+                          (netdev->flags & IFF_ALLMULTI)) {
                /* Too many to filter perfectly -- accept all multicasts. */
                ocp_data |= RCR_AM;
                mc_filter[1] = 0xffffffff;
                mc_filter[0] = 0xffffffff;
        } else {
-               struct netdev_hw_addr *ha;
-
                mc_filter[1] = 0;
                mc_filter[0] = 0;
-               netdev_for_each_mc_addr(ha, netdev) {
-                       int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
 
-                       mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
-                       ocp_data |= RCR_AM;
+               if (netdev->flags & IFF_MULTICAST) {
+                       struct netdev_hw_addr *ha;
+
+                       netdev_for_each_mc_addr(ha, netdev) {
+                               int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
+
+                               mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
+                               ocp_data |= RCR_AM;
+                       }
                }
        }
 
@@ -8601,11 +8607,11 @@ static void rtl8152_get_drvinfo(struct net_device *netdev,
 {
        struct r8152 *tp = netdev_priv(netdev);
 
-       strlcpy(info->driver, MODULENAME, sizeof(info->driver));
-       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->driver, MODULENAME, sizeof(info->driver));
+       strscpy(info->version, DRIVER_VERSION, sizeof(info->version));
        usb_make_path(tp->udev, info->bus_info, sizeof(info->bus_info));
        if (!IS_ERR_OR_NULL(tp->rtl_fw.fw))
-               strlcpy(info->fw_version, tp->rtl_fw.version,
+               strscpy(info->fw_version, tp->rtl_fw.version,
                        sizeof(info->fw_version));
 }
 
@@ -9581,6 +9587,8 @@ static bool rtl8152_supports_lenovo_macpassthru(struct usb_device *udev)
 
        if (vendor_id == VENDOR_ID_LENOVO) {
                switch (product_id) {
+               case DEVICE_ID_LENOVO_USB_C_TRAVEL_HUB:
+               case DEVICE_ID_THINKPAD_ONELINK_PLUS_DOCK:
                case DEVICE_ID_THINKPAD_THUNDERBOLT3_DOCK_GEN2:
                case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN2:
                case DEVICE_ID_THINKPAD_USB_C_DOCK_GEN3:
@@ -9828,6 +9836,7 @@ static const struct usb_device_id rtl8152_table[] = {
        REALTEK_USB_DEVICE(VENDOR_ID_MICROSOFT, 0x0927),
        REALTEK_USB_DEVICE(VENDOR_ID_SAMSUNG, 0xa101),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x304f),
+       REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3054),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3062),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3069),
        REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x3082),
index 3d2bf2a..97afd73 100644 (file)
@@ -769,8 +769,8 @@ static void rtl8150_get_drvinfo(struct net_device *netdev, struct ethtool_drvinf
 {
        rtl8150_t *dev = netdev_priv(netdev);
 
-       strlcpy(info->driver, driver_name, sizeof(info->driver));
-       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->driver, driver_name, sizeof(info->driver));
+       strscpy(info->version, DRIVER_VERSION, sizeof(info->version));
        usb_make_path(dev->udev, info->bus_info, sizeof(info->bus_info));
 }
 
index bb4cbe8..b3ae949 100644 (file)
@@ -612,8 +612,8 @@ static void sierra_net_get_drvinfo(struct net_device *net,
 {
        /* Inherit standard device info */
        usbnet_get_drvinfo(net, info);
-       strlcpy(info->driver, driver_name, sizeof(info->driver));
-       strlcpy(info->version, DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->driver, driver_name, sizeof(info->driver));
+       strscpy(info->version, DRIVER_VERSION, sizeof(info->version));
 }
 
 static u32 sierra_net_get_link(struct net_device *net)
index aaa89b4..fd399a8 100644 (file)
@@ -1050,9 +1050,9 @@ void usbnet_get_drvinfo (struct net_device *net, struct ethtool_drvinfo *info)
 {
        struct usbnet *dev = netdev_priv(net);
 
-       strlcpy (info->driver, dev->driver_name, sizeof info->driver);
-       strlcpy (info->fw_version, dev->driver_info->description,
-               sizeof info->fw_version);
+       strscpy(info->driver, dev->driver_name, sizeof(info->driver));
+       strscpy(info->fw_version, dev->driver_info->description,
+               sizeof(info->fw_version));
        usb_make_path (dev->udev, info->bus_info, sizeof info->bus_info);
 }
 EXPORT_SYMBOL_GPL(usbnet_get_drvinfo);
index 466da01..550c85a 100644 (file)
@@ -128,8 +128,8 @@ static int veth_get_link_ksettings(struct net_device *dev,
 
 static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static void veth_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
index 9cce7de..e0e5708 100644 (file)
@@ -2594,9 +2594,9 @@ static void virtnet_get_drvinfo(struct net_device *dev,
        struct virtnet_info *vi = netdev_priv(dev);
        struct virtio_device *vdev = vi->vdev;
 
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->version, VIRTNET_DRIVER_VERSION, sizeof(info->version));
-       strlcpy(info->bus_info, virtio_bus_name(vdev), sizeof(info->bus_info));
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->version, VIRTNET_DRIVER_VERSION, sizeof(info->version));
+       strscpy(info->bus_info, virtio_bus_name(vdev), sizeof(info->bus_info));
 
 }
 
index e2034ad..18cf7c7 100644 (file)
@@ -209,12 +209,12 @@ vmxnet3_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
 {
        struct vmxnet3_adapter *adapter = netdev_priv(netdev);
 
-       strlcpy(drvinfo->driver, vmxnet3_driver_name, sizeof(drvinfo->driver));
+       strscpy(drvinfo->driver, vmxnet3_driver_name, sizeof(drvinfo->driver));
 
-       strlcpy(drvinfo->version, VMXNET3_DRIVER_VERSION_REPORT,
+       strscpy(drvinfo->version, VMXNET3_DRIVER_VERSION_REPORT,
                sizeof(drvinfo->version));
 
-       strlcpy(drvinfo->bus_info, pci_name(adapter->pdev),
+       strscpy(drvinfo->bus_info, pci_name(adapter->pdev),
                sizeof(drvinfo->bus_info));
 }
 
index 5df7a0a..badf6f0 100644 (file)
@@ -1541,8 +1541,8 @@ static const struct l3mdev_ops vrf_l3mdev_ops = {
 static void vrf_get_drvinfo(struct net_device *dev,
                            struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 }
 
 static const struct ethtool_ops vrf_ethtool_ops = {
index c328524..6ab669d 100644 (file)
@@ -713,12 +713,9 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
 
        off_vx = skb_gro_offset(skb);
        hlen = off_vx + sizeof(*vh);
-       vh   = skb_gro_header_fast(skb, off_vx);
-       if (skb_gro_header_hard(skb, hlen)) {
-               vh = skb_gro_header_slow(skb, hlen, off_vx);
-               if (unlikely(!vh))
-                       goto out;
-       }
+       vh = skb_gro_header(skb, hlen, off_vx);
+       if (unlikely(!vh))
+               goto out;
 
        skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
 
@@ -3313,8 +3310,8 @@ static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
 static void vxlan_get_drvinfo(struct net_device *netdev,
                              struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->version, VXLAN_VERSION, sizeof(drvinfo->version));
-       strlcpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver));
+       strscpy(drvinfo->version, VXLAN_VERSION, sizeof(drvinfo->version));
+       strscpy(drvinfo->driver, "vxlan", sizeof(drvinfo->driver));
 }
 
 static int vxlan_get_link_ksettings(struct net_device *dev,
index d0f3b6d..0c0644e 100644 (file)
@@ -621,6 +621,7 @@ static const struct genl_ops genl_ops[] = {
 static struct genl_family genl_family __ro_after_init = {
        .ops = genl_ops,
        .n_ops = ARRAY_SIZE(genl_ops),
+       .resv_start_op = WG_CMD_SET_DEVICE + 1,
        .name = WG_GENL_NAME,
        .version = WG_GENL_VERSION,
        .maxattr = WGDEVICE_A_MAX,
index 276954b..d1ac640 100644 (file)
@@ -98,6 +98,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = true,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA988X_HW_2_0_VERSION,
@@ -136,6 +137,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = true,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA9887_HW_1_0_VERSION,
@@ -175,6 +177,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA6174_HW_3_2_VERSION,
@@ -209,6 +212,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .supports_peer_stats_info = true,
                .dynamic_sar_support = true,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA6174_HW_2_1_VERSION,
@@ -247,6 +251,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA6174_HW_2_1_VERSION,
@@ -285,6 +290,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA6174_HW_3_0_VERSION,
@@ -323,6 +329,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA6174_HW_3_2_VERSION,
@@ -365,6 +372,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .supports_peer_stats_info = true,
                .dynamic_sar_support = true,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA99X0_HW_2_0_DEV_VERSION,
@@ -409,6 +417,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA9984_HW_1_0_DEV_VERSION,
@@ -460,6 +469,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA9888_HW_2_0_DEV_VERSION,
@@ -508,6 +518,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA9377_HW_1_0_DEV_VERSION,
@@ -546,6 +557,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA9377_HW_1_1_DEV_VERSION,
@@ -586,6 +598,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA9377_HW_1_1_DEV_VERSION,
@@ -617,6 +630,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .credit_size_workaround = true,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = QCA4019_HW_1_0_DEV_VERSION,
@@ -662,6 +676,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = false,
                .hw_restart_disconnect = false,
+               .use_fw_tx_credits = true,
        },
        {
                .id = WCN3990_HW_1_0_DEV_VERSION,
@@ -693,6 +708,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
                .tx_stats_over_pktlog = false,
                .dynamic_sar_support = true,
                .hw_restart_disconnect = true,
+               .use_fw_tx_credits = false,
        },
 };
 
index fab3980..6d1784f 100644 (file)
@@ -947,13 +947,18 @@ int ath10k_htc_wait_target(struct ath10k_htc *htc)
                return -ECOMM;
        }
 
-       htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
+       if (ar->hw_params.use_fw_tx_credits)
+               htc->total_transmit_credits = __le16_to_cpu(msg->ready.credit_count);
+       else
+               htc->total_transmit_credits = 1;
+
        htc->target_credit_size = __le16_to_cpu(msg->ready.credit_size);
 
        ath10k_dbg(ar, ATH10K_DBG_HTC,
-                  "Target ready! transmit resources: %d size:%d\n",
+                  "Target ready! transmit resources: %d size:%d actual credits:%d\n",
                   htc->total_transmit_credits,
-                  htc->target_credit_size);
+                  htc->target_credit_size,
+                  msg->ready.credit_count);
 
        if ((htc->total_transmit_credits == 0) ||
            (htc->target_credit_size == 0)) {
index 93acf0d..1b99f3a 100644 (file)
@@ -635,6 +635,8 @@ struct ath10k_hw_params {
        bool dynamic_sar_support;
 
        bool hw_restart_disconnect;
+
+       bool use_fw_tx_credits;
 };
 
 struct htt_resp;
index 9dd3b8f..23381a9 100644 (file)
@@ -864,11 +864,36 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr)
        return 0;
 }
 
+static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer)
+{
+       int peer_id, i;
+
+       lockdep_assert_held(&ar->conf_mutex);
+
+       for_each_set_bit(peer_id, peer->peer_ids,
+                        ATH10K_MAX_NUM_PEER_IDS) {
+               ar->peer_map[peer_id] = NULL;
+       }
+
+       /* Double check that peer is properly un-referenced from
+        * the peer_map
+        */
+       for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+               if (ar->peer_map[i] == peer) {
+                       ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
+                                   peer->addr, peer, i);
+                       ar->peer_map[i] = NULL;
+               }
+       }
+
+       list_del(&peer->list);
+       kfree(peer);
+       ar->num_peers--;
+}
+
 static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 {
        struct ath10k_peer *peer, *tmp;
-       int peer_id;
-       int i;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -880,25 +905,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
                ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n",
                            peer->addr, vdev_id);
 
-               for_each_set_bit(peer_id, peer->peer_ids,
-                                ATH10K_MAX_NUM_PEER_IDS) {
-                       ar->peer_map[peer_id] = NULL;
-               }
-
-               /* Double check that peer is properly un-referenced from
-                * the peer_map
-                */
-               for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
-                       if (ar->peer_map[i] == peer) {
-                               ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n",
-                                           peer->addr, peer, i);
-                               ar->peer_map[i] = NULL;
-                       }
-               }
-
-               list_del(&peer->list);
-               kfree(peer);
-               ar->num_peers--;
+               ath10k_peer_map_cleanup(ar, peer);
        }
        spin_unlock_bh(&ar->data_lock);
 }
@@ -7621,10 +7628,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
                                /* Clean up the peer object as well since we
                                 * must have failed to do this above.
                                 */
-                               list_del(&peer->list);
-                               ar->peer_map[i] = NULL;
-                               kfree(peer);
-                               ar->num_peers--;
+                               ath10k_peer_map_cleanup(ar, peer);
                        }
                }
                spin_unlock_bh(&ar->data_lock);
index e11c7e9..a20e0ae 100644 (file)
@@ -1124,7 +1124,7 @@ void ath6kl_cfg80211_ch_switch_notify(struct ath6kl_vif *vif, int freq,
 }
 
 static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
-                                  u8 key_index, bool pairwise,
+                                  int link_id, u8 key_index, bool pairwise,
                                   const u8 *mac_addr,
                                   struct key_params *params)
 {
@@ -1249,7 +1249,7 @@ static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
-                                  u8 key_index, bool pairwise,
+                                  int link_id, u8 key_index, bool pairwise,
                                   const u8 *mac_addr)
 {
        struct ath6kl *ar = ath6kl_priv(ndev);
@@ -1279,7 +1279,7 @@ static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
-                                  u8 key_index, bool pairwise,
+                                  int link_id, u8 key_index, bool pairwise,
                                   const u8 *mac_addr, void *cookie,
                                   void (*callback) (void *cookie,
                                                     struct key_params *))
@@ -1314,7 +1314,7 @@ static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
-                                          struct net_device *ndev,
+                                          struct net_device *ndev, int link_id,
                                           u8 key_index, bool unicast,
                                           bool multicast)
 {
index 9b5c7d8..201e455 100644 (file)
@@ -1014,7 +1014,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name)
 
                switch (ie_id) {
                case ATH6KL_FW_IE_FW_VERSION:
-                       strlcpy(ar->wiphy->fw_version, data,
+                       strscpy(ar->wiphy->fw_version, data,
                                min(sizeof(ar->wiphy->fw_version), ie_len+1));
 
                        ath6kl_dbg(ATH6KL_DBG_BOOT,
index 994ec48..ca05b07 100644 (file)
@@ -364,33 +364,27 @@ ret:
 }
 
 static void ath9k_htc_fw_panic_report(struct htc_target *htc_handle,
-                                     struct sk_buff *skb)
+                                     struct sk_buff *skb, u32 len)
 {
        uint32_t *pattern = (uint32_t *)skb->data;
 
-       switch (*pattern) {
-       case 0x33221199:
-               {
+       if (*pattern == 0x33221199 && len >= sizeof(struct htc_panic_bad_vaddr)) {
                struct htc_panic_bad_vaddr *htc_panic;
                htc_panic = (struct htc_panic_bad_vaddr *) skb->data;
                dev_err(htc_handle->dev, "ath: firmware panic! "
                        "exccause: 0x%08x; pc: 0x%08x; badvaddr: 0x%08x.\n",
                        htc_panic->exccause, htc_panic->pc,
                        htc_panic->badvaddr);
-               break;
-               }
-       case 0x33221299:
-               {
+               return;
+       }
+       if (*pattern == 0x33221299) {
                struct htc_panic_bad_epid *htc_panic;
                htc_panic = (struct htc_panic_bad_epid *) skb->data;
                dev_err(htc_handle->dev, "ath: firmware panic! "
                        "bad epid: 0x%08x\n", htc_panic->epid);
-               break;
-               }
-       default:
-               dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
-               break;
+               return;
        }
+       dev_err(htc_handle->dev, "ath: unknown panic pattern!\n");
 }
 
 /*
@@ -411,16 +405,26 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
        if (!htc_handle || !skb)
                return;
 
+       /* A valid message requires len >= 8.
+        *
+        *   sizeof(struct htc_frame_hdr) == 8
+        *   sizeof(struct htc_ready_msg) == 8
+        *   sizeof(struct htc_panic_bad_vaddr) == 16
+        *   sizeof(struct htc_panic_bad_epid) == 8
+        */
+       if (unlikely(len < sizeof(struct htc_frame_hdr)))
+               goto invalid;
        htc_hdr = (struct htc_frame_hdr *) skb->data;
        epid = htc_hdr->endpoint_id;
 
        if (epid == 0x99) {
-               ath9k_htc_fw_panic_report(htc_handle, skb);
+               ath9k_htc_fw_panic_report(htc_handle, skb, len);
                kfree_skb(skb);
                return;
        }
 
        if (epid < 0 || epid >= ENDPOINT_MAX) {
+invalid:
                if (pipe_id != USB_REG_IN_PIPE)
                        dev_kfree_skb_any(skb);
                else
@@ -432,21 +436,30 @@ void ath9k_htc_rx_msg(struct htc_target *htc_handle,
 
                /* Handle trailer */
                if (htc_hdr->flags & HTC_FLAGS_RECV_TRAILER) {
-                       if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000)
+                       if (be32_to_cpu(*(__be32 *) skb->data) == 0x00C60000) {
                                /* Move past the Watchdog pattern */
                                htc_hdr = (struct htc_frame_hdr *)(skb->data + 4);
+                               len -= 4;
+                       }
                }
 
                /* Get the message ID */
+               if (unlikely(len < sizeof(struct htc_frame_hdr) + sizeof(__be16)))
+                       goto invalid;
                msg_id = (__be16 *) ((void *) htc_hdr +
                                     sizeof(struct htc_frame_hdr));
 
                /* Now process HTC messages */
                switch (be16_to_cpu(*msg_id)) {
                case HTC_MSG_READY_ID:
+                       if (unlikely(len < sizeof(struct htc_ready_msg)))
+                               goto invalid;
                        htc_process_target_rdy(htc_handle, htc_hdr);
                        break;
                case HTC_MSG_CONNECT_SERVICE_RESPONSE_ID:
+                       if (unlikely(len < sizeof(struct htc_frame_hdr) +
+                                    sizeof(struct htc_conn_svc_rspmsg)))
+                               goto invalid;
                        htc_process_conn_rsp(htc_handle, htc_hdr);
                        break;
                default:
index 1ab09e1..4c1aecd 100644 (file)
@@ -105,7 +105,7 @@ static void carl9170_fw_info(struct ar9170 *ar)
                         CARL9170FW_GET_MONTH(fw_date),
                         CARL9170FW_GET_DAY(fw_date));
 
-               strlcpy(ar->hw->wiphy->fw_version, motd_desc->release,
+               strscpy(ar->hw->wiphy->fw_version, motd_desc->release,
                        sizeof(ar->hw->wiphy->fw_version));
        }
 }
index f93bdff..40f9a7e 100644 (file)
@@ -1620,7 +1620,7 @@ static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage,
 }
 
 static int wil_cfg80211_add_key(struct wiphy *wiphy,
-                               struct net_device *ndev,
+                               struct net_device *ndev, int link_id,
                                u8 key_index, bool pairwise,
                                const u8 *mac_addr,
                                struct key_params *params)
@@ -1696,7 +1696,7 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
 }
 
 static int wil_cfg80211_del_key(struct wiphy *wiphy,
-                               struct net_device *ndev,
+                               struct net_device *ndev, int link_id,
                                u8 key_index, bool pairwise,
                                const u8 *mac_addr)
 {
@@ -1723,7 +1723,7 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
 
 /* Need to be present or wiphy_new() will WARN */
 static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
-                                       struct net_device *ndev,
+                                       struct net_device *ndev, int link_id,
                                        u8 key_index, bool unicast,
                                        bool multicast)
 {
@@ -2072,8 +2072,8 @@ void wil_cfg80211_ap_recovery(struct wil6210_priv *wil)
                key_params.key = vif->gtk;
                key_params.key_len = vif->gtk_len;
                key_params.seq_len = IEEE80211_GCMP_PN_LEN;
-               rc = wil_cfg80211_add_key(wiphy, ndev, vif->gtk_index, false,
-                                         NULL, &key_params);
+               rc = wil_cfg80211_add_key(wiphy, ndev, -1, vif->gtk_index,
+                                         false, NULL, &key_params);
                if (rc)
                        wil_err(wil, "vif %d recovery add key failed (%d)\n",
                                i, rc);
index 7da87c9..94e61db 100644 (file)
@@ -1305,7 +1305,7 @@ void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len)
                        board_file = WIL_BOARD_FILE_NAME;
        }
 
-       strlcpy(buf, board_file, len);
+       strscpy(buf, board_file, len);
 }
 
 static int wil_get_bl_info(struct wil6210_priv *wil)
index 87a88f2..e76b38a 100644 (file)
@@ -445,7 +445,7 @@ int wil_if_add(struct wil6210_priv *wil)
 
        wil_dbg_misc(wil, "entered");
 
-       strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
+       strscpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
 
        rc = wiphy_register(wiphy);
        if (rc < 0) {
index ea7bd40..6a5976a 100644 (file)
@@ -780,7 +780,7 @@ static void wmi_evt_ready(struct wil6210_vif *vif, int id, void *d, int len)
                return; /* FW load will fail after timeout */
        }
        /* ignore MAC address, we already have it from the boot loader */
-       strlcpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
+       strscpy(wiphy->fw_version, wil->fw_version, sizeof(wiphy->fw_version));
 
        if (len > offsetof(struct wmi_ready_event, rfc_read_calib_result)) {
                wil_dbg_wmi(wil, "rfc calibration result %d\n",
index 0361c8e..45d079b 100644 (file)
@@ -1518,7 +1518,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port,
        priv->firmware = NULL;
        priv->firmware_type = fw_type;
        if (firmware) /* module parameter */
-               strlcpy(priv->firmware_id, firmware, sizeof(priv->firmware_id));
+               strscpy(priv->firmware_id, firmware, sizeof(priv->firmware_id));
        priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI;
        priv->station_state = STATION_STATE_DOWN;
        priv->do_rx_crc = 0;
index 982a772..bfe1be3 100644 (file)
@@ -118,7 +118,7 @@ static int b43_register_led(struct b43_wldev *dev, struct b43_led *led,
        led->wl = dev->wl;
        led->index = led_index;
        led->activelow = activelow;
-       strlcpy(led->name, name, sizeof(led->name));
+       strscpy(led->name, name, sizeof(led->name));
        atomic_set(&led->state, 0);
 
        led->led_dev.name = led->name;
index 38b5be3..79e6fd2 100644 (file)
@@ -88,7 +88,7 @@ static int b43legacy_register_led(struct b43legacy_wldev *dev,
        led->dev = dev;
        led->index = led_index;
        led->activelow = activelow;
-       strlcpy(led->name, name, sizeof(led->name));
+       strscpy(led->name, name, sizeof(led->name));
 
        led->led_dev.name = led->name;
        led->led_dev.default_trigger = default_trigger;
index 2c95a08..02a56ed 100644 (file)
@@ -368,8 +368,7 @@ brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
 
        /* await txstatus signal for firmware if active */
        if (brcmf_fws_fc_active(bcdc->fws)) {
-               if (!success)
-                       brcmf_fws_bustxfail(bcdc->fws, txp);
+               brcmf_fws_bustxcomplete(bcdc->fws, txp, success);
        } else {
                if (brcmf_proto_bcdc_hdrpull(bus_if->drvr, false, txp, &ifp))
                        brcmu_pkt_buf_free_skb(txp);
index db45da3..7c72ea2 100644 (file)
@@ -2361,7 +2361,8 @@ done:
 
 static s32
 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev,
-                                 u8 key_idx, bool unicast, bool multicast)
+                                 int link_id, u8 key_idx, bool unicast,
+                                 bool multicast)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_pub *drvr = ifp->drvr;
@@ -2395,7 +2396,8 @@ done:
 
 static s32
 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
-                      u8 key_idx, bool pairwise, const u8 *mac_addr)
+                      int link_id, u8 key_idx, bool pairwise,
+                      const u8 *mac_addr)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_wsec_key *key;
@@ -2432,8 +2434,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
 
 static s32
 brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
-                      u8 key_idx, bool pairwise, const u8 *mac_addr,
-                      struct key_params *params)
+                      int link_id, u8 key_idx, bool pairwise,
+                      const u8 *mac_addr, struct key_params *params)
 {
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_if *ifp = netdev_priv(ndev);
@@ -2457,8 +2459,8 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
        }
 
        if (params->key_len == 0)
-               return brcmf_cfg80211_del_key(wiphy, ndev, key_idx, pairwise,
-                                             mac_addr);
+               return brcmf_cfg80211_del_key(wiphy, ndev, -1, key_idx,
+                                             pairwise, mac_addr);
 
        if (params->key_len > sizeof(key->data)) {
                bphy_err(drvr, "Too long key length (%u)\n", params->key_len);
@@ -2553,8 +2555,9 @@ done:
 }
 
 static s32
-brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx,
-                      bool pairwise, const u8 *mac_addr, void *cookie,
+brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
+                      int link_id, u8 key_idx, bool pairwise,
+                      const u8 *mac_addr, void *cookie,
                       void (*callback)(void *cookie,
                                        struct key_params *params))
 {
@@ -2610,7 +2613,8 @@ done:
 
 static s32
 brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
-                                      struct net_device *ndev, u8 key_idx)
+                                      struct net_device *ndev, int link_id,
+                                      u8 key_idx)
 {
        struct brcmf_if *ifp = netdev_priv(ndev);
 
@@ -6431,6 +6435,7 @@ static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg)
        cfg->dongle_up = false; /* dongle down */
        brcmf_abort_scanning(cfg);
        brcmf_deinit_priv_mem(cfg);
+       brcmf_clear_assoc_ies(cfg);
 }
 
 static void init_vif_event(struct brcmf_cfg80211_vif_event *event)
index 7485e78..372deeb 100644 (file)
@@ -261,7 +261,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
                                     &revinfo, sizeof(revinfo));
        if (err < 0) {
                bphy_err(drvr, "retrieving revision info failed, %d\n", err);
-               strlcpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
+               strscpy(ri->chipname, "UNKNOWN", sizeof(ri->chipname));
        } else {
                ri->vendorid = le32_to_cpu(revinfo.vendorid);
                ri->deviceid = le32_to_cpu(revinfo.deviceid);
@@ -314,7 +314,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
 
        /* locate firmware version number for ethtool */
        ptr = strrchr(buf, ' ') + 1;
-       strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+       strscpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
 
        /* Query for 'clmver' to get CLM version info from firmware */
        memset(buf, 0, sizeof(buf));
@@ -424,11 +424,11 @@ static void brcmf_mp_attach(void)
         * if not set then if available use the platform data version. To make
         * sure it gets initialized at all, always copy the module param version
         */
-       strlcpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
+       strscpy(brcmf_mp_global.firmware_path, brcmf_firmware_path,
                BRCMF_FW_ALTPATH_LEN);
        if ((brcmfmac_pdata) && (brcmfmac_pdata->fw_alternative_path) &&
            (brcmf_mp_global.firmware_path[0] == '\0')) {
-               strlcpy(brcmf_mp_global.firmware_path,
+               strscpy(brcmf_mp_global.firmware_path,
                        brcmfmac_pdata->fw_alternative_path,
                        BRCMF_FW_ALTPATH_LEN);
        }
index bd164a0..2627221 100644 (file)
@@ -561,10 +561,10 @@ static void brcmf_ethtool_get_drvinfo(struct net_device *ndev,
 
        if (drvr->revinfo.result == 0)
                brcmu_dotrev_str(drvr->revinfo.driverrev, drev);
-       strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
-       strlcpy(info->version, drev, sizeof(info->version));
-       strlcpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
-       strlcpy(info->bus_info, dev_name(drvr->bus_if->dev),
+       strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
+       strscpy(info->version, drev, sizeof(info->version));
+       strscpy(info->fw_version, drvr->fwver, sizeof(info->fw_version));
+       strscpy(info->bus_info, dev_name(drvr->bus_if->dev),
                sizeof(info->bus_info));
 }
 
@@ -1480,8 +1480,10 @@ int brcmf_netdev_wait_pend8021x(struct brcmf_if *ifp)
                                 !brcmf_get_pend_8021x_cnt(ifp),
                                 MAX_WAIT_FOR_8021X_TX);
 
-       if (!err)
+       if (!err) {
                bphy_err(drvr, "Timed out waiting for no pending 802.1x packets\n");
+               atomic_set(&ifp->pend_8021x_cnt, 0);
+       }
 
        return !err;
 }
index b8379e4..15e99d8 100644 (file)
@@ -769,7 +769,7 @@ brcmf_fw_alloc_request(u32 chip, u32 chiprev,
                fwnames[j].path[0] = '\0';
                /* check if firmware path is provided by module parameter */
                if (brcmf_mp_global.firmware_path[0] != '\0') {
-                       strlcpy(fwnames[j].path, mp_path,
+                       strscpy(fwnames[j].path, mp_path,
                                BRCMF_FW_NAME_LEN);
 
                        if (end != '/') {
index 096f6b9..e1127d7 100644 (file)
@@ -419,7 +419,6 @@ void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,
                                flowid = flow->hash[i].flowid;
                                if (flow->rings[flowid]->status != RING_OPEN)
                                        continue;
-                               flow->rings[flowid]->status = RING_CLOSING;
                                brcmf_msgbuf_delete_flowring(drvr, flowid);
                        }
                }
@@ -458,10 +457,8 @@ void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,
                if ((sta || (memcmp(hash[i].mac, peer, ETH_ALEN) == 0)) &&
                    (hash[i].ifidx == ifidx)) {
                        flowid = flow->hash[i].flowid;
-                       if (flow->rings[flowid]->status == RING_OPEN) {
-                               flow->rings[flowid]->status = RING_CLOSING;
+                       if (flow->rings[flowid]->status == RING_OPEN)
                                brcmf_msgbuf_delete_flowring(drvr, flowid);
-                       }
                }
        }
 
index d58525e..36af819 100644 (file)
@@ -688,7 +688,7 @@ static void brcmf_fws_macdesc_set_name(struct brcmf_fws_info *fws,
                                       struct brcmf_fws_mac_descriptor *desc)
 {
        if (desc == &fws->desc.other)
-               strlcpy(desc->name, "MAC-OTHER", sizeof(desc->name));
+               strscpy(desc->name, "MAC-OTHER", sizeof(desc->name));
        else if (desc->mac_handle)
                scnprintf(desc->name, sizeof(desc->name), "MAC-%d:%d",
                          desc->mac_handle, desc->interface_id);
@@ -2475,7 +2475,8 @@ bool brcmf_fws_fc_active(struct brcmf_fws_info *fws)
        return fws->fcmode != BRCMF_FWS_FCMODE_NONE;
 }
 
-void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
+void brcmf_fws_bustxcomplete(struct brcmf_fws_info *fws, struct sk_buff *skb,
+                            bool success)
 {
        u32 hslot;
 
@@ -2483,11 +2484,14 @@ void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb)
                brcmu_pkt_buf_free_skb(skb);
                return;
        }
-       brcmf_fws_lock(fws);
-       hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
-       brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot, 0, 0,
-                             1);
-       brcmf_fws_unlock(fws);
+
+       if (!success) {
+               brcmf_fws_lock(fws);
+               hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
+               brcmf_fws_txs_process(fws, BRCMF_FWS_TXSTATUS_HOST_TOSSED, hslot,
+                                     0, 0, 1);
+               brcmf_fws_unlock(fws);
+       }
 }
 
 void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked)
index b16a9d1..f9c36cd 100644 (file)
@@ -40,7 +40,8 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb);
 void brcmf_fws_reset_interface(struct brcmf_if *ifp);
 void brcmf_fws_add_interface(struct brcmf_if *ifp);
 void brcmf_fws_del_interface(struct brcmf_if *ifp);
-void brcmf_fws_bustxfail(struct brcmf_fws_info *fws, struct sk_buff *skb);
+void brcmf_fws_bustxcomplete(struct brcmf_fws_info *fws, struct sk_buff *skb,
+                            bool success);
 void brcmf_fws_bus_blocked(struct brcmf_pub *drvr, bool flow_blocked);
 void brcmf_fws_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb);
 
index b2d0f75..cec53f9 100644 (file)
@@ -71,6 +71,7 @@
 #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS     32
 #define BRCMF_MSGBUF_UPDATE_RX_PTR_THRS                48
 
+#define BRCMF_MAX_TXSTATUS_WAIT_RETRIES                10
 
 struct msgbuf_common_hdr {
        u8                              msgtype;
@@ -806,8 +807,12 @@ static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
        flowid = brcmf_flowring_lookup(flow, eh->h_dest, skb->priority, ifidx);
        if (flowid == BRCMF_FLOWRING_INVALID_ID) {
                flowid = brcmf_msgbuf_flowring_create(msgbuf, ifidx, skb);
-               if (flowid == BRCMF_FLOWRING_INVALID_ID)
+               if (flowid == BRCMF_FLOWRING_INVALID_ID) {
                        return -ENOMEM;
+               } else {
+                       brcmf_flowring_enqueue(flow, flowid, skb);
+                       return 0;
+               }
        }
        queue_count = brcmf_flowring_enqueue(flow, flowid, skb);
        force = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);
@@ -1395,9 +1400,27 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
        struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
        struct msgbuf_tx_flowring_delete_req *delete;
        struct brcmf_commonring *commonring;
+       struct brcmf_commonring *commonring_del = msgbuf->flowrings[flowid];
+       struct brcmf_flowring *flow = msgbuf->flow;
        void *ret_ptr;
        u8 ifidx;
        int err;
+       int retry = BRCMF_MAX_TXSTATUS_WAIT_RETRIES;
+
+       /* make sure it is not in txflow */
+       brcmf_commonring_lock(commonring_del);
+       flow->rings[flowid]->status = RING_CLOSING;
+       brcmf_commonring_unlock(commonring_del);
+
+       /* wait for commonring txflow finished */
+       while (retry && atomic_read(&commonring_del->outstanding_tx)) {
+               usleep_range(5000, 10000);
+               retry--;
+       }
+       if (!retry) {
+               brcmf_err("timed out waiting for txstatus\n");
+               atomic_set(&commonring_del->outstanding_tx, 0);
+       }
 
        /* no need to submit if firmware can not be reached */
        if (drvr->bus_if->state != BRCMF_BUS_UP) {
index fabfbb0..d0a7465 100644 (file)
@@ -158,12 +158,12 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
        struct brcmf_pno_macaddr_le pfn_mac;
        u8 *mac_addr = NULL;
        u8 *mac_mask = NULL;
-       int err, i;
+       int err, i, ri;
 
-       for (i = 0; i < pi->n_reqs; i++)
-               if (pi->reqs[i]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
-                       mac_addr = pi->reqs[i]->mac_addr;
-                       mac_mask = pi->reqs[i]->mac_addr_mask;
+       for (ri = 0; ri < pi->n_reqs; ri++)
+               if (pi->reqs[ri]->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
+                       mac_addr = pi->reqs[ri]->mac_addr;
+                       mac_mask = pi->reqs[ri]->mac_addr_mask;
                        break;
                }
 
@@ -185,7 +185,7 @@ static int brcmf_pno_set_random(struct brcmf_if *ifp, struct brcmf_pno_info *pi)
        pfn_mac.mac[0] |= 0x02;
 
        brcmf_dbg(SCAN, "enabling random mac: reqid=%llu mac=%pM\n",
-                 pi->reqs[i]->reqid, pfn_mac.mac);
+                 pi->reqs[ri]->reqid, pfn_mac.mac);
        err = brcmf_fil_iovar_data_set(ifp, "pfn_macaddr", &pfn_mac,
                                       sizeof(pfn_mac));
        if (err)
index ae1f3ad..2b0df07 100644 (file)
                                         */
 
 /********************************************************************
- * Phy/Core Configuration.  Defines macros to to check core phy/rev *
+ * Phy/Core Configuration.  Defines macros to check core phy/rev *
  * compile-time configuration.  Defines default core support.       *
  * ******************************************************************
  */
index 5234511..ac36c89 100644 (file)
@@ -5907,8 +5907,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
        struct ipw2100_priv *priv = libipw_priv(dev);
        char fw_ver[64], ucode_ver[64];
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 
        ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver));
        ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver));
@@ -5916,7 +5916,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
        snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s",
                 fw_ver, priv->eeprom_version, ucode_ver);
 
-       strlcpy(info->bus_info, pci_name(priv->pci_dev),
+       strscpy(info->bus_info, pci_name(priv->pci_dev),
                sizeof(info->bus_info));
 }
 
index 029dace..5b483de 100644 (file)
@@ -10424,8 +10424,8 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
        char date[32];
        u32 len;
 
-       strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
-       strlcpy(info->version, DRV_VERSION, sizeof(info->version));
+       strscpy(info->driver, DRV_NAME, sizeof(info->driver));
+       strscpy(info->version, DRV_VERSION, sizeof(info->version));
 
        len = sizeof(vers);
        ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len);
@@ -10434,7 +10434,7 @@ static void ipw_ethtool_get_drvinfo(struct net_device *dev,
 
        snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)",
                 vers, date);
-       strlcpy(info->bus_info, pci_name(p->pci_dev),
+       strscpy(info->bus_info, pci_name(p->pci_dev),
                sizeof(info->bus_info));
 }
 
index 846138d..7352d5b 100644 (file)
@@ -3254,7 +3254,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr,
 
        if (count) {
                char *p = buffer;
-               strlcpy(buffer, buf, sizeof(buffer));
+               strscpy(buffer, buf, sizeof(buffer));
                channel = simple_strtoul(p, NULL, 0);
                if (channel)
                        params.channel = channel;
index 0a376f1..4e0a0c8 100644 (file)
@@ -3848,7 +3848,7 @@ static void prism2_get_drvinfo(struct net_device *dev,
        iface = netdev_priv(dev);
        local = iface->local;
 
-       strlcpy(info->driver, "hostap", sizeof(info->driver));
+       strscpy(info->driver, "hostap", sizeof(info->driver));
        snprintf(info->fw_version, sizeof(info->fw_version),
                 "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff,
                 (local->sta_fw_ver >> 8) & 0xff,
index 1f301a5..ed3b1c8 100644 (file)
@@ -652,7 +652,6 @@ struct mac80211_hwsim_data {
        u32 ciphers[ARRAY_SIZE(hwsim_ciphers)];
 
        struct mac_address addresses[2];
-       struct ieee80211_chanctx_conf *chanctx;
        int channels, idx;
        bool use_chanctx;
        bool destroy_on_close;
@@ -1299,6 +1298,8 @@ static void mac80211_hwsim_config_mac_nl(struct ieee80211_hw *hw,
        struct sk_buff *skb;
        void *msg_head;
 
+       WARN_ON(!is_valid_ether_addr(addr));
+
        if (!_portid && !hwsim_virtio_enabled)
                return;
 
@@ -1561,6 +1562,19 @@ static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
 #endif
 }
 
+static void mac80211_hwsim_rx(struct mac80211_hwsim_data *data,
+                             struct ieee80211_rx_status *rx_status,
+                             struct sk_buff *skb)
+{
+       memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
+
+       mac80211_hwsim_add_vendor_rtap(skb);
+
+       data->rx_pkts++;
+       data->rx_bytes += skb->len;
+       ieee80211_rx_irqsafe(data->hw, skb);
+}
+
 static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
                                          struct sk_buff *skb,
                                          struct ieee80211_channel *chan)
@@ -1688,13 +1702,7 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
 
                rx_status.mactime = now + data2->tsf_offset;
 
-               memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
-
-               mac80211_hwsim_add_vendor_rtap(nskb);
-
-               data2->rx_pkts++;
-               data2->rx_bytes += nskb->len;
-               ieee80211_rx_irqsafe(data2->hw, nskb);
+               mac80211_hwsim_rx(data2, &rx_status, nskb);
        }
        spin_unlock(&hwsim_radio_lock);
 
@@ -1714,12 +1722,7 @@ mac80211_hwsim_select_tx_link(struct mac80211_hwsim_data *data,
        if (!vif->valid_links)
                return &vif->bss_conf;
 
-       /* FIXME: handle multicast TX properly */
-       if (is_multicast_ether_addr(hdr->addr1) || WARN_ON_ONCE(!sta)) {
-               unsigned int first_link = ffs(vif->valid_links) - 1;
-
-               return rcu_dereference(vif->link_conf[first_link]);
-       }
+       WARN_ON(is_multicast_ether_addr(hdr->addr1));
 
        if (WARN_ON_ONCE(!sta->valid_links))
                return &vif->bss_conf;
@@ -2866,11 +2869,6 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw,
 static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
                                      struct ieee80211_chanctx_conf *ctx)
 {
-       struct mac80211_hwsim_data *hwsim = hw->priv;
-
-       mutex_lock(&hwsim->mutex);
-       hwsim->chanctx = ctx;
-       mutex_unlock(&hwsim->mutex);
        hwsim_set_chanctx_magic(ctx);
        wiphy_dbg(hw->wiphy,
                  "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
@@ -2882,11 +2880,6 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw,
 static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw,
                                          struct ieee80211_chanctx_conf *ctx)
 {
-       struct mac80211_hwsim_data *hwsim = hw->priv;
-
-       mutex_lock(&hwsim->mutex);
-       hwsim->chanctx = NULL;
-       mutex_unlock(&hwsim->mutex);
        wiphy_dbg(hw->wiphy,
                  "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
                  ctx->def.chan->center_freq, ctx->def.width,
@@ -2899,11 +2892,6 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw,
                                          struct ieee80211_chanctx_conf *ctx,
                                          u32 changed)
 {
-       struct mac80211_hwsim_data *hwsim = hw->priv;
-
-       mutex_lock(&hwsim->mutex);
-       hwsim->chanctx = ctx;
-       mutex_unlock(&hwsim->mutex);
        hwsim_check_chanctx_magic(ctx);
        wiphy_dbg(hw->wiphy,
                  "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n",
@@ -2995,10 +2983,15 @@ static int mac80211_hwsim_change_vif_links(struct ieee80211_hw *hw,
                                           u16 old_links, u16 new_links,
                                           struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
 {
-       unsigned long rem = old_links & ~new_links ?: BIT(0);
+       unsigned long rem = old_links & ~new_links;
        unsigned long add = new_links & ~old_links;
        int i;
 
+       if (!old_links)
+               rem |= BIT(0);
+       if (!new_links)
+               add |= BIT(0);
+
        for_each_set_bit(i, &rem, IEEE80211_MLD_MAX_NUM_LINKS)
                mac80211_hwsim_config_mac_nl(hw, old[i]->addr, false);
 
@@ -3021,6 +3014,8 @@ static int mac80211_hwsim_change_sta_links(struct ieee80211_hw *hw,
                                           struct ieee80211_sta *sta,
                                           u16 old_links, u16 new_links)
 {
+       hwsim_check_sta_magic(sta);
+
        return 0;
 }
 
@@ -3208,8 +3203,112 @@ out_err:
 
 static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
        {
-               .types_mask = BIT(NL80211_IFTYPE_STATION) |
-                             BIT(NL80211_IFTYPE_AP),
+               .types_mask = BIT(NL80211_IFTYPE_STATION),
+               .he_cap = {
+                       .has_he = true,
+                       .he_cap_elem = {
+                               .mac_cap_info[0] =
+                                       IEEE80211_HE_MAC_CAP0_HTC_HE,
+                               .mac_cap_info[1] =
+                                       IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
+                                       IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
+                               .mac_cap_info[2] =
+                                       IEEE80211_HE_MAC_CAP2_BSR |
+                                       IEEE80211_HE_MAC_CAP2_MU_CASCADING |
+                                       IEEE80211_HE_MAC_CAP2_ACK_EN,
+                               .mac_cap_info[3] =
+                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
+                                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3,
+                               .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU,
+                               .phy_cap_info[1] =
+                                       IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
+                                       IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
+                                       IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
+                                       IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS,
+                               .phy_cap_info[2] =
+                                       IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
+                                       IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
+                                       IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
+                                       IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
+                                       IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO,
+
+                               /* Leave all the other PHY capability bytes
+                                * unset, as DCM, beam forming, RU and PPE
+                                * threshold information are not supported
+                                */
+                       },
+                       .he_mcs_nss_supp = {
+                               .rx_mcs_80 = cpu_to_le16(0xfffa),
+                               .tx_mcs_80 = cpu_to_le16(0xfffa),
+                               .rx_mcs_160 = cpu_to_le16(0xffff),
+                               .tx_mcs_160 = cpu_to_le16(0xffff),
+                               .rx_mcs_80p80 = cpu_to_le16(0xffff),
+                               .tx_mcs_80p80 = cpu_to_le16(0xffff),
+                       },
+               },
+               .eht_cap = {
+                       .has_eht = true,
+                       .eht_cap_elem = {
+                               .mac_cap_info[0] =
+                                       IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
+                                       IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
+                                       IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
+                               .phy_cap_info[0] =
+                                       IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
+                                       IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
+                                       IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
+                                       IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
+                                       IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE,
+                               .phy_cap_info[3] =
+                                       IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK,
+                               .phy_cap_info[4] =
+                                       IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
+                                       IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP |
+                                       IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
+                                       IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI |
+                                       IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK,
+                               .phy_cap_info[5] =
+                                       IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
+                                       IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
+                                       IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT |
+                                       IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK |
+                                       IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK,
+                               .phy_cap_info[6] =
+                                       IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK |
+                                       IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK,
+                               .phy_cap_info[7] =
+                                       IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW,
+                       },
+
+                       /* For all MCS and bandwidth, set 8 NSS for both Tx and
+                        * Rx
+                        */
+                       .eht_mcs_nss_supp = {
+                               /*
+                                * Since B0, B1, B2 and B3 are not set in
+                                * the supported channel width set field in the
+                                * HE PHY capabilities information field the
+                                * device is a 20MHz only device on 2.4GHz band.
+                                */
+                               .only_20mhz = {
+                                       .rx_tx_mcs7_max_nss = 0x88,
+                                       .rx_tx_mcs9_max_nss = 0x88,
+                                       .rx_tx_mcs11_max_nss = 0x88,
+                                       .rx_tx_mcs13_max_nss = 0x88,
+                               },
+                       },
+                       /* PPE threshold information is not supported */
+               },
+       },
+       {
+               .types_mask = BIT(NL80211_IFTYPE_AP),
                .he_cap = {
                        .has_he = true,
                        .he_cap_elem = {
@@ -3356,9 +3455,132 @@ static const struct ieee80211_sband_iftype_data sband_capa_2ghz[] = {
 
 static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
        {
-               /* TODO: should we support other types, e.g., P2P?*/
-               .types_mask = BIT(NL80211_IFTYPE_STATION) |
-                             BIT(NL80211_IFTYPE_AP),
+               /* TODO: should we support other types, e.g., P2P? */
+               .types_mask = BIT(NL80211_IFTYPE_STATION),
+               .he_cap = {
+                       .has_he = true,
+                       .he_cap_elem = {
+                               .mac_cap_info[0] =
+                                       IEEE80211_HE_MAC_CAP0_HTC_HE,
+                               .mac_cap_info[1] =
+                                       IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
+                                       IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
+                               .mac_cap_info[2] =
+                                       IEEE80211_HE_MAC_CAP2_BSR |
+                                       IEEE80211_HE_MAC_CAP2_MU_CASCADING |
+                                       IEEE80211_HE_MAC_CAP2_ACK_EN,
+                               .mac_cap_info[3] =
+                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
+                                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3,
+                               .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU,
+                               .phy_cap_info[0] =
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G,
+                               .phy_cap_info[1] =
+                                       IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
+                                       IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
+                                       IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
+                                       IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS,
+                               .phy_cap_info[2] =
+                                       IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
+                                       IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
+                                       IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
+                                       IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
+                                       IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO,
+
+                               /* Leave all the other PHY capability bytes
+                                * unset, as DCM, beam forming, RU and PPE
+                                * threshold information are not supported
+                                */
+                       },
+                       .he_mcs_nss_supp = {
+                               .rx_mcs_80 = cpu_to_le16(0xfffa),
+                               .tx_mcs_80 = cpu_to_le16(0xfffa),
+                               .rx_mcs_160 = cpu_to_le16(0xfffa),
+                               .tx_mcs_160 = cpu_to_le16(0xfffa),
+                               .rx_mcs_80p80 = cpu_to_le16(0xfffa),
+                               .tx_mcs_80p80 = cpu_to_le16(0xfffa),
+                       },
+               },
+               .eht_cap = {
+                       .has_eht = true,
+                       .eht_cap_elem = {
+                               .mac_cap_info[0] =
+                                       IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
+                                       IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
+                                       IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
+                               .phy_cap_info[0] =
+                                       IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
+                                       IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
+                                       IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
+                                       IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
+                                       IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE |
+                                       IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
+                               .phy_cap_info[1] =
+                                       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
+                                       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK,
+                               .phy_cap_info[2] =
+                                       IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK |
+                                       IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK,
+                               .phy_cap_info[3] =
+                                       IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK,
+                               .phy_cap_info[4] =
+                                       IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
+                                       IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP |
+                                       IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
+                                       IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI |
+                                       IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK,
+                               .phy_cap_info[5] =
+                                       IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
+                                       IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
+                                       IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT |
+                                       IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK |
+                                       IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK,
+                               .phy_cap_info[6] =
+                                       IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK |
+                                       IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK,
+                               .phy_cap_info[7] =
+                                       IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW |
+                                       IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ,
+                       },
+
+                       /* For all MCS and bandwidth, set 8 NSS for both Tx and
+                        * Rx
+                        */
+                       .eht_mcs_nss_supp = {
+                               /*
+                                * As B1 and B2 are set in the supported
+                                * channel width set field in the HE PHY
+                                * capabilities information field include all
+                                * the following MCS/NSS.
+                                */
+                               .bw._80 = {
+                                       .rx_tx_mcs9_max_nss = 0x88,
+                                       .rx_tx_mcs11_max_nss = 0x88,
+                                       .rx_tx_mcs13_max_nss = 0x88,
+                               },
+                               .bw._160 = {
+                                       .rx_tx_mcs9_max_nss = 0x88,
+                                       .rx_tx_mcs11_max_nss = 0x88,
+                                       .rx_tx_mcs13_max_nss = 0x88,
+                               },
+                       },
+                       /* PPE threshold information is not supported */
+               },
+       },
+       {
+               .types_mask = BIT(NL80211_IFTYPE_AP),
                .he_cap = {
                        .has_he = true,
                        .he_cap_elem = {
@@ -3529,9 +3751,153 @@ static const struct ieee80211_sband_iftype_data sband_capa_5ghz[] = {
 
 static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {
        {
-               /* TODO: should we support other types, e.g., P2P?*/
-               .types_mask = BIT(NL80211_IFTYPE_STATION) |
-                             BIT(NL80211_IFTYPE_AP),
+               /* TODO: should we support other types, e.g., P2P? */
+               .types_mask = BIT(NL80211_IFTYPE_STATION),
+               .he_6ghz_capa = {
+                       .capa = cpu_to_le16(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START |
+                                           IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP |
+                                           IEEE80211_HE_6GHZ_CAP_MAX_MPDU_LEN |
+                                           IEEE80211_HE_6GHZ_CAP_SM_PS |
+                                           IEEE80211_HE_6GHZ_CAP_RD_RESPONDER |
+                                           IEEE80211_HE_6GHZ_CAP_TX_ANTPAT_CONS |
+                                           IEEE80211_HE_6GHZ_CAP_RX_ANTPAT_CONS),
+               },
+               .he_cap = {
+                       .has_he = true,
+                       .he_cap_elem = {
+                               .mac_cap_info[0] =
+                                       IEEE80211_HE_MAC_CAP0_HTC_HE,
+                               .mac_cap_info[1] =
+                                       IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US |
+                                       IEEE80211_HE_MAC_CAP1_MULTI_TID_AGG_RX_QOS_8,
+                               .mac_cap_info[2] =
+                                       IEEE80211_HE_MAC_CAP2_BSR |
+                                       IEEE80211_HE_MAC_CAP2_MU_CASCADING |
+                                       IEEE80211_HE_MAC_CAP2_ACK_EN,
+                               .mac_cap_info[3] =
+                                       IEEE80211_HE_MAC_CAP3_OMI_CONTROL |
+                                       IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_EXT_3,
+                               .mac_cap_info[4] = IEEE80211_HE_MAC_CAP4_AMSDU_IN_AMPDU,
+                               .phy_cap_info[0] =
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G |
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G |
+                                       IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G,
+                               .phy_cap_info[1] =
+                                       IEEE80211_HE_PHY_CAP1_PREAMBLE_PUNC_RX_MASK |
+                                       IEEE80211_HE_PHY_CAP1_DEVICE_CLASS_A |
+                                       IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD |
+                                       IEEE80211_HE_PHY_CAP1_MIDAMBLE_RX_TX_MAX_NSTS,
+                               .phy_cap_info[2] =
+                                       IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US |
+                                       IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ |
+                                       IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ |
+                                       IEEE80211_HE_PHY_CAP2_UL_MU_FULL_MU_MIMO |
+                                       IEEE80211_HE_PHY_CAP2_UL_MU_PARTIAL_MU_MIMO,
+
+                               /* Leave all the other PHY capability bytes
+                                * unset, as DCM, beam forming, RU and PPE
+                                * threshold information are not supported
+                                */
+                       },
+                       .he_mcs_nss_supp = {
+                               .rx_mcs_80 = cpu_to_le16(0xfffa),
+                               .tx_mcs_80 = cpu_to_le16(0xfffa),
+                               .rx_mcs_160 = cpu_to_le16(0xfffa),
+                               .tx_mcs_160 = cpu_to_le16(0xfffa),
+                               .rx_mcs_80p80 = cpu_to_le16(0xfffa),
+                               .tx_mcs_80p80 = cpu_to_le16(0xfffa),
+                       },
+               },
+               .eht_cap = {
+                       .has_eht = true,
+                       .eht_cap_elem = {
+                               .mac_cap_info[0] =
+                                       IEEE80211_EHT_MAC_CAP0_EPCS_PRIO_ACCESS |
+                                       IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
+                                       IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
+                               .phy_cap_info[0] =
+                                       IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ |
+                                       IEEE80211_EHT_PHY_CAP0_242_TONE_RU_GT20MHZ |
+                                       IEEE80211_EHT_PHY_CAP0_NDP_4_EHT_LFT_32_GI |
+                                       IEEE80211_EHT_PHY_CAP0_PARTIAL_BW_UL_MU_MIMO |
+                                       IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMER |
+                                       IEEE80211_EHT_PHY_CAP0_SU_BEAMFORMEE |
+                                       IEEE80211_EHT_PHY_CAP0_BEAMFORMEE_SS_80MHZ_MASK,
+                               .phy_cap_info[1] =
+                                       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_80MHZ_MASK |
+                                       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_160MHZ_MASK |
+                                       IEEE80211_EHT_PHY_CAP1_BEAMFORMEE_SS_320MHZ_MASK,
+                               .phy_cap_info[2] =
+                                       IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_80MHZ_MASK |
+                                       IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_160MHZ_MASK |
+                                       IEEE80211_EHT_PHY_CAP2_SOUNDING_DIM_320MHZ_MASK,
+                               .phy_cap_info[3] =
+                                       IEEE80211_EHT_PHY_CAP3_NG_16_SU_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP3_NG_16_MU_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP3_CODEBOOK_4_2_SU_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_CODEBOOK_7_5_MU_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_SU_BF_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_MU_BF_PART_BW_FDBK |
+                                       IEEE80211_EHT_PHY_CAP3_TRIG_CQI_FDBK,
+                               .phy_cap_info[4] =
+                                       IEEE80211_EHT_PHY_CAP4_PART_BW_DL_MU_MIMO |
+                                       IEEE80211_EHT_PHY_CAP4_PSR_SR_SUPP |
+                                       IEEE80211_EHT_PHY_CAP4_POWER_BOOST_FACT_SUPP |
+                                       IEEE80211_EHT_PHY_CAP4_EHT_MU_PPDU_4_EHT_LTF_08_GI |
+                                       IEEE80211_EHT_PHY_CAP4_MAX_NC_MASK,
+                               .phy_cap_info[5] =
+                                       IEEE80211_EHT_PHY_CAP5_NON_TRIG_CQI_FEEDBACK |
+                                       IEEE80211_EHT_PHY_CAP5_TX_LESS_242_TONE_RU_SUPP |
+                                       IEEE80211_EHT_PHY_CAP5_RX_LESS_242_TONE_RU_SUPP |
+                                       IEEE80211_EHT_PHY_CAP5_PPE_THRESHOLD_PRESENT |
+                                       IEEE80211_EHT_PHY_CAP5_COMMON_NOMINAL_PKT_PAD_MASK |
+                                       IEEE80211_EHT_PHY_CAP5_MAX_NUM_SUPP_EHT_LTF_MASK,
+                               .phy_cap_info[6] =
+                                       IEEE80211_EHT_PHY_CAP6_MAX_NUM_SUPP_EHT_LTF_MASK |
+                                       IEEE80211_EHT_PHY_CAP6_MCS15_SUPP_MASK |
+                                       IEEE80211_EHT_PHY_CAP6_EHT_DUP_6GHZ_SUPP,
+                               .phy_cap_info[7] =
+                                       IEEE80211_EHT_PHY_CAP7_20MHZ_STA_RX_NDP_WIDER_BW |
+                                       IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_80MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_160MHZ |
+                                       IEEE80211_EHT_PHY_CAP7_MU_BEAMFORMER_320MHZ,
+                       },
+
+                       /* For all MCS and bandwidth, set 8 NSS for both Tx and
+                        * Rx
+                        */
+                       .eht_mcs_nss_supp = {
+                               /*
+                                * As B1 and B2 are set in the supported
+                                * channel width set field in the HE PHY
+                                * capabilities information field and 320MHz in
+                                * 6GHz is supported include all the following
+                                * MCS/NSS.
+                                */
+                               .bw._80 = {
+                                       .rx_tx_mcs9_max_nss = 0x88,
+                                       .rx_tx_mcs11_max_nss = 0x88,
+                                       .rx_tx_mcs13_max_nss = 0x88,
+                               },
+                               .bw._160 = {
+                                       .rx_tx_mcs9_max_nss = 0x88,
+                                       .rx_tx_mcs11_max_nss = 0x88,
+                                       .rx_tx_mcs13_max_nss = 0x88,
+                               },
+                               .bw._320 = {
+                                       .rx_tx_mcs9_max_nss = 0x88,
+                                       .rx_tx_mcs11_max_nss = 0x88,
+                                       .rx_tx_mcs13_max_nss = 0x88,
+                               },
+                       },
+                       /* PPE threshold information is not supported */
+               },
+       },
+       {
+               .types_mask = BIT(NL80211_IFTYPE_AP),
                .he_6ghz_capa = {
                        .capa = cpu_to_le16(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START |
                                            IEEE80211_HE_6GHZ_CAP_MAX_AMPDU_LEN_EXP |
@@ -3896,7 +4262,6 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                hw->wiphy->max_remain_on_channel_duration = 1000;
                data->if_combination.radar_detect_widths = 0;
                data->if_combination.num_different_channels = data->channels;
-               data->chanctx = NULL;
        } else {
                data->if_combination.num_different_channels = 1;
                data->if_combination.radar_detect_widths =
@@ -4471,13 +4836,9 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
        if (data2->use_chanctx) {
                if (data2->tmp_chan)
                        channel = data2->tmp_chan;
-               else if (data2->chanctx)
-                       channel = data2->chanctx->def.chan;
        } else {
                channel = data2->channel;
        }
-       if (!channel)
-               goto out;
 
        if (!hwsim_virtio_enabled) {
                if (hwsim_net_get_netgroup(genl_info_net(info)) !=
@@ -4508,6 +4869,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
                                                          rx_status.freq);
                if (!iter_data.channel)
                        goto out;
+               rx_status.band = iter_data.channel->band;
 
                mutex_lock(&data2->mutex);
                if (!hwsim_chans_compat(iter_data.channel, channel)) {
@@ -4520,11 +4882,13 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
                        }
                }
                mutex_unlock(&data2->mutex);
+       } else if (!channel) {
+               goto out;
        } else {
                rx_status.freq = channel->center_freq;
+               rx_status.band = channel->band;
        }
 
-       rx_status.band = channel->band;
        rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
        rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
 
@@ -4534,10 +4898,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
            ieee80211_is_probe_resp(hdr->frame_control))
                rx_status.boottime_ns = ktime_get_boottime_ns();
 
-       memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
-       data2->rx_pkts++;
-       data2->rx_bytes += skb->len;
-       ieee80211_rx_irqsafe(data2->hw, skb);
+       mac80211_hwsim_rx(data2, &rx_status, skb);
 
        return 0;
 err:
@@ -4912,6 +5273,7 @@ static struct genl_family hwsim_genl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = hwsim_ops,
        .n_small_ops = ARRAY_SIZE(hwsim_ops),
+       .resv_start_op = HWSIM_CMD_DEL_MAC_ADDR + 1,
        .mcgrps = hwsim_mcgrps,
        .n_mcgrps = ARRAY_SIZE(hwsim_mcgrps),
 };
index b0b3f59..5e3ae00 100644 (file)
@@ -1435,7 +1435,7 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int lbs_cfg_set_default_key(struct wiphy *wiphy,
-                                  struct net_device *netdev,
+                                  struct net_device *netdev, int link_id,
                                   u8 key_index, bool unicast,
                                   bool multicast)
 {
@@ -1455,8 +1455,8 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
 
 
 static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
-                          u8 idx, bool pairwise, const u8 *mac_addr,
-                          struct key_params *params)
+                          int link_id, u8 idx, bool pairwise,
+                          const u8 *mac_addr, struct key_params *params)
 {
        struct lbs_private *priv = wiphy_priv(wiphy);
        u16 key_info;
@@ -1516,7 +1516,8 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
 
 
 static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
-                          u8 key_index, bool pairwise, const u8 *mac_addr)
+                          int link_id, u8 key_index, bool pairwise,
+                          const u8 *mac_addr)
 {
 
        lbs_deb_assoc("del_key: key_idx %d, mac_addr %pM\n",
index d8e4f29..9f53308 100644 (file)
@@ -20,8 +20,8 @@ static void lbs_ethtool_get_drvinfo(struct net_device *dev,
                priv->fwrelease >> 16 & 0xff,
                priv->fwrelease >>  8 & 0xff,
                priv->fwrelease       & 0xff);
-       strlcpy(info->driver, "libertas", sizeof(info->driver));
-       strlcpy(info->version, lbs_driver_version, sizeof(info->version));
+       strscpy(info->driver, "libertas", sizeof(info->driver));
+       strscpy(info->version, lbs_driver_version, sizeof(info->version));
 }
 
 /*
index 134114a..535995e 100644 (file)
@@ -142,7 +142,8 @@ static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy)
  */
 static int
 mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr)
+                        int link_id, u8 key_index, bool pairwise,
+                        const u8 *mac_addr)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
        static const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
@@ -431,7 +432,7 @@ mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy,
  */
 static int
 mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-                                u8 key_index, bool unicast,
+                                int link_id, u8 key_index, bool unicast,
                                 bool multicast)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
@@ -456,8 +457,8 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
  */
 static int
 mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr,
-                        struct key_params *params)
+                        int link_id, u8 key_index, bool pairwise,
+                        const u8 *mac_addr, struct key_params *params)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
        struct mwifiex_wep_key *wep_key;
@@ -494,6 +495,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
 static int
 mwifiex_cfg80211_set_default_mgmt_key(struct wiphy *wiphy,
                                      struct net_device *netdev,
+                                     int link_id,
                                      u8 key_index)
 {
        struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev);
index 3ac373d..b890479 100644 (file)
@@ -540,8 +540,9 @@ static int wilc_wfi_cfg_copy_wpa_info(struct wilc_wfi_key *key_info,
        return 0;
 }
 
-static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                  bool pairwise, const u8 *mac_addr, struct key_params *params)
+static int add_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                  u8 key_index, bool pairwise, const u8 *mac_addr,
+                  struct key_params *params)
 
 {
        int ret = 0, keylen = params->key_len;
@@ -644,7 +645,7 @@ static int add_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
        return ret;
 }
 
-static int del_key(struct wiphy *wiphy, struct net_device *netdev,
+static int del_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,
                   u8 key_index,
                   bool pairwise,
                   const u8 *mac_addr)
@@ -685,8 +686,9 @@ static int del_key(struct wiphy *wiphy, struct net_device *netdev,
        return 0;
 }
 
-static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                  bool pairwise, const u8 *mac_addr, void *cookie,
+static int get_key(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                  u8 key_index, bool pairwise, const u8 *mac_addr,
+                  void *cookie,
                   void (*callback)(void *cookie, struct key_params *))
 {
        struct wilc_vif *vif = netdev_priv(netdev);
@@ -723,13 +725,14 @@ static int get_key(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
 
 /* wiphy_new_nm() will WARNON if not present */
 static int set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-                          u8 key_index, bool unicast, bool multicast)
+                          int link_id, u8 key_index, bool unicast,
+                          bool multicast)
 {
        return 0;
 }
 
 static int set_default_mgmt_key(struct wiphy *wiphy, struct net_device *netdev,
-                               u8 key_index)
+                               int link_id, u8 key_index)
 {
        struct wilc_vif *vif = netdev_priv(netdev);
 
@@ -994,12 +997,11 @@ bool wilc_wfi_mgmt_frame_rx(struct wilc_vif *vif, u8 *buff, u32 size)
 {
        struct wilc *wl = vif->wilc;
        struct wilc_priv *priv = &vif->priv;
-       int freq, ret;
+       int freq;
 
        freq = ieee80211_channel_to_frequency(wl->op_ch, NL80211_BAND_2GHZ);
-       ret = cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
 
-       return ret;
+       return cfg80211_rx_mgmt(&priv->wdev, freq, 0, buff, size, 0);
 }
 
 void wilc_wfi_p2p_rx(struct wilc_vif *vif, u8 *buff, u32 size)
index b5a1b65..03b7229 100644 (file)
@@ -229,7 +229,7 @@ struct net_device *wilc_wfi_init_mon_interface(struct wilc *wl,
                return NULL;
 
        wl->monitor_dev->type = ARPHRD_IEEE80211_RADIOTAP;
-       strlcpy(wl->monitor_dev->name, name, IFNAMSIZ);
+       strscpy(wl->monitor_dev->name, name, IFNAMSIZ);
        wl->monitor_dev->netdev_ops = &wilc_wfi_netdev_ops;
        wl->monitor_dev->needs_free_netdev = true;
 
index 1593e81..bfdf03b 100644 (file)
@@ -532,8 +532,8 @@ qtnf_dump_station(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int qtnf_add_key(struct wiphy *wiphy, struct net_device *dev,
-                       u8 key_index, bool pairwise, const u8 *mac_addr,
-                       struct key_params *params)
+                       int link_id, u8 key_index, bool pairwise,
+                       const u8 *mac_addr, struct key_params *params)
 {
        struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
        int ret;
@@ -548,7 +548,8 @@ static int qtnf_add_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int qtnf_del_key(struct wiphy *wiphy, struct net_device *dev,
-                       u8 key_index, bool pairwise, const u8 *mac_addr)
+                       int link_id, u8 key_index, bool pairwise,
+                       const u8 *mac_addr)
 {
        struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
        int ret;
@@ -569,7 +570,8 @@ static int qtnf_del_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int qtnf_set_default_key(struct wiphy *wiphy, struct net_device *dev,
-                               u8 key_index, bool unicast, bool multicast)
+                               int link_id, u8 key_index, bool unicast,
+                               bool multicast)
 {
        struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
        int ret;
@@ -585,7 +587,7 @@ static int qtnf_set_default_key(struct wiphy *wiphy, struct net_device *dev,
 
 static int
 qtnf_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev,
-                         u8 key_index)
+                         int link_id, u8 key_index)
 {
        struct qtnf_vif *vif = qtnf_netdev_get_priv(dev);
        int ret;
@@ -721,9 +723,8 @@ qtnf_disconnect(struct wiphy *wiphy, struct net_device *dev,
                return -EFAULT;
        }
 
-       if (vif->wdev.iftype != NL80211_IFTYPE_STATION) {
+       if (vif->wdev.iftype != NL80211_IFTYPE_STATION)
                return -EOPNOTSUPP;
-       }
 
        ret = qtnf_cmd_send_disconnect(vif, reason_code);
        if (ret)
@@ -750,7 +751,6 @@ qtnf_dump_survey(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_channel *chan;
        int ret;
 
-
        sband = wiphy->bands[NL80211_BAND_2GHZ];
        if (sband && idx >= sband->n_channels) {
                idx -= sband->n_channels;
@@ -1223,7 +1223,7 @@ int qtnf_wiphy_register(struct qtnf_hw_info *hw_info, struct qtnf_wmac *mac)
                        mac->macinfo.extended_capabilities_len;
        }
 
-       strlcpy(wiphy->fw_version, hw_info->fw_version,
+       strscpy(wiphy->fw_version, hw_info->fw_version,
                sizeof(wiphy->fw_version));
        wiphy->hw_version = hw_info->hw_version;
 
index 0fad536..b1b7347 100644 (file)
@@ -967,7 +967,7 @@ qtnf_cmd_resp_proc_hw_info(struct qtnf_bus *bus,
                hwinfo->total_rx_chain, hwinfo->total_tx_chain,
                hwinfo->fw_ver);
 
-       strlcpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
+       strscpy(hwinfo->fw_version, bld_label, sizeof(hwinfo->fw_version));
        hwinfo->hw_version = hw_ver;
 
        return 0;
index 49421d1..f7d95c9 100644 (file)
@@ -143,7 +143,7 @@ static int rtl8187_register_led(struct ieee80211_hw *dev,
        led->dev = dev;
        led->ledpin = ledpin;
        led->is_radio = is_radio;
-       strlcpy(led->name, name, sizeof(led->name));
+       strscpy(led->name, name, sizeof(led->name));
 
        led->led_dev.name = led->name;
        led->led_dev.default_trigger = default_trigger;
index c66f072..f3a107f 100644 (file)
@@ -1878,13 +1878,6 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
 
                /* We have 8 bits to indicate validity */
                map_addr = offset * 8;
-               if (map_addr >= EFUSE_MAP_LEN) {
-                       dev_warn(dev, "%s: Illegal map_addr (%04x), "
-                                "efuse corrupt!\n",
-                                __func__, map_addr);
-                       ret = -EINVAL;
-                       goto exit;
-               }
                for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
                        /* Check word enable condition in the section */
                        if (word_mask & BIT(i)) {
@@ -1895,6 +1888,13 @@ static int rtl8xxxu_read_efuse(struct rtl8xxxu_priv *priv)
                        ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8);
                        if (ret)
                                goto exit;
+                       if (map_addr >= EFUSE_MAP_LEN - 1) {
+                               dev_warn(dev, "%s: Illegal map_addr (%04x), "
+                                        "efuse corrupt!\n",
+                                        __func__, map_addr);
+                               ret = -EINVAL;
+                               goto exit;
+                       }
                        priv->efuse_wifi.raw[map_addr++] = val8;
 
                        ret = rtl8xxxu_read_efuse8(priv, efuse_addr++, &val8);
index 15e6a6a..d18c092 100644 (file)
@@ -2386,11 +2386,10 @@ void rtl92d_phy_reload_iqk_setting(struct ieee80211_hw *hw, u8 channel)
                        rtl_dbg(rtlpriv, COMP_SCAN, DBG_LOUD,
                                "Just Read IQK Matrix reg for channel:%d....\n",
                                channel);
-                       _rtl92d_phy_patha_fill_iqk_matrix(hw, true,
-                                       rtlphy->iqk_matrix[
-                                       indexforchannel].value, 0,
-                                       (rtlphy->iqk_matrix[
-                                       indexforchannel].value[0][2] == 0));
+                       if (rtlphy->iqk_matrix[indexforchannel].value[0][0] != 0)
+                               _rtl92d_phy_patha_fill_iqk_matrix(hw, true,
+                                       rtlphy->iqk_matrix[indexforchannel].value, 0,
+                                       rtlphy->iqk_matrix[indexforchannel].value[0][2] == 0);
                        if (IS_92D_SINGLEPHY(rtlhal->version)) {
                                if ((rtlphy->iqk_matrix[
                                        indexforchannel].value[0][4] != 0)
index 76c7f32..038a30b 100644 (file)
@@ -30,11 +30,11 @@ void rtw_bf_disassoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
 void rtw_bf_assoc(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
                  struct ieee80211_bss_conf *bss_conf)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct ieee80211_hw *hw = rtwdev->hw;
        struct rtw_vif *rtwvif = (struct rtw_vif *)vif->drv_priv;
        struct rtw_bfee *bfee = &rtwvif->bfee;
        struct rtw_bf_info *bfinfo = &rtwdev->bf_info;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct ieee80211_sta *sta;
        struct ieee80211_sta_vht_cap *vht_cap;
        struct ieee80211_sta_vht_cap *ic_vht_cap;
index cac053f..6276ad6 100644 (file)
@@ -13,7 +13,7 @@
 static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
                                   u8 rssi, u8 rssi_thresh)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u8 tol = chip->rssi_tolerance;
        u8 next_state;
 
@@ -36,7 +36,7 @@ static u8 rtw_coex_next_rssi_state(struct rtw_dev *rtwdev, u8 pre_state,
 static void rtw_coex_limited_tx(struct rtw_dev *rtwdev,
                                bool tx_limit_en, bool ampdu_limit_en)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        u8 num_of_active_port = 1;
@@ -365,7 +365,7 @@ static void rtw_coex_set_wl_pri_mask(struct rtw_dev *rtwdev, u8 bitmap,
 
 void rtw_coex_write_scbd(struct rtw_dev *rtwdev, u16 bitpos, bool set)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        u16 val = 0x2;
@@ -400,7 +400,7 @@ EXPORT_SYMBOL(rtw_coex_write_scbd);
 
 static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (!chip->scbd_support)
                return 0;
@@ -410,7 +410,7 @@ static u16 rtw_coex_read_scbd(struct rtw_dev *rtwdev)
 
 static void rtw_coex_check_rfk(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_rfe *coex_rfe = &coex->rfe;
@@ -489,7 +489,7 @@ static void rtw_coex_monitor_bt_ctr(struct rtw_dev *rtwdev)
 
 static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
@@ -524,10 +524,10 @@ static void rtw_coex_monitor_bt_enable(struct rtw_dev *rtwdev)
 
 static void rtw_coex_update_wl_link_info(struct rtw_dev *rtwdev, u8 reason)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_traffic_stats *stats = &rtwdev->stats;
        bool is_5G = false;
        bool wl_busy = false;
@@ -706,10 +706,10 @@ static const char *rtw_coex_get_bt_status_string(u8 bt_status)
 
 static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 i;
        u8 rssi_state;
        u8 rssi_step;
@@ -806,7 +806,7 @@ static void rtw_coex_update_bt_link_info(struct rtw_dev *rtwdev)
 
 static void rtw_coex_update_wl_ch_info(struct rtw_dev *rtwdev, u8 type)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        struct rtw_coex_dm *coex_dm = &rtwdev->coex.dm;
        struct rtw_coex_stat *coex_stat = &rtwdev->coex.stat;
@@ -933,7 +933,7 @@ EXPORT_SYMBOL(rtw_coex_write_indirect_reg);
 
 static void rtw_coex_coex_ctrl_owner(struct rtw_dev *rtwdev, bool wifi_control)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_hw_reg *btg_reg = chip->btg_reg;
 
        if (wifi_control) {
@@ -981,7 +981,7 @@ static void rtw_coex_mimo_ps(struct rtw_dev *rtwdev, bool force, bool state)
 static void rtw_btc_wltoggle_table_a(struct rtw_dev *rtwdev, bool force,
                                     u8 table_case)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        u8 h2c_para[6] = {0};
        u32 table_wl = 0x5a5a5a5a;
@@ -1065,9 +1065,9 @@ static void rtw_coex_set_table(struct rtw_dev *rtwdev, bool force, u32 table0,
 
 static void rtw_coex_table(struct rtw_dev *rtwdev, bool force, u8 type)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_dm *coex_dm = &coex->dm;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        struct rtw_coex_stat *coex_stat = &coex->stat;
 
@@ -1135,9 +1135,9 @@ static void rtw_coex_power_save_state(struct rtw_dev *rtwdev, u8 ps_type,
 static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
                              u8 byte3, u8 byte4, u8 byte5)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_dm *coex_dm = &coex->dm;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        u8 ps_type = COEX_PS_WIFI_NATIVE;
        bool ap_enable = false;
@@ -1193,10 +1193,10 @@ static void rtw_coex_set_tdma(struct rtw_dev *rtwdev, u8 byte1, u8 byte2,
 
 static void rtw_coex_tdma(struct rtw_dev *rtwdev, bool force, u32 tcase)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        struct rtw_coex_stat *coex_stat = &coex->stat;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        u8 n, type;
        bool turn_on;
@@ -1526,8 +1526,8 @@ static u8 rtw_coex_algorithm(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -1549,11 +1549,11 @@ static void rtw_coex_action_coex_all_off(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 level = 0;
        bool bt_afh_loss = true;
 
@@ -1594,8 +1594,8 @@ static void rtw_coex_action_freerun(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -1619,8 +1619,8 @@ static void rtw_coex_action_rf4ce(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -1644,10 +1644,10 @@ static void rtw_coex_action_bt_whql_test(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
        u32 slot_type = 0;
 
@@ -1684,11 +1684,11 @@ static void rtw_coex_action_bt_relink(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_idle(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_rfe *coex_rfe = &coex->rfe;
        u8 table_case = 0xff, tdma_case = 0xff;
 
@@ -1753,10 +1753,10 @@ exit:
 
 static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        bool wl_hi_pri = false;
        u8 table_case, tdma_case;
        u32 slot_type = 0;
@@ -1853,11 +1853,11 @@ static void rtw_coex_action_bt_inquiry(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        struct rtw_coex_dm *coex_dm = &coex->dm;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -1901,10 +1901,10 @@ static void rtw_coex_action_bt_game_hid(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -1932,10 +1932,10 @@ static void rtw_coex_action_bt_hfp(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
        u32 slot_type = 0;
        bool bt_multi_link_remain = false, is_toggle_table = false;
@@ -2015,11 +2015,11 @@ static void rtw_coex_action_bt_hid(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
        u32 slot_type = 0;
 
@@ -2057,10 +2057,10 @@ static void rtw_coex_action_bt_a2dp(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
        bool ap_enable = false;
 
@@ -2096,10 +2096,10 @@ static void rtw_coex_action_bt_a2dpsink(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -2133,11 +2133,11 @@ static void rtw_coex_action_bt_pan(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case, interval = 0;
        u32 slot_type = 0;
        bool is_toggle_table = false;
@@ -2190,10 +2190,10 @@ static void rtw_coex_action_bt_a2dp_hid(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
        bool wl_cpt_test = false, bt_cpt_test = false;
 
@@ -2247,10 +2247,10 @@ static void rtw_coex_action_bt_a2dp_pan(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -2282,10 +2282,10 @@ static void rtw_coex_action_bt_pan_hid(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -2316,9 +2316,9 @@ static void rtw_coex_action_bt_a2dp_pan_hid(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        u8 table_case, tdma_case;
 
@@ -2348,8 +2348,8 @@ static void rtw_coex_action_wl_under5g(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -2372,9 +2372,9 @@ static void rtw_coex_action_wl_only(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        u8 table_case, tdma_case;
 
@@ -2411,10 +2411,10 @@ static void rtw_coex_action_wl_native_lps(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
        u32 slot_type = 0;
 
@@ -2451,8 +2451,8 @@ static void rtw_coex_action_wl_linkscan(struct rtw_dev *rtwdev)
 
 static void rtw_coex_action_wl_not_connected(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 table_case, tdma_case;
 
        rtw_dbg(rtwdev, RTW_DBG_COEX, "[BTCoex], %s()\n", __func__);
@@ -2528,8 +2528,8 @@ static void rtw_coex_action_wl_connected(struct rtw_dev *rtwdev)
 
 static void rtw_coex_run_coex(struct rtw_dev *rtwdev, u8 reason)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        bool rf4ce_en = false;
@@ -3002,9 +3002,9 @@ void rtw_coex_media_status_notify(struct rtw_dev *rtwdev, u8 type)
 
 void rtw_coex_bt_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_dm *coex_dm = &coex->dm;
        u32 bt_relink_time;
        u8 i, rsp_source = 0, type;
@@ -3270,8 +3270,8 @@ static const u8 coex_bt_hidinfo_xb[] = {0x58, 0x62, 0x6f};
 
 void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_hid *hidinfo;
        struct rtw_coex_hid_info_a *hida;
@@ -3360,8 +3360,8 @@ void rtw_coex_bt_hid_info_notify(struct rtw_dev *rtwdev, u8 *buf, u8 length)
 
 void rtw_coex_query_bt_hid_list(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex_stat *coex_stat = &coex->stat;
        struct rtw_coex_hid *hidinfo;
        u8 i, handle;
@@ -3582,7 +3582,7 @@ static const char *rtw_coex_get_reason_string(u8 reason)
 static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
                                   u32 wl_reg_6c4)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        u8 ans = 0xFF;
        u8 n, i;
@@ -3618,8 +3618,8 @@ static u8 rtw_coex_get_table_index(struct rtw_dev *rtwdev, u32 wl_reg_6c0,
 
 static u8 rtw_coex_get_tdma_index(struct rtw_dev *rtwdev, u8 *tdma_para)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u8 ans = 0xFF;
        u8 n, i, j;
        u8 load_cur_tab_val;
@@ -3736,7 +3736,7 @@ static int rtw_coex_val_info(struct rtw_dev *rtwdev,
 
 static void rtw_coex_set_coexinfo_hw(struct rtw_dev *rtwdev, struct seq_file *m)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_reg_domain *reg;
        char addr_info[INFO_SIZE];
        int n_addr = 0;
@@ -3910,7 +3910,7 @@ static const char *rtw_coex_get_wl_coex_mode(u8 coex_wl_link_mode)
 
 void rtw_coex_display_coex_info(struct rtw_dev *rtwdev, struct seq_file *m)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_dm_info *dm_info = &rtwdev->dm_info;
        struct rtw_coex *coex = &rtwdev->coex;
        struct rtw_coex_stat *coex_stat = &coex->stat;
index 07fa7aa..57cf29d 100644 (file)
@@ -327,7 +327,7 @@ struct coex_rf_para {
 
 static inline void rtw_coex_set_init(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->coex_set_init(rtwdev);
 }
@@ -335,7 +335,7 @@ static inline void rtw_coex_set_init(struct rtw_dev *rtwdev)
 static inline
 void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (!chip->ops->coex_set_ant_switch)
                return;
@@ -345,28 +345,28 @@ void rtw_coex_set_ant_switch(struct rtw_dev *rtwdev, u8 ctrl_type, u8 pos_type)
 
 static inline void rtw_coex_set_gnt_fix(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->coex_set_gnt_fix(rtwdev);
 }
 
 static inline void rtw_coex_set_gnt_debug(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->coex_set_gnt_debug(rtwdev);
 }
 
 static inline  void rtw_coex_set_rfe_type(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->coex_set_rfe_type(rtwdev);
 }
 
 static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->coex_set_wl_tx_power(rtwdev, wl_pwr);
 }
@@ -374,7 +374,7 @@ static inline void rtw_coex_set_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr)
 static inline
 void rtw_coex_set_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->coex_set_wl_rx_gain(rtwdev, low_gain);
 }
index 7cde6bc..9ebe544 100644 (file)
@@ -621,11 +621,13 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
        struct rtw_debugfs_priv *debugfs_priv = m->private;
        struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
        struct rtw_hal *hal = &rtwdev->hal;
-       u8 path, rate;
+       u8 path, rate, bw, ch, regd;
        struct rtw_power_params pwr_param = {0};
-       u8 bw = hal->current_band_width;
-       u8 ch = hal->current_channel;
-       u8 regd = rtw_regd_get(rtwdev);
+
+       mutex_lock(&rtwdev->mutex);
+       bw = hal->current_band_width;
+       ch = hal->current_channel;
+       regd = rtw_regd_get(rtwdev);
 
        seq_printf(m, "channel: %u\n", ch);
        seq_printf(m, "bandwidth: %u\n", bw);
@@ -667,6 +669,7 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v)
        }
 
        mutex_unlock(&hal->tx_power_mutex);
+       mutex_unlock(&rtwdev->mutex);
 
        return 0;
 }
index c266c84..b85075c 100644 (file)
@@ -86,7 +86,7 @@ static int rtw_dump_logical_efuse_map(struct rtw_dev *rtwdev, u8 *phy_map,
 
 static int rtw_dump_physical_efuse_map(struct rtw_dev *rtwdev, u8 *map)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u32 size = rtwdev->efuse.physical_size;
        u32 efuse_ctl;
        u32 addr;
@@ -145,7 +145,7 @@ EXPORT_SYMBOL(rtw_read8_physical_efuse);
 
 int rtw_parse_efuse_map(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        u32 phy_size = efuse->physical_size;
        u32 log_size = efuse->logical_size;
index 4fdab03..babba68 100644 (file)
@@ -14,6 +14,8 @@
 #include "util.h"
 #include "wow.h"
 #include "ps.h"
+#include "phy.h"
+#include "mac.h"
 
 static void rtw_fw_c2h_cmd_handle_ext(struct rtw_dev *rtwdev,
                                      struct sk_buff *skb)
@@ -904,7 +906,7 @@ void rtw_send_rsvd_page_h2c(struct rtw_dev *rtwdev)
 static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw)
 {
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req;
        struct rtw_nlo_info_hdr *nlo_hdr;
        struct cfg80211_ssid *ssid;
@@ -959,7 +961,7 @@ static struct sk_buff *rtw_nlo_info_get(struct ieee80211_hw *hw)
 static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw)
 {
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_pno_request *pno_req = &rtwdev->wow.pno_req;
        struct ieee80211_channel *channels = pno_req->channels;
        struct sk_buff *skb;
@@ -993,7 +995,7 @@ static struct sk_buff *rtw_cs_channel_info_get(struct ieee80211_hw *hw)
 static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw)
 {
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
        struct rtw_lps_pg_dpk_hdr *dpk_hdr;
        struct sk_buff *skb;
@@ -1018,7 +1020,7 @@ static struct sk_buff *rtw_lps_pg_dpk_get(struct ieee80211_hw *hw)
 static struct sk_buff *rtw_lps_pg_info_get(struct ieee80211_hw *hw)
 {
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_lps_conf *conf = &rtwdev->lps_conf;
        struct rtw_lps_pg_info_hdr *pg_info_hdr;
        struct rtw_wow_param *rtw_wow = &rtwdev->wow;
@@ -1122,7 +1124,7 @@ static void rtw_fill_rsvd_page_desc(struct rtw_dev *rtwdev, struct sk_buff *skb,
                                    enum rtw_rsvd_packet_type type)
 {
        struct rtw_tx_pkt_info pkt_info = {0};
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u8 *pkt_desc;
 
        rtw_tx_rsvd_page_pkt_info_update(rtwdev, &pkt_info, skb, type);
@@ -1433,7 +1435,7 @@ static int  __rtw_build_rsvd_page_from_vifs(struct rtw_dev *rtwdev)
 static u8 *rtw_build_rsvd_page(struct rtw_dev *rtwdev, u32 *size)
 {
        struct ieee80211_hw *hw = rtwdev->hw;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct sk_buff *iter;
        struct rtw_rsvd_page *rsvd_pkt;
        u32 page = 0;
@@ -1647,7 +1649,7 @@ out:
 static void rtw_fw_read_fifo(struct rtw_dev *rtwdev, enum rtw_fw_fifo_sel sel,
                             u32 offset, u32 size, u32 *buf)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u32 start_pg, residue;
 
        if (sel >= RTW_FW_FIFO_MAX) {
@@ -1706,7 +1708,7 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
 static void __rtw_fw_update_pkt(struct rtw_dev *rtwdev, u8 pkt_id, u16 size,
                                u8 location)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u8 h2c_pkt[H2C_PKT_SIZE] = {0};
        u16 total_size = H2C_PKT_HDR_SIZE + H2C_PKT_UPDATE_PKT_LEN;
 
@@ -1818,8 +1820,8 @@ static int rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
                                   struct sk_buff_head *list, u8 *bands,
                                   struct rtw_vif *rtwvif)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct ieee80211_scan_ies *ies = rtwvif->scan_ies;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct sk_buff *new;
        u8 idx;
 
@@ -1841,16 +1843,23 @@ static int rtw_append_probe_req_ie(struct rtw_dev *rtwdev, struct sk_buff *skb,
 static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
                                         struct sk_buff_head *probe_req_list)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct sk_buff *skb, *tmp;
        u8 page_offset = 1, *buf, page_size = chip->page_size;
-       u8 pages = page_offset + num_probes * RTW_PROBE_PG_CNT;
        u16 pg_addr = rtwdev->fifo.rsvd_h2c_info_addr, loc;
        u16 buf_offset = page_size * page_offset;
        u8 tx_desc_sz = chip->tx_pkt_desc_sz;
+       u8 page_cnt, pages;
        unsigned int pkt_len;
        int ret;
 
+       if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM))
+               page_cnt = RTW_OLD_PROBE_PG_CNT;
+       else
+               page_cnt = RTW_PROBE_PG_CNT;
+
+       pages = page_offset + num_probes * page_cnt;
+
        buf = kzalloc(page_size * pages, GFP_KERNEL);
        if (!buf)
                return -ENOMEM;
@@ -1859,7 +1868,7 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
        skb_queue_walk_safe(probe_req_list, skb, tmp) {
                skb_unlink(skb, probe_req_list);
                rtw_fill_rsvd_page_desc(rtwdev, skb, RSVD_PROBE_REQ);
-               if (skb->len > page_size * RTW_PROBE_PG_CNT) {
+               if (skb->len > page_size * page_cnt) {
                        ret = -EINVAL;
                        goto out;
                }
@@ -1869,8 +1878,8 @@ static int _rtw_hw_scan_update_probe_req(struct rtw_dev *rtwdev, u8 num_probes,
                loc = pg_addr - rtwdev->fifo.rsvd_boundary + page_offset;
                __rtw_fw_update_pkt(rtwdev, RTW_PACKET_PROBE_REQ, pkt_len, loc);
 
-               buf_offset += RTW_PROBE_PG_CNT * page_size;
-               page_offset += RTW_PROBE_PG_CNT;
+               buf_offset += page_cnt * page_size;
+               page_offset += page_cnt;
                kfree_skb(skb);
        }
 
@@ -2048,6 +2057,9 @@ void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
        rtwvif->scan_req = req;
 
        ieee80211_stop_queues(rtwdev->hw);
+       rtw_leave_lps_deep(rtwdev);
+       rtw_hci_flush_all_queues(rtwdev, false);
+       rtw_mac_flush_all_queues(rtwdev, false);
        if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
                get_random_mask_addr(mac_addr, req->mac_addr,
                                     req->mac_addr_mask);
@@ -2080,10 +2092,9 @@ void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
        rtw_core_scan_complete(rtwdev, vif, true);
 
        rtwvif = (struct rtw_vif *)vif->drv_priv;
-       if (rtwvif->net_type == RTW_NET_MGD_LINKED) {
-               hal->current_channel = chan;
-               hal->current_band_type = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
-       }
+       if (chan)
+               rtw_store_op_chan(rtwdev, false);
+       rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
        ieee80211_wake_queues(rtwdev->hw);
        ieee80211_scan_completed(rtwdev->hw, &info);
 
@@ -2124,6 +2135,7 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
                        bool enable)
 {
        struct rtw_vif *rtwvif = vif ? (struct rtw_vif *)vif->drv_priv : NULL;
+       struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
        struct rtw_ch_switch_option cs_option = {0};
        struct rtw_chan_list chan_list = {0};
        int ret = 0;
@@ -2132,7 +2144,7 @@ int rtw_hw_scan_offload(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
                return -EINVAL;
 
        cs_option.switch_en = enable;
-       cs_option.back_op_en = rtwvif->net_type == RTW_NET_MGD_LINKED;
+       cs_option.back_op_en = scan_info->op_chan != 0;
        if (enable) {
                ret = rtw_hw_scan_prehandle(rtwdev, rtwvif, &chan_list);
                if (ret)
@@ -2171,14 +2183,33 @@ void rtw_hw_scan_status_report(struct rtw_dev *rtwdev, struct sk_buff *skb)
                rtw_dbg(rtwdev, RTW_DBG_HW_SCAN, "HW scan aborted with code: %d\n", rc);
 }
 
-void rtw_store_op_chan(struct rtw_dev *rtwdev)
+void rtw_store_op_chan(struct rtw_dev *rtwdev, bool backup)
 {
        struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
        struct rtw_hal *hal = &rtwdev->hal;
+       u8 band;
+
+       if (backup) {
+               scan_info->op_chan = hal->current_channel;
+               scan_info->op_bw = hal->current_band_width;
+               scan_info->op_pri_ch_idx = hal->current_primary_channel_index;
+               scan_info->op_pri_ch = hal->primary_channel;
+       } else {
+               band = scan_info->op_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
+               rtw_update_channel(rtwdev, scan_info->op_chan,
+                                  scan_info->op_pri_ch,
+                                  band, scan_info->op_bw);
+       }
+}
 
-       scan_info->op_chan = hal->current_channel;
-       scan_info->op_bw = hal->current_band_width;
-       scan_info->op_pri_ch_idx = hal->current_primary_channel_index;
+void rtw_clear_op_chan(struct rtw_dev *rtwdev)
+{
+       struct rtw_hw_scan_info *scan_info = &rtwdev->scan_info;
+
+       scan_info->op_chan = 0;
+       scan_info->op_bw = 0;
+       scan_info->op_pri_ch_idx = 0;
+       scan_info->op_pri_ch = 0;
 }
 
 static bool rtw_is_op_chan(struct rtw_dev *rtwdev, u8 channel)
@@ -2193,7 +2224,7 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
        struct rtw_hal *hal = &rtwdev->hal;
        struct rtw_c2h_cmd *c2h;
        enum rtw_scan_notify_id id;
-       u8 chan, status;
+       u8 chan, band, status;
 
        if (!test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
                return;
@@ -2204,10 +2235,13 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
        status = GET_CHAN_SWITCH_STATUS(c2h->payload);
 
        if (id == RTW_SCAN_NOTIFY_ID_POSTSWITCH) {
-               if (rtw_is_op_chan(rtwdev, chan))
+               band = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
+               rtw_update_channel(rtwdev, chan, chan, band,
+                                  RTW_CHANNEL_WIDTH_20);
+               if (rtw_is_op_chan(rtwdev, chan)) {
+                       rtw_store_op_chan(rtwdev, false);
                        ieee80211_wake_queues(rtwdev->hw);
-               hal->current_channel = chan;
-               hal->current_band_type = chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
+               }
        } else if (id == RTW_SCAN_NOTIFY_ID_PRESWITCH) {
                if (IS_CH_5G_BAND(chan)) {
                        rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G);
@@ -2220,7 +2254,12 @@ void rtw_hw_scan_chan_switch(struct rtw_dev *rtwdev, struct sk_buff *skb)
                                chan_type = COEX_SWITCH_TO_24G_NOFORSCAN;
                        rtw_coex_switchband_notify(rtwdev, chan_type);
                }
-               if (rtw_is_op_chan(rtwdev, chan))
+               /* The channel of C2H RTW_SCAN_NOTIFY_ID_PRESWITCH is next
+                * channel that hardware will switch. We need to stop queue
+                * if next channel is non-op channel.
+                */
+               if (!rtw_is_op_chan(rtwdev, chan) &&
+                   rtw_is_op_chan(rtwdev, hal->current_channel))
                        ieee80211_stop_queues(rtwdev->hw);
        }
 
index 7a37675..a5a9658 100644 (file)
@@ -41,7 +41,8 @@
 #define RTW_EX_CH_INFO_HDR_SIZE                2
 #define RTW_SCAN_WIDTH                 0
 #define RTW_PRI_CH_IDX                 1
-#define RTW_PROBE_PG_CNT               2
+#define RTW_OLD_PROBE_PG_CNT           2
+#define RTW_PROBE_PG_CNT               4
 
 enum rtw_c2h_cmd_id {
        C2H_CCX_TX_RPT = 0x03,
@@ -120,6 +121,10 @@ enum rtw_fw_feature {
        FW_FEATURE_MAX = BIT(31),
 };
 
+enum rtw_fw_feature_ext {
+       FW_FEATURE_EXT_OLD_PAGE_NUM = BIT(0),
+};
+
 enum rtw_beacon_filter_offload_mode {
        BCN_FILTER_OFFLOAD_MODE_0 = 0,
        BCN_FILTER_OFFLOAD_MODE_1,
@@ -323,6 +328,11 @@ struct rtw_fw_hdr_legacy {
        __le32 rsvd5;
 } __packed;
 
+#define RTW_FW_VER_CODE(ver, sub_ver, idx)     \
+       (((ver) << 16) | ((sub_ver) << 8) | (idx))
+#define RTW_FW_SUIT_VER_CODE(s)        \
+       RTW_FW_VER_CODE((s).version, (s).sub_version, (s).sub_index)
+
 /* C2H */
 #define GET_CCX_REPORT_SEQNUM_V0(c2h_payload)  (c2h_payload[6] & 0xfc)
 #define GET_CCX_REPORT_STATUS_V0(c2h_payload)  (c2h_payload[0] & 0xc0)
@@ -770,6 +780,12 @@ static inline bool rtw_fw_feature_check(struct rtw_fw_state *fw,
        return !!(fw->feature & feature);
 }
 
+static inline bool rtw_fw_feature_ext_check(struct rtw_fw_state *fw,
+                                           enum rtw_fw_feature_ext feature)
+{
+       return !!(fw->feature_ext & feature);
+}
+
 void rtw_fw_c2h_cmd_rx_irqsafe(struct rtw_dev *rtwdev, u32 pkt_offset,
                               struct sk_buff *skb);
 void rtw_fw_c2h_cmd_handle(struct rtw_dev *rtwdev, struct sk_buff *skb);
@@ -831,7 +847,8 @@ int rtw_fw_dump_fifo(struct rtw_dev *rtwdev, u8 fifo_sel, u32 addr, u32 size,
                     u32 *buffer);
 void rtw_fw_scan_notify(struct rtw_dev *rtwdev, bool start);
 void rtw_fw_adaptivity(struct rtw_dev *rtwdev);
-void rtw_store_op_chan(struct rtw_dev *rtwdev);
+void rtw_store_op_chan(struct rtw_dev *rtwdev, bool backup);
+void rtw_clear_op_chan(struct rtw_dev *rtwdev);
 void rtw_hw_scan_start(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
                       struct ieee80211_scan_request *req);
 void rtw_hw_scan_complete(struct rtw_dev *rtwdev, struct ieee80211_vif *vif,
index caf2603..52076e8 100644 (file)
@@ -243,7 +243,7 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
 
 static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_pwr_seq_cmd **pwr_seq;
        u8 rpwm;
        bool cur_pwr;
@@ -587,7 +587,7 @@ static int
 download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data,
                         u32 src, u32 dst, u32 size)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u32 desc_size = chip->tx_pkt_desc_sz;
        u8 first_part;
        u32 mem_offset;
@@ -934,7 +934,7 @@ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
 static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev,
                                       u32 prio_queue, bool drop)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_prioq_addr *addr;
        bool wsize;
        u16 avail_page, rsvd_page;
@@ -996,7 +996,7 @@ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop)
 
 static int txdma_queue_mapping(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_rqpn *rqpn = NULL;
        u16 txdma_pq_map = 0;
 
@@ -1037,8 +1037,8 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev)
 
 static int set_trx_fifo_info(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fifo_conf *fifo = &rtwdev->fifo;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u16 cur_pg_addr;
        u8 csi_buf_pg_num = chip->csi_buf_pg_num;
 
@@ -1092,8 +1092,8 @@ static int __priority_queue_cfg(struct rtw_dev *rtwdev,
                                const struct rtw_page_table *pg_tbl,
                                u16 pubq_num)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fifo_conf *fifo = &rtwdev->fifo;
-       struct rtw_chip_info *chip = rtwdev->chip;
 
        rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num);
        rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num);
@@ -1123,8 +1123,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev,
                                       const struct rtw_page_table *pg_tbl,
                                       u16 pubq_num)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fifo_conf *fifo = &rtwdev->fifo;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u32 val32;
 
        val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num);
@@ -1149,8 +1149,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev,
 
 static int priority_queue_cfg(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fifo_conf *fifo = &rtwdev->fifo;
-       struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_page_table *pg_tbl = NULL;
        u16 pubq_num;
        int ret;
@@ -1277,7 +1277,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev)
 
 int rtw_mac_init(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        int ret;
 
        ret = rtw_init_trx_cfg(rtwdev);
index c7b98a0..07578cc 100644 (file)
@@ -101,7 +101,8 @@ static int rtw_ops_config(struct ieee80211_hw *hw, u32 changed)
                rtw_set_channel(rtwdev);
 
        if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
-           (hw->conf.flags & IEEE80211_CONF_IDLE))
+           (hw->conf.flags & IEEE80211_CONF_IDLE) &&
+           !test_bit(RTW_FLAG_SCANNING, rtwdev->flags))
                rtw_enter_ips(rtwdev);
 
 out:
@@ -377,7 +378,6 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
                        rtw_coex_media_status_notify(rtwdev, vif->cfg.assoc);
                        if (rtw_bf_support)
                                rtw_bf_assoc(rtwdev, vif, conf);
-                       rtw_store_op_chan(rtwdev);
                } else {
                        rtw_leave_lps(rtwdev);
                        rtw_bf_disassoc(rtwdev, vif, conf);
@@ -395,6 +395,10 @@ static void rtw_ops_bss_info_changed(struct ieee80211_hw *hw,
        if (changed & BSS_CHANGED_BSSID) {
                ether_addr_copy(rtwvif->bssid, conf->bssid);
                config |= PORT_SET_BSSID;
+               if (is_zero_ether_addr(rtwvif->bssid))
+                       rtw_clear_op_chan(rtwdev);
+               else
+                       rtw_store_op_chan(rtwdev, true);
        }
 
        if (changed & BSS_CHANGED_BEACON_INT) {
@@ -434,7 +438,7 @@ static int rtw_ops_start_ap(struct ieee80211_hw *hw,
                            struct ieee80211_bss_conf *link_conf)
 {
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        mutex_lock(&rtwdev->mutex);
        chip->ops->phy_calibration(rtwdev);
@@ -752,7 +756,7 @@ static int rtw_ops_set_antenna(struct ieee80211_hw *hw,
                               u32 rx_antenna)
 {
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        int ret;
 
        if (!chip->ops->set_antenna)
@@ -872,7 +876,9 @@ static int rtw_ops_set_sar_specs(struct ieee80211_hw *hw,
 {
        struct rtw_dev *rtwdev = hw->priv;
 
+       mutex_lock(&rtwdev->mutex);
        rtw_set_sar_specs(rtwdev, sar);
+       mutex_unlock(&rtwdev->mutex);
 
        return 0;
 }
index 76dc9da..67151db 100644 (file)
@@ -353,7 +353,7 @@ struct rtw_fwcd_hdr {
 
 static int rtw_fwcd_prep(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fwcd_desc *desc = &rtwdev->fw.fwcd_desc;
        const struct rtw_fwcd_segs *segs = chip->fwcd_segs;
        u32 prep_size = chip->fw_rxff_size + sizeof(struct rtw_fwcd_hdr);
@@ -675,67 +675,126 @@ void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period)
        rtw_write8(rtwdev, REG_DTIM_COUNTER_ROOT, dtim_period - 1);
 }
 
+void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
+                       u8 primary_channel, enum rtw_supported_band band,
+                       enum rtw_bandwidth bandwidth)
+{
+       enum nl80211_band nl_band = rtw_hw_to_nl80211_band(band);
+       struct rtw_hal *hal = &rtwdev->hal;
+       u8 *cch_by_bw = hal->cch_by_bw;
+       u32 center_freq, primary_freq;
+       enum rtw_sar_bands sar_band;
+       u8 primary_channel_idx;
+
+       center_freq = ieee80211_channel_to_frequency(center_channel, nl_band);
+       primary_freq = ieee80211_channel_to_frequency(primary_channel, nl_band);
+
+       /* assign the center channel used while 20M bw is selected */
+       cch_by_bw[RTW_CHANNEL_WIDTH_20] = primary_channel;
+
+       /* assign the center channel used while current bw is selected */
+       cch_by_bw[bandwidth] = center_channel;
+
+       switch (bandwidth) {
+       case RTW_CHANNEL_WIDTH_20:
+       default:
+               primary_channel_idx = RTW_SC_DONT_CARE;
+               break;
+       case RTW_CHANNEL_WIDTH_40:
+               if (primary_freq > center_freq)
+                       primary_channel_idx = RTW_SC_20_UPPER;
+               else
+                       primary_channel_idx = RTW_SC_20_LOWER;
+               break;
+       case RTW_CHANNEL_WIDTH_80:
+               if (primary_freq > center_freq) {
+                       if (primary_freq - center_freq == 10)
+                               primary_channel_idx = RTW_SC_20_UPPER;
+                       else
+                               primary_channel_idx = RTW_SC_20_UPMOST;
+
+                       /* assign the center channel used
+                        * while 40M bw is selected
+                        */
+                       cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_channel + 4;
+               } else {
+                       if (center_freq - primary_freq == 10)
+                               primary_channel_idx = RTW_SC_20_LOWER;
+                       else
+                               primary_channel_idx = RTW_SC_20_LOWEST;
+
+                       /* assign the center channel used
+                        * while 40M bw is selected
+                        */
+                       cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_channel - 4;
+               }
+               break;
+       }
+
+       switch (center_channel) {
+       case 1 ... 14:
+               sar_band = RTW_SAR_BAND_0;
+               break;
+       case 36 ... 64:
+               sar_band = RTW_SAR_BAND_1;
+               break;
+       case 100 ... 144:
+               sar_band = RTW_SAR_BAND_3;
+               break;
+       case 149 ... 177:
+               sar_band = RTW_SAR_BAND_4;
+               break;
+       default:
+               WARN(1, "unknown ch(%u) to SAR band\n", center_channel);
+               sar_band = RTW_SAR_BAND_0;
+               break;
+       }
+
+       hal->current_primary_channel_index = primary_channel_idx;
+       hal->current_band_width = bandwidth;
+       hal->primary_channel = primary_channel;
+       hal->current_channel = center_channel;
+       hal->current_band_type = band;
+       hal->sar_band = sar_band;
+}
+
 void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
                            struct rtw_channel_params *chan_params)
 {
        struct ieee80211_channel *channel = chandef->chan;
        enum nl80211_chan_width width = chandef->width;
-       u8 *cch_by_bw = chan_params->cch_by_bw;
        u32 primary_freq, center_freq;
        u8 center_chan;
        u8 bandwidth = RTW_CHANNEL_WIDTH_20;
-       u8 primary_chan_idx = 0;
-       u8 i;
 
        center_chan = channel->hw_value;
        primary_freq = channel->center_freq;
        center_freq = chandef->center_freq1;
 
-       /* assign the center channel used while 20M bw is selected */
-       cch_by_bw[RTW_CHANNEL_WIDTH_20] = channel->hw_value;
-
        switch (width) {
        case NL80211_CHAN_WIDTH_20_NOHT:
        case NL80211_CHAN_WIDTH_20:
                bandwidth = RTW_CHANNEL_WIDTH_20;
-               primary_chan_idx = RTW_SC_DONT_CARE;
                break;
        case NL80211_CHAN_WIDTH_40:
                bandwidth = RTW_CHANNEL_WIDTH_40;
-               if (primary_freq > center_freq) {
-                       primary_chan_idx = RTW_SC_20_UPPER;
+               if (primary_freq > center_freq)
                        center_chan -= 2;
-               } else {
-                       primary_chan_idx = RTW_SC_20_LOWER;
+               else
                        center_chan += 2;
-               }
                break;
        case NL80211_CHAN_WIDTH_80:
                bandwidth = RTW_CHANNEL_WIDTH_80;
                if (primary_freq > center_freq) {
-                       if (primary_freq - center_freq == 10) {
-                               primary_chan_idx = RTW_SC_20_UPPER;
+                       if (primary_freq - center_freq == 10)
                                center_chan -= 2;
-                       } else {
-                               primary_chan_idx = RTW_SC_20_UPMOST;
+                       else
                                center_chan -= 6;
-                       }
-                       /* assign the center channel used
-                        * while 40M bw is selected
-                        */
-                       cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan + 4;
                } else {
-                       if (center_freq - primary_freq == 10) {
-                               primary_chan_idx = RTW_SC_20_LOWER;
+                       if (center_freq - primary_freq == 10)
                                center_chan += 2;
-                       } else {
-                               primary_chan_idx = RTW_SC_20_LOWEST;
+                       else
                                center_chan += 6;
-                       }
-                       /* assign the center channel used
-                        * while 40M bw is selected
-                        */
-                       cch_by_bw[RTW_CHANNEL_WIDTH_40] = center_chan - 4;
                }
                break;
        default:
@@ -745,60 +804,30 @@ void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
 
        chan_params->center_chan = center_chan;
        chan_params->bandwidth = bandwidth;
-       chan_params->primary_chan_idx = primary_chan_idx;
-
-       /* assign the center channel used while current bw is selected */
-       cch_by_bw[bandwidth] = center_chan;
-
-       for (i = bandwidth + 1; i <= RTW_MAX_CHANNEL_WIDTH; i++)
-               cch_by_bw[i] = 0;
+       chan_params->primary_chan = channel->hw_value;
 }
 
 void rtw_set_channel(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct ieee80211_hw *hw = rtwdev->hw;
        struct rtw_hal *hal = &rtwdev->hal;
-       struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_channel_params ch_param;
-       u8 center_chan, bandwidth, primary_chan_idx;
-       u8 i;
+       u8 center_chan, primary_chan, bandwidth, band;
 
        rtw_get_channel_params(&hw->conf.chandef, &ch_param);
        if (WARN(ch_param.center_chan == 0, "Invalid channel\n"))
                return;
 
        center_chan = ch_param.center_chan;
+       primary_chan = ch_param.primary_chan;
        bandwidth = ch_param.bandwidth;
-       primary_chan_idx = ch_param.primary_chan_idx;
-
-       hal->current_band_width = bandwidth;
-       hal->current_channel = center_chan;
-       hal->current_primary_channel_index = primary_chan_idx;
-       hal->current_band_type = center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
-
-       switch (center_chan) {
-       case 1 ... 14:
-               hal->sar_band = RTW_SAR_BAND_0;
-               break;
-       case 36 ... 64:
-               hal->sar_band = RTW_SAR_BAND_1;
-               break;
-       case 100 ... 144:
-               hal->sar_band = RTW_SAR_BAND_3;
-               break;
-       case 149 ... 177:
-               hal->sar_band = RTW_SAR_BAND_4;
-               break;
-       default:
-               WARN(1, "unknown ch(%u) to SAR band\n", center_chan);
-               hal->sar_band = RTW_SAR_BAND_0;
-               break;
-       }
+       band = ch_param.center_chan > 14 ? RTW_BAND_5G : RTW_BAND_2G;
 
-       for (i = RTW_CHANNEL_WIDTH_20; i <= RTW_MAX_CHANNEL_WIDTH; i++)
-               hal->cch_by_bw[i] = ch_param.cch_by_bw[i];
+       rtw_update_channel(rtwdev, center_chan, primary_chan, band, bandwidth);
 
-       chip->ops->set_channel(rtwdev, center_chan, bandwidth, primary_chan_idx);
+       chip->ops->set_channel(rtwdev, center_chan, bandwidth,
+                              hal->current_primary_channel_index);
 
        if (hal->current_band_type == RTW_BAND_5G) {
                rtw_coex_switchband_notify(rtwdev, COEX_SWITCH_TO_5G);
@@ -821,7 +850,7 @@ void rtw_set_channel(struct rtw_dev *rtwdev)
 
 void rtw_chip_prepare_tx(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (rtwdev->need_rfk) {
                rtwdev->need_rfk = false;
@@ -890,8 +919,8 @@ static u8 hw_bw_cap_to_bitamp(u8 bw_cap)
 
 static void rtw_hw_config_rf_ant_num(struct rtw_dev *rtwdev, u8 hw_ant_num)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_hal *hal = &rtwdev->hal;
-       struct rtw_chip_info *chip = rtwdev->chip;
 
        if (hw_ant_num == EFUSE_HW_CAP_IGNORE ||
            hw_ant_num >= hal->rf_path_num)
@@ -1240,7 +1269,7 @@ void rtw_update_sta_info(struct rtw_dev *rtwdev, struct rtw_sta_info *si,
 
 static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fw_state *fw;
 
        fw = &rtwdev->fw;
@@ -1261,7 +1290,7 @@ static int rtw_wait_firmware_completion(struct rtw_dev *rtwdev)
 static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
                                                       struct rtw_fw_state *fw)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (rtw_disable_lps_deep_mode || !chip->lps_deep_mode_supported ||
            !fw->feature)
@@ -1280,7 +1309,7 @@ static enum rtw_lps_deep_mode rtw_update_lps_deep_mode(struct rtw_dev *rtwdev,
 
 static int rtw_power_on(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_fw_state *fw = &rtwdev->fw;
        bool wifi_only;
        int ret;
@@ -1469,8 +1498,8 @@ void rtw_core_stop(struct rtw_dev *rtwdev)
 static void rtw_init_ht_cap(struct rtw_dev *rtwdev,
                            struct ieee80211_sta_ht_cap *ht_cap)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
-       struct rtw_chip_info *chip = rtwdev->chip;
 
        ht_cap->ht_supported = true;
        ht_cap->cap = 0;
@@ -1552,8 +1581,23 @@ static void rtw_init_vht_cap(struct rtw_dev *rtwdev,
        vht_cap->vht_mcs.tx_highest = highest;
 }
 
+static u16 rtw_get_max_scan_ie_len(struct rtw_dev *rtwdev)
+{
+       u16 len;
+
+       len = rtwdev->chip->max_scan_ie_len;
+
+       if (!rtw_fw_feature_check(&rtwdev->fw, FW_FEATURE_SCAN_OFFLOAD) &&
+           rtwdev->chip->id == RTW_CHIP_TYPE_8822C)
+               len = IEEE80211_MAX_DATA_LEN;
+       else if (rtw_fw_feature_ext_check(&rtwdev->fw, FW_FEATURE_EXT_OLD_PAGE_NUM))
+               len -= RTW_OLD_PROBE_PG_CNT * TX_PAGE_SIZE;
+
+       return len;
+}
+
 static void rtw_set_supported_band(struct ieee80211_hw *hw,
-                                  struct rtw_chip_info *chip)
+                                  const struct rtw_chip_info *chip)
 {
        struct rtw_dev *rtwdev = hw->priv;
        struct ieee80211_supported_band *sband;
@@ -1585,7 +1629,7 @@ err_out:
 }
 
 static void rtw_unset_supported_band(struct ieee80211_hw *hw,
-                                    struct rtw_chip_info *chip)
+                                    const struct rtw_chip_info *chip)
 {
        kfree(hw->wiphy->bands[NL80211_BAND_2GHZ]);
        kfree(hw->wiphy->bands[NL80211_BAND_5GHZ]);
@@ -1607,7 +1651,7 @@ static void rtw_vif_smps_iter(void *data, u8 *mac,
 
 void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool txrx_1ss)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_hal *hal = &rtwdev->hal;
 
        if (!chip->ops->config_txrx_mode || rtwdev->hal.txrx_1ss == txrx_1ss)
@@ -1631,6 +1675,10 @@ static void __update_firmware_feature(struct rtw_dev *rtwdev,
 
        feature = le32_to_cpu(fw_hdr->feature);
        fw->feature = feature & FW_FEATURE_SIG ? feature : 0;
+
+       if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C &&
+           RTW_FW_SUIT_VER_CODE(rtwdev->fw) < RTW_FW_VER_CODE(9, 9, 13))
+               fw->feature_ext |= FW_FEATURE_EXT_OLD_PAGE_NUM;
 }
 
 static void __update_firmware_info(struct rtw_dev *rtwdev,
@@ -1724,7 +1772,7 @@ static int rtw_load_firmware(struct rtw_dev *rtwdev, enum rtw_fw_type type)
 
 static int rtw_chip_parameter_setup(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_hal *hal = &rtwdev->hal;
        struct rtw_efuse *efuse = &rtwdev->efuse;
 
@@ -1982,7 +2030,7 @@ static void rtw_stats_init(struct rtw_dev *rtwdev)
 
 int rtw_core_init(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_coex *coex = &rtwdev->coex;
        int ret;
 
@@ -2045,7 +2093,7 @@ int rtw_core_init(struct rtw_dev *rtwdev)
        ret = rtw_load_firmware(rtwdev, RTW_NORMAL_FW);
        if (ret) {
                rtw_warn(rtwdev, "no firmware loaded\n");
-               return ret;
+               goto out;
        }
 
        if (chip->wow_fw_name) {
@@ -2055,11 +2103,15 @@ int rtw_core_init(struct rtw_dev *rtwdev)
                        wait_for_completion(&rtwdev->fw.completion);
                        if (rtwdev->fw.firmware)
                                release_firmware(rtwdev->fw.firmware);
-                       return ret;
+                       goto out;
                }
        }
 
        return 0;
+
+out:
+       destroy_workqueue(rtwdev->tx_wq);
+       return ret;
 }
 EXPORT_SYMBOL(rtw_core_init);
 
@@ -2136,7 +2188,7 @@ int rtw_register_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
 
        hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
        hw->wiphy->max_scan_ssids = RTW_SCAN_MAX_SSIDS;
-       hw->wiphy->max_scan_ie_len = RTW_SCAN_MAX_IE_LEN;
+       hw->wiphy->max_scan_ie_len = rtw_get_max_scan_ie_len(rtwdev);
 
        wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
        wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_SCAN_RANDOM_SN);
@@ -2180,7 +2232,7 @@ EXPORT_SYMBOL(rtw_register_hw);
 
 void rtw_unregister_hw(struct rtw_dev *rtwdev, struct ieee80211_hw *hw)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        ieee80211_unregister_hw(hw);
        rtw_unset_supported_band(hw, chip);
index 7db627f..bccd7b2 100644 (file)
@@ -22,7 +22,6 @@
 #define MAX_PG_CAM_BACKUP_NUM          8
 
 #define RTW_SCAN_MAX_SSIDS             4
-#define RTW_SCAN_MAX_IE_LEN            128
 
 #define RTW_MAX_PATTERN_NUM            12
 #define RTW_MAX_PATTERN_MASK_SIZE      16
@@ -33,6 +32,7 @@
 #define RFREG_MASK                     0xfffff
 #define INV_RF_DATA                    0xffffffff
 #define TX_PAGE_SIZE_SHIFT             7
+#define TX_PAGE_SIZE                   (1 << TX_PAGE_SIZE_SHIFT)
 
 #define RTW_CHANNEL_WIDTH_MAX          3
 #define RTW_RF_PATH_MAX                        4
@@ -510,12 +510,8 @@ struct rtw_timer_list {
 
 struct rtw_channel_params {
        u8 center_chan;
+       u8 primary_chan;
        u8 bandwidth;
-       u8 primary_chan_idx;
-       /* center channel by different available bandwidth,
-        * val of (bw > current bandwidth) is invalid
-        */
-       u8 cch_by_bw[RTW_MAX_CHANNEL_WIDTH + 1];
 };
 
 struct rtw_hw_reg {
@@ -1232,6 +1228,7 @@ struct rtw_chip_info {
        const char *wow_fw_name;
        const struct wiphy_wowlan_support *wowlan_stub;
        const u8 max_sched_scan_ssids;
+       const u16 max_scan_ie_len;
 
        /* coex paras */
        u32 coex_para_ver;
@@ -1853,6 +1850,7 @@ struct rtw_fw_state {
        u8 sub_index;
        u16 h2c_version;
        u32 feature;
+       u32 feature_ext;
 };
 
 enum rtw_sar_sources {
@@ -1896,6 +1894,7 @@ struct rtw_hal {
        u8 current_primary_channel_index;
        u8 current_band_width;
        u8 current_band_type;
+       u8 primary_channel;
 
        /* center channel for different available bandwidth,
         * val of (bw > current_band_width) is invalid
@@ -1967,6 +1966,7 @@ struct rtw_hw_scan_info {
        struct ieee80211_vif *scanning_vif;
        u8 probe_pg_size;
        u8 op_pri_ch_idx;
+       u8 op_pri_ch;
        u8 op_chan;
        u8 op_bw;
 };
@@ -1978,7 +1978,7 @@ struct rtw_dev {
        struct rtw_hci hci;
 
        struct rtw_hw_scan_info scan_info;
-       struct rtw_chip_info *chip;
+       const struct rtw_chip_info *chip;
        struct rtw_hal hal;
        struct rtw_fifo_conf fifo;
        struct rtw_fw_state fw;
@@ -2132,6 +2132,20 @@ static inline int rtw_chip_dump_fw_crash(struct rtw_dev *rtwdev)
        return 0;
 }
 
+static inline
+enum nl80211_band rtw_hw_to_nl80211_band(enum rtw_supported_band hw_band)
+{
+       switch (hw_band) {
+       default:
+       case RTW_BAND_2G:
+               return NL80211_BAND_2GHZ;
+       case RTW_BAND_5G:
+               return NL80211_BAND_5GHZ;
+       case RTW_BAND_60G:
+               return NL80211_BAND_60GHZ;
+       }
+}
+
 void rtw_set_rx_freq_band(struct rtw_rx_pkt_stat *pkt_stat, u8 channel);
 void rtw_set_dtim_period(struct rtw_dev *rtwdev, int dtim_period);
 void rtw_get_channel_params(struct cfg80211_chan_def *chandef,
@@ -2173,4 +2187,7 @@ int rtw_dump_fw(struct rtw_dev *rtwdev, const u32 ocp_src, u32 size,
                u32 fwcd_item);
 int rtw_dump_reg(struct rtw_dev *rtwdev, const u32 addr, const u32 size);
 void rtw_set_txrx_1ss(struct rtw_dev *rtwdev, bool config_1ss);
+void rtw_update_channel(struct rtw_dev *rtwdev, u8 center_channel,
+                       u8 primary_channel, enum rtw_supported_band band,
+                       enum rtw_bandwidth bandwidth);
 #endif
index 24d5695..7abb1e2 100644 (file)
@@ -322,7 +322,7 @@ static int rtw_pci_init_trx_ring(struct rtw_dev *rtwdev)
        struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
        struct rtw_pci_tx_ring *tx_ring;
        struct rtw_pci_rx_ring *rx_ring;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        int i = 0, j = 0, tx_alloced = 0, rx_alloced = 0;
        int tx_desc_size, rx_desc_size;
        u32 len;
@@ -721,7 +721,7 @@ static void rtw_pci_dma_check(struct rtw_dev *rtwdev,
                              u32 idx)
 {
        struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_pci_rx_buffer_desc *buf_desc;
        u32 desc_sz = chip->rx_buf_desc_sz;
        u16 total_pkt_size;
@@ -834,7 +834,7 @@ static int rtw_pci_tx_write_data(struct rtw_dev *rtwdev,
                                 struct sk_buff *skb, u8 queue)
 {
        struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_pci_tx_ring *ring;
        struct rtw_pci_tx_data *tx_data;
        dma_addr_t dma;
@@ -1073,7 +1073,7 @@ static int rtw_pci_get_hw_rx_ring_nr(struct rtw_dev *rtwdev,
 static u32 rtw_pci_rx_napi(struct rtw_dev *rtwdev, struct rtw_pci *rtwpci,
                           u8 hw_queue, u32 limit)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct napi_struct *napi = &rtwpci->napi;
        struct rtw_pci_rx_ring *ring = &rtwpci->rx_rings[RTW_RX_QUEUE_MPDU];
        struct rtw_rx_pkt_stat pkt_stat;
@@ -1425,7 +1425,7 @@ static void rtw_pci_link_ps(struct rtw_dev *rtwdev, bool enter)
 
 static void rtw_pci_link_cfg(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
        struct pci_dev *pdev = rtwpci->pdev;
        u16 link_ctrl;
@@ -1467,7 +1467,7 @@ static void rtw_pci_link_cfg(struct rtw_dev *rtwdev)
 
 static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        switch (chip->id) {
        case RTW_CHIP_TYPE_8822C:
@@ -1483,7 +1483,7 @@ static void rtw_pci_interface_cfg(struct rtw_dev *rtwdev)
 static void rtw_pci_phy_cfg(struct rtw_dev *rtwdev)
 {
        struct rtw_pci *rtwpci = (struct rtw_pci *)rtwdev->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct pci_dev *pdev = rtwpci->pdev;
        const struct rtw_intf_phy_para *para;
        u16 cut;
@@ -1538,7 +1538,7 @@ static int __maybe_unused rtw_pci_suspend(struct device *dev)
 {
        struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
 
        if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6)
@@ -1550,7 +1550,7 @@ static int __maybe_unused rtw_pci_resume(struct device *dev)
 {
        struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct rtw_dev *rtwdev = hw->priv;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
 
        if (chip->id == RTW_CHIP_TYPE_8822C && efuse->rfe_option == 6)
@@ -1848,7 +1848,7 @@ void rtw_pci_shutdown(struct pci_dev *pdev)
 {
        struct ieee80211_hw *hw = pci_get_drvdata(pdev);
        struct rtw_dev *rtwdev;
-       struct rtw_chip_info *chip;
+       const struct rtw_chip_info *chip;
 
        if (!hw)
                return;
index 8982e0c..bd7d05e 100644 (file)
@@ -138,7 +138,7 @@ EXPORT_SYMBOL(rtw_phy_set_edcca_th);
 
 void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_dm_info *dm_info = &rtwdev->dm_info;
 
        /* turn off in debugfs for debug usage */
@@ -165,7 +165,7 @@ void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev)
 
 static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        rtw_phy_adaptivity_set_mode(rtwdev);
        if (chip->ops->adaptivity_init)
@@ -180,7 +180,7 @@ static void rtw_phy_adaptivity(struct rtw_dev *rtwdev)
 
 static void rtw_phy_cfo_init(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (chip->ops->cfo_init)
                chip->ops->cfo_init(rtwdev);
@@ -199,7 +199,7 @@ static void rtw_phy_tx_path_div_init(struct rtw_dev *rtwdev)
 
 void rtw_phy_init(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_dm_info *dm_info = &rtwdev->dm_info;
        u32 addr, mask;
 
@@ -226,7 +226,7 @@ EXPORT_SYMBOL(rtw_phy_init);
 
 void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_hal *hal = &rtwdev->hal;
        u32 addr, mask;
        u8 path;
@@ -245,7 +245,7 @@ void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi)
 
 static void rtw_phy_stat_false_alarm(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        chip->ops->false_alarm_statistics(rtwdev);
 }
@@ -603,7 +603,7 @@ static void rtw_phy_rrsr_update(struct rtw_dev *rtwdev)
 
 static void rtw_phy_dpk_track(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (chip->ops->dpk_track)
                chip->ops->dpk_track(rtwdev);
@@ -659,7 +659,7 @@ EXPORT_SYMBOL(rtw_phy_parsing_cfo);
 
 static void rtw_phy_cfo_track(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (chip->ops->cfo_track)
                chip->ops->cfo_track(rtwdev);
@@ -720,8 +720,8 @@ static u8 rtw_phy_cck_pd_lv(struct rtw_dev *rtwdev)
 
 static void rtw_phy_cck_pd(struct rtw_dev *rtwdev)
 {
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_dm_info *dm_info = &rtwdev->dm_info;
-       struct rtw_chip_info *chip = rtwdev->chip;
        u32 cck_fa = dm_info->cck_fa_cnt;
        u8 level;
 
@@ -816,23 +816,18 @@ static u8 rtw_phy_linear_2_db(u64 linear)
        u8 j;
        u32 dB;
 
-       if (linear >= db_invert_table[11][7])
-               return 96; /* maximum 96 dB */
-
        for (i = 0; i < 12; i++) {
-               if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][7])
-                       break;
-               else if (i > 2 && linear <= db_invert_table[i][7])
-                       break;
+               for (j = 0; j < 8; j++) {
+                       if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j])
+                               goto cnt;
+                       else if (i > 2 && linear <= db_invert_table[i][j])
+                               goto cnt;
+               }
        }
 
-       for (j = 0; j < 8; j++) {
-               if (i <= 2 && (linear << FRAC_BITS) <= db_invert_table[i][j])
-                       break;
-               else if (i > 2 && linear <= db_invert_table[i][j])
-                       break;
-       }
+       return 96; /* maximum 96 dB */
 
+cnt:
        if (j == 0 && i == 0)
                goto end;
 
@@ -900,7 +895,7 @@ u32 rtw_phy_read_rf(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
                    u32 addr, u32 mask)
 {
        struct rtw_hal *hal = &rtwdev->hal;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const u32 *base_addr = chip->rf_base_addr;
        u32 val, direct_addr;
 
@@ -923,7 +918,7 @@ u32 rtw_phy_read_rf_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
                         u32 addr, u32 mask)
 {
        struct rtw_hal *hal = &rtwdev->hal;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_rf_sipi_addr *rf_sipi_addr;
        const struct rtw_rf_sipi_addr *rf_sipi_addr_a;
        u32 val32;
@@ -972,8 +967,8 @@ bool rtw_phy_write_rf_reg_sipi(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
                               u32 addr, u32 mask, u32 data)
 {
        struct rtw_hal *hal = &rtwdev->hal;
-       struct rtw_chip_info *chip = rtwdev->chip;
-       u32 *sipi_addr = chip->rf_sipi_addr;
+       const struct rtw_chip_info *chip = rtwdev->chip;
+       const u32 *sipi_addr = chip->rf_sipi_addr;
        u32 data_and_addr;
        u32 old_data = 0;
        u32 shift;
@@ -1012,7 +1007,7 @@ bool rtw_phy_write_rf_reg(struct rtw_dev *rtwdev, enum rtw_rf_path rf_path,
                          u32 addr, u32 mask, u32 data)
 {
        struct rtw_hal *hal = &rtwdev->hal;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const u32 *base_addr = chip->rf_base_addr;
        u32 direct_addr;
 
@@ -1747,7 +1742,7 @@ EXPORT_SYMBOL(rtw_phy_cfg_rf);
 
 static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_dpk_info *dpk_info = &rtwdev->dm_info.dpk_info;
 
        if (!chip->rfk_init_tbl)
@@ -1766,7 +1761,7 @@ static void rtw_load_rfk_table(struct rtw_dev *rtwdev)
 
 void rtw_phy_load_tables(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u8 rf_path;
 
        rtw_load_table(rtwdev, chip->mac_tbl);
@@ -1875,7 +1870,7 @@ static u8 rtw_get_channel_group(u8 channel, u8 rate)
 
 static s8 rtw_phy_get_dis_dpd_by_rate_diff(struct rtw_dev *rtwdev, u16 rate)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        s8 dpd_diff = 0;
 
        if (!chip->en_dis_dpd)
@@ -1909,7 +1904,7 @@ static u8 rtw_phy_get_2g_tx_power_index(struct rtw_dev *rtwdev,
                                        enum rtw_bandwidth bandwidth,
                                        u8 rate, u8 group)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u8 tx_power;
        bool mcs_rate;
        bool above_2ss;
@@ -1956,7 +1951,7 @@ static u8 rtw_phy_get_5g_tx_power_index(struct rtw_dev *rtwdev,
                                        enum rtw_bandwidth bandwidth,
                                        u8 rate, u8 group)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        u8 tx_power;
        u8 upper, lower;
        bool mcs_rate;
@@ -2209,7 +2204,7 @@ static void rtw_phy_set_tx_power_level_by_path(struct rtw_dev *rtwdev,
 
 void rtw_phy_set_tx_power_level(struct rtw_dev *rtwdev, u8 channel)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_hal *hal = &rtwdev->hal;
        u8 path;
 
@@ -2484,7 +2479,7 @@ static void rtw_phy_set_tx_path_by_reg(struct rtw_dev *rtwdev,
 {
        struct rtw_path_div *path_div = &rtwdev->dm_path_div;
        enum rtw_bb_path tx_path_sel_cck = tx_path_sel_1ss;
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (tx_path_sel_1ss == path_div->current_tx_path)
                return;
@@ -2539,7 +2534,7 @@ static void rtw_phy_tx_path_diversity_2ss(struct rtw_dev *rtwdev)
 
 void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
 
        if (!chip->path_div_supported)
                return;
index b6c5ae6..ccfcbd3 100644 (file)
@@ -114,7 +114,7 @@ const struct rtw_table name ## _tbl = {                     \
 
 static inline const struct rtw_rfe_def *rtw_get_rfe_def(struct rtw_dev *rtwdev)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct rtw_efuse *efuse = &rtwdev->efuse;
        const struct rtw_rfe_def *rfe_def = NULL;
 
index bfa64c0..c93da74 100644 (file)
@@ -19,14 +19,14 @@ static int rtw_ips_pwr_up(struct rtw_dev *rtwdev)
                rtw_err(rtwdev, "leave idle state failed\n");
 
        rtw_set_channel(rtwdev);
-       clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
 
        return ret;
 }
 
 int rtw_enter_ips(struct rtw_dev *rtwdev)
 {
-       set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags);
+       if (test_and_set_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags))
+               return 0;
 
        rtw_coex_ips_notify(rtwdev, COEX_IPS_ENTER);
 
@@ -50,6 +50,9 @@ int rtw_leave_ips(struct rtw_dev *rtwdev)
 {
        int ret;
 
+       if (!test_and_clear_bit(RTW_FLAG_INACTIVE_PS, rtwdev->flags))
+               return 0;
+
        rtw_hci_link_ps(rtwdev, false);
 
        ret = rtw_ips_pwr_up(rtwdev);
index 315c2b1..2f547cb 100644 (file)
@@ -479,6 +479,7 @@ void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
        rtw_dbg(rtwdev, RTW_DBG_REGD, "regd state: %d -> %d\n",
                rtwdev->regd.state, next_regd.state);
 
+       mutex_lock(&rtwdev->mutex);
        rtwdev->regd = next_regd;
        rtw_dbg_regd_dump(rtwdev, "get alpha2 %c%c from initiator %d: ",
                          request->alpha2[0],
@@ -487,6 +488,7 @@ void rtw_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 
        rtw_phy_adaptivity_set_mode(rtwdev);
        rtw_phy_set_tx_power_level(rtwdev, hal->current_channel);
+       mutex_unlock(&rtwdev->mutex);
 }
 
 u8 rtw_regd_get(struct rtw_dev *rtwdev)
index 993bd6b..0a4f770 100644 (file)
@@ -2720,7 +2720,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
        .max_power_index = 0x3f,
        .csi_buf_pg_num = 0,
        .band = RTW_BAND_2G,
-       .page_size = 128,
+       .page_size = TX_PAGE_SIZE,
        .dig_min = 0x20,
        .ht_supported = true,
        .vht_supported = false,
@@ -2748,6 +2748,7 @@ const struct rtw_chip_info rtw8723d_hw_spec = {
        .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl,
        .iqk_threshold = 8,
        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16,
+       .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
 
        .coex_para_ver = 0x2007022f,
        .bt_desired_ver = 0x2f,
index 025262a..9afdc5c 100644 (file)
@@ -1898,7 +1898,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
        .max_power_index = 0x3f,
        .csi_buf_pg_num = 0,
        .band = RTW_BAND_2G | RTW_BAND_5G,
-       .page_size = 128,
+       .page_size = TX_PAGE_SIZE,
        .dig_min = 0x1c,
        .ht_supported = true,
        .vht_supported = true,
@@ -1926,6 +1926,7 @@ const struct rtw_chip_info rtw8821c_hw_spec = {
        .bfer_su_max_num = 2,
        .bfer_mu_max_num = 1,
        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_2,
+       .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
 
        .coex_para_ver = 0x19092746,
        .bt_desired_ver = 0x46,
index 3218488..690e35c 100644 (file)
@@ -2517,7 +2517,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
        .max_power_index = 0x3f,
        .csi_buf_pg_num = 0,
        .band = RTW_BAND_2G | RTW_BAND_5G,
-       .page_size = 128,
+       .page_size = TX_PAGE_SIZE,
        .dig_min = 0x1c,
        .ht_supported = true,
        .vht_supported = true,
@@ -2549,6 +2549,7 @@ const struct rtw_chip_info rtw8822b_hw_spec = {
        .l2h_th_ini_cs = 10 + EDCCA_IGI_BASE,
        .l2h_th_ini_ad = -14 + EDCCA_IGI_BASE,
        .ampdu_density = IEEE80211_HT_MPDU_DENSITY_2,
+       .max_scan_ie_len = IEEE80211_MAX_DATA_LEN,
 
        .coex_para_ver = 0x20070206,
        .bt_desired_ver = 0x6,
index 09f9e4a..fccb15d 100644 (file)
@@ -5330,7 +5330,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
        .max_power_index = 0x7f,
        .csi_buf_pg_num = 50,
        .band = RTW_BAND_2G | RTW_BAND_5G,
-       .page_size = 128,
+       .page_size = TX_PAGE_SIZE,
        .dig_min = 0x20,
        .default_1ss_tx_path = BB_PATH_A,
        .path_div_supported = true,
@@ -5375,6 +5375,7 @@ const struct rtw_chip_info rtw8822c_hw_spec = {
        .wowlan_stub = &rtw_wowlan_stub_8822c,
        .max_sched_scan_ssids = 4,
 #endif
+       .max_scan_ie_len = (RTW_PROBE_PG_CNT - 1) * TX_PAGE_SIZE,
        .coex_para_ver = 0x22020720,
        .bt_desired_ver = 0x20,
        .scbd_support = true,
index 60d40a5..ab39245 100644 (file)
@@ -384,7 +384,7 @@ void rtw_tx_pkt_info_update(struct rtw_dev *rtwdev,
                            struct ieee80211_sta *sta,
                            struct sk_buff *skb)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        struct rtw_sta_info *si;
@@ -424,7 +424,7 @@ void rtw_tx_rsvd_page_pkt_info_update(struct rtw_dev *rtwdev,
                                      struct sk_buff *skb,
                                      enum rtw_rsvd_packet_type type)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
        bool bmc;
 
@@ -475,7 +475,7 @@ rtw_tx_write_data_rsvd_page_get(struct rtw_dev *rtwdev,
                                struct rtw_tx_pkt_info *pkt_info,
                                u8 *buf, u32 size)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct sk_buff *skb;
        u32 tx_pkt_desc_sz;
        u32 length;
@@ -501,7 +501,7 @@ rtw_tx_write_data_h2c_get(struct rtw_dev *rtwdev,
                          struct rtw_tx_pkt_info *pkt_info,
                          u8 *buf, u32 size)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        struct sk_buff *skb;
        u32 tx_pkt_desc_sz;
        u32 length;
index 2c515af..cdfd66a 100644 (file)
@@ -23,7 +23,7 @@ EXPORT_SYMBOL(check_hw_ready);
 
 bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
 
        if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
@@ -37,7 +37,7 @@ bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val)
 
 bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value)
 {
-       struct rtw_chip_info *chip = rtwdev->chip;
+       const struct rtw_chip_info *chip = rtwdev->chip;
        const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr;
 
        if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1))
index 3006482..a87f2af 100644 (file)
@@ -12,6 +12,7 @@ rtw89_core-y += core.o \
                sar.o \
                coex.o \
                ps.o \
+               chan.o \
                ser.o
 
 obj-$(CONFIG_RTW89_8852A) += rtw89_8852a.o
diff --git a/drivers/net/wireless/realtek/rtw89/chan.c b/drivers/net/wireless/realtek/rtw89/chan.c
new file mode 100644 (file)
index 0000000..a4f61c2
--- /dev/null
@@ -0,0 +1,235 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+/* Copyright(c) 2020-2022  Realtek Corporation
+ */
+
+#include "chan.h"
+#include "debug.h"
+
+static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
+                                                u8 center_chan)
+{
+       switch (band) {
+       default:
+       case RTW89_BAND_2G:
+               switch (center_chan) {
+               default:
+               case 1 ... 14:
+                       return RTW89_CH_2G;
+               }
+       case RTW89_BAND_5G:
+               switch (center_chan) {
+               default:
+               case 36 ... 64:
+                       return RTW89_CH_5G_BAND_1;
+               case 100 ... 144:
+                       return RTW89_CH_5G_BAND_3;
+               case 149 ... 177:
+                       return RTW89_CH_5G_BAND_4;
+               }
+       case RTW89_BAND_6G:
+               switch (center_chan) {
+               default:
+               case 1 ... 29:
+                       return RTW89_CH_6G_BAND_IDX0;
+               case 33 ... 61:
+                       return RTW89_CH_6G_BAND_IDX1;
+               case 65 ... 93:
+                       return RTW89_CH_6G_BAND_IDX2;
+               case 97 ... 125:
+                       return RTW89_CH_6G_BAND_IDX3;
+               case 129 ... 157:
+                       return RTW89_CH_6G_BAND_IDX4;
+               case 161 ... 189:
+                       return RTW89_CH_6G_BAND_IDX5;
+               case 193 ... 221:
+                       return RTW89_CH_6G_BAND_IDX6;
+               case 225 ... 253:
+                       return RTW89_CH_6G_BAND_IDX7;
+               }
+       }
+}
+
+static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
+                                                      u32 center_freq,
+                                                      u32 primary_freq)
+{
+       u8 primary_chan_idx;
+       u32 offset;
+
+       switch (bw) {
+       default:
+       case RTW89_CHANNEL_WIDTH_20:
+               primary_chan_idx = RTW89_SC_DONT_CARE;
+               break;
+       case RTW89_CHANNEL_WIDTH_40:
+               if (primary_freq > center_freq)
+                       primary_chan_idx = RTW89_SC_20_UPPER;
+               else
+                       primary_chan_idx = RTW89_SC_20_LOWER;
+               break;
+       case RTW89_CHANNEL_WIDTH_80:
+       case RTW89_CHANNEL_WIDTH_160:
+               if (primary_freq > center_freq) {
+                       offset = (primary_freq - center_freq - 10) / 20;
+                       primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
+               } else {
+                       offset = (center_freq - primary_freq - 10) / 20;
+                       primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
+               }
+               break;
+       }
+
+       return primary_chan_idx;
+}
+
+void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
+                      enum rtw89_band band, enum rtw89_bandwidth bandwidth)
+{
+       enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
+       u32 center_freq, primary_freq;
+
+       memset(chan, 0, sizeof(*chan));
+       chan->channel = center_chan;
+       chan->primary_channel = primary_chan;
+       chan->band_type = band;
+       chan->band_width = bandwidth;
+
+       center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
+       primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
+
+       chan->freq = center_freq;
+       chan->subband_type = rtw89_get_subband_type(band, center_chan);
+       chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
+                                                     primary_freq);
+}
+
+bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
+                             enum rtw89_sub_entity_idx idx,
+                             const struct rtw89_chan *new)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       struct rtw89_chan *chan = &hal->chan[idx];
+       struct rtw89_chan_rcd *rcd = &hal->chan_rcd[idx];
+       bool band_changed;
+
+       rcd->prev_primary_channel = chan->primary_channel;
+       rcd->prev_band_type = chan->band_type;
+       band_changed = new->band_type != chan->band_type;
+
+       *chan = *new;
+       return band_changed;
+}
+
+static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
+                                         enum rtw89_sub_entity_idx idx,
+                                         const struct cfg80211_chan_def *chandef,
+                                         bool from_stack)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       hal->chandef[idx] = *chandef;
+
+       if (from_stack)
+               set_bit(idx, hal->entity_map);
+}
+
+void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
+                                enum rtw89_sub_entity_idx idx,
+                                const struct cfg80211_chan_def *chandef)
+{
+       __rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
+}
+
+static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
+{
+       struct cfg80211_chan_def chandef = {0};
+
+       rtw89_get_default_chandef(&chandef);
+       __rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &chandef, false);
+}
+
+void rtw89_entity_init(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
+       rtw89_config_default_chandef(rtwdev);
+}
+
+enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       enum rtw89_entity_mode mode;
+       u8 weight;
+
+       weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
+       switch (weight) {
+       default:
+               rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
+               bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
+               fallthrough;
+       case 0:
+               rtw89_config_default_chandef(rtwdev);
+               fallthrough;
+       case 1:
+               mode = RTW89_ENTITY_MODE_SCC;
+               break;
+       }
+
+       rtw89_set_entity_mode(rtwdev, mode);
+       return mode;
+}
+
+int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
+                         struct ieee80211_chanctx_conf *ctx)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       u8 idx;
+
+       idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
+       if (idx >= chip->support_chanctx_num)
+               return -ENOENT;
+
+       rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
+       rtw89_set_channel(rtwdev);
+       cfg->idx = idx;
+       return 0;
+}
+
+void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
+                             struct ieee80211_chanctx_conf *ctx)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+
+       clear_bit(cfg->idx, hal->entity_map);
+       rtw89_set_channel(rtwdev);
+}
+
+void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
+                             struct ieee80211_chanctx_conf *ctx,
+                             u32 changed)
+{
+       struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
+       u8 idx = cfg->idx;
+
+       if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
+               rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
+               rtw89_set_channel(rtwdev);
+       }
+}
+
+int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
+                                struct rtw89_vif *rtwvif,
+                                struct ieee80211_chanctx_conf *ctx)
+{
+       return 0;
+}
+
+void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
+                                   struct rtw89_vif *rtwvif,
+                                   struct ieee80211_chanctx_conf *ctx)
+{
+}
diff --git a/drivers/net/wireless/realtek/rtw89/chan.h b/drivers/net/wireless/realtek/rtw89/chan.h
new file mode 100644 (file)
index 0000000..ecbd450
--- /dev/null
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+ * Copyright(c) 2020-2022  Realtek Corporation
+ */
+
+#ifndef __RTW89_CHAN_H__
+#define __RTW89_CHAN_H__
+
+#include "core.h"
+
+static inline bool rtw89_get_entity_state(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       return READ_ONCE(hal->entity_active);
+}
+
+static inline void rtw89_set_entity_state(struct rtw89_dev *rtwdev, bool active)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       WRITE_ONCE(hal->entity_active, active);
+}
+
+static inline
+enum rtw89_entity_mode rtw89_get_entity_mode(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       return READ_ONCE(hal->entity_mode);
+}
+
+static inline void rtw89_set_entity_mode(struct rtw89_dev *rtwdev,
+                                        enum rtw89_entity_mode mode)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       WRITE_ONCE(hal->entity_mode, mode);
+}
+
+void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
+                      enum rtw89_band band, enum rtw89_bandwidth bandwidth);
+bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
+                             enum rtw89_sub_entity_idx idx,
+                             const struct rtw89_chan *new);
+void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
+                                enum rtw89_sub_entity_idx idx,
+                                const struct cfg80211_chan_def *chandef);
+void rtw89_entity_init(struct rtw89_dev *rtwdev);
+enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev);
+int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
+                         struct ieee80211_chanctx_conf *ctx);
+void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
+                             struct ieee80211_chanctx_conf *ctx);
+void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
+                             struct ieee80211_chanctx_conf *ctx,
+                             u32 changed);
+int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
+                                struct rtw89_vif *rtwvif,
+                                struct ieee80211_chanctx_conf *ctx);
+void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
+                                   struct rtw89_vif *rtwvif,
+                                   struct ieee80211_chanctx_conf *ctx);
+
+#endif
index 683854b..732502b 100644 (file)
@@ -261,6 +261,9 @@ enum btc_cx_poicy_type {
        /* TDMA off + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo */
        BTC_CXP_OFF_BWB1 = (BTC_CXP_OFF << 8) | 7,
 
+       /* TDMA off + pri: WL_Hi-Tx > BT, BT_Hi > other-WL > BT_Lo */
+       BTC_CXP_OFF_BWB2 = (BTC_CXP_OFF << 8) | 8,
+
        /* TDMA off+Bcn-Protect + pri: WL_Hi-Tx > BT_Hi_Rx, BT_Hi > WL > BT_Lo*/
        BTC_CXP_OFFB_BWB0 = (BTC_CXP_OFFB << 8) | 0,
 
@@ -270,6 +273,21 @@ enum btc_cx_poicy_type {
        /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
        BTC_CXP_OFFE_DEF2 = (BTC_CXP_OFFE << 8) | 1,
 
+       /* TDMA off + Ext-Ctrl + pri: default */
+       BTC_CXP_OFFE_2GBWISOB = (BTC_CXP_OFFE << 8) | 2,
+
+       /* TDMA off + Ext-Ctrl + pri: E2G-slot block all BT */
+       BTC_CXP_OFFE_2GISOB = (BTC_CXP_OFFE << 8) | 3,
+
+       /* TDMA off + Ext-Ctrl + pri: E2G-slot WL > BT */
+       BTC_CXP_OFFE_2GBWMIXB = (BTC_CXP_OFFE << 8) | 4,
+
+       /* TDMA off + Ext-Ctrl + pri: E2G/EBT-slot WL > BT */
+       BTC_CXP_OFFE_WL = (BTC_CXP_OFFE << 8) | 5,
+
+       /* TDMA off + Ext-Ctrl + pri: default */
+       BTC_CXP_OFFE_2GBWMIXB2 = (BTC_CXP_OFFE << 8) | 6,
+
        /* TDMA Fix slot-0: W1:B1 = 30:30 */
        BTC_CXP_FIX_TD3030 = (BTC_CXP_FIX << 8) | 0,
 
@@ -300,6 +318,9 @@ enum btc_cx_poicy_type {
        /* TDMA Fix slot-9: W1:B1 = 40:20 */
        BTC_CXP_FIX_TD4020 = (BTC_CXP_FIX << 8) | 9,
 
+       /* TDMA Fix slot-9: W1:B1 = 40:10 */
+       BTC_CXP_FIX_TD4010ISO = (BTC_CXP_FIX << 8) | 10,
+
        /* PS-TDMA Fix slot-0: W1:B1 = 30:30 */
        BTC_CXP_PFIX_TD3030 = (BTC_CXP_PFIX << 8) | 0,
 
@@ -322,25 +343,25 @@ enum btc_cx_poicy_type {
        BTC_CXP_PFIX_TDW1B1 = (BTC_CXP_PFIX << 8) | 6,
 
        /* TDMA Auto slot-0: W1:B1 = 50:200 */
-       BTC_CXP_AUTO_TD50200 = (BTC_CXP_AUTO << 8) | 0,
+       BTC_CXP_AUTO_TD50B1 = (BTC_CXP_AUTO << 8) | 0,
 
        /* TDMA Auto slot-1: W1:B1 = 60:200 */
-       BTC_CXP_AUTO_TD60200 = (BTC_CXP_AUTO << 8) | 1,
+       BTC_CXP_AUTO_TD60B1 = (BTC_CXP_AUTO << 8) | 1,
 
        /* TDMA Auto slot-2: W1:B1 = 20:200 */
-       BTC_CXP_AUTO_TD20200 = (BTC_CXP_AUTO << 8) | 2,
+       BTC_CXP_AUTO_TD20B1 = (BTC_CXP_AUTO << 8) | 2,
 
        /* TDMA Auto slot-3: W1:B1 = user-define */
        BTC_CXP_AUTO_TDW1B1 = (BTC_CXP_AUTO << 8) | 3,
 
        /* PS-TDMA Auto slot-0: W1:B1 = 50:200 */
-       BTC_CXP_PAUTO_TD50200 = (BTC_CXP_PAUTO << 8) | 0,
+       BTC_CXP_PAUTO_TD50B1 = (BTC_CXP_PAUTO << 8) | 0,
 
        /* PS-TDMA Auto slot-1: W1:B1 = 60:200 */
-       BTC_CXP_PAUTO_TD60200 = (BTC_CXP_PAUTO << 8) | 1,
+       BTC_CXP_PAUTO_TD60B1 = (BTC_CXP_PAUTO << 8) | 1,
 
        /* PS-TDMA Auto slot-2: W1:B1 = 20:200 */
-       BTC_CXP_PAUTO_TD20200 = (BTC_CXP_PAUTO << 8) | 2,
+       BTC_CXP_PAUTO_TD20B1 = (BTC_CXP_PAUTO << 8) | 2,
 
        /* PS-TDMA Auto slot-3: W1:B1 = user-define */
        BTC_CXP_PAUTO_TDW1B1 = (BTC_CXP_PAUTO << 8) | 3,
@@ -434,6 +455,16 @@ enum btc_wl_link_mode {
        BTC_WLINK_MAX
 };
 
+enum btc_wl_mrole_type {
+       BTC_WLMROLE_NONE = 0x0,
+       BTC_WLMROLE_STA_GC,
+       BTC_WLMROLE_STA_GC_NOA,
+       BTC_WLMROLE_STA_GO,
+       BTC_WLMROLE_STA_GO_NOA,
+       BTC_WLMROLE_STA_STA,
+       BTC_WLMROLE_MAX
+};
+
 enum btc_bt_hid_type {
        BTC_HID_218 = BIT(0),
        BTC_HID_418 = BIT(1),
@@ -531,6 +562,7 @@ enum btc_reason_and_action {
 #define BTC_FREERUN_ANTISO_MIN 30
 #define BTC_TDMA_BTHID_MAX 2
 #define BTC_BLINK_NOCONNECT 0
+#define BTC_B1_MAX 250 /* unit ms */
 
 static void _run_coex(struct rtw89_dev *rtwdev,
                      enum btc_reason_and_action reason);
@@ -551,8 +583,10 @@ static void _send_fw_cmd(struct rtw89_dev *rtwdev, u8 h2c_class, u8 h2c_func,
                            "[BTC], %s(): return by btc not init!!\n", __func__);
                pfwinfo->cnt_h2c_fail++;
                return;
-       } else if ((wl->status.map.rf_off_pre == 1 && wl->status.map.rf_off == 1) ||
-                  (wl->status.map.lps_pre == 1 && wl->status.map.lps == 1)) {
+       } else if ((wl->status.map.rf_off_pre == BTC_LPS_RF_OFF &&
+                   wl->status.map.rf_off == BTC_LPS_RF_OFF) ||
+                  (wl->status.map.lps_pre == BTC_LPS_RF_OFF &&
+                   wl->status.map.lps == BTC_LPS_RF_OFF)) {
                rtw89_debug(rtwdev, RTW89_DBG_BTC,
                            "[BTC], %s(): return by wl off!!\n", __func__);
                pfwinfo->cnt_h2c_fail++;
@@ -869,18 +903,23 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                           struct rtw89_btc_btf_fwinfo *pfwinfo,
                           u8 *prptbuf, u32 index)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
        struct rtw89_btc_rpt_cmn_info *pcinfo = NULL;
        struct rtw89_btc_wl_info *wl = &btc->cx.wl;
-       struct rtw89_btc_fbtc_rpt_ctrl *prpt = NULL;
+       struct rtw89_btc_bt_info *bt = &btc->cx.bt;
+       struct rtw89_btc_fbtc_rpt_ctrl *prpt;
+       struct rtw89_btc_fbtc_rpt_ctrl_v1 *prpt_v1;
        struct rtw89_btc_fbtc_cysta *pcysta_le32 = NULL;
+       struct rtw89_btc_fbtc_cysta_v1 *pcysta_v1 = NULL;
        struct rtw89_btc_fbtc_cysta_cpu pcysta[1];
        struct rtw89_btc_prpt *btc_prpt = NULL;
        struct rtw89_btc_fbtc_slot *rtp_slot = NULL;
        u8 rpt_type = 0, *rpt_content = NULL, *pfinfo = NULL;
-       u16 wl_slot_set = 0;
+       u16 wl_slot_set = 0, wl_slot_real = 0;
        u32 trace_step = btc->ctrl.trace_step, rpt_len = 0, diff_t;
+       u32 cnt_leak_slot = 0, bt_slot_real = 0, cnt_rx_imr = 0;
        u8 i;
 
        rtw89_debug(rtwdev, RTW89_DBG_BTC,
@@ -904,17 +943,27 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
        switch (rpt_type) {
        case BTC_RPT_TYPE_CTRL:
                pcinfo = &pfwinfo->rpt_ctrl.cinfo;
-               pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
-               pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
-               pcinfo->req_fver = BTCRPT_VER;
+               if (chip->chip_id == RTL8852A) {
+                       pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo);
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo);
+               } else {
+                       pfinfo = (u8 *)(&pfwinfo->rpt_ctrl.finfo_v1);
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_ctrl.finfo_v1);
+               }
+               pcinfo->req_fver = chip->fcxbtcrpt_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
        case BTC_RPT_TYPE_TDMA:
                pcinfo = &pfwinfo->rpt_fbtc_tdma.cinfo;
-               pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_tdma.finfo);
-               pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
-               pcinfo->req_fver = FCXTDMA_VER;
+               if (chip->chip_id == RTL8852A) {
+                       pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo;
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo);
+               } else {
+                       pfinfo = (u8 *)&pfwinfo->rpt_fbtc_tdma.finfo_v1;
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_tdma.finfo_v1);
+               }
+               pcinfo->req_fver = chip->fcxtdma_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -922,17 +971,23 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_slots.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_slots.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_slots.finfo);
-               pcinfo->req_fver = FCXSLOTS_VER;
+               pcinfo->req_fver = chip->fcxslots_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
        case BTC_RPT_TYPE_CYSTA:
                pcinfo = &pfwinfo->rpt_fbtc_cysta.cinfo;
-               pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
-               pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
-               rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
-               pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
-               pcinfo->req_fver = FCXCYSTA_VER;
+               if (chip->chip_id == RTL8852A) {
+                       pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo);
+                       pcysta_le32 = &pfwinfo->rpt_fbtc_cysta.finfo;
+                       rtw89_btc_fbtc_cysta_to_cpu(pcysta_le32, pcysta);
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo);
+               } else {
+                       pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_cysta.finfo_v1);
+                       pcysta_v1 = &pfwinfo->rpt_fbtc_cysta.finfo_v1;
+                       pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_cysta.finfo_v1);
+               }
+               pcinfo->req_fver = chip->fcxcysta_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -941,7 +996,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_step.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_step.finfo.step[0]) *
                                  trace_step + 8;
-               pcinfo->req_fver = FCXSTEP_VER;
+               pcinfo->req_fver = chip->fcxstep_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -949,7 +1004,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_nullsta.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_nullsta.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_nullsta.finfo);
-               pcinfo->req_fver = FCXNULLSTA_VER;
+               pcinfo->req_fver = chip->fcxnullsta_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -957,7 +1012,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_mregval.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_mregval.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_mregval.finfo);
-               pcinfo->req_fver = FCXMREG_VER;
+               pcinfo->req_fver = chip->fcxmreg_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -965,7 +1020,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_gpio_dbg.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_gpio_dbg.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_gpio_dbg.finfo);
-               pcinfo->req_fver = FCXGPIODBG_VER;
+               pcinfo->req_fver = chip->fcxgpiodbg_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -973,7 +1028,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_btver.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btver.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btver.finfo);
-               pcinfo->req_fver = FCX_BTVER_VER;
+               pcinfo->req_fver = chip->fcxbtver_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -981,7 +1036,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_btscan.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btscan.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btscan.finfo);
-               pcinfo->req_fver = FCX_BTSCAN_VER;
+               pcinfo->req_fver = chip->fcxbtscan_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -989,7 +1044,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_btafh.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btafh.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btafh.finfo);
-               pcinfo->req_fver = FCX_BTAFH_VER;
+               pcinfo->req_fver = chip->fcxbtafh_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -997,7 +1052,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                pcinfo = &pfwinfo->rpt_fbtc_btdev.cinfo;
                pfinfo = (u8 *)(&pfwinfo->rpt_fbtc_btdev.finfo);
                pcinfo->req_len = sizeof(pfwinfo->rpt_fbtc_btdev.finfo);
-               pcinfo->req_fver = FCX_BTDEVINFO_VER;
+               pcinfo->req_fver = chip->fcxbtdevinfo_ver;
                pcinfo->rx_len = rpt_len;
                pcinfo->rx_cnt++;
                break;
@@ -1026,7 +1081,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
        memcpy(pfinfo, rpt_content, pcinfo->req_len);
        pcinfo->valid = 1;
 
-       if (rpt_type == BTC_RPT_TYPE_TDMA) {
+       if (rpt_type == BTC_RPT_TYPE_TDMA && chip->chip_id == RTL8852A) {
                rtw89_debug(rtwdev, RTW89_DBG_BTC,
                            "[BTC], %s(): check %d %zu\n", __func__,
                            BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
@@ -1039,7 +1094,8 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                                    dm->tdma_now.type, dm->tdma_now.rxflctrl,
                                    dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
                                    dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
-                                   dm->tdma_now.rsvd0, dm->tdma_now.rsvd1);
+                                   dm->tdma_now.rxflctrl_role,
+                                   dm->tdma_now.option_ctrl);
 
                        rtw89_debug(rtwdev, RTW89_DBG_BTC,
                                    "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
@@ -1050,14 +1106,46 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                                    pfwinfo->rpt_fbtc_tdma.finfo.wtgle_n,
                                    pfwinfo->rpt_fbtc_tdma.finfo.leak_n,
                                    pfwinfo->rpt_fbtc_tdma.finfo.ext_ctrl,
-                                   pfwinfo->rpt_fbtc_tdma.finfo.rsvd0,
-                                   pfwinfo->rpt_fbtc_tdma.finfo.rsvd1);
+                                   pfwinfo->rpt_fbtc_tdma.finfo.rxflctrl_role,
+                                   pfwinfo->rpt_fbtc_tdma.finfo.option_ctrl);
                }
 
                _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
                             memcmp(&dm->tdma_now,
                                    &pfwinfo->rpt_fbtc_tdma.finfo,
                                    sizeof(dm->tdma_now)));
+       } else if (rpt_type == BTC_RPT_TYPE_TDMA) {
+               rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                           "[BTC], %s(): check %d %zu\n", __func__,
+                           BTC_DCNT_TDMA_NONSYNC, sizeof(dm->tdma_now));
+
+               if (memcmp(&dm->tdma_now, &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
+                          sizeof(dm->tdma_now)) != 0) {
+                       rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                                   "[BTC], %s(): %d tdma_now %x %x %x %x %x %x %x %x\n",
+                                   __func__, BTC_DCNT_TDMA_NONSYNC,
+                                   dm->tdma_now.type, dm->tdma_now.rxflctrl,
+                                   dm->tdma_now.txpause, dm->tdma_now.wtgle_n,
+                                   dm->tdma_now.leak_n, dm->tdma_now.ext_ctrl,
+                                   dm->tdma_now.rxflctrl_role,
+                                   dm->tdma_now.option_ctrl);
+                       rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                                   "[BTC], %s(): %d rpt_fbtc_tdma %x %x %x %x %x %x %x %x\n",
+                                   __func__, BTC_DCNT_TDMA_NONSYNC,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.type,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.txpause,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.wtgle_n,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.leak_n,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.ext_ctrl,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.rxflctrl_role,
+                                   pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma.option_ctrl);
+               }
+
+               _chk_btc_err(rtwdev, BTC_DCNT_TDMA_NONSYNC,
+                            memcmp(&dm->tdma_now,
+                                   &pfwinfo->rpt_fbtc_tdma.finfo_v1.tdma,
+                                   sizeof(dm->tdma_now)));
        }
 
        if (rpt_type == BTC_RPT_TYPE_SLOT) {
@@ -1097,7 +1185,7 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                                    sizeof(dm->slot_now)));
        }
 
-       if (rpt_type == BTC_RPT_TYPE_CYSTA &&
+       if (rpt_type == BTC_RPT_TYPE_CYSTA && chip->chip_id == RTL8852A &&
            pcysta->cycles >= BTC_CYSTA_CHK_PERIOD) {
                /* Check Leak-AP */
                if (pcysta->slot_cnt[CXST_LK] != 0 &&
@@ -1120,16 +1208,55 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                }
 
                _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_W1]);
-               _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_W1]);
+               _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE, pcysta->slot_cnt[CXST_B1]);
                _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE, (u32)pcysta->cycles);
+       } else if (rpt_type == BTC_RPT_TYPE_CYSTA && pcysta_v1 &&
+                  le16_to_cpu(pcysta_v1->cycles) >= BTC_CYSTA_CHK_PERIOD) {
+               cnt_leak_slot = le32_to_cpu(pcysta_v1->slot_cnt[CXST_LK]);
+               cnt_rx_imr = le32_to_cpu(pcysta_v1->leak_slot.cnt_rximr);
+               /* Check Leak-AP */
+               if (cnt_leak_slot != 0 && cnt_rx_imr != 0 &&
+                   dm->tdma_now.rxflctrl) {
+                       if (cnt_leak_slot < BTC_LEAK_AP_TH * cnt_rx_imr)
+                               dm->leak_ap = 1;
+               }
+
+               /* Check diff time between real WL slot and W1 slot */
+               if (dm->tdma_now.type == CXTDMA_OFF) {
+                       wl_slot_set = le16_to_cpu(dm->slot_now[CXST_W1].dur);
+                       wl_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_WL]);
+                       if (wl_slot_real > wl_slot_set) {
+                               diff_t = wl_slot_real - wl_slot_set;
+                               _chk_btc_err(rtwdev, BTC_DCNT_WL_SLOT_DRIFT, diff_t);
+                       }
+               }
+
+               /* Check diff time between real BT slot and EBT/E5G slot */
+               if (dm->tdma_now.type == CXTDMA_OFF &&
+                   dm->tdma_now.ext_ctrl == CXECTL_EXT &&
+                   btc->bt_req_len != 0) {
+                       bt_slot_real = le16_to_cpu(pcysta_v1->cycle_time.tavg[CXT_BT]);
+
+                       if (btc->bt_req_len > bt_slot_real) {
+                               diff_t = btc->bt_req_len - bt_slot_real;
+                               _chk_btc_err(rtwdev, BTC_DCNT_BT_SLOT_DRIFT, diff_t);
+                       }
+               }
+
+               _chk_btc_err(rtwdev, BTC_DCNT_W1_FREEZE,
+                            le32_to_cpu(pcysta_v1->slot_cnt[CXST_W1]));
+               _chk_btc_err(rtwdev, BTC_DCNT_B1_FREEZE,
+                            le32_to_cpu(pcysta_v1->slot_cnt[CXST_B1]));
+               _chk_btc_err(rtwdev, BTC_DCNT_CYCLE_FREEZE,
+                            (u32)le16_to_cpu(pcysta_v1->cycles));
        }
 
-       if (rpt_type == BTC_RPT_TYPE_CTRL) {
+       if (rpt_type == BTC_RPT_TYPE_CTRL && chip->chip_id == RTL8852A) {
                prpt = &pfwinfo->rpt_ctrl.finfo;
                btc->fwinfo.rpt_en_map = prpt->rpt_enable;
                wl->ver_info.fw_coex = prpt->wl_fw_coex_ver;
                wl->ver_info.fw = prpt->wl_fw_ver;
-               dm->wl_fw_cx_offload = !!(prpt->wl_fw_cx_offload);
+               dm->wl_fw_cx_offload = !!prpt->wl_fw_cx_offload;
 
                _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
                             pfwinfo->event[BTF_EVNT_RPT]);
@@ -1142,6 +1269,33 @@ static u32 _chk_btc_report(struct rtw89_dev *rtwdev,
                        btc->cx.cnt_bt[BTC_BCNT_POLUT] =
                                rtw89_mac_get_plt_cnt(rtwdev, RTW89_MAC_0);
                }
+       } else if (rpt_type == BTC_RPT_TYPE_CTRL) {
+               prpt_v1 = &pfwinfo->rpt_ctrl.finfo_v1;
+               btc->fwinfo.rpt_en_map = le32_to_cpu(prpt_v1->rpt_info.en);
+               wl->ver_info.fw_coex = le32_to_cpu(prpt_v1->wl_fw_info.cx_ver);
+               wl->ver_info.fw = le32_to_cpu(prpt_v1->wl_fw_info.fw_ver);
+               dm->wl_fw_cx_offload = !!le32_to_cpu(prpt_v1->wl_fw_info.cx_offload);
+
+               for (i = RTW89_PHY_0; i < RTW89_PHY_MAX; i++)
+                       memcpy(&dm->gnt.band[i], &prpt_v1->gnt_val[i],
+                              sizeof(dm->gnt.band[i]));
+
+               btc->cx.cnt_bt[BTC_BCNT_HIPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_TX]);
+               btc->cx.cnt_bt[BTC_BCNT_HIPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_HI_RX]);
+               btc->cx.cnt_bt[BTC_BCNT_LOPRI_TX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_TX]);
+               btc->cx.cnt_bt[BTC_BCNT_LOPRI_RX] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_LO_RX]);
+               btc->cx.cnt_bt[BTC_BCNT_POLUT] = le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_POLLUTED]);
+
+               _chk_btc_err(rtwdev, BTC_DCNT_BTCNT_FREEZE, 0);
+               _chk_btc_err(rtwdev, BTC_DCNT_RPT_FREEZE,
+                            pfwinfo->event[BTF_EVNT_RPT]);
+
+               if (le32_to_cpu(prpt_v1->bt_cnt[BTC_BCNT_RFK_TIMEOUT]) > 0)
+                       bt->rfk_info.map.timeout = 1;
+               else
+                       bt->rfk_info.map.timeout = 0;
+
+               dm->error.map.bt_rfk_timeout = bt->rfk_info.map.timeout;
        }
 
        if (rpt_type >= BTC_RPT_TYPE_BT_VER &&
@@ -1182,10 +1336,12 @@ static void _parse_btc_report(struct rtw89_dev *rtwdev,
 
 static void _append_tdma(struct rtw89_dev *rtwdev)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
-       struct rtw89_btc_btf_tlv *tlv = NULL;
-       struct rtw89_btc_fbtc_tdma *v = NULL;
+       struct rtw89_btc_btf_tlv *tlv;
+       struct rtw89_btc_fbtc_tdma *v;
+       struct rtw89_btc_fbtc_tdma_v1 *v1;
        u16 len = btc->policy_len;
 
        if (!btc->update_policy_force &&
@@ -1197,12 +1353,19 @@ static void _append_tdma(struct rtw89_dev *rtwdev)
        }
 
        tlv = (struct rtw89_btc_btf_tlv *)&btc->policy[len];
-       v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
        tlv->type = CXPOLICY_TDMA;
-       tlv->len = sizeof(*v);
-
-       memcpy(v, &dm->tdma, sizeof(*v));
-       btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
+       if (chip->chip_id == RTL8852A) {
+               v = (struct rtw89_btc_fbtc_tdma *)&tlv->val[0];
+               tlv->len = sizeof(*v);
+               memcpy(v, &dm->tdma, sizeof(*v));
+               btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v);
+       } else {
+               tlv->len = sizeof(*v1);
+               v1 = (struct rtw89_btc_fbtc_tdma_v1 *)&tlv->val[0];
+               v1->fver = chip->fcxtdma_ver;
+               v1->tdma = dm->tdma;
+               btc->policy_len += BTC_TLV_HDR_LEN  + sizeof(*v1);
+       }
 
        rtw89_debug(rtwdev, RTW89_DBG_BTC,
                    "[BTC], %s(): type:%d, rxflctrl=%d, txpause=%d, wtgle_n=%d, leak_n=%d, ext_ctrl=%d\n",
@@ -1408,12 +1571,17 @@ static void _fw_set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
 
 static void _fw_set_drv_info(struct rtw89_dev *rtwdev, u8 type)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
        switch (type) {
        case CXDRVINFO_INIT:
                rtw89_fw_h2c_cxdrv_init(rtwdev);
                break;
        case CXDRVINFO_ROLE:
-               rtw89_fw_h2c_cxdrv_role(rtwdev);
+               if (chip->chip_id == RTL8852A)
+                       rtw89_fw_h2c_cxdrv_role(rtwdev);
+               else
+                       rtw89_fw_h2c_cxdrv_role_v1(rtwdev);
                break;
        case CXDRVINFO_CTRL:
                rtw89_fw_h2c_cxdrv_ctrl(rtwdev);
@@ -1683,28 +1851,45 @@ static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
        struct rtw89_btc_bt_info *bt = &btc->cx.bt;
        struct rtw89_btc_bt_link_info *b = &bt->link_info;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
+       struct rtw89_btc_wl_active_role *r;
+       struct rtw89_btc_wl_active_role_v1 *r1;
        u8 en = 0, i, ch = 0, bw = 0;
+       u8 mode, connect_cnt;
 
        if (btc->ctrl.manual || wl->status.map.scan)
                return;
 
-       /* TODO if include module->ant.type == BTC_ANT_SHARED */
+       if (chip->chip_id == RTL8852A) {
+               mode = wl_rinfo->link_mode;
+               connect_cnt = wl_rinfo->connect_cnt;
+       } else {
+               mode = wl_rinfo_v1->link_mode;
+               connect_cnt = wl_rinfo_v1->connect_cnt;
+       }
+
        if (wl->status.map.rf_off || bt->whql_test ||
-           wl_rinfo->link_mode == BTC_WLINK_NOLINK ||
-           wl_rinfo->link_mode == BTC_WLINK_5G ||
-           wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX) {
+           mode == BTC_WLINK_NOLINK || mode == BTC_WLINK_5G ||
+           connect_cnt > BTC_TDMA_WLROLE_MAX) {
                en = false;
-       } else if (wl_rinfo->link_mode == BTC_WLINK_2G_MCC ||
-                  wl_rinfo->link_mode == BTC_WLINK_2G_SCC) {
+       } else if (mode == BTC_WLINK_2G_MCC || mode == BTC_WLINK_2G_SCC) {
                en = true;
                /* get p2p channel */
                for (i = 0; i < RTW89_PORT_NUM; i++) {
-                       if (wl_rinfo->active_role[i].role ==
-                           RTW89_WIFI_ROLE_P2P_GO ||
-                           wl_rinfo->active_role[i].role ==
-                           RTW89_WIFI_ROLE_P2P_CLIENT) {
-                               ch = wl_rinfo->active_role[i].ch;
-                               bw = wl_rinfo->active_role[i].bw;
+                       r = &wl_rinfo->active_role[i];
+                       r1 = &wl_rinfo_v1->active_role_v1[i];
+
+                       if (chip->chip_id == RTL8852A &&
+                           (r->role == RTW89_WIFI_ROLE_P2P_GO ||
+                            r->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
+                               ch = r->ch;
+                               bw = r->bw;
+                               break;
+                       } else if (chip->chip_id != RTL8852A &&
+                                  (r1->role == RTW89_WIFI_ROLE_P2P_GO ||
+                                   r1->role == RTW89_WIFI_ROLE_P2P_CLIENT)) {
+                               ch = r1->ch;
+                               bw = r1->bw;
                                break;
                        }
                }
@@ -1712,10 +1897,18 @@ static void _set_bt_afh_info(struct rtw89_dev *rtwdev)
                en = true;
                /* get 2g channel  */
                for (i = 0; i < RTW89_PORT_NUM; i++) {
-                       if (wl_rinfo->active_role[i].connected &&
-                           wl_rinfo->active_role[i].band == RTW89_BAND_2G) {
-                               ch = wl_rinfo->active_role[i].ch;
-                               bw = wl_rinfo->active_role[i].bw;
+                       r = &wl_rinfo->active_role[i];
+                       r1 = &wl_rinfo_v1->active_role_v1[i];
+
+                       if (chip->chip_id == RTL8852A &&
+                           r->connected && r->band == RTW89_BAND_2G) {
+                               ch = r->ch;
+                               bw = r->bw;
+                               break;
+                       } else if (chip->chip_id != RTL8852A &&
+                                  r1->connected && r1->band == RTW89_BAND_2G) {
+                               ch = r1->ch;
+                               bw = r1->bw;
                                break;
                        }
                }
@@ -1768,6 +1961,7 @@ static bool _check_freerun(struct rtw89_dev *rtwdev)
        struct rtw89_btc_wl_info *wl = &btc->cx.wl;
        struct rtw89_btc_bt_info *bt = &btc->cx.bt;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
        struct rtw89_btc_bt_link_info *bt_linfo = &bt->link_info;
        struct rtw89_btc_bt_hid_desc *hid = &bt_linfo->hid_desc;
 
@@ -1777,7 +1971,8 @@ static bool _check_freerun(struct rtw89_dev *rtwdev)
        }
 
        /* The below is dedicated antenna case */
-       if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX) {
+       if (wl_rinfo->connect_cnt > BTC_TDMA_WLROLE_MAX ||
+           wl_rinfo_v1->connect_cnt > BTC_TDMA_WLROLE_MAX) {
                btc->dm.trx_para_level = 5;
                return true;
        }
@@ -1826,6 +2021,7 @@ static bool _check_freerun(struct rtw89_dev *rtwdev)
 }
 
 #define _tdma_set_flctrl(btc, flc) ({(btc)->dm.tdma.rxflctrl = flc; })
+#define _tdma_set_flctrl_role(btc, role) ({(btc)->dm.tdma.rxflctrl_role = role; })
 #define _tdma_set_tog(btc, wtg) ({(btc)->dm.tdma.wtgle_n = wtg; })
 #define _tdma_set_lek(btc, lek) ({(btc)->dm.tdma.leak_n = lek; })
 
@@ -1901,38 +2097,363 @@ union btc_btinfo {
        struct btc_btinfo_hb3 hb3;
 };
 
-static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
-                       enum btc_reason_and_action action)
+static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
+                       enum btc_reason_and_action action)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
+       chip->ops->btc_set_policy(rtwdev, policy_type);
+       _fw_set_policy(rtwdev, policy_type, action);
+}
+
+#define BTC_B1_MAX 250 /* unit ms */
+void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type)
+{
+       struct rtw89_btc *btc = &rtwdev->btc;
+       struct rtw89_btc_dm *dm = &btc->dm;
+       struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
+       struct rtw89_btc_fbtc_slot *s = dm->slot;
+       u8 type;
+       u32 tbl_w1, tbl_b1, tbl_b4;
+
+       if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
+               if (btc->cx.wl.status.map._4way)
+                       tbl_w1 = cxtbl[1];
+               else
+                       tbl_w1 = cxtbl[8];
+               tbl_b1 = cxtbl[3];
+               tbl_b4 = cxtbl[3];
+       } else {
+               tbl_w1 = cxtbl[16];
+               tbl_b1 = cxtbl[17];
+               tbl_b4 = cxtbl[17];
+       }
+
+       type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
+       btc->bt_req_en = false;
+
+       switch (type) {
+       case BTC_CXP_USERDEF0:
+               *t = t_def[CXTD_OFF];
+               s[CXST_OFF] = s_def[CXST_OFF];
+               _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
+               btc->update_policy_force = true;
+               break;
+       case BTC_CXP_OFF: /* TDMA off */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
+               *t = t_def[CXTD_OFF];
+               s[CXST_OFF] = s_def[CXST_OFF];
+
+               switch (policy_type) {
+               case BTC_CXP_OFF_BT:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
+                       break;
+               case BTC_CXP_OFF_WL:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[1]);
+                       break;
+               case BTC_CXP_OFF_EQ0:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[0]);
+                       break;
+               case BTC_CXP_OFF_EQ1:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[16]);
+                       break;
+               case BTC_CXP_OFF_EQ2:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[17]);
+                       break;
+               case BTC_CXP_OFF_EQ3:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[18]);
+                       break;
+               case BTC_CXP_OFF_BWB0:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[5]);
+                       break;
+               case BTC_CXP_OFF_BWB1:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
+                       break;
+               }
+               break;
+       case BTC_CXP_OFFB: /* TDMA off + beacon protect */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
+               *t = t_def[CXTD_OFF_B2];
+               s[CXST_OFF] = s_def[CXST_OFF];
+               switch (policy_type) {
+               case BTC_CXP_OFFB_BWB0:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
+                       break;
+               }
+               break;
+       case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
+               btc->bt_req_en = true;
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_OFF_EXT];
+               switch (policy_type) {
+               case BTC_CXP_OFFE_DEF:
+                       s[CXST_E2G] = s_def[CXST_E2G];
+                       s[CXST_E5G] = s_def[CXST_E5G];
+                       s[CXST_EBT] = s_def[CXST_EBT];
+                       s[CXST_ENULL] = s_def[CXST_ENULL];
+                       break;
+               case BTC_CXP_OFFE_DEF2:
+                       _slot_set(btc, CXST_E2G, 20, cxtbl[1], SLOT_ISO);
+                       s[CXST_E5G] = s_def[CXST_E5G];
+                       s[CXST_EBT] = s_def[CXST_EBT];
+                       s[CXST_ENULL] = s_def[CXST_ENULL];
+                       break;
+               }
+               break;
+       case BTC_CXP_FIX: /* TDMA Fix-Slot */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_FIX];
+               switch (policy_type) {
+               case BTC_CXP_FIX_TD3030:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD5050:
+                       _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD2030:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD4010:
+                       _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD4020:
+                       _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX);
+                       _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD7010:
+                       _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD2060:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD3060:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TD2080:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_FIX_TDW1B1: /* W1:B1 = user-define */
+                       _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
+                                 tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
+                                 tbl_b1, SLOT_MIX);
+                       break;
+               }
+               break;
+       case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_PFIX];
+               if (btc->cx.wl.role_info.role_map.role.ap)
+                       _tdma_set_flctrl(btc, CXFLC_QOSNULL);
+
+               switch (policy_type) {
+               case BTC_CXP_PFIX_TD3030:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PFIX_TD5050:
+                       _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 50, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PFIX_TD2030:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 30, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PFIX_TD2060:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PFIX_TD3070:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 60, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PFIX_TD2080:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
+                       break;
+               }
+               break;
+       case BTC_CXP_AUTO: /* TDMA Auto-Slot */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_AUTO];
+               switch (policy_type) {
+               case BTC_CXP_AUTO_TD50B1:
+                       _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO_TD60B1:
+                       _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO_TD20B1:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
+                       _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
+                                 tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
+                                 tbl_b1, SLOT_MIX);
+                       break;
+               }
+               break;
+       case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_PAUTO];
+               switch (policy_type) {
+               case BTC_CXP_PAUTO_TD50B1:
+                       _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO_TD60B1:
+                       _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO_TD20B1:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO_TDW1B1:
+                       _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
+                                 tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
+                                 tbl_b1, SLOT_MIX);
+                       break;
+               }
+               break;
+       case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_AUTO2];
+               switch (policy_type) {
+               case BTC_CXP_AUTO2_TD3050:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO2_TD3070:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO2_TD5050:
+                       _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO2_TD6060:
+                       _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO2_TD2080:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
+                       _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
+                                 tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
+                                 tbl_b4, SLOT_MIX);
+                       break;
+               }
+               break;
+       case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
+               _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
+               *t = t_def[CXTD_PAUTO2];
+               switch (policy_type) {
+               case BTC_CXP_PAUTO2_TD3050:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO2_TD3070:
+                       _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 70, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO2_TD5050:
+                       _slot_set(btc, CXST_W1, 50, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 50, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO2_TD6060:
+                       _slot_set(btc, CXST_W1, 60, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 60, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO2_TD2080:
+                       _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, 80, tbl_b4, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
+                       break;
+               case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
+                       _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
+                                 tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
+                                 tbl_b4, SLOT_MIX);
+                       break;
+               }
+               break;
+       }
+}
+EXPORT_SYMBOL(rtw89_btc_set_policy);
+
+void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type)
 {
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &btc->dm;
        struct rtw89_btc_fbtc_tdma *t = &dm->tdma;
        struct rtw89_btc_fbtc_slot *s = dm->slot;
-       u8 type;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &btc->cx.wl.role_info_v1;
+       struct rtw89_btc_bt_hid_desc *hid = &btc->cx.bt.link_info.hid_desc;
+       struct rtw89_btc_bt_hfp_desc *hfp = &btc->cx.bt.link_info.hfp_desc;
+       u8 type, null_role;
        u32 tbl_w1, tbl_b1, tbl_b4;
 
+       type = FIELD_GET(BTC_CXP_MASK, policy_type);
+
        if (btc->mdinfo.ant.type == BTC_ANT_SHARED) {
                if (btc->cx.wl.status.map._4way)
                        tbl_w1 = cxtbl[1];
+               else if (hid->exist && hid->type == BTC_HID_218)
+                       tbl_w1 = cxtbl[7]; /* Ack/BA no break bt Hi-Pri-rx */
                else
                        tbl_w1 = cxtbl[8];
-               tbl_b1 = cxtbl[3];
-               tbl_b4 = cxtbl[3];
+
+               if (dm->leak_ap &&
+                   (type == BTC_CXP_PFIX || type == BTC_CXP_PAUTO2)) {
+                       tbl_b1 = cxtbl[3];
+                       tbl_b4 = cxtbl[3];
+               } else if (hid->exist && hid->type == BTC_HID_218) {
+                       tbl_b1 = cxtbl[4]; /* Ack/BA no break bt Hi-Pri-rx */
+                       tbl_b4 = cxtbl[4];
+               } else {
+                       tbl_b1 = cxtbl[2];
+                       tbl_b4 = cxtbl[2];
+               }
        } else {
                tbl_w1 = cxtbl[16];
                tbl_b1 = cxtbl[17];
                tbl_b4 = cxtbl[17];
        }
 
-       type = (u8)((policy_type & BTC_CXP_MASK) >> 8);
        btc->bt_req_en = false;
 
        switch (type) {
        case BTC_CXP_USERDEF0:
+               btc->update_policy_force = true;
                *t = t_def[CXTD_OFF];
                s[CXST_OFF] = s_def[CXST_OFF];
                _slot_set_tbl(btc, CXST_OFF, cxtbl[2]);
-               btc->update_policy_force = true;
                break;
        case BTC_CXP_OFF: /* TDMA off */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
@@ -1964,22 +2485,35 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                case BTC_CXP_OFF_BWB1:
                        _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
                        break;
+               case BTC_CXP_OFF_BWB2:
+                       _slot_set_tbl(btc, CXST_OFF, cxtbl[7]);
+                       break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_OFFB: /* TDMA off + beacon protect */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, false);
                *t = t_def[CXTD_OFF_B2];
                s[CXST_OFF] = s_def[CXST_OFF];
+
                switch (policy_type) {
                case BTC_CXP_OFFB_BWB0:
                        _slot_set_tbl(btc, CXST_OFF, cxtbl[8]);
                        break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_OFFE: /* TDMA off + beacon protect + Ext_control */
                btc->bt_req_en = true;
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_OFF_EXT];
+
+               /* To avoid wl-s0 tx break by hid/hfp tx */
+               if (hid->exist || hfp->exist)
+                       tbl_w1 = cxtbl[16];
+
                switch (policy_type) {
                case BTC_CXP_OFFE_DEF:
                        s[CXST_E2G] = s_def[CXST_E2G];
@@ -1993,11 +2527,14 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                        s[CXST_EBT] = s_def[CXST_EBT];
                        s[CXST_ENULL] = s_def[CXST_ENULL];
                        break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_FIX: /* TDMA Fix-Slot */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_FIX];
+
                switch (policy_type) {
                case BTC_CXP_FIX_TD3030:
                        _slot_set(btc, CXST_W1, 30, tbl_w1, SLOT_ISO);
@@ -2015,9 +2552,9 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                        _slot_set(btc, CXST_W1, 40, tbl_w1, SLOT_ISO);
                        _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
                        break;
-               case BTC_CXP_FIX_TD4020:
-                       _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_MIX);
-                       _slot_set(btc, CXST_B1, 20, tbl_b1, SLOT_MIX);
+               case BTC_CXP_FIX_TD4010ISO:
+                       _slot_set(btc, CXST_W1, 40, cxtbl[1], SLOT_ISO);
+                       _slot_set(btc, CXST_B1, 10, tbl_b1, SLOT_MIX);
                        break;
                case BTC_CXP_FIX_TD7010:
                        _slot_set(btc, CXST_W1, 70, tbl_w1, SLOT_ISO);
@@ -2041,13 +2578,13 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                        _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
                                  tbl_b1, SLOT_MIX);
                        break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_PFIX: /* PS-TDMA Fix-Slot */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_PFIX];
-               if (btc->cx.wl.role_info.role_map.role.ap)
-                       _tdma_set_flctrl(btc, CXFLC_QOSNULL);
 
                switch (policy_type) {
                case BTC_CXP_PFIX_TD3030:
@@ -2074,23 +2611,32 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                        _slot_set(btc, CXST_W1, 20, tbl_w1, SLOT_ISO);
                        _slot_set(btc, CXST_B1, 80, tbl_b1, SLOT_MIX);
                        break;
+               case BTC_CXP_PFIX_TDW1B1: /* W1:B1 = user-define */
+                       _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
+                                 tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
+                                 tbl_b1, SLOT_MIX);
+                       break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_AUTO: /* TDMA Auto-Slot */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_AUTO];
+
                switch (policy_type) {
-               case BTC_CXP_AUTO_TD50200:
+               case BTC_CXP_AUTO_TD50B1:
                        _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        break;
-               case BTC_CXP_AUTO_TD60200:
+               case BTC_CXP_AUTO_TD60B1:
                        _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        break;
-               case BTC_CXP_AUTO_TD20200:
+               case BTC_CXP_AUTO_TD20B1:
                        _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        break;
                case BTC_CXP_AUTO_TDW1B1: /* W1:B1 = user-define */
                        _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
@@ -2098,23 +2644,26 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                        _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
                                  tbl_b1, SLOT_MIX);
                        break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_PAUTO: /* PS-TDMA Auto-Slot */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_PAUTO];
+
                switch (policy_type) {
-               case BTC_CXP_PAUTO_TD50200:
+               case BTC_CXP_PAUTO_TD50B1:
                        _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        break;
-               case BTC_CXP_PAUTO_TD60200:
+               case BTC_CXP_PAUTO_TD60B1:
                        _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        break;
-               case BTC_CXP_PAUTO_TD20200:
+               case BTC_CXP_PAUTO_TD20B1:
                        _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        break;
                case BTC_CXP_PAUTO_TDW1B1:
                        _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
@@ -2122,86 +2671,112 @@ static void _set_policy(struct rtw89_dev *rtwdev, u16 policy_type,
                        _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
                                  tbl_b1, SLOT_MIX);
                        break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_AUTO2: /* TDMA Auto-Slot2 */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_AUTO2];
+
                switch (policy_type) {
                case BTC_CXP_AUTO2_TD3050:
                        _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_AUTO2_TD3070:
                        _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_AUTO2_TD5050:
                        _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_AUTO2_TD6060:
                        _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_AUTO2_TD2080:
                        _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_AUTO2_TDW1B4: /* W1:B1 = user-define */
                        _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
                                  tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
+                                 tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
                                  tbl_b4, SLOT_MIX);
                        break;
+               default:
+                       break;
                }
                break;
        case BTC_CXP_PAUTO2: /* PS-TDMA Auto-Slot2 */
                _write_scbd(rtwdev, BTC_WSCB_TDMA, true);
                *t = t_def[CXTD_PAUTO2];
+
                switch (policy_type) {
                case BTC_CXP_PAUTO2_TD3050:
                        _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_PAUTO2_TD3070:
                        _slot_set(btc, CXST_W1,  30, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  70, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_PAUTO2_TD5050:
                        _slot_set(btc, CXST_W1,  50, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  50, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_PAUTO2_TD6060:
                        _slot_set(btc, CXST_W1,  60, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  60, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_PAUTO2_TD2080:
                        _slot_set(btc, CXST_W1,  20, tbl_w1, SLOT_ISO);
-                       _slot_set(btc, CXST_B1, 200, tbl_b1, SLOT_MIX);
+                       _slot_set(btc, CXST_B1, BTC_B1_MAX, tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4,  80, tbl_b4, SLOT_MIX);
                        break;
                case BTC_CXP_PAUTO2_TDW1B4: /* W1:B1 = user-define */
                        _slot_set(btc, CXST_W1, dm->slot_dur[CXST_W1],
                                  tbl_w1, SLOT_ISO);
+                       _slot_set(btc, CXST_B1, dm->slot_dur[CXST_B1],
+                                 tbl_b1, SLOT_MIX);
                        _slot_set(btc, CXST_B4, dm->slot_dur[CXST_B4],
                                  tbl_b4, SLOT_MIX);
                        break;
+               default:
+                       break;
                }
                break;
        }
 
-       _fw_set_policy(rtwdev, policy_type, action);
+       if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC && dm->tdma.rxflctrl) {
+               null_role = FIELD_PREP(0x0f, dm->wl_scc.null_role1) |
+                           FIELD_PREP(0xf0, dm->wl_scc.null_role2);
+               _tdma_set_flctrl_role(btc, null_role);
+       }
+
+       /* enter leak_slot after each null-1 */
+       if (dm->leak_ap && dm->tdma.leak_n > 1)
+               _tdma_set_lek(btc, 1);
+
+       if (dm->tdma_instant_excute) {
+               btc->dm.tdma.option_ctrl |= BIT(0);
+               btc->update_policy_force = true;
+       }
 }
+EXPORT_SYMBOL(rtw89_btc_set_policy_v1);
 
 static void _set_gnt_bt(struct rtw89_dev *rtwdev, u8 phy_map, u8 state)
 {
@@ -2537,7 +3112,7 @@ static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
                                    BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP);
                } else {
                        _set_policy(rtwdev,
-                                   BTC_CXP_PAUTO_TD50200, BTC_ACT_BT_A2DP);
+                                   BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP);
                }
                break;
        case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP */
@@ -2554,12 +3129,12 @@ static void _action_bt_a2dp(struct rtw89_dev *rtwdev)
                        _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
                                    BTC_ACT_BT_A2DP);
                } else {
-                       _set_policy(rtwdev, BTC_CXP_AUTO_TD50200,
+                       _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
                                    BTC_ACT_BT_A2DP);
                }
                break;
        case BTC_WIDLE:  /* wl-idle + bt-A2DP */
-               _set_policy(rtwdev, BTC_CXP_AUTO_TD20200, BTC_ACT_BT_A2DP);
+               _set_policy(rtwdev, BTC_CXP_AUTO_TD20B1, BTC_ACT_BT_A2DP);
                break;
        }
 }
@@ -2639,7 +3214,7 @@ static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
                                    BTC_CXP_PAUTO_TDW1B1, BTC_ACT_BT_A2DP_HID);
                } else {
                        _set_policy(rtwdev,
-                                   BTC_CXP_PAUTO_TD50200, BTC_ACT_BT_A2DP_HID);
+                                   BTC_CXP_PAUTO_TD50B1, BTC_ACT_BT_A2DP_HID);
                }
                break;
        case BTC_WBUSY_BSCAN: /* wl-busy + bt-inq + bt-A2DP+HID */
@@ -2657,7 +3232,7 @@ static void _action_bt_a2dp_hid(struct rtw89_dev *rtwdev)
                        _set_policy(rtwdev, BTC_CXP_AUTO_TDW1B1,
                                    BTC_ACT_BT_A2DP_HID);
                } else {
-                       _set_policy(rtwdev, BTC_CXP_AUTO_TD50200,
+                       _set_policy(rtwdev, BTC_CXP_AUTO_TD50B1,
                                    BTC_ACT_BT_A2DP_HID);
                }
                break;
@@ -2792,19 +3367,27 @@ static void _action_wl_rfk(struct rtw89_dev *rtwdev)
 
 static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_wl_info *wl = &btc->cx.wl;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
        struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
-       bool is_btg = false;
+       bool is_btg;
+       u8 mode;
 
        if (btc->ctrl.manual)
                return;
 
+       if (chip->chip_id == RTL8852A)
+               mode = wl_rinfo->link_mode;
+       else
+               mode = wl_rinfo_v1->link_mode;
+
        /* notify halbb ignore GNT_BT or not for WL BB Rx-AGC control */
-       if (wl_rinfo->link_mode == BTC_WLINK_5G) /* always 0 if 5G */
+       if (mode == BTC_WLINK_5G) /* always 0 if 5G */
                is_btg = false;
-       else if (wl_rinfo->link_mode == BTC_WLINK_25G_DBCC &&
+       else if (mode == BTC_WLINK_25G_DBCC &&
                 wl_dinfo->real_band[RTW89_PHY_1] != RTW89_BAND_2G)
                is_btg = false;
        else
@@ -2816,7 +3399,7 @@ static void _set_btg_ctrl(struct rtw89_dev *rtwdev)
 
        btc->dm.wl_btg_rx = is_btg;
 
-       if (wl_rinfo->link_mode == BTC_WLINK_25G_MCC)
+       if (mode == BTC_WLINK_25G_MCC)
                return;
 
        rtw89_ctrl_btg(rtwdev, is_btg);
@@ -2889,6 +3472,7 @@ static void rtw89_tx_time_iter(void *data, struct ieee80211_sta *sta)
 
 static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_cx *cx = &btc->cx;
        struct rtw89_btc_dm *dm = &btc->dm;
@@ -2898,16 +3482,22 @@ static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
        struct rtw89_btc_bt_hfp_desc *hfp = &b->hfp_desc;
        struct rtw89_btc_bt_hid_desc *hid = &b->hid_desc;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
        struct rtw89_txtime_data data = {.rtwdev = rtwdev};
-       u8 mode = wl_rinfo->link_mode;
-       u8 tx_retry = 0;
-       u32 tx_time = 0;
-       u16 enable = 0;
+       u8 mode;
+       u8 tx_retry;
+       u32 tx_time;
+       u16 enable;
        bool reenable = false;
 
        if (btc->ctrl.manual)
                return;
 
+       if (chip->chip_id == RTL8852A)
+               mode = wl_rinfo->link_mode;
+       else
+               mode = wl_rinfo_v1->link_mode;
+
        if (btc->dm.freerun || btc->ctrl.igno_bt || b->profile_cnt.now == 0 ||
            mode == BTC_WLINK_5G || mode == BTC_WLINK_NOLINK) {
                enable = 0;
@@ -2951,13 +3541,21 @@ static void _set_wl_tx_limit(struct rtw89_dev *rtwdev)
 
 static void _set_bt_rx_agc(struct rtw89_dev *rtwdev)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_wl_info *wl = &btc->cx.wl;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
        struct rtw89_btc_bt_info *bt = &btc->cx.bt;
        bool bt_hi_lna_rx = false;
+       u8 mode;
 
-       if (wl_rinfo->link_mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
+       if (chip->chip_id == RTL8852A)
+               mode = wl_rinfo->link_mode;
+       else
+               mode = wl_rinfo_v1->link_mode;
+
+       if (mode != BTC_WLINK_NOLINK && btc->dm.wl_btg_rx)
                bt_hi_lna_rx = true;
 
        if (bt_hi_lna_rx == bt->hi_lna_rx)
@@ -3145,6 +3743,68 @@ static void _action_wl_2g_scc(struct rtw89_dev *rtwdev)
        }
 }
 
+static void _action_wl_2g_scc_v1(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_btc *btc = &rtwdev->btc;
+       struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+       struct rtw89_btc_bt_info *bt = &btc->cx.bt;
+       struct rtw89_btc_dm *dm = &btc->dm;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
+       u16 policy_type = BTC_CXP_OFF_BT;
+       u32 dur;
+
+       if (btc->mdinfo.ant.type == BTC_ANT_DEDICATED) {
+               policy_type = BTC_CXP_OFF_EQ0;
+       } else {
+               /* shared-antenna */
+               switch (wl_rinfo->mrole_type) {
+               case BTC_WLMROLE_STA_GC:
+                       dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
+                       dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_P2P_CLIENT;
+                       dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
+                       _action_by_bt(rtwdev);
+                       return;
+               case BTC_WLMROLE_STA_STA:
+                       dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
+                       dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_STATION;
+                       dm->wl_scc.ebt_null = 0; /* no ext-slot-control */
+                       _action_by_bt(rtwdev);
+                       return;
+               case BTC_WLMROLE_STA_GC_NOA:
+               case BTC_WLMROLE_STA_GO:
+               case BTC_WLMROLE_STA_GO_NOA:
+                       dm->wl_scc.null_role1 = RTW89_WIFI_ROLE_STATION;
+                       dm->wl_scc.null_role2 = RTW89_WIFI_ROLE_NONE;
+                       dur = wl_rinfo->mrole_noa_duration;
+
+                       if (wl->status.map._4way) {
+                               dm->wl_scc.ebt_null = 0;
+                               policy_type = BTC_CXP_OFFE_WL;
+                       } else if (bt->link_info.status.map.connect == 0) {
+                               dm->wl_scc.ebt_null = 0;
+                               policy_type = BTC_CXP_OFFE_2GISOB;
+                       } else if (bt->link_info.a2dp_desc.exist &&
+                                  dur < btc->bt_req_len) {
+                               dm->wl_scc.ebt_null = 1; /* tx null at EBT */
+                               policy_type = BTC_CXP_OFFE_2GBWMIXB2;
+                       } else if (bt->link_info.a2dp_desc.exist ||
+                                  bt->link_info.pan_desc.exist) {
+                               dm->wl_scc.ebt_null = 1; /* tx null at EBT */
+                               policy_type = BTC_CXP_OFFE_2GBWISOB;
+                       } else {
+                               dm->wl_scc.ebt_null = 0;
+                               policy_type = BTC_CXP_OFFE_2GBWISOB;
+                       }
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       _set_ant(rtwdev, NM_EXEC, BTC_PHY_ALL, BTC_ANT_W2G);
+       _set_policy(rtwdev, policy_type, BTC_ACT_WL_2G_SCC);
+}
+
 static void _action_wl_2g_ap(struct rtw89_dev *rtwdev)
 {
        struct rtw89_btc *btc = &rtwdev->btc;
@@ -3434,6 +4094,156 @@ static void _update_wl_info(struct rtw89_dev *rtwdev)
        _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
 }
 
+static void _update_wl_info_v1(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_btc *btc = &rtwdev->btc;
+       struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+       struct rtw89_btc_wl_link_info *wl_linfo = wl->link_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo = &wl->role_info_v1;
+       struct rtw89_btc_wl_dbcc_info *wl_dinfo = &wl->dbcc_info;
+       u8 cnt_connect = 0, cnt_connecting = 0, cnt_active = 0;
+       u8 cnt_2g = 0, cnt_5g = 0, phy;
+       u32 wl_2g_ch[2] = {}, wl_5g_ch[2] = {};
+       bool b2g = false, b5g = false, client_joined = false;
+       u8 i;
+
+       memset(wl_rinfo, 0, sizeof(*wl_rinfo));
+
+       for (i = 0; i < RTW89_PORT_NUM; i++) {
+               if (!wl_linfo[i].active)
+                       continue;
+
+               cnt_active++;
+               wl_rinfo->active_role_v1[cnt_active - 1].role = wl_linfo[i].role;
+               wl_rinfo->active_role_v1[cnt_active - 1].pid = wl_linfo[i].pid;
+               wl_rinfo->active_role_v1[cnt_active - 1].phy = wl_linfo[i].phy;
+               wl_rinfo->active_role_v1[cnt_active - 1].band = wl_linfo[i].band;
+               wl_rinfo->active_role_v1[cnt_active - 1].noa = (u8)wl_linfo[i].noa;
+               wl_rinfo->active_role_v1[cnt_active - 1].connected = 0;
+
+               wl->port_id[wl_linfo[i].role] = wl_linfo[i].pid;
+
+               phy = wl_linfo[i].phy;
+
+               if (rtwdev->dbcc_en && phy < RTW89_PHY_MAX) {
+                       wl_dinfo->role[phy] = wl_linfo[i].role;
+                       wl_dinfo->op_band[phy] = wl_linfo[i].band;
+                       _update_dbcc_band(rtwdev, phy);
+                       _fw_set_drv_info(rtwdev, CXDRVINFO_DBCC);
+               }
+
+               if (wl_linfo[i].connected == MLME_NO_LINK) {
+                       continue;
+               } else if (wl_linfo[i].connected == MLME_LINKING) {
+                       cnt_connecting++;
+               } else {
+                       cnt_connect++;
+                       if ((wl_linfo[i].role == RTW89_WIFI_ROLE_P2P_GO ||
+                            wl_linfo[i].role == RTW89_WIFI_ROLE_AP) &&
+                            wl_linfo[i].client_cnt > 1)
+                               client_joined = true;
+               }
+
+               wl_rinfo->role_map.val |= BIT(wl_linfo[i].role);
+               wl_rinfo->active_role_v1[cnt_active - 1].ch = wl_linfo[i].ch;
+               wl_rinfo->active_role_v1[cnt_active - 1].bw = wl_linfo[i].bw;
+               wl_rinfo->active_role_v1[cnt_active - 1].connected = 1;
+
+               /* only care 2 roles + BT coex */
+               if (wl_linfo[i].band != RTW89_BAND_2G) {
+                       if (cnt_5g <= ARRAY_SIZE(wl_5g_ch) - 1)
+                               wl_5g_ch[cnt_5g] = wl_linfo[i].ch;
+                       cnt_5g++;
+                       b5g = true;
+               } else {
+                       if (cnt_2g <= ARRAY_SIZE(wl_2g_ch) - 1)
+                               wl_2g_ch[cnt_2g] = wl_linfo[i].ch;
+                       cnt_2g++;
+                       b2g = true;
+               }
+       }
+
+       wl_rinfo->connect_cnt = cnt_connect;
+
+       /* Be careful to change the following sequence!! */
+       if (cnt_connect == 0) {
+               wl_rinfo->link_mode = BTC_WLINK_NOLINK;
+               wl_rinfo->role_map.role.none = 1;
+       } else if (!b2g && b5g) {
+               wl_rinfo->link_mode = BTC_WLINK_5G;
+       } else if (wl_rinfo->role_map.role.nan) {
+               wl_rinfo->link_mode = BTC_WLINK_2G_NAN;
+       } else if (cnt_connect > BTC_TDMA_WLROLE_MAX) {
+               wl_rinfo->link_mode = BTC_WLINK_OTHER;
+       } else  if (b2g && b5g && cnt_connect == 2) {
+               if (rtwdev->dbcc_en) {
+                       switch (wl_dinfo->role[RTW89_PHY_0]) {
+                       case RTW89_WIFI_ROLE_STATION:
+                               wl_rinfo->link_mode = BTC_WLINK_2G_STA;
+                               break;
+                       case RTW89_WIFI_ROLE_P2P_GO:
+                               wl_rinfo->link_mode = BTC_WLINK_2G_GO;
+                               break;
+                       case RTW89_WIFI_ROLE_P2P_CLIENT:
+                               wl_rinfo->link_mode = BTC_WLINK_2G_GC;
+                               break;
+                       case RTW89_WIFI_ROLE_AP:
+                               wl_rinfo->link_mode = BTC_WLINK_2G_AP;
+                               break;
+                       default:
+                               wl_rinfo->link_mode = BTC_WLINK_OTHER;
+                               break;
+                       }
+               } else {
+                       wl_rinfo->link_mode = BTC_WLINK_25G_MCC;
+               }
+       } else if (!b5g && cnt_connect == 2) {
+               if (wl_rinfo->role_map.role.station &&
+                   (wl_rinfo->role_map.role.p2p_go ||
+                   wl_rinfo->role_map.role.p2p_gc ||
+                   wl_rinfo->role_map.role.ap)) {
+                       if (wl_2g_ch[0] == wl_2g_ch[1])
+                               wl_rinfo->link_mode = BTC_WLINK_2G_SCC;
+                       else
+                               wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
+               } else {
+                       wl_rinfo->link_mode = BTC_WLINK_2G_MCC;
+               }
+       } else if (!b5g && cnt_connect == 1) {
+               if (wl_rinfo->role_map.role.station)
+                       wl_rinfo->link_mode = BTC_WLINK_2G_STA;
+               else if (wl_rinfo->role_map.role.ap)
+                       wl_rinfo->link_mode = BTC_WLINK_2G_AP;
+               else if (wl_rinfo->role_map.role.p2p_go)
+                       wl_rinfo->link_mode = BTC_WLINK_2G_GO;
+               else if (wl_rinfo->role_map.role.p2p_gc)
+                       wl_rinfo->link_mode = BTC_WLINK_2G_GC;
+               else
+                       wl_rinfo->link_mode = BTC_WLINK_OTHER;
+       }
+
+       /* if no client_joined, don't care P2P-GO/AP role */
+       if (wl_rinfo->role_map.role.p2p_go || wl_rinfo->role_map.role.ap) {
+               if (!client_joined) {
+                       if (wl_rinfo->link_mode == BTC_WLINK_2G_SCC ||
+                           wl_rinfo->link_mode == BTC_WLINK_2G_MCC) {
+                               wl_rinfo->link_mode = BTC_WLINK_2G_STA;
+                               wl_rinfo->connect_cnt = 1;
+                       } else if (wl_rinfo->link_mode == BTC_WLINK_2G_GO ||
+                                wl_rinfo->link_mode == BTC_WLINK_2G_AP) {
+                               wl_rinfo->link_mode = BTC_WLINK_NOLINK;
+                               wl_rinfo->connect_cnt = 0;
+                       }
+               }
+       }
+
+       rtw89_debug(rtwdev, RTW89_DBG_BTC,
+                   "[BTC], cnt_connect = %d, connecting = %d, link_mode = %d\n",
+                   cnt_connect, cnt_connecting, wl_rinfo->link_mode);
+
+       _fw_set_drv_info(rtwdev, CXDRVINFO_ROLE);
+}
+
 #define BTC_CHK_HANG_MAX 3
 #define BTC_SCB_INV_VALUE GENMASK(31, 0)
 
@@ -3584,23 +4394,31 @@ static bool _chk_wl_rfk_request(struct rtw89_dev *rtwdev)
 static
 void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_dm *dm = &rtwdev->btc.dm;
        struct rtw89_btc_cx *cx = &btc->cx;
        struct rtw89_btc_wl_info *wl = &btc->cx.wl;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
-       u8 mode = wl_rinfo->link_mode;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
+       u8 mode;
 
        lockdep_assert_held(&rtwdev->mutex);
-       rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
-                   __func__, reason, mode);
-       rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
-                   __func__, dm->wl_only, dm->bt_only);
 
        dm->run_reason = reason;
        _update_dm_step(rtwdev, reason);
        _update_btc_state_map(rtwdev);
 
+       if (chip->chip_id == RTL8852A)
+               mode = wl_rinfo->link_mode;
+       else
+               mode = wl_rinfo_v1->link_mode;
+
+       rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): reason=%d, mode=%d\n",
+                   __func__, reason, mode);
+       rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): wl_only=%d, bt_only=%d\n",
+                   __func__, dm->wl_only, dm->bt_only);
+
        /* Be careful to change the following function sequence!! */
        if (btc->ctrl.manual) {
                rtw89_debug(rtwdev, RTW89_DBG_BTC,
@@ -3708,7 +4526,10 @@ void _run_coex(struct rtw89_dev *rtwdev, enum btc_reason_and_action reason)
                _action_wl_2g_gc(rtwdev);
                break;
        case BTC_WLINK_2G_SCC:
-               _action_wl_2g_scc(rtwdev);
+               if (chip->chip_id == RTL8852A)
+                       _action_wl_2g_scc(rtwdev);
+               else if (chip->chip_id == RTL8852C)
+                       _action_wl_2g_scc_v1(rtwdev);
                break;
        case BTC_WLINK_2G_MCC:
                _action_wl_2g_mcc(rtwdev);
@@ -3743,11 +4564,14 @@ void rtw89_btc_ntfy_poweron(struct rtw89_dev *rtwdev)
 void rtw89_btc_ntfy_poweroff(struct rtw89_dev *rtwdev)
 {
        struct rtw89_btc *btc = &rtwdev->btc;
+       struct rtw89_btc_wl_info *wl = &btc->cx.wl;
 
        rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): !!\n", __func__);
        btc->dm.cnt_notify[BTC_NCNT_POWER_OFF]++;
 
        btc->cx.wl.status.map.rf_off = 1;
+       btc->cx.wl.status.map.busy = 0;
+       wl->status.map.lps = BTC_LPS_OFF;
 
        _write_scbd(rtwdev, BTC_WSCB_ALL, false);
        _run_coex(rtwdev, BTC_RSN_NTFY_POWEROFF);
@@ -4150,7 +4974,8 @@ enum btc_wl_mode {
 void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
                              struct rtw89_sta *rtwsta, enum btc_role_state state)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
        struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
        struct rtw89_btc *btc = &rtwdev->btc;
@@ -4165,8 +4990,7 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
                    vif->type == NL80211_IFTYPE_STATION);
        rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], port=%d\n", rtwvif->port);
        rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], band=%d ch=%d bw=%d\n",
-                   hal->current_band_type, hal->current_channel,
-                   hal->current_band_width);
+                   chan->band_type, chan->channel, chan->band_width);
        rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], associated=%d\n",
                    state == BTC_ROLE_MSTS_STA_CONN_END);
        rtw89_debug(rtwdev, RTW89_DBG_BTC,
@@ -4205,9 +5029,9 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
        r.connected = MLME_LINKED;
        r.bcn_period = vif->bss_conf.beacon_int;
        r.dtim_period = vif->bss_conf.dtim_period;
-       r.band = hal->current_band_type;
-       r.ch = hal->current_channel;
-       r.bw = hal->current_band_width;
+       r.band = chan->band_type;
+       r.ch = chan->channel;
+       r.bw = chan->band_width;
        ether_addr_copy(r.mac_addr, rtwvif->mac_addr);
 
        if (rtwsta && vif->type == NL80211_IFTYPE_STATION)
@@ -4218,7 +5042,10 @@ void rtw89_btc_ntfy_role_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif
        wlinfo = &wl->link_info[r.pid];
 
        memcpy(wlinfo, &r, sizeof(*wlinfo));
-       _update_wl_info(rtwdev);
+       if (chip->chip_id == RTL8852A)
+               _update_wl_info(rtwdev);
+       else
+               _update_wl_info_v1(rtwdev);
 
        if (wlinfo->role == RTW89_WIFI_ROLE_STATION &&
            wlinfo->connected == MLME_NO_LINK)
@@ -4240,6 +5067,7 @@ void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_sta
        const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+       u32 val;
 
        rtw89_debug(rtwdev, RTW89_DBG_BTC, "[BTC], %s(): rf_state = %d\n",
                    __func__, rf_state);
@@ -4249,10 +5077,12 @@ void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_sta
        case BTC_RFCTRL_WL_OFF:
                wl->status.map.rf_off = 1;
                wl->status.map.lps = BTC_LPS_OFF;
+               wl->status.map.busy = 0;
                break;
        case BTC_RFCTRL_FW_CTRL:
                wl->status.map.rf_off = 0;
                wl->status.map.lps = BTC_LPS_RF_OFF;
+               wl->status.map.busy = 0;
                break;
        case BTC_RFCTRL_WL_ON:
        default:
@@ -4262,14 +5092,17 @@ void rtw89_btc_ntfy_radio_state(struct rtw89_dev *rtwdev, enum btc_rfctrl rf_sta
        }
 
        if (rf_state == BTC_RFCTRL_WL_ON) {
+               btc->dm.cnt_dm[BTC_DCNT_BTCNT_FREEZE] = 0;
                rtw89_btc_fw_en_rpt(rtwdev,
                                    RPT_EN_MREG | RPT_EN_BT_VER_INFO, true);
-               _write_scbd(rtwdev, BTC_WSCB_ACTIVE, true);
+               val = BTC_WSCB_ACTIVE | BTC_WSCB_ON | BTC_WSCB_BTLOG;
+               _write_scbd(rtwdev, val, true);
                _update_bt_scbd(rtwdev, true);
                chip->ops->btc_init_cfg(rtwdev);
        } else {
                rtw89_btc_fw_en_rpt(rtwdev, RPT_EN_ALL, false);
-               _write_scbd(rtwdev, BTC_WSCB_ACTIVE | BTC_WSCB_WLBUSY, false);
+               if (rf_state == BTC_RFCTRL_WL_OFF)
+                       _write_scbd(rtwdev, BTC_WSCB_ALL, false);
        }
 
        _run_coex(rtwdev, BTC_RSN_NTFY_RADIO_STATE);
@@ -4726,23 +5559,29 @@ static void _show_wl_role_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 
 static void _show_wl_info(struct rtw89_dev *rtwdev, struct seq_file *m)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_btc *btc = &rtwdev->btc;
        struct rtw89_btc_cx *cx = &btc->cx;
        struct rtw89_btc_wl_info *wl = &cx->wl;
        struct rtw89_btc_wl_role_info *wl_rinfo = &wl->role_info;
+       struct rtw89_btc_wl_role_info_v1 *wl_rinfo_v1 = &wl->role_info_v1;
+       u8 mode;
 
        if (!(btc->dm.coex_info_map & BTC_COEX_INFO_WL))
                return;
 
        seq_puts(m, "========== [WL Status] ==========\n");
 
-       seq_printf(m, " %-15s : link_mode:%d, ",
-                  "[status]", (u32)wl_rinfo->link_mode);
+       if (chip->chip_id == RTL8852A)
+               mode = wl_rinfo->link_mode;
+       else
+               mode = wl_rinfo_v1->link_mode;
+
+       seq_printf(m, " %-15s : link_mode:%d, ", "[status]", mode);
 
        seq_printf(m,
-                  "rf_off:%s, power_save:%s, scan:%s(band:%d/phy_map:0x%x), ",
-                  wl->status.map.rf_off ? "Y" : "N",
-                  wl->status.map.lps ? "Y" : "N",
+                  "rf_off:%d, power_save:%d, scan:%s(band:%d/phy_map:0x%x), ",
+                  wl->status.map.rf_off, wl->status.map.lps,
                   wl->status.map.scan ? "Y" : "N",
                   wl->scan_info.band[RTW89_PHY_0], wl->scan_info.phy_map);
 
@@ -4969,9 +5808,15 @@ static const char *steps_to_str(u16 step)
        CASE_BTC_POLICY_STR(OFF_EQ3);
        CASE_BTC_POLICY_STR(OFF_BWB0);
        CASE_BTC_POLICY_STR(OFF_BWB1);
+       CASE_BTC_POLICY_STR(OFF_BWB2);
        CASE_BTC_POLICY_STR(OFFB_BWB0);
        CASE_BTC_POLICY_STR(OFFE_DEF);
        CASE_BTC_POLICY_STR(OFFE_DEF2);
+       CASE_BTC_POLICY_STR(OFFE_2GBWISOB);
+       CASE_BTC_POLICY_STR(OFFE_2GISOB);
+       CASE_BTC_POLICY_STR(OFFE_2GBWMIXB);
+       CASE_BTC_POLICY_STR(OFFE_WL);
+       CASE_BTC_POLICY_STR(OFFE_2GBWMIXB2);
        CASE_BTC_POLICY_STR(FIX_TD3030);
        CASE_BTC_POLICY_STR(FIX_TD5050);
        CASE_BTC_POLICY_STR(FIX_TD2030);
@@ -4982,6 +5827,7 @@ static const char *steps_to_str(u16 step)
        CASE_BTC_POLICY_STR(FIX_TD2080);
        CASE_BTC_POLICY_STR(FIX_TDW1B1);
        CASE_BTC_POLICY_STR(FIX_TD4020);
+       CASE_BTC_POLICY_STR(FIX_TD4010ISO);
        CASE_BTC_POLICY_STR(PFIX_TD3030);
        CASE_BTC_POLICY_STR(PFIX_TD5050);
        CASE_BTC_POLICY_STR(PFIX_TD2030);
@@ -4989,13 +5835,13 @@ static const char *steps_to_str(u16 step)
        CASE_BTC_POLICY_STR(PFIX_TD3070);
        CASE_BTC_POLICY_STR(PFIX_TD2080);
        CASE_BTC_POLICY_STR(PFIX_TDW1B1);
-       CASE_BTC_POLICY_STR(AUTO_TD50200);
-       CASE_BTC_POLICY_STR(AUTO_TD60200);
-       CASE_BTC_POLICY_STR(AUTO_TD20200);
+       CASE_BTC_POLICY_STR(AUTO_TD50B1);
+       CASE_BTC_POLICY_STR(AUTO_TD60B1);
+       CASE_BTC_POLICY_STR(AUTO_TD20B1);
        CASE_BTC_POLICY_STR(AUTO_TDW1B1);
-       CASE_BTC_POLICY_STR(PAUTO_TD50200);
-       CASE_BTC_POLICY_STR(PAUTO_TD60200);
-       CASE_BTC_POLICY_STR(PAUTO_TD20200);
+       CASE_BTC_POLICY_STR(PAUTO_TD50B1);
+       CASE_BTC_POLICY_STR(PAUTO_TD60B1);
+       CASE_BTC_POLICY_STR(PAUTO_TD20B1);
        CASE_BTC_POLICY_STR(PAUTO_TDW1B1);
        CASE_BTC_POLICY_STR(AUTO2_TD3050);
        CASE_BTC_POLICY_STR(AUTO2_TD3070);
index c3a722d..ca16afa 100644 (file)
@@ -162,17 +162,19 @@ void rtw89_coex_act1_work(struct work_struct *work);
 void rtw89_coex_bt_devinfo_work(struct work_struct *work);
 void rtw89_coex_rfk_chk_work(struct work_struct *work);
 void rtw89_coex_power_on(struct rtw89_dev *rtwdev);
+void rtw89_btc_set_policy(struct rtw89_dev *rtwdev, u16 policy_type);
+void rtw89_btc_set_policy_v1(struct rtw89_dev *rtwdev, u16 policy_type);
 
 static inline u8 rtw89_btc_phymap(struct rtw89_dev *rtwdev,
                                  enum rtw89_phy_idx phy_idx,
                                  enum rtw89_rf_path_bit paths)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u8 phy_map;
 
        phy_map = FIELD_PREP(BTC_RFK_PATH_MAP, paths) |
                  FIELD_PREP(BTC_RFK_PHY_MAP, BIT(phy_idx)) |
-                 FIELD_PREP(BTC_RFK_BAND_MAP, hal->current_band_type);
+                 FIELD_PREP(BTC_RFK_BAND_MAP, chan->band_type);
 
        return phy_map;
 }
index a5880a5..71ee237 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/udp.h>
 
 #include "cam.h"
+#include "chan.h"
 #include "coex.h"
 #include "core.h"
 #include "efuse.h"
@@ -224,18 +225,22 @@ static void rtw89_traffic_stats_accu(struct rtw89_dev *rtwdev,
        }
 }
 
-static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
-                                    struct rtw89_channel_params *chan_param)
+void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef)
+{
+       cfg80211_chandef_create(chandef, &rtw89_channels_2ghz[0],
+                               NL80211_CHAN_NO_HT);
+}
+
+static void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
+                                    struct rtw89_chan *chan)
 {
        struct ieee80211_channel *channel = chandef->chan;
        enum nl80211_chan_width width = chandef->width;
        u32 primary_freq, center_freq;
        u8 center_chan;
        u8 bandwidth = RTW89_CHANNEL_WIDTH_20;
-       u8 primary_chan_idx = 0;
        u32 offset;
        u8 band;
-       u8 subband;
 
        center_chan = channel->hw_value;
        primary_freq = channel->center_freq;
@@ -245,15 +250,12 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
        case NL80211_CHAN_WIDTH_20_NOHT:
        case NL80211_CHAN_WIDTH_20:
                bandwidth = RTW89_CHANNEL_WIDTH_20;
-               primary_chan_idx = RTW89_SC_DONT_CARE;
                break;
        case NL80211_CHAN_WIDTH_40:
                bandwidth = RTW89_CHANNEL_WIDTH_40;
                if (primary_freq > center_freq) {
-                       primary_chan_idx = RTW89_SC_20_UPPER;
                        center_chan -= 2;
                } else {
-                       primary_chan_idx = RTW89_SC_20_LOWER;
                        center_chan += 2;
                }
                break;
@@ -262,11 +264,9 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
                bandwidth = nl_to_rtw89_bandwidth(width);
                if (primary_freq > center_freq) {
                        offset = (primary_freq - center_freq - 10) / 20;
-                       primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
                        center_chan -= 2 + offset * 4;
                } else {
                        offset = (center_freq - primary_freq - 10) / 20;
-                       primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
                        center_chan += 2 + offset * 4;
                }
                break;
@@ -288,110 +288,76 @@ static void rtw89_get_channel_params(struct cfg80211_chan_def *chandef,
                break;
        }
 
-       switch (band) {
-       default:
-       case RTW89_BAND_2G:
-               switch (center_chan) {
-               default:
-               case 1 ... 14:
-                       subband = RTW89_CH_2G;
-                       break;
-               }
-               break;
-       case RTW89_BAND_5G:
-               switch (center_chan) {
-               default:
-               case 36 ... 64:
-                       subband = RTW89_CH_5G_BAND_1;
-                       break;
-               case 100 ... 144:
-                       subband = RTW89_CH_5G_BAND_3;
-                       break;
-               case 149 ... 177:
-                       subband = RTW89_CH_5G_BAND_4;
-                       break;
-               }
-               break;
-       case RTW89_BAND_6G:
-               switch (center_chan) {
-               default:
-               case 1 ... 29:
-                       subband = RTW89_CH_6G_BAND_IDX0;
-                       break;
-               case 33 ... 61:
-                       subband = RTW89_CH_6G_BAND_IDX1;
-                       break;
-               case 65 ... 93:
-                       subband = RTW89_CH_6G_BAND_IDX2;
-                       break;
-               case 97 ... 125:
-                       subband = RTW89_CH_6G_BAND_IDX3;
-                       break;
-               case 129 ... 157:
-                       subband = RTW89_CH_6G_BAND_IDX4;
-                       break;
-               case 161 ... 189:
-                       subband = RTW89_CH_6G_BAND_IDX5;
-                       break;
-               case 193 ... 221:
-                       subband = RTW89_CH_6G_BAND_IDX6;
-                       break;
-               case 225 ... 253:
-                       subband = RTW89_CH_6G_BAND_IDX7;
-                       break;
-               }
-               break;
-       }
+       rtw89_chan_create(chan, center_chan, channel->hw_value, band, bandwidth);
+}
+
+void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       const struct rtw89_chan *chan;
+       enum rtw89_sub_entity_idx sub_entity_idx;
+       enum rtw89_phy_idx phy_idx;
+       enum rtw89_entity_mode mode;
+       bool entity_active;
+
+       entity_active = rtw89_get_entity_state(rtwdev);
+       if (!entity_active)
+               return;
 
-       chan_param->center_chan = center_chan;
-       chan_param->center_freq = center_freq;
-       chan_param->primary_chan = channel->hw_value;
-       chan_param->bandwidth = bandwidth;
-       chan_param->pri_ch_idx = primary_chan_idx;
-       chan_param->band_type = band;
-       chan_param->subband_type = subband;
+       mode = rtw89_get_entity_mode(rtwdev);
+       if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
+               return;
+
+       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);
 }
 
 void rtw89_set_channel(struct rtw89_dev *rtwdev)
 {
-       struct ieee80211_hw *hw = rtwdev->hw;
        const struct rtw89_chip_info *chip = rtwdev->chip;
-       struct rtw89_hal *hal = &rtwdev->hal;
-       struct rtw89_channel_params ch_param;
+       const struct cfg80211_chan_def *chandef;
+       enum rtw89_sub_entity_idx sub_entity_idx;
+       enum rtw89_mac_idx mac_idx;
+       enum rtw89_phy_idx phy_idx;
+       struct rtw89_chan chan;
        struct rtw89_channel_help_params bak;
-       u8 center_chan, bandwidth;
+       enum rtw89_entity_mode mode;
        bool band_changed;
+       bool entity_active;
+
+       entity_active = rtw89_get_entity_state(rtwdev);
 
-       rtw89_get_channel_params(&hw->conf.chandef, &ch_param);
-       if (WARN(ch_param.center_chan == 0, "Invalid channel\n"))
+       mode = rtw89_entity_recalc(rtwdev);
+       if (WARN(mode != RTW89_ENTITY_MODE_SCC, "Invalid ent mode: %d\n", mode))
                return;
 
-       center_chan = ch_param.center_chan;
-       bandwidth = ch_param.bandwidth;
-       band_changed = hal->current_band_type != ch_param.band_type ||
-                      hal->current_channel == 0;
+       sub_entity_idx = RTW89_SUB_ENTITY_0;
+       mac_idx = RTW89_MAC_0;
+       phy_idx = RTW89_PHY_0;
+       chandef = rtw89_chandef_get(rtwdev, sub_entity_idx);
+       rtw89_get_channel_params(chandef, &chan);
+       if (WARN(chan.channel == 0, "Invalid channel\n"))
+               return;
 
-       hal->current_band_width = bandwidth;
-       hal->current_channel = center_chan;
-       hal->current_freq = ch_param.center_freq;
-       hal->prev_primary_channel = hal->current_primary_channel;
-       hal->prev_band_type = hal->current_band_type;
-       hal->current_primary_channel = ch_param.primary_chan;
-       hal->current_band_type = ch_param.band_type;
-       hal->current_subband = ch_param.subband_type;
+       band_changed = rtw89_assign_entity_chan(rtwdev, sub_entity_idx, &chan);
 
-       rtw89_chip_set_channel_prepare(rtwdev, &bak);
+       rtw89_chip_set_channel_prepare(rtwdev, &bak, &chan, mac_idx, phy_idx);
 
-       chip->ops->set_channel(rtwdev, &ch_param);
+       chip->ops->set_channel(rtwdev, &chan, mac_idx, phy_idx);
 
-       rtw89_chip_set_txpwr(rtwdev);
+       rtw89_core_set_chip_txpwr(rtwdev);
 
-       rtw89_chip_set_channel_done(rtwdev, &bak);
+       rtw89_chip_set_channel_done(rtwdev, &bak, &chan, mac_idx, phy_idx);
 
-       if (band_changed) {
-               rtw89_btc_ntfy_switch_band(rtwdev, RTW89_PHY_0, hal->current_band_type);
-               rtw89_chip_rfk_band_changed(rtwdev);
+       if (!entity_active || band_changed) {
+               rtw89_btc_ntfy_switch_band(rtwdev, phy_idx, chan.band_type);
+               rtw89_chip_rfk_band_changed(rtwdev, phy_idx);
        }
+
+       rtw89_set_entity_state(rtwdev, true);
 }
 
 static enum rtw89_core_tx_type
@@ -529,8 +495,8 @@ static u16 rtw89_core_get_mgmt_rate(struct rtw89_dev *rtwdev,
        struct sk_buff *skb = tx_req->skb;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_vif *vif = tx_info->control.vif;
-       struct rtw89_hal *hal = &rtwdev->hal;
-       u16 lowest_rate = hal->current_band_type == RTW89_BAND_2G ?
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u16 lowest_rate = chan->band_type == RTW89_BAND_2G ?
                          RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6;
 
        if (!vif || !vif->bss_conf.basic_rates || !tx_req->sta)
@@ -546,6 +512,7 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
        struct ieee80211_vif *vif = tx_req->vif;
        struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
        struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u8 qsel, ch_dma;
 
        qsel = desc_info->hiq ? RTW89_TX_QSEL_B0_HI : RTW89_TX_QSEL_B0_MGMT;
@@ -564,9 +531,9 @@ rtw89_core_tx_update_mgmt_info(struct rtw89_dev *rtwdev,
        desc_info->data_rate = rtw89_core_get_mgmt_rate(rtwdev, tx_req);
 
        rtw89_debug(rtwdev, RTW89_DBG_TXRX,
-                   "tx mgmt frame with rate 0x%x on channel %d (bw %d)\n",
-                   desc_info->data_rate, rtwdev->hal.current_channel,
-                   rtwdev->hal.current_band_width);
+                   "tx mgmt frame with rate 0x%x on channel %d (band %d, bw %d)\n",
+                   desc_info->data_rate, chan->channel, chan->band_type,
+                   chan->band_width);
 }
 
 static void
@@ -591,15 +558,16 @@ static void rtw89_core_get_no_ul_ofdma_htc(struct rtw89_dev *rtwdev, __le32 *htc
        };
        const struct rtw89_chip_info *chip = rtwdev->chip;
        struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u8 om_bandwidth;
 
        if (!chip->dis_2g_40m_ul_ofdma ||
-           hal->current_band_type != RTW89_BAND_2G ||
-           hal->current_band_width != RTW89_CHANNEL_WIDTH_40)
+           chan->band_type != RTW89_BAND_2G ||
+           chan->band_width != RTW89_CHANNEL_WIDTH_40)
                return;
 
-       om_bandwidth = hal->current_band_width < ARRAY_SIZE(rtw89_bandwidth_to_om) ?
-                      rtw89_bandwidth_to_om[hal->current_band_width] : 0;
+       om_bandwidth = chan->band_width < ARRAY_SIZE(rtw89_bandwidth_to_om) ?
+                      rtw89_bandwidth_to_om[chan->band_width] : 0;
        *htc = le32_encode_bits(RTW89_HTC_VARIANT_HE, RTW89_HTC_MASK_VARIANT) |
               le32_encode_bits(RTW89_HTC_VARIANT_HE_CID_OM, RTW89_HTC_MASK_CTL_ID) |
               le32_encode_bits(hal->rx_nss - 1, RTW89_HTC_MASK_HTC_OM_RX_NSS) |
@@ -617,6 +585,7 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
                                 enum btc_pkt_type pkt_type)
 {
        struct ieee80211_sta *sta = tx_req->sta;
+       struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
        struct sk_buff *skb = tx_req->skb;
        struct ieee80211_hdr *hdr = (void *)skb->data;
        __le16 fc = hdr->frame_control;
@@ -634,6 +603,9 @@ __rtw89_core_tx_check_he_qos_htc(struct rtw89_dev *rtwdev,
        if (skb_headroom(skb) < IEEE80211_HT_CTL_LEN)
                return false;
 
+       if (rtwsta && rtwsta->ra_report.might_fallback_legacy)
+               return false;
+
        return true;
 }
 
@@ -713,7 +685,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
        struct ieee80211_vif *vif = tx_req->vif;
        struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
        struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
        struct sk_buff *skb = tx_req->skb;
        u8 tid, tid_indicate;
@@ -738,7 +710,7 @@ rtw89_core_tx_update_data_info(struct rtw89_dev *rtwdev,
 
        if (rate_pattern->enable)
                desc_info->data_retry_lowest_rate = rate_pattern->rate;
-       else if (hal->current_band_type == RTW89_BAND_2G)
+       else if (chan->band_type == RTW89_BAND_2G)
                desc_info->data_retry_lowest_rate = RTW89_HW_RATE_CCK1;
        else
                desc_info->data_retry_lowest_rate = RTW89_HW_RATE_OFDM6;
@@ -1448,8 +1420,11 @@ static void rtw89_core_rx_stats(struct rtw89_dev *rtwdev,
 static void rtw89_correct_cck_chan(struct rtw89_dev *rtwdev,
                                   struct ieee80211_rx_status *status)
 {
-       u16 chan = rtwdev->hal.prev_primary_channel;
-       u8 band = chan <= 14 ? NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
+       const struct rtw89_chan_rcd *rcd =
+               rtw89_chan_rcd_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u16 chan = rcd->prev_primary_channel;
+       u8 band = rcd->prev_band_type == RTW89_BAND_2G ?
+                 NL80211_BAND_2GHZ : NL80211_BAND_5GHZ;
 
        if (status->band != NL80211_BAND_2GHZ &&
            status->encoding == RX_ENC_LEGACY &&
@@ -1661,19 +1636,20 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
                                        struct rtw89_rx_desc_info *desc_info,
                                        struct ieee80211_rx_status *rx_status)
 {
-       struct ieee80211_hw *hw = rtwdev->hw;
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct cfg80211_chan_def *chandef =
+               rtw89_chandef_get(rtwdev, RTW89_SUB_ENTITY_0);
+       const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u16 data_rate;
        u8 data_rate_mode;
 
        /* currently using single PHY */
-       rx_status->freq = hw->conf.chandef.chan->center_freq;
-       rx_status->band = hw->conf.chandef.chan->band;
+       rx_status->freq = chandef->chan->center_freq;
+       rx_status->band = chandef->chan->band;
 
        if (rtwdev->scanning &&
            RTW89_CHK_FW_FEATURE(SCAN_OFFLOAD, &rtwdev->fw)) {
-               u8 chan = hal->current_primary_channel;
-               u8 band = hal->current_band_type;
+               u8 chan = cur->primary_channel;
+               u8 band = cur->band_type;
                enum nl80211_band nl_band;
 
                nl_band = rtw89_hw_to_nl80211_band(band);
@@ -2266,45 +2242,69 @@ void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits)
        bitmap_zero(addr, nbits);
 }
 
-int rtw89_core_acquire_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
+int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
+                                   struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
 {
-       struct rtw89_ba_cam_entry *entry;
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
+       struct rtw89_ba_cam_entry *entry = NULL, *tmp;
        u8 idx;
+       int i;
 
-       idx = rtw89_core_acquire_bit_map(rtwsta->ba_cam_map, RTW89_BA_CAM_NUM);
-       if (idx == RTW89_BA_CAM_NUM) {
-               /* allocate a static BA CAM to tid=0, so replace the existing
+       lockdep_assert_held(&rtwdev->mutex);
+
+       idx = rtw89_core_acquire_bit_map(cam_info->ba_cam_map, chip->bacam_num);
+       if (idx == chip->bacam_num) {
+               /* allocate a static BA CAM to tid=0/5, so replace the existing
                 * one if BA CAM is full. Hardware will process the original tid
                 * automatically.
                 */
-               if (tid != 0)
+               if (tid != 0 && tid != 5)
                        return -ENOSPC;
 
-               idx = 0;
+               for_each_set_bit(i, cam_info->ba_cam_map, chip->bacam_num) {
+                       tmp = &cam_info->ba_cam_entry[i];
+                       if (tmp->tid == 0 || tmp->tid == 5)
+                               continue;
+
+                       idx = i;
+                       entry = tmp;
+                       list_del(&entry->list);
+                       break;
+               }
+
+               if (!entry)
+                       return -ENOSPC;
+       } else {
+               entry = &cam_info->ba_cam_entry[idx];
        }
 
-       entry = &rtwsta->ba_cam_entry[idx];
        entry->tid = tid;
+       list_add_tail(&entry->list, &rtwsta->ba_cam_list);
+
        *cam_idx = idx;
 
        return 0;
 }
 
-int rtw89_core_release_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
+int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
+                                   struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx)
 {
-       struct rtw89_ba_cam_entry *entry;
-       int i;
+       struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
+       struct rtw89_ba_cam_entry *entry = NULL, *tmp;
+       u8 idx;
 
-       for (i = 0; i < RTW89_BA_CAM_NUM; i++) {
-               if (!test_bit(i, rtwsta->ba_cam_map))
-                       continue;
+       lockdep_assert_held(&rtwdev->mutex);
 
-               entry = &rtwsta->ba_cam_entry[i];
+       list_for_each_entry_safe(entry, tmp, &rtwsta->ba_cam_list, list) {
                if (entry->tid != tid)
                        continue;
 
-               rtw89_core_release_bit_map(rtwsta->ba_cam_map, i);
-               *cam_idx = i;
+               idx = entry - cam_info->ba_cam_entry;
+               list_del(&entry->list);
+
+               rtw89_core_release_bit_map(cam_info->ba_cam_map, idx);
+               *cam_idx = idx;
                return 0;
        }
 
@@ -2367,6 +2367,7 @@ int rtw89_core_sta_add(struct rtw89_dev *rtwdev,
 
        rtwsta->rtwvif = rtwvif;
        rtwsta->prev_rssi = 0;
+       INIT_LIST_HEAD(&rtwsta->ba_cam_list);
 
        for (i = 0; i < ARRAY_SIZE(sta->txq); i++)
                rtw89_core_txq_init(rtwdev, sta->txq[i]);
@@ -2669,8 +2670,7 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
                phy_cap_info = he_cap->he_cap_elem.phy_cap_info;
 
                he_cap->has_he = true;
-               if (i == NL80211_IFTYPE_AP)
-                       mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE;
+               mac_cap_info[0] = IEEE80211_HE_MAC_CAP0_HTC_HE;
                if (i == NL80211_IFTYPE_STATION)
                        mac_cap_info[1] = IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_16US;
                mac_cap_info[2] = IEEE80211_HE_MAC_CAP2_ALL_ACK |
@@ -2706,6 +2706,8 @@ static void rtw89_init_he_cap(struct rtw89_dev *rtwdev,
                        phy_cap_info[3] |= IEEE80211_HE_PHY_CAP3_RX_PARTIAL_BW_SU_IN_20MHZ_MU;
                phy_cap_info[4] = IEEE80211_HE_PHY_CAP4_SU_BEAMFORMEE |
                                  IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_UNDER_80MHZ_4;
+               if (chip->support_bw160)
+                       phy_cap_info[4] |= IEEE80211_HE_PHY_CAP4_BEAMFORMEE_MAX_STS_ABOVE_80MHZ_4;
                phy_cap_info[5] = no_ng16 ? 0 :
                                  IEEE80211_HE_PHY_CAP5_NG16_SU_FEEDBACK |
                                  IEEE80211_HE_PHY_CAP5_NG16_MU_FEEDBACK;
@@ -2894,6 +2896,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
 
        rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_WL_ON);
        rtw89_fw_h2c_fw_log(rtwdev, rtwdev->fw.fw_log_enable);
+       rtw89_fw_h2c_init_ba_cam(rtwdev);
 
        return 0;
 }
@@ -2987,6 +2990,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
                return ret;
        }
        rtw89_ser_init(rtwdev);
+       rtw89_entity_init(rtwdev);
 
        return 0;
 }
@@ -3007,7 +3011,7 @@ EXPORT_SYMBOL(rtw89_core_deinit);
 void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
                           const u8 *mac_addr, bool hw_scan)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
 
        rtwdev->scanning = true;
        rtw89_leave_lps(rtwdev);
@@ -3015,7 +3019,7 @@ void rtw89_core_scan_start(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
                rtw89_leave_ips(rtwdev);
 
        ether_addr_copy(rtwvif->mac_addr, mac_addr);
-       rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, hal->current_band_type);
+       rtw89_btc_ntfy_scan_start(rtwdev, RTW89_PHY_0, chan->band_type);
        rtw89_chip_rfk_scan(rtwdev, true);
        rtw89_hci_recalc_int_mit(rtwdev);
 
@@ -3141,6 +3145,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
        hw->vif_data_size = sizeof(struct rtw89_vif);
        hw->sta_data_size = sizeof(struct rtw89_sta);
        hw->txq_data_size = sizeof(struct rtw89_txq);
+       hw->chanctx_data_size = sizeof(struct rtw89_chanctx_cfg);
 
        SET_IEEE80211_PERM_ADDR(hw, efuse->addr);
 
@@ -3234,6 +3239,63 @@ void rtw89_core_unregister(struct rtw89_dev *rtwdev)
 }
 EXPORT_SYMBOL(rtw89_core_unregister);
 
+struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
+                                          u32 bus_data_size,
+                                          const struct rtw89_chip_info *chip)
+{
+       struct ieee80211_hw *hw;
+       struct rtw89_dev *rtwdev;
+       struct ieee80211_ops *ops;
+       u32 driver_data_size;
+       u32 early_feat_map = 0;
+       bool no_chanctx;
+
+       rtw89_early_fw_feature_recognize(device, chip, &early_feat_map);
+
+       ops = kmemdup(&rtw89_ops, sizeof(rtw89_ops), GFP_KERNEL);
+       if (!ops)
+               goto err;
+
+       no_chanctx = chip->support_chanctx_num == 0 ||
+                    !(early_feat_map & BIT(RTW89_FW_FEATURE_SCAN_OFFLOAD));
+
+       if (no_chanctx) {
+               ops->add_chanctx = NULL;
+               ops->remove_chanctx = NULL;
+               ops->change_chanctx = NULL;
+               ops->assign_vif_chanctx = NULL;
+               ops->unassign_vif_chanctx = NULL;
+       }
+
+       driver_data_size = sizeof(struct rtw89_dev) + bus_data_size;
+       hw = ieee80211_alloc_hw(driver_data_size, ops);
+       if (!hw)
+               goto err;
+
+       rtwdev = hw->priv;
+       rtwdev->hw = hw;
+       rtwdev->dev = device;
+       rtwdev->ops = ops;
+       rtwdev->chip = chip;
+
+       rtw89_debug(rtwdev, RTW89_DBG_FW, "probe driver %s chanctx\n",
+                   no_chanctx ? "without" : "with");
+
+       return rtwdev;
+
+err:
+       kfree(ops);
+       return NULL;
+}
+EXPORT_SYMBOL(rtw89_alloc_ieee80211_hw);
+
+void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev)
+{
+       kfree(rtwdev->ops);
+       ieee80211_free_hw(rtwdev->hw);
+}
+EXPORT_SYMBOL(rtw89_free_ieee80211_hw);
+
 MODULE_AUTHOR("Realtek Corporation");
 MODULE_DESCRIPTION("Realtek 802.11ax wireless core module");
 MODULE_LICENSE("Dual BSD/GPL");
index 7a9d6f5..b5fa61e 100644 (file)
@@ -542,6 +542,12 @@ enum rtw89_phy_idx {
        RTW89_PHY_MAX
 };
 
+enum rtw89_sub_entity_idx {
+       RTW89_SUB_ENTITY_0 = 0,
+
+       NUM_OF_RTW89_SUB_ENTITY,
+};
+
 enum rtw89_rf_path {
        RF_PATH_A = 0,
        RF_PATH_B = 1,
@@ -624,14 +630,23 @@ enum rtw89_sc_offset {
        RTW89_SC_40_LOWER       = 10,
 };
 
-struct rtw89_channel_params {
-       u8 center_chan;
-       u32 center_freq;
-       u8 primary_chan;
-       u8 bandwidth;
-       u8 pri_ch_idx;
-       u8 band_type;
-       u8 subband_type;
+struct rtw89_chan {
+       u8 channel;
+       u8 primary_channel;
+       enum rtw89_band band_type;
+       enum rtw89_bandwidth band_width;
+
+       /* The follow-up are derived from the above. We must ensure that it
+        * is assigned correctly in rtw89_chan_create() if new one is added.
+        */
+       u32 freq;
+       enum rtw89_subband subband_type;
+       enum rtw89_sc_offset pri_ch_idx;
+};
+
+struct rtw89_chan_rcd {
+       u8 prev_primary_channel;
+       enum rtw89_band prev_band_type;
 };
 
 struct rtw89_channel_help_params {
@@ -793,7 +808,7 @@ struct rtw89_mac_ax_gnt {
        u8 gnt_bt;
        u8 gnt_wl_sw_en;
        u8 gnt_wl;
-};
+} __packed;
 
 #define RTW89_MAC_AX_COEX_GNT_NR 2
 struct rtw89_mac_ax_coex_gnt {
@@ -848,6 +863,7 @@ enum rtw89_btc_dcnt {
        BTC_DCNT_SLOT_NONSYNC,
        BTC_DCNT_BTCNT_FREEZE,
        BTC_DCNT_WL_SLOT_DRIFT,
+       BTC_DCNT_BT_SLOT_DRIFT,
        BTC_DCNT_WL_STA_LAST,
        BTC_DCNT_NUM,
 };
@@ -920,12 +936,12 @@ struct rtw89_btc_wl_smap {
        u32 roaming: 1;
        u32 _4way: 1;
        u32 rf_off: 1;
-       u32 lps: 1;
+       u32 lps: 2;
        u32 ips: 1;
        u32 init_ok: 1;
        u32 traffic_dir : 2;
        u32 rf_off_pre: 1;
-       u32 lps_pre: 1;
+       u32 lps_pre: 2;
 };
 
 enum rtw89_tfc_lv {
@@ -1108,6 +1124,27 @@ struct rtw89_btc_wl_active_role {
        u16 rx_rate;
 };
 
+struct rtw89_btc_wl_active_role_v1 {
+       u8 connected: 1;
+       u8 pid: 3;
+       u8 phy: 1;
+       u8 noa: 1;
+       u8 band: 2;
+
+       u8 client_ps: 1;
+       u8 bw: 7;
+
+       u8 role;
+       u8 ch;
+
+       u16 tx_lvl;
+       u16 rx_lvl;
+       u16 tx_rate;
+       u16 rx_rate;
+
+       u32 noa_duration; /* ms */
+};
+
 struct rtw89_btc_wl_role_info_bpos {
        u16 none: 1;
        u16 station: 1;
@@ -1123,6 +1160,12 @@ struct rtw89_btc_wl_role_info_bpos {
        u16 nan: 1;
 };
 
+struct rtw89_btc_wl_scc_ctrl {
+       u8 null_role1;
+       u8 null_role2;
+       u8 ebt_null; /* if tx null at EBT slot */
+};
+
 union rtw89_btc_wl_role_info_map {
        u16 val;
        struct rtw89_btc_wl_role_info_bpos role;
@@ -1135,6 +1178,21 @@ struct rtw89_btc_wl_role_info { /* struct size must be n*4 bytes */
        struct rtw89_btc_wl_active_role active_role[RTW89_PORT_NUM];
 };
 
+struct rtw89_btc_wl_role_info_v1 { /* struct size must be n*4 bytes */
+       u8 connect_cnt;
+       u8 link_mode;
+       union rtw89_btc_wl_role_info_map role_map;
+       struct rtw89_btc_wl_active_role_v1 active_role_v1[RTW89_PORT_NUM];
+       u32 mrole_type; /* btc_wl_mrole_type */
+       u32 mrole_noa_duration; /* ms */
+
+       u32 dbcc_en: 1;
+       u32 dbcc_chg: 1;
+       u32 dbcc_2g_phy: 2; /* which phy operate in 2G, HW_PHY_0 or HW_PHY_1 */
+       u32 link_mode_chg: 1;
+       u32 rsvd: 27;
+};
+
 struct rtw89_btc_wl_ver_info {
        u32 fw_coex; /* match with which coex_ver */
        u32 fw;
@@ -1240,6 +1298,7 @@ struct rtw89_btc_wl_info {
        struct rtw89_btc_wl_ver_info  ver_info;
        struct rtw89_btc_wl_afh_info afh_info;
        struct rtw89_btc_wl_role_info role_info;
+       struct rtw89_btc_wl_role_info_v1 role_info_v1;
        struct rtw89_btc_wl_scan_info scan_info;
        struct rtw89_btc_wl_dbcc_info dbcc_info;
        struct rtw89_btc_rf_para rf_para;
@@ -1346,32 +1405,43 @@ struct rtw89_btc_cx {
 };
 
 struct rtw89_btc_fbtc_tdma {
-       u8 type;
+       u8 type; /* chip_info::fcxtdma_ver */
        u8 rxflctrl;
        u8 txpause;
        u8 wtgle_n;
        u8 leak_n;
        u8 ext_ctrl;
-       u8 rsvd0;
-       u8 rsvd1;
+       u8 rxflctrl_role;
+       u8 option_ctrl;
+} __packed;
+
+struct rtw89_btc_fbtc_tdma_v1 {
+       u8 fver; /* chip_info::fcxtdma_ver */
+       u8 rsvd;
+       __le16 rsvd1;
+       struct rtw89_btc_fbtc_tdma tdma;
 } __packed;
 
 #define CXMREG_MAX 30
 #define FCXMAX_STEP 255 /*STEP trace record cnt, Max:65535, default:255*/
-#define BTCRPT_VER 1
 #define BTC_CYCLE_SLOT_MAX 48 /* must be even number, non-zero */
 
-enum rtw89_btc_bt_rfk_counter {
+enum rtw89_btc_bt_sta_counter {
        BTC_BCNT_RFK_REQ = 0,
        BTC_BCNT_RFK_GO = 1,
        BTC_BCNT_RFK_REJECT = 2,
        BTC_BCNT_RFK_FAIL = 3,
        BTC_BCNT_RFK_TIMEOUT = 4,
-       BTC_BCNT_RFK_MAX
+       BTC_BCNT_HI_TX = 5,
+       BTC_BCNT_HI_RX = 6,
+       BTC_BCNT_LO_TX = 7,
+       BTC_BCNT_LO_RX = 8,
+       BTC_BCNT_POLLUTED = 9,
+       BTC_BCNT_STA_MAX
 };
 
 struct rtw89_btc_fbtc_rpt_ctrl {
-       u16 fver;
+       u16 fver; /* chip_info::fcxbtcrpt_ver */
        u16 rpt_cnt; /* tmr counters */
        u32 wl_fw_coex_ver; /* match which driver's coex version */
        u32 wl_fw_cx_offload;
@@ -1384,11 +1454,56 @@ struct rtw89_btc_fbtc_rpt_ctrl {
        u32 mb_a2dp_empty_cnt; /* a2dp empty count */
        u32 mb_a2dp_flct_cnt; /* a2dp empty flow control counter */
        u32 mb_a2dp_full_cnt; /* a2dp empty full counter */
-       u32 bt_rfk_cnt[BTC_BCNT_RFK_MAX];
+       u32 bt_rfk_cnt[BTC_BCNT_HI_TX];
        u32 c2h_cnt; /* fw send c2h counter  */
        u32 h2c_cnt; /* fw recv h2c counter */
 } __packed;
 
+struct rtw89_btc_fbtc_rpt_ctrl_info {
+       __le32 cnt; /* fw report counter */
+       __le32 en; /* report map */
+       __le32 para; /* not used */
+
+       __le32 cnt_c2h; /* fw send c2h counter  */
+       __le32 cnt_h2c; /* fw recv h2c counter */
+       __le32 len_c2h; /* The total length of the last C2H  */
+
+       __le32 cnt_aoac_rf_on;  /* rf-on counter for aoac switch notify */
+       __le32 cnt_aoac_rf_off; /* rf-off counter for aoac switch notify */
+} __packed;
+
+struct rtw89_btc_fbtc_rpt_ctrl_wl_fw_info {
+       __le32 cx_ver; /* match which driver's coex version */
+       __le32 cx_offload;
+       __le32 fw_ver;
+} __packed;
+
+struct rtw89_btc_fbtc_rpt_ctrl_a2dp_empty {
+       __le32 cnt_empty; /* a2dp empty count */
+       __le32 cnt_flowctrl; /* a2dp empty flow control counter */
+       __le32 cnt_tx;
+       __le32 cnt_ack;
+       __le32 cnt_nack;
+} __packed;
+
+struct rtw89_btc_fbtc_rpt_ctrl_bt_mailbox {
+       __le32 cnt_send_ok; /* fw send mailbox ok counter */
+       __le32 cnt_send_fail; /* fw send mailbox fail counter */
+       __le32 cnt_recv; /* fw recv mailbox counter */
+       struct rtw89_btc_fbtc_rpt_ctrl_a2dp_empty a2dp;
+} __packed;
+
+struct rtw89_btc_fbtc_rpt_ctrl_v1 {
+       u8 fver;
+       u8 rsvd;
+       __le16 rsvd1;
+       struct rtw89_btc_fbtc_rpt_ctrl_info rpt_info;
+       struct rtw89_btc_fbtc_rpt_ctrl_wl_fw_info wl_fw_info;
+       struct rtw89_btc_fbtc_rpt_ctrl_bt_mailbox bt_mbx_info;
+       __le32 bt_cnt[BTC_BCNT_STA_MAX];
+       struct rtw89_mac_ax_gnt gnt_val[RTW89_PHY_MAX];
+} __packed;
+
 enum rtw89_fbtc_ext_ctrl_type {
        CXECTL_OFF = 0x0, /* tdma off */
        CXECTL_B2 = 0x1, /* allow B2 (beacon-early) */
@@ -1457,10 +1572,9 @@ enum { /* STEP TYPE */
        CXSTEP_MAX,
 };
 
-#define FCXGPIODBG_VER 1
 #define BTC_DBG_MAX1  32
 struct rtw89_btc_fbtc_gpio_dbg {
-       u8 fver;
+       u8 fver; /* chip_info::fcxgpiodbg_ver */
        u8 rsvd;
        u16 rsvd2;
        u32 en_map; /* which debug signal (see btc_wl_gpio_debug) is enable */
@@ -1468,9 +1582,8 @@ struct rtw89_btc_fbtc_gpio_dbg {
        u8 gpio_map[BTC_DBG_MAX1]; /*the debug signals to GPIO-Position */
 } __packed;
 
-#define FCXMREG_VER 1
 struct rtw89_btc_fbtc_mreg_val {
-       u8 fver;
+       u8 fver; /* chip_info::fcxmreg_ver */
        u8 reg_num;
        __le16 rsvd;
        __le32 mreg_val[CXMREG_MAX];
@@ -1492,16 +1605,14 @@ struct rtw89_btc_fbtc_slot {
        __le16 cxtype;
 } __packed;
 
-#define FCXSLOTS_VER 1
 struct rtw89_btc_fbtc_slots {
-       u8 fver;
+       u8 fver; /* chip_info::fcxslots_ver */
        u8 tbl_num;
        __le16 rsvd;
        __le32 update_map;
        struct rtw89_btc_fbtc_slot slot[CXST_MAX];
 } __packed;
 
-#define FCXSTEP_VER 2
 struct rtw89_btc_fbtc_step {
        u8 type;
        u8 val;
@@ -1509,7 +1620,7 @@ struct rtw89_btc_fbtc_step {
 } __packed;
 
 struct rtw89_btc_fbtc_steps {
-       u8 fver;
+       u8 fver; /* chip_info::fcxstep_ver */
        u8 rsvd;
        __le16 cnt;
        __le16 pos_old;
@@ -1517,9 +1628,8 @@ struct rtw89_btc_fbtc_steps {
        struct rtw89_btc_fbtc_step step[FCXMAX_STEP];
 } __packed;
 
-#define FCXCYSTA_VER 2
 struct rtw89_btc_fbtc_cysta { /* statistics for cycles */
-       u8 fver;
+       u8 fver; /* chip_info::fcxcysta_ver */
        u8 rsvd;
        __le16 cycles; /* total cycle number */
        __le16 cycles_a2dp[CXT_FLCTRL_MAX];
@@ -1544,19 +1654,71 @@ struct rtw89_btc_fbtc_cysta { /* statistics for cycles */
        __le16 tslot_cycle[BTC_CYCLE_SLOT_MAX];
 } __packed;
 
-#define FCXNULLSTA_VER 1
-struct rtw89_btc_fbtc_cynullsta { /* cycle null statistics */
+struct rtw89_btc_fbtc_fdd_try_info {
+       __le16 cycles[CXT_FLCTRL_MAX];
+       __le16 tavg[CXT_FLCTRL_MAX]; /* avg try BT-Slot-TDD/BT-slot-FDD time */
+       __le16 tmax[CXT_FLCTRL_MAX]; /* max try BT-Slot-TDD/BT-slot-FDD time */
+} __packed;
+
+struct rtw89_btc_fbtc_cycle_time_info {
+       __le16 tavg[CXT_MAX]; /* avg wl/bt cycle time */
+       __le16 tmax[CXT_MAX]; /* max wl/bt cycle time */
+       __le16 tmaxdiff[CXT_MAX]; /* max wl-wl bt-bt cycle diff time */
+} __packed;
+
+struct rtw89_btc_fbtc_a2dp_trx_stat {
+       u8 empty_cnt;
+       u8 retry_cnt;
+       u8 tx_rate;
+       u8 tx_cnt;
+       u8 ack_cnt;
+       u8 nack_cnt;
+       u8 rsvd1;
+       u8 rsvd2;
+} __packed;
+
+struct rtw89_btc_fbtc_cycle_a2dp_empty_info {
+       __le16 cnt; /* a2dp empty cnt */
+       __le16 cnt_timeout; /* a2dp empty timeout cnt*/
+       __le16 tavg; /* avg a2dp empty time */
+       __le16 tmax; /* max a2dp empty time */
+} __packed;
+
+struct rtw89_btc_fbtc_cycle_leak_info {
+       __le32 cnt_rximr; /* the rximr occur at leak slot  */
+       __le16 tavg; /* avg leak-slot time */
+       __le16 tmax; /* max leak-slot time */
+} __packed;
+
+struct rtw89_btc_fbtc_cysta_v1 { /* statistics for cycles */
        u8 fver;
        u8 rsvd;
+       __le16 cycles; /* total cycle number */
+       __le16 slot_step_time[BTC_CYCLE_SLOT_MAX];
+       struct rtw89_btc_fbtc_cycle_time_info cycle_time;
+       struct rtw89_btc_fbtc_fdd_try_info fdd_try;
+       struct rtw89_btc_fbtc_cycle_a2dp_empty_info a2dp_ept;
+       struct rtw89_btc_fbtc_a2dp_trx_stat a2dp_trx[BTC_CYCLE_SLOT_MAX];
+       struct rtw89_btc_fbtc_cycle_leak_info leak_slot;
+       __le32 slot_cnt[CXST_MAX]; /* slot count */
+       __le32 bcn_cnt[CXBCN_MAX];
+       __le32 collision_cnt; /* counter for event/timer occur at the same time */
+       __le32 skip_cnt;
+       __le32 except_cnt;
+       __le32 except_map;
+} __packed;
+
+struct rtw89_btc_fbtc_cynullsta { /* cycle null statistics */
+       u8 fver; /* chip_info::fcxnullsta_ver */
+       u8 rsvd;
        __le16 rsvd2;
        __le32 max_t[2]; /* max_t for 0:null0/1:null1 */
        __le32 avg_t[2]; /* avg_t for 0:null0/1:null1 */
        __le32 result[2][4]; /* 0:fail, 1:ok, 2:on_time, 3:retry */
 } __packed;
 
-#define FCX_BTVER_VER 1
 struct rtw89_btc_fbtc_btver {
-       u8 fver;
+       u8 fver; /* chip_info::fcxbtver_ver */
        u8 rsvd;
        __le16 rsvd2;
        __le32 coex_ver; /*bit[15:8]->shared, bit[7:0]->non-shared */
@@ -1564,17 +1726,15 @@ struct rtw89_btc_fbtc_btver {
        __le32 feature;
 } __packed;
 
-#define FCX_BTSCAN_VER 1
 struct rtw89_btc_fbtc_btscan {
-       u8 fver;
+       u8 fver; /* chip_info::fcxbtscan_ver */
        u8 rsvd;
        __le16 rsvd2;
        u8 scan[6];
 } __packed;
 
-#define FCX_BTAFH_VER 1
 struct rtw89_btc_fbtc_btafh {
-       u8 fver;
+       u8 fver; /* chip_info::fcxbtafh_ver */
        u8 rsvd;
        __le16 rsvd2;
        u8 afh_l[4]; /*bit0:2402, bit1: 2403.... bit31:2433 */
@@ -1582,9 +1742,8 @@ struct rtw89_btc_fbtc_btafh {
        u8 afh_h[4]; /*bit0:2466, bit1:2467......bit14:2480 */
 } __packed;
 
-#define FCX_BTDEVINFO_VER 1
 struct rtw89_btc_fbtc_btdevinfo {
-       u8 fver;
+       u8 fver; /* chip_info::fcxbtdevinfo_ver */
        u8 rsvd;
        __le16 vendor_id;
        __le32 dev_name; /* only 24 bits valid */
@@ -1609,6 +1768,7 @@ struct rtw89_btc_dm {
        struct rtw89_btc_rf_trx_para rf_trx_para;
        struct rtw89_btc_wl_tx_limit_para wl_tx_limit;
        struct rtw89_btc_dm_step dm_step;
+       struct rtw89_btc_wl_scc_ctrl wl_scc;
        union rtw89_btc_dm_error_map error;
        u32 cnt_dm[BTC_DCNT_NUM];
        u32 cnt_notify[BTC_NCNT_NUM];
@@ -1628,7 +1788,8 @@ struct rtw89_btc_dm {
        u32 wl_btg_rx: 1;
        u32 trx_para_level: 8;
        u32 wl_stb_chg: 1;
-       u32 rsvd: 3;
+       u32 tdma_instant_excute: 1;
+       u32 rsvd: 2;
 
        u16 slot_dur[CXST_MAX];
 
@@ -1650,8 +1811,6 @@ struct rtw89_btc_dbg {
        u32 rb_val;
 };
 
-#define FCXTDMA_VER 1
-
 enum rtw89_btc_btf_fw_event {
        BTF_EVNT_RPT = 0,
        BTF_EVNT_BT_INFO = 1,
@@ -1704,12 +1863,18 @@ struct rtw89_btc_rpt_cmn_info {
 
 struct rtw89_btc_report_ctrl_state {
        struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
-       struct rtw89_btc_fbtc_rpt_ctrl finfo; /* info from fw */
+       union {
+               struct rtw89_btc_fbtc_rpt_ctrl finfo; /* info from fw for 52A*/
+               struct rtw89_btc_fbtc_rpt_ctrl_v1 finfo_v1; /* info from fw for 52C*/
+       };
 };
 
 struct rtw89_btc_rpt_fbtc_tdma {
        struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
-       struct rtw89_btc_fbtc_tdma finfo; /* info from fw */
+       union {
+               struct rtw89_btc_fbtc_tdma finfo; /* info from fw */
+               struct rtw89_btc_fbtc_tdma_v1 finfo_v1; /* info from fw for 52C*/
+       };
 };
 
 struct rtw89_btc_rpt_fbtc_slots {
@@ -1719,7 +1884,10 @@ struct rtw89_btc_rpt_fbtc_slots {
 
 struct rtw89_btc_rpt_fbtc_cysta {
        struct rtw89_btc_rpt_cmn_info cinfo; /* common info, by driver */
-       struct rtw89_btc_fbtc_cysta finfo; /* info from fw */
+       union {
+               struct rtw89_btc_fbtc_cysta finfo; /* info from fw for 52A*/
+               struct rtw89_btc_fbtc_cysta_v1 finfo_v1; /* info from fw for 52C*/
+       };
 };
 
 struct rtw89_btc_rpt_fbtc_step {
@@ -1911,19 +2079,20 @@ struct rtw89_ra_report {
        struct rate_info txrate;
        u32 bit_rate;
        u16 hw_rate;
+       bool might_fallback_legacy;
 };
 
 DECLARE_EWMA(rssi, 10, 16);
 
-#define RTW89_BA_CAM_NUM 2
-
 struct rtw89_ba_cam_entry {
+       struct list_head list;
        u8 tid;
 };
 
 #define RTW89_MAX_ADDR_CAM_NUM         128
 #define RTW89_MAX_BSSID_CAM_NUM                20
 #define RTW89_MAX_SEC_CAM_NUM          128
+#define RTW89_MAX_BA_CAM_NUM           8
 #define RTW89_SEC_CAM_IN_ADDR_CAM      7
 
 struct rtw89_addr_cam_entry {
@@ -1979,6 +2148,7 @@ struct rtw89_sta {
        __le32 htc_template;
        struct rtw89_addr_cam_entry addr_cam; /* AP mode or TDLS peer only */
        struct rtw89_bssid_cam_entry bssid_cam; /* TDLS peer only */
+       struct list_head ba_cam_list;
 
        bool use_cfg_mask;
        struct cfg80211_bitrate_mask mask;
@@ -1987,9 +2157,6 @@ struct rtw89_sta {
        u32 ampdu_max_time:4;
        bool cctl_tx_retry_limit;
        u32 data_tx_cnt_lmt:6;
-
-       DECLARE_BITMAP(ba_cam_map, RTW89_BA_CAM_NUM);
-       struct rtw89_ba_cam_entry ba_cam_entry[RTW89_BA_CAM_NUM];
 };
 
 struct rtw89_efuse {
@@ -2100,20 +2267,29 @@ struct rtw89_chip_ops {
        bool (*write_rf)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                         u32 addr, u32 mask, u32 data);
        void (*set_channel)(struct rtw89_dev *rtwdev,
-                           struct rtw89_channel_params *param);
+                           const struct rtw89_chan *chan,
+                           enum rtw89_mac_idx mac_idx,
+                           enum rtw89_phy_idx phy_idx);
        void (*set_channel_help)(struct rtw89_dev *rtwdev, bool enter,
-                                struct rtw89_channel_help_params *p);
+                                struct rtw89_channel_help_params *p,
+                                const struct rtw89_chan *chan,
+                                enum rtw89_mac_idx mac_idx,
+                                enum rtw89_phy_idx phy_idx);
        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 (*rfk_init)(struct rtw89_dev *rtwdev);
        void (*rfk_channel)(struct rtw89_dev *rtwdev);
-       void (*rfk_band_changed)(struct rtw89_dev *rtwdev);
+       void (*rfk_band_changed)(struct rtw89_dev *rtwdev,
+                                enum rtw89_phy_idx phy_idx);
        void (*rfk_scan)(struct rtw89_dev *rtwdev, bool start);
        void (*rfk_track)(struct rtw89_dev *rtwdev);
        void (*power_trim)(struct rtw89_dev *rtwdev);
-       void (*set_txpwr)(struct rtw89_dev *rtwdev);
-       void (*set_txpwr_ctrl)(struct rtw89_dev *rtwdev);
+       void (*set_txpwr)(struct rtw89_dev *rtwdev,
+                         const struct rtw89_chan *chan,
+                         enum rtw89_phy_idx phy_idx);
+       void (*set_txpwr_ctrl)(struct rtw89_dev *rtwdev,
+                              enum rtw89_phy_idx phy_idx);
        int (*init_txpwr_unit)(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx);
        u8 (*get_thermal)(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path);
        void (*ctrl_btg)(struct rtw89_dev *rtwdev, bool btg);
@@ -2150,6 +2326,7 @@ struct rtw89_chip_ops {
        void (*btc_bt_aci_imp)(struct rtw89_dev *rtwdev);
        void (*btc_update_bt_cnt)(struct rtw89_dev *rtwdev);
        void (*btc_wl_s1_standby)(struct rtw89_dev *rtwdev, bool state);
+       void (*btc_set_policy)(struct rtw89_dev *rtwdev, u16 policy_type);
 };
 
 enum rtw89_dma_ch {
@@ -2384,6 +2561,7 @@ struct rtw89_chip_info {
        const struct rtw89_hfc_param_ini *hfc_param_ini;
        const struct rtw89_dle_mem *dle_mem;
        u32 rf_base_addr[2];
+       u8 support_chanctx_num;
        u8 support_bands;
        bool support_bw160;
        bool hw_sec_hdr;
@@ -2393,6 +2571,9 @@ struct rtw89_chip_info {
        u8 acam_num;
        u8 bcam_num;
        u8 scam_num;
+       u8 bacam_num;
+       u8 bacam_dynamic_num;
+       bool bacam_v1;
 
        u8 sec_ctrl_efuse_size;
        u32 physical_efuse_size;
@@ -2437,6 +2618,19 @@ struct rtw89_chip_info {
        u8 scbd;
        u8 mailbox;
 
+       u8 fcxbtcrpt_ver;
+       u8 fcxtdma_ver;
+       u8 fcxslots_ver;
+       u8 fcxcysta_ver;
+       u8 fcxstep_ver;
+       u8 fcxnullsta_ver;
+       u8 fcxmreg_ver;
+       u8 fcxgpiodbg_ver;
+       u8 fcxbtver_ver;
+       u8 fcxbtscan_ver;
+       u8 fcxbtafh_ver;
+       u8 fcxbtdevinfo_ver;
+
        u8 afh_guard_ch;
        const u8 *wl_rssi_thres;
        const u8 *bt_rssi_thres;
@@ -2536,6 +2730,18 @@ struct rtw89_fw_suit {
 #define RTW89_FW_SUIT_VER_CODE(s)      \
        RTW89_FW_VER_CODE((s)->major_ver, (s)->minor_ver, (s)->sub_ver, (s)->sub_idex)
 
+#define RTW89_MFW_HDR_VER_CODE(mfw_hdr)                \
+       RTW89_FW_VER_CODE((mfw_hdr)->ver.major, \
+                         (mfw_hdr)->ver.minor, \
+                         (mfw_hdr)->ver.sub,   \
+                         (mfw_hdr)->ver.idx)
+
+#define RTW89_FW_HDR_VER_CODE(fw_hdr)                          \
+       RTW89_FW_VER_CODE(GET_FW_HDR_MAJOR_VERSION(fw_hdr),     \
+                         GET_FW_HDR_MINOR_VERSION(fw_hdr),     \
+                         GET_FW_HDR_SUBVERSION(fw_hdr),        \
+                         GET_FW_HDR_SUBINDEX(fw_hdr))
+
 struct rtw89_fw_info {
        const struct firmware *firmware;
        struct rtw89_dev *rtwdev;
@@ -2558,6 +2764,8 @@ struct rtw89_cam_info {
        DECLARE_BITMAP(addr_cam_map, RTW89_MAX_ADDR_CAM_NUM);
        DECLARE_BITMAP(bssid_cam_map, RTW89_MAX_BSSID_CAM_NUM);
        DECLARE_BITMAP(sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
+       DECLARE_BITMAP(ba_cam_map, RTW89_MAX_BA_CAM_NUM);
+       struct rtw89_ba_cam_entry ba_cam_entry[RTW89_MAX_BA_CAM_NUM];
 };
 
 enum rtw89_sar_sources {
@@ -2599,17 +2807,17 @@ struct rtw89_sar_info {
        };
 };
 
+struct rtw89_chanctx_cfg {
+       enum rtw89_sub_entity_idx idx;
+};
+
+enum rtw89_entity_mode {
+       RTW89_ENTITY_MODE_SCC,
+};
+
 struct rtw89_hal {
        u32 rx_fltr;
        u8 cv;
-       u8 current_channel;
-       u32 current_freq;
-       u8 prev_primary_channel;
-       u8 current_primary_channel;
-       enum rtw89_subband current_subband;
-       u8 current_band_width;
-       u8 prev_band_type;
-       u8 current_band_type;
        u32 sw_amsdu_max_size;
        u32 antenna_tx;
        u32 antenna_rx;
@@ -2617,6 +2825,15 @@ struct rtw89_hal {
        u8 rx_nss;
        bool support_cckpd;
        bool support_igi;
+
+       DECLARE_BITMAP(entity_map, NUM_OF_RTW89_SUB_ENTITY);
+       struct cfg80211_chan_def chandef[NUM_OF_RTW89_SUB_ENTITY];
+
+       bool entity_active;
+       enum rtw89_entity_mode entity_mode;
+
+       struct rtw89_chan chan[NUM_OF_RTW89_SUB_ENTITY];
+       struct rtw89_chan_rcd chan_rcd[NUM_OF_RTW89_SUB_ENTITY];
 };
 
 #define RTW89_MAX_MAC_ID_NUM 128
@@ -3119,6 +3336,7 @@ struct rtw89_phy_efuse_gain {
 struct rtw89_dev {
        struct ieee80211_hw *hw;
        struct device *dev;
+       const struct ieee80211_ops *ops;
 
        bool dbcc_en;
        struct rtw89_hw_scan_info scan_info;
@@ -3588,16 +3806,51 @@ struct rtw89_bssid_cam_entry *rtw89_get_bssid_cam_of(struct rtw89_vif *rtwvif,
 
 static inline
 void rtw89_chip_set_channel_prepare(struct rtw89_dev *rtwdev,
-                                   struct rtw89_channel_help_params *p)
+                                   struct rtw89_channel_help_params *p,
+                                   const struct rtw89_chan *chan,
+                                   enum rtw89_mac_idx mac_idx,
+                                   enum rtw89_phy_idx phy_idx)
 {
-       rtwdev->chip->ops->set_channel_help(rtwdev, true, p);
+       rtwdev->chip->ops->set_channel_help(rtwdev, true, p, chan,
+                                           mac_idx, phy_idx);
 }
 
 static inline
 void rtw89_chip_set_channel_done(struct rtw89_dev *rtwdev,
-                                struct rtw89_channel_help_params *p)
+                                struct rtw89_channel_help_params *p,
+                                const struct rtw89_chan *chan,
+                                enum rtw89_mac_idx mac_idx,
+                                enum rtw89_phy_idx phy_idx)
+{
+       rtwdev->chip->ops->set_channel_help(rtwdev, false, p, chan,
+                                           mac_idx, phy_idx);
+}
+
+static inline
+const struct cfg80211_chan_def *rtw89_chandef_get(struct rtw89_dev *rtwdev,
+                                                 enum rtw89_sub_entity_idx idx)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       return &hal->chandef[idx];
+}
+
+static inline
+const struct rtw89_chan *rtw89_chan_get(struct rtw89_dev *rtwdev,
+                                       enum rtw89_sub_entity_idx idx)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       return &hal->chan[idx];
+}
+
+static inline
+const struct rtw89_chan_rcd *rtw89_chan_rcd_get(struct rtw89_dev *rtwdev,
+                                               enum rtw89_sub_entity_idx idx)
 {
-       rtwdev->chip->ops->set_channel_help(rtwdev, false, p);
+       struct rtw89_hal *hal = &rtwdev->hal;
+
+       return &hal->chan_rcd[idx];
 }
 
 static inline void rtw89_chip_fem_setup(struct rtw89_dev *rtwdev)
@@ -3632,12 +3885,13 @@ static inline void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev)
                chip->ops->rfk_channel(rtwdev);
 }
 
-static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev)
+static inline void rtw89_chip_rfk_band_changed(struct rtw89_dev *rtwdev,
+                                              enum rtw89_phy_idx phy_idx)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
 
        if (chip->ops->rfk_band_changed)
-               chip->ops->rfk_band_changed(rtwdev);
+               chip->ops->rfk_band_changed(rtwdev, phy_idx);
 }
 
 static inline void rtw89_chip_rfk_scan(struct rtw89_dev *rtwdev, bool start)
@@ -3661,19 +3915,7 @@ static inline void rtw89_chip_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
        const struct rtw89_chip_info *chip = rtwdev->chip;
 
        if (chip->ops->set_txpwr_ctrl)
-               chip->ops->set_txpwr_ctrl(rtwdev);
-}
-
-static inline void rtw89_chip_set_txpwr(struct rtw89_dev *rtwdev)
-{
-       const struct rtw89_chip_info *chip = rtwdev->chip;
-       u8 ch = rtwdev->hal.current_channel;
-
-       if (!ch)
-               return;
-
-       if (chip->ops->set_txpwr)
-               chip->ops->set_txpwr(rtwdev);
+               chip->ops->set_txpwr_ctrl(rtwdev,  RTW89_PHY_0);
 }
 
 static inline void rtw89_chip_power_trim(struct rtw89_dev *rtwdev)
@@ -3906,12 +4148,20 @@ int rtw89_core_init(struct rtw89_dev *rtwdev);
 void rtw89_core_deinit(struct rtw89_dev *rtwdev);
 int rtw89_core_register(struct rtw89_dev *rtwdev);
 void rtw89_core_unregister(struct rtw89_dev *rtwdev);
+struct rtw89_dev *rtw89_alloc_ieee80211_hw(struct device *device,
+                                          u32 bus_data_size,
+                                          const struct rtw89_chip_info *chip);
+void rtw89_free_ieee80211_hw(struct rtw89_dev *rtwdev);
+void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
+void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
 void rtw89_set_channel(struct rtw89_dev *rtwdev);
 u8 rtw89_core_acquire_bit_map(unsigned long *addr, unsigned long size);
 void rtw89_core_release_bit_map(unsigned long *addr, u8 bit);
 void rtw89_core_release_all_bits_map(unsigned long *addr, unsigned int nbits);
-int rtw89_core_acquire_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
-int rtw89_core_release_sta_ba_entry(struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
+int rtw89_core_acquire_sta_ba_entry(struct rtw89_dev *rtwdev,
+                                   struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
+int rtw89_core_release_sta_ba_entry(struct rtw89_dev *rtwdev,
+                                   struct rtw89_sta *rtwsta, u8 tid, u8 *cam_idx);
 void rtw89_vif_type_mapping(struct ieee80211_vif *vif, bool assoc);
 int rtw89_chip_info_setup(struct rtw89_dev *rtwdev);
 bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate);
index 829c61d..738cfcd 100644 (file)
@@ -525,7 +525,8 @@ static int __print_txpwr_map(struct seq_file *m, struct rtw89_dev *rtwdev,
 
 static void __print_regd(struct seq_file *m, struct rtw89_dev *rtwdev)
 {
-       u8 band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 band = chan->band_type;
        u8 regd = rtw89_regd_get(rtwdev, band);
 
        switch (regd) {
@@ -2305,6 +2306,7 @@ static void rtw89_sta_info_get_iter(void *data, struct ieee80211_sta *sta)
                           he_gi_str[rate->he_gi] : "N/A");
        else
                seq_printf(m, "Legacy %d", rate->legacy);
+       seq_printf(m, "%s", rtwsta->ra_report.might_fallback_legacy ? " FB_G" : "");
        seq_printf(m, "\t(hw_rate=0x%x)", rtwsta->ra_report.hw_rate);
        seq_printf(m, "\t==> agg_wait=%d (%d)\n", rtwsta->max_agg_wait,
                   sta->max_rc_amsdu_len);
@@ -2433,6 +2435,26 @@ void rtw89_vif_ids_get_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
        rtw89_dump_addr_cam(m, &rtwvif->addr_cam);
 }
 
+static void rtw89_dump_ba_cam(struct seq_file *m, struct rtw89_sta *rtwsta)
+{
+       struct rtw89_vif *rtwvif = rtwsta->rtwvif;
+       struct rtw89_dev *rtwdev = rtwvif->rtwdev;
+       struct rtw89_ba_cam_entry *entry;
+       bool first = true;
+
+       list_for_each_entry(entry, &rtwsta->ba_cam_list, list) {
+               if (first) {
+                       seq_puts(m, "\tba_cam ");
+                       first = false;
+               } else {
+                       seq_puts(m, ", ");
+               }
+               seq_printf(m, "tid[%u]=%d", entry->tid,
+                          (int)(entry - rtwdev->cam_info.ba_cam_entry));
+       }
+       seq_puts(m, "\n");
+}
+
 static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
 {
        struct rtw89_sta *rtwsta = (struct rtw89_sta *)sta->drv_priv;
@@ -2441,6 +2463,7 @@ static void rtw89_sta_ids_get_iter(void *data, struct ieee80211_sta *sta)
        seq_printf(m, "STA [%d] %pM %s\n", rtwsta->mac_id, sta->addr,
                   sta->tdls ? "(TDLS)" : "");
        rtw89_dump_addr_cam(m, &rtwsta->addr_cam);
+       rtw89_dump_ba_cam(m, rtwsta);
 }
 
 static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
@@ -2449,6 +2472,8 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
        struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
        struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
 
+       mutex_lock(&rtwdev->mutex);
+
        seq_puts(m, "map:\n");
        seq_printf(m, "\tmac_id:    %*ph\n", (int)sizeof(rtwdev->mac_id_map),
                   rtwdev->mac_id_map);
@@ -2458,12 +2483,16 @@ static int rtw89_debug_priv_stations_get(struct seq_file *m, void *v)
                   cam_info->bssid_cam_map);
        seq_printf(m, "\tsec_cam:   %*ph\n", (int)sizeof(cam_info->sec_cam_map),
                   cam_info->sec_cam_map);
+       seq_printf(m, "\tba_cam:    %*ph\n", (int)sizeof(cam_info->ba_cam_map),
+                  cam_info->ba_cam_map);
 
        ieee80211_iterate_active_interfaces_atomic(rtwdev->hw,
                IEEE80211_IFACE_ITER_NORMAL, rtw89_vif_ids_get_iter, m);
 
        ieee80211_iterate_stations_atomic(rtwdev->hw, rtw89_sta_ids_get_iter, m);
 
+       mutex_unlock(&rtwdev->mutex);
+
        return 0;
 }
 
index 6473015..8e4d0e1 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include "cam.h"
+#include "chan.h"
 #include "coex.h"
 #include "debug.h"
 #include "fw.h"
@@ -247,6 +248,46 @@ static void rtw89_fw_recognize_features(struct rtw89_dev *rtwdev)
        }
 }
 
+void rtw89_early_fw_feature_recognize(struct device *device,
+                                     const struct rtw89_chip_info *chip,
+                                     u32 *early_feat_map)
+{
+       union {
+               struct rtw89_mfw_hdr mfw_hdr;
+               u8 fw_hdr[RTW89_FW_HDR_SIZE];
+       } buf = {};
+       const struct firmware *firmware;
+       u32 ver_code;
+       int ret;
+       int i;
+
+       ret = request_partial_firmware_into_buf(&firmware, chip->fw_name,
+                                               device, &buf, sizeof(buf), 0);
+       if (ret) {
+               dev_err(device, "failed to early request firmware: %d\n", ret);
+               goto out;
+       }
+
+       ver_code = buf.mfw_hdr.sig != RTW89_MFW_SIG ?
+                  RTW89_FW_HDR_VER_CODE(&buf.fw_hdr) :
+                  RTW89_MFW_HDR_VER_CODE(&buf.mfw_hdr);
+       if (!ver_code)
+               goto out;
+
+       for (i = 0; i < ARRAY_SIZE(fw_feat_tbl); i++) {
+               const struct __fw_feat_cfg *ent = &fw_feat_tbl[i];
+
+               if (chip->chip_id != ent->chip_id)
+                       continue;
+
+               if (ent->cond(ver_code, ent->ver_code))
+                       *early_feat_map |= BIT(ent->feature);
+       }
+
+out:
+       release_firmware(firmware);
+}
+
 int rtw89_fw_recognize(struct rtw89_dev *rtwdev)
 {
        int ret;
@@ -638,14 +679,16 @@ EXPORT_SYMBOL(rtw89_fw_h2c_dctl_sec_cam_v1);
 int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
                        bool valid, struct ieee80211_ampdu_params *params)
 {
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       struct rtw89_vif *rtwvif = rtwsta->rtwvif;
        u8 macid = rtwsta->mac_id;
        struct sk_buff *skb;
        u8 entry_idx;
        int ret;
 
        ret = valid ?
-             rtw89_core_acquire_sta_ba_entry(rtwsta, params->tid, &entry_idx) :
-             rtw89_core_release_sta_ba_entry(rtwsta, params->tid, &entry_idx);
+             rtw89_core_acquire_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx) :
+             rtw89_core_release_sta_ba_entry(rtwdev, rtwsta, params->tid, &entry_idx);
        if (ret) {
                /* it still works even if we don't have static BA CAM, because
                 * hardware can create dynamic BA CAM automatically.
@@ -663,7 +706,10 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
        }
        skb_put(skb, H2C_BA_CAM_LEN);
        SET_BA_CAM_MACID(skb->data, macid);
-       SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx);
+       if (chip->bacam_v1)
+               SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx);
+       else
+               SET_BA_CAM_ENTRY_IDX(skb->data, entry_idx);
        if (!valid)
                goto end;
        SET_BA_CAM_VALID(skb->data, valid);
@@ -676,6 +722,11 @@ int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
        SET_BA_CAM_INIT_REQ(skb->data, 1);
        SET_BA_CAM_SSN(skb->data, params->ssn);
 
+       if (chip->bacam_v1) {
+               SET_BA_CAM_STD_EN(skb->data, 1);
+               SET_BA_CAM_BAND(skb->data, rtwvif->mac_idx);
+       }
+
 end:
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
                              H2C_CAT_MAC,
@@ -695,6 +746,56 @@ fail:
        return -EBUSY;
 }
 
+static int rtw89_fw_h2c_init_dynamic_ba_cam_v1(struct rtw89_dev *rtwdev,
+                                              u8 entry_idx, u8 uid)
+{
+       struct sk_buff *skb;
+
+       skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_BA_CAM_LEN);
+       if (!skb) {
+               rtw89_err(rtwdev, "failed to alloc skb for dynamic h2c ba cam\n");
+               return -ENOMEM;
+       }
+       skb_put(skb, H2C_BA_CAM_LEN);
+
+       SET_BA_CAM_VALID(skb->data, 1);
+       SET_BA_CAM_ENTRY_IDX_V1(skb->data, entry_idx);
+       SET_BA_CAM_UID(skb->data, uid);
+       SET_BA_CAM_BAND(skb->data, 0);
+       SET_BA_CAM_STD_EN(skb->data, 0);
+
+       rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+                             H2C_CAT_MAC,
+                             H2C_CL_BA_CAM,
+                             H2C_FUNC_MAC_BA_CAM, 0, 1,
+                             H2C_BA_CAM_LEN);
+
+       if (rtw89_h2c_tx(rtwdev, skb, false)) {
+               rtw89_err(rtwdev, "failed to send h2c\n");
+               goto fail;
+       }
+
+       return 0;
+fail:
+       dev_kfree_skb_any(skb);
+
+       return -EBUSY;
+}
+
+void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+       u8 entry_idx = chip->bacam_num;
+       u8 uid = 0;
+       int i;
+
+       for (i = 0; i < chip->bacam_dynamic_num; i++) {
+               rtw89_fw_h2c_init_dynamic_ba_cam_v1(rtwdev, entry_idx, uid);
+               entry_idx++;
+               uid++;
+       }
+}
+
 #define H2C_LOG_CFG_LEN 12
 int rtw89_fw_h2c_fw_log(struct rtw89_dev *rtwdev, bool enable)
 {
@@ -926,9 +1027,9 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
                                struct ieee80211_sta *sta)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
-       struct rtw89_hal *hal = &rtwdev->hal;
        struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
        struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct sk_buff *skb;
        u8 pads[RTW89_PPE_BW_NUM];
        u8 mac_id = rtwsta ? rtwsta->mac_id : rtwvif->mac_id;
@@ -947,7 +1048,7 @@ int rtw89_fw_h2c_assoc_cmac_tbl(struct rtw89_dev *rtwdev,
        SET_CTRL_INFO_OPERATION(skb->data, 1);
        SET_CMC_TBL_DISRTSFB(skb->data, 1);
        SET_CMC_TBL_DISDATAFB(skb->data, 1);
-       if (hal->current_band_type == RTW89_BAND_2G)
+       if (chan->band_type == RTW89_BAND_2G)
                SET_CMC_TBL_RTS_RTY_LOWEST_RATE(skb->data, RTW89_HW_RATE_CCK1);
        else
                SET_CMC_TBL_RTS_RTY_LOWEST_RATE(skb->data, RTW89_HW_RATE_OFDM6);
@@ -1036,8 +1137,8 @@ fail:
 int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
                               struct rtw89_vif *rtwvif)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct sk_buff *skb;
        struct sk_buff *skb_beacon;
        u16 tim_offset;
@@ -1066,7 +1167,7 @@ int rtw89_fw_h2c_update_beacon(struct rtw89_dev *rtwdev,
        SET_BCN_UPD_MACID(skb->data, rtwvif->mac_id);
        SET_BCN_UPD_SSN_SEL(skb->data, RTW89_MGMT_HW_SSN_SEL);
        SET_BCN_UPD_SSN_MODE(skb->data, RTW89_MGMT_HW_SEQ_MODE);
-       SET_BCN_UPD_RATE(skb->data, hal->current_band_type == RTW89_BAND_2G ?
+       SET_BCN_UPD_RATE(skb->data, chan->band_type == RTW89_BAND_2G ?
                                    RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6);
 
        skb_put_data(skb, skb_beacon->data, skb_beacon->len);
@@ -1407,7 +1508,12 @@ fail:
        return -EBUSY;
 }
 
+#define PORT_DATA_OFFSET 4
+#define H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN 12
 #define H2C_LEN_CXDRVINFO_ROLE (4 + 12 * RTW89_PORT_NUM + H2C_LEN_CXDRVHDR)
+#define H2C_LEN_CXDRVINFO_ROLE_V1 (4 + 16 * RTW89_PORT_NUM + \
+                                  H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN + \
+                                  H2C_LEN_CXDRVHDR)
 int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
 {
        struct rtw89_btc *btc = &rtwdev->btc;
@@ -1416,6 +1522,7 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
        struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
        struct rtw89_btc_wl_active_role *active = role_info->active_role;
        struct sk_buff *skb;
+       u8 offset = 0;
        u8 *cmd;
        int i;
 
@@ -1447,19 +1554,19 @@ int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev)
        RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, bpos->nan);
 
        for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
-               RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, active->connected, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, active->pid, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, active->phy, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, active->noa, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, active->band, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, active->client_ps, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, active->bw, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, active->role, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, active->ch, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, active->tx_lvl, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, active->rx_lvl, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, active->tx_rate, i);
-               RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, active->rx_rate, i);
+               RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, active->connected, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, active->pid, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, active->phy, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, active->noa, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, active->band, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, active->client_ps, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, active->bw, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, active->role, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, active->ch, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, active->tx_lvl, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, active->rx_lvl, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, active->tx_rate, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, active->rx_rate, i, offset);
        }
 
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -1479,6 +1586,87 @@ fail:
        return -EBUSY;
 }
 
+int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_btc *btc = &rtwdev->btc;
+       struct rtw89_btc_wl_info *wl = &btc->cx.wl;
+       struct rtw89_btc_wl_role_info_v1 *role_info = &wl->role_info_v1;
+       struct rtw89_btc_wl_role_info_bpos *bpos = &role_info->role_map.role;
+       struct rtw89_btc_wl_active_role_v1 *active = role_info->active_role_v1;
+       struct sk_buff *skb;
+       u8 *cmd, offset;
+       int i;
+
+       skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, H2C_LEN_CXDRVINFO_ROLE_V1);
+       if (!skb) {
+               rtw89_err(rtwdev, "failed to alloc skb for h2c cxdrv_role\n");
+               return -ENOMEM;
+       }
+       skb_put(skb, H2C_LEN_CXDRVINFO_ROLE_V1);
+       cmd = skb->data;
+
+       RTW89_SET_FWCMD_CXHDR_TYPE(cmd, CXDRVINFO_ROLE);
+       RTW89_SET_FWCMD_CXHDR_LEN(cmd, H2C_LEN_CXDRVINFO_ROLE_V1 - H2C_LEN_CXDRVHDR);
+
+       RTW89_SET_FWCMD_CXROLE_CONNECT_CNT(cmd, role_info->connect_cnt);
+       RTW89_SET_FWCMD_CXROLE_LINK_MODE(cmd, role_info->link_mode);
+
+       RTW89_SET_FWCMD_CXROLE_ROLE_NONE(cmd, bpos->none);
+       RTW89_SET_FWCMD_CXROLE_ROLE_STA(cmd, bpos->station);
+       RTW89_SET_FWCMD_CXROLE_ROLE_AP(cmd, bpos->ap);
+       RTW89_SET_FWCMD_CXROLE_ROLE_VAP(cmd, bpos->vap);
+       RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC(cmd, bpos->adhoc);
+       RTW89_SET_FWCMD_CXROLE_ROLE_ADHOC_MASTER(cmd, bpos->adhoc_master);
+       RTW89_SET_FWCMD_CXROLE_ROLE_MESH(cmd, bpos->mesh);
+       RTW89_SET_FWCMD_CXROLE_ROLE_MONITOR(cmd, bpos->moniter);
+       RTW89_SET_FWCMD_CXROLE_ROLE_P2P_DEV(cmd, bpos->p2p_device);
+       RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GC(cmd, bpos->p2p_gc);
+       RTW89_SET_FWCMD_CXROLE_ROLE_P2P_GO(cmd, bpos->p2p_go);
+       RTW89_SET_FWCMD_CXROLE_ROLE_NAN(cmd, bpos->nan);
+
+       offset = PORT_DATA_OFFSET;
+       for (i = 0; i < RTW89_PORT_NUM; i++, active++) {
+               RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(cmd, active->connected, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_PID(cmd, active->pid, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_PHY(cmd, active->phy, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_NOA(cmd, active->noa, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_BAND(cmd, active->band, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(cmd, active->client_ps, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_BW(cmd, active->bw, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_ROLE(cmd, active->role, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_CH(cmd, active->ch, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(cmd, active->tx_lvl, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(cmd, active->rx_lvl, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(cmd, active->tx_rate, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(cmd, active->rx_rate, i, offset);
+               RTW89_SET_FWCMD_CXROLE_ACT_NOA_DUR(cmd, active->noa_duration, i, offset);
+       }
+
+       offset = H2C_LEN_CXDRVINFO_ROLE_V1 - H2C_LEN_CXDRVINFO_ROLE_DBCC_LEN;
+       RTW89_SET_FWCMD_CXROLE_MROLE_TYPE(cmd, role_info->mrole_type, offset);
+       RTW89_SET_FWCMD_CXROLE_MROLE_NOA(cmd, role_info->mrole_noa_duration, offset);
+       RTW89_SET_FWCMD_CXROLE_DBCC_EN(cmd, role_info->dbcc_en, offset);
+       RTW89_SET_FWCMD_CXROLE_DBCC_CHG(cmd, role_info->dbcc_chg, offset);
+       RTW89_SET_FWCMD_CXROLE_DBCC_2G_PHY(cmd, role_info->dbcc_2g_phy, offset);
+       RTW89_SET_FWCMD_CXROLE_LINK_MODE_CHG(cmd, role_info->link_mode_chg, offset);
+
+       rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+                             H2C_CAT_OUTSRC, BTFC_SET,
+                             SET_DRV_INFO, 0, 0,
+                             H2C_LEN_CXDRVINFO_ROLE_V1);
+
+       if (rtw89_h2c_tx(rtwdev, skb, false)) {
+               rtw89_err(rtwdev, "failed to send h2c\n");
+               goto fail;
+       }
+
+       return 0;
+fail:
+       dev_kfree_skb_any(skb);
+
+       return -EBUSY;
+}
+
 #define H2C_LEN_CXDRVINFO_CTRL (4 + H2C_LEN_CXDRVHDR)
 int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev)
 {
@@ -1788,6 +1976,7 @@ fail:
 
 int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
 {
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
        struct rtw89_fw_h2c_rf_get_mccch *mccch;
        struct sk_buff *skb;
@@ -1804,8 +1993,8 @@ int rtw89_fw_h2c_rf_ntfy_mcc(struct rtw89_dev *rtwdev)
        mccch->ch_1 = cpu_to_le32(mcc_info->ch[1]);
        mccch->band_0 = cpu_to_le32(mcc_info->band[0]);
        mccch->band_1 = cpu_to_le32(mcc_info->band[1]);
-       mccch->current_channel = cpu_to_le32(rtwdev->hal.current_channel);
-       mccch->current_band_type = cpu_to_le32(rtwdev->hal.current_band_type);
+       mccch->current_channel = cpu_to_le32(chan->channel);
+       mccch->current_band_type = cpu_to_le32(chan->band_type);
 
        rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
                              H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_NOTIFY,
@@ -2377,18 +2566,18 @@ out:
 void rtw89_store_op_chan(struct rtw89_dev *rtwdev, bool backup)
 {
        struct rtw89_hw_scan_info *scan_info = &rtwdev->scan_info;
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *cur = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       struct rtw89_chan new;
 
        if (backup) {
-               scan_info->op_pri_ch = hal->current_primary_channel;
-               scan_info->op_chan = hal->current_channel;
-               scan_info->op_bw = hal->current_band_width;
-               scan_info->op_band = hal->current_band_type;
+               scan_info->op_pri_ch = cur->primary_channel;
+               scan_info->op_chan = cur->channel;
+               scan_info->op_bw = cur->band_width;
+               scan_info->op_band = cur->band_type;
        } else {
-               hal->current_primary_channel = scan_info->op_pri_ch;
-               hal->current_channel = scan_info->op_chan;
-               hal->current_band_width = scan_info->op_bw;
-               hal->current_band_type = scan_info->op_band;
+               rtw89_chan_create(&new, scan_info->op_chan, scan_info->op_pri_ch,
+                                 scan_info->op_band, scan_info->op_bw);
+               rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
        }
 }
 
index e75ad22..edd43f0 100644 (file)
@@ -2006,69 +2006,104 @@ static inline void RTW89_SET_FWCMD_CXROLE_ROLE_NAN(void *cmd, u16 val)
        le16p_replace_bits((__le16 *)((u8 *)(cmd) + 4), val, BIT(11));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_CONNECTED(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(0));
+       u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, BIT(0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_PID(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_PID(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, GENMASK(3, 1));
+       u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, GENMASK(3, 1));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_PHY(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_PHY(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(4));
+       u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, BIT(4));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_NOA(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_NOA(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, BIT(5));
+       u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, BIT(5));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_BAND(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_BAND(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (6 + 12 * (n)), val, GENMASK(7, 6));
+       u8p_replace_bits((u8 *)cmd + (6 + (12 + offset) * n), val, GENMASK(7, 6));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_CLIENT_PS(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (7 + 12 * (n)), val, BIT(0));
+       u8p_replace_bits((u8 *)cmd + (7 + (12 + offset) * n), val, BIT(0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_BW(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_BW(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (7 + 12 * (n)), val, GENMASK(7, 1));
+       u8p_replace_bits((u8 *)cmd + (7 + (12 + offset) * n), val, GENMASK(7, 1));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_ROLE(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_ROLE(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (8 + 12 * (n)), val, GENMASK(7, 0));
+       u8p_replace_bits((u8 *)cmd + (8 + (12 + offset) * n), val, GENMASK(7, 0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_CH(void *cmd, u8 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_CH(void *cmd, u8 val, int n, u8 offset)
 {
-       u8p_replace_bits((u8 *)(cmd) + (9 + 12 * (n)), val, GENMASK(7, 0));
+       u8p_replace_bits((u8 *)cmd + (9 + (12 + offset) * n), val, GENMASK(7, 0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(void *cmd, u16 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_LVL(void *cmd, u16 val, int n, u8 offset)
 {
-       le16p_replace_bits((__le16 *)((u8 *)(cmd) + (10 + 12 * (n))), val, GENMASK(15, 0));
+       le16p_replace_bits((__le16 *)((u8 *)cmd + (10 + (12 + offset) * n)), val, GENMASK(15, 0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(void *cmd, u16 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_LVL(void *cmd, u16 val, int n, u8 offset)
 {
-       le16p_replace_bits((__le16 *)((u8 *)(cmd) + (12 + 12 * (n))), val, GENMASK(15, 0));
+       le16p_replace_bits((__le16 *)((u8 *)cmd + (12 + (12 + offset) * n)), val, GENMASK(15, 0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(void *cmd, u16 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_TX_RATE(void *cmd, u16 val, int n, u8 offset)
 {
-       le16p_replace_bits((__le16 *)((u8 *)(cmd) + (14 + 12 * (n))), val, GENMASK(15, 0));
+       le16p_replace_bits((__le16 *)((u8 *)cmd + (14 + (12 + offset) * n)), val, GENMASK(15, 0));
 }
 
-static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(void *cmd, u16 val, int n)
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_RX_RATE(void *cmd, u16 val, int n, u8 offset)
 {
-       le16p_replace_bits((__le16 *)((u8 *)(cmd) + (16 + 12 * (n))), val, GENMASK(15, 0));
+       le16p_replace_bits((__le16 *)((u8 *)cmd + (16 + (12 + offset) * n)), val, GENMASK(15, 0));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_ACT_NOA_DUR(void *cmd, u32 val, int n, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + (20 + (12 + offset) * n)), val, GENMASK(31, 0));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_MROLE_TYPE(void *cmd, u32 val, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + offset), val, GENMASK(31, 0));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_MROLE_NOA(void *cmd, u32 val, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 4), val, GENMASK(31, 0));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_DBCC_EN(void *cmd, u32 val, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, BIT(0));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_DBCC_CHG(void *cmd, u32 val, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, BIT(1));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_DBCC_2G_PHY(void *cmd, u32 val, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, GENMASK(3, 2));
+}
+
+static inline void RTW89_SET_FWCMD_CXROLE_LINK_MODE_CHG(void *cmd, u32 val, u8 offset)
+{
+       le32p_replace_bits((__le32 *)((u8 *)cmd + offset + 8), val, BIT(4));
 }
 
 static inline void RTW89_SET_FWCMD_CXCTRL_MANUAL(void *cmd, u32 val)
@@ -2446,7 +2481,14 @@ struct rtw89_mfw_info {
 struct rtw89_mfw_hdr {
        u8 sig; /* RTW89_MFW_SIG */
        u8 fw_nr;
-       u8 rsvd[14];
+       u8 rsvd0[2];
+       struct {
+               u8 major;
+               u8 minor;
+               u8 sub;
+               u8 idx;
+       } ver;
+       u8 rsvd1[8];
        struct rtw89_mfw_info info[];
 } __packed;
 
@@ -2563,6 +2605,9 @@ struct rtw89_fw_h2c_rf_get_mccch {
 
 int rtw89_fw_check_rdy(struct rtw89_dev *rtwdev);
 int rtw89_fw_recognize(struct rtw89_dev *rtwdev);
+void rtw89_early_fw_feature_recognize(struct device *device,
+                                     const struct rtw89_chip_info *chip,
+                                     u32 *early_feat_map);
 int rtw89_fw_download(struct rtw89_dev *rtwdev, enum rtw89_fw_type type);
 int rtw89_load_firmware(struct rtw89_dev *rtwdev);
 void rtw89_unload_firmware(struct rtw89_dev *rtwdev);
@@ -2600,6 +2645,7 @@ int rtw89_fw_h2c_set_ofld_cfg(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_ra(struct rtw89_dev *rtwdev, struct rtw89_ra_info *ra, bool csi);
 int rtw89_fw_h2c_cxdrv_init(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_cxdrv_role(struct rtw89_dev *rtwdev);
+int rtw89_fw_h2c_cxdrv_role_v1(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_cxdrv_ctrl(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_cxdrv_rfk(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_del_pkt_offload(struct rtw89_dev *rtwdev, u8 id);
@@ -2623,6 +2669,7 @@ void rtw89_fw_free_all_early_h2c(struct rtw89_dev *rtwdev);
 int rtw89_fw_h2c_general_pkt(struct rtw89_dev *rtwdev, u8 macid);
 int rtw89_fw_h2c_ba_cam(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta,
                        bool valid, struct ieee80211_ampdu_params *params);
+void rtw89_fw_h2c_init_ba_cam_v1(struct rtw89_dev *rtwdev);
 
 int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
                          struct rtw89_lps_parm *lps_param);
@@ -2643,4 +2690,12 @@ int rtw89_hw_scan_offload(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif,
 void rtw89_hw_scan_abort(struct rtw89_dev *rtwdev, struct ieee80211_vif *vif);
 int rtw89_fw_h2c_trigger_cpu_exception(struct rtw89_dev *rtwdev);
 
+static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
+{
+       const struct rtw89_chip_info *chip = rtwdev->chip;
+
+       if (chip->bacam_v1)
+               rtw89_fw_h2c_init_ba_cam_v1(rtwdev);
+}
+
 #endif
index 93124b8..f5bae0b 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include "cam.h"
+#include "chan.h"
 #include "debug.h"
 #include "fw.h"
 #include "mac.h"
@@ -1053,18 +1054,29 @@ void rtw89_mac_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
        enum rtw89_rpwm_req_pwr_state state;
        unsigned long delay = enter ? 10 : 150;
        int ret;
+       int i;
 
        if (enter)
                state = rtw89_mac_get_req_pwr_state(rtwdev);
        else
                state = RTW89_MAC_RPWM_REQ_PWR_STATE_ACTIVE;
 
-       rtw89_mac_send_rpwm(rtwdev, state, false);
-       ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret, !ret,
-                                      delay, 15000, false, rtwdev, state);
-       if (ret)
-               rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
-                         enter ? "entering" : "leaving");
+       for (i = 0; i < RPWM_TRY_CNT; i++) {
+               rtw89_mac_send_rpwm(rtwdev, state, false);
+               ret = read_poll_timeout_atomic(rtw89_mac_check_cpwm_state, ret,
+                                              !ret, delay, 15000, false,
+                                              rtwdev, state);
+               if (!ret)
+                       break;
+
+               if (i == RPWM_TRY_CNT - 1)
+                       rtw89_err(rtwdev, "firmware failed to ack for %s ps mode\n",
+                                 enter ? "entering" : "leaving");
+               else
+                       rtw89_debug(rtwdev, RTW89_DBG_UNEXP,
+                                   "%d time firmware failed to ack for %s ps mode\n",
+                                   i + 1, enter ? "entering" : "leaving");
+       }
 }
 
 void rtw89_mac_notify_wake(struct rtw89_dev *rtwdev)
@@ -1081,7 +1093,6 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
        const struct rtw89_chip_info *chip = rtwdev->chip;
        const struct rtw89_pwr_cfg * const *cfg_seq;
        int (*cfg_func)(struct rtw89_dev *rtwdev);
-       struct rtw89_hal *hal = &rtwdev->hal;
        int ret;
        u8 val;
 
@@ -1113,7 +1124,7 @@ static int rtw89_mac_power_switch(struct rtw89_dev *rtwdev, bool on)
                clear_bit(RTW89_FLAG_POWERON, rtwdev->flags);
                clear_bit(RTW89_FLAG_FW_RDY, rtwdev->flags);
                rtw89_write8(rtwdev, R_AX_SCOREBOARD + 3, MAC_AX_NOTIFY_PWR_MAJOR);
-               hal->current_channel = 0;
+               rtw89_set_entity_state(rtwdev, false);
        }
 
        return 0;
@@ -1734,7 +1745,7 @@ static int addr_cam_init(struct rtw89_dev *rtwdev, u8 mac_idx)
        rtw89_write32(rtwdev, reg, val);
 
        ret = read_poll_timeout(rtw89_read16, p_val, !(p_val & B_AX_ADDR_CAM_CLR),
-                               1, TRXCFG_WAIT_CNT, false, rtwdev, B_AX_ADDR_CAM_CLR);
+                               1, TRXCFG_WAIT_CNT, false, rtwdev, reg);
        if (ret) {
                rtw89_err(rtwdev, "[ERR]ADDR_CAM reset\n");
                return ret;
@@ -1747,13 +1758,19 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx)
 {
        u32 ret;
        u32 reg;
+       u32 val;
 
        ret = rtw89_mac_check_mac_en(rtwdev, mac_idx, RTW89_CMAC_SEL);
        if (ret)
                return ret;
 
        reg = rtw89_mac_reg_by_idx(R_AX_PREBKF_CFG_1, mac_idx);
-       rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK, SIFS_MACTXEN_T1);
+       if (rtwdev->chip->chip_id == RTL8852C)
+               rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
+                                  SIFS_MACTXEN_T1_V1);
+       else
+               rtw89_write32_mask(rtwdev, reg, B_AX_SIFS_MACTXEN_T1_MASK,
+                                  SIFS_MACTXEN_T1);
 
        if (rtwdev->chip->chip_id == RTL8852B) {
                reg = rtw89_mac_reg_by_idx(R_AX_SCH_EXT_CTRL, mac_idx);
@@ -1764,7 +1781,16 @@ static int scheduler_init(struct rtw89_dev *rtwdev, u8 mac_idx)
        rtw89_write32_clr(rtwdev, reg, B_AX_BTCCA_EN);
 
        reg = rtw89_mac_reg_by_idx(R_AX_PREBKF_CFG_0, mac_idx);
-       rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK, SCH_PREBKF_24US);
+       if (rtwdev->chip->chip_id == RTL8852C) {
+               val = rtw89_read32_mask(rtwdev, R_AX_SEC_ENG_CTRL,
+                                       B_AX_TX_PARTIAL_MODE);
+               if (!val)
+                       rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK,
+                                          SCH_PREBKF_24US);
+       } else {
+               rtw89_write32_mask(rtwdev, reg, B_AX_PREBKF_TIME_MASK,
+                                  SCH_PREBKF_24US);
+       }
 
        return 0;
 }
@@ -3524,6 +3550,26 @@ static void rtw89_mac_port_cfg_bcn_early(struct rtw89_dev *rtwdev,
                                BCN_ERLY_DEF);
 }
 
+static void rtw89_mac_port_cfg_tbtt_shift(struct rtw89_dev *rtwdev,
+                                         struct rtw89_vif *rtwvif)
+{
+       const struct rtw89_port_reg *p = &rtw_port_base;
+       u16 val;
+
+       if (rtwdev->chip->chip_id != RTL8852C)
+               return;
+
+       if (rtwvif->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT &&
+           rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
+               return;
+
+       val = FIELD_PREP(B_AX_TBTT_SHIFT_OFST_MAG, 1) |
+                        B_AX_TBTT_SHIFT_OFST_SIGN;
+
+       rtw89_write16_port_mask(rtwdev, rtwvif, p->tbtt_shift,
+                               B_AX_TBTT_SHIFT_OFST_MASK, val);
+}
+
 int rtw89_mac_vif_init(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
        int ret;
@@ -3598,6 +3644,7 @@ int rtw89_mac_port_update(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
        rtw89_mac_port_cfg_bcn_hold_time(rtwdev, rtwvif);
        rtw89_mac_port_cfg_bcn_mask_area(rtwdev, rtwvif);
        rtw89_mac_port_cfg_tbtt_early(rtwdev, rtwvif);
+       rtw89_mac_port_cfg_tbtt_shift(rtwdev, rtwvif);
        rtw89_mac_port_cfg_bss_color(rtwdev, rtwvif);
        rtw89_mac_port_cfg_mbssid(rtwdev, rtwvif);
        rtw89_mac_port_cfg_func_en(rtwdev, rtwvif);
@@ -3655,7 +3702,7 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
                           u32 len)
 {
        struct ieee80211_vif *vif = rtwdev->scan_info.scanning_vif;
-       struct rtw89_hal *hal = &rtwdev->hal;
+       struct rtw89_chan new;
        u8 reason, status, tx_fail, band;
        u16 chan;
 
@@ -3681,12 +3728,8 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
                rtw89_hw_scan_complete(rtwdev, vif, false);
                break;
        case RTW89_SCAN_ENTER_CH_NOTIFY:
-               hal->prev_band_type = hal->current_band_type;
-               hal->current_band_type = band;
-               hal->prev_primary_channel = hal->current_primary_channel;
-               hal->current_primary_channel = chan;
-               hal->current_channel = chan;
-               hal->current_band_width = RTW89_CHANNEL_WIDTH_20;
+               rtw89_chan_create(&new, chan, chan, band, RTW89_CHANNEL_WIDTH_20);
+               rtw89_assign_entity_chan(rtwdev, RTW89_SUB_ENTITY_0, &new);
                if (rtw89_is_op_chan(rtwdev, band, chan)) {
                        rtw89_store_op_chan(rtwdev, false);
                        ieee80211_wake_queues(rtwdev->hw);
index f666193..986e359 100644 (file)
@@ -11,6 +11,7 @@
 #define ADDR_CAM_ENT_SIZE  0x40
 #define BSSID_CAM_ENT_SIZE 0x08
 #define HFC_PAGE_UNIT 64
+#define RPWM_TRY_CNT 3
 
 enum rtw89_mac_hwmod_sel {
        RTW89_DMAC_SEL = 0,
index cef27e7..668370c 100644 (file)
@@ -3,6 +3,7 @@
  */
 
 #include "cam.h"
+#include "chan.h"
 #include "coex.h"
 #include "debug.h"
 #include "fw.h"
@@ -85,8 +86,11 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, u32 changed)
                }
        }
 
-       if (changed & IEEE80211_CONF_CHANGE_CHANNEL)
+       if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+               rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0,
+                                           &hw->conf.chandef);
                rtw89_set_channel(rtwdev);
+       }
 
        if ((changed & IEEE80211_CONF_CHANGE_IDLE) &&
            (hw->conf.flags & IEEE80211_CONF_IDLE))
@@ -235,11 +239,12 @@ static u8 rtw89_aifsn_to_aifs(struct rtw89_dev *rtwdev,
                              struct rtw89_vif *rtwvif, u8 aifsn)
 {
        struct ieee80211_vif *vif = rtwvif_to_vif(rtwvif);
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u8 slot_time;
        u8 sifs;
 
        slot_time = vif->bss_conf.use_short_slot ? 9 : 20;
-       sifs = rtwdev->hal.current_band_type == RTW89_BAND_5G ? 16 : 10;
+       sifs = chan->band_type == RTW89_BAND_5G ? 16 : 10;
 
        return aifsn * slot_time + sifs;
 }
@@ -772,6 +777,69 @@ static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw,
        rtw89_phy_ra_updata_sta(rtwdev, sta, changed);
 }
 
+static int rtw89_ops_add_chanctx(struct ieee80211_hw *hw,
+                                struct ieee80211_chanctx_conf *ctx)
+{
+       struct rtw89_dev *rtwdev = hw->priv;
+       int ret;
+
+       mutex_lock(&rtwdev->mutex);
+       ret = rtw89_chanctx_ops_add(rtwdev, ctx);
+       mutex_unlock(&rtwdev->mutex);
+
+       return ret;
+}
+
+static void rtw89_ops_remove_chanctx(struct ieee80211_hw *hw,
+                                    struct ieee80211_chanctx_conf *ctx)
+{
+       struct rtw89_dev *rtwdev = hw->priv;
+
+       mutex_lock(&rtwdev->mutex);
+       rtw89_chanctx_ops_remove(rtwdev, ctx);
+       mutex_unlock(&rtwdev->mutex);
+}
+
+static void rtw89_ops_change_chanctx(struct ieee80211_hw *hw,
+                                    struct ieee80211_chanctx_conf *ctx,
+                                    u32 changed)
+{
+       struct rtw89_dev *rtwdev = hw->priv;
+
+       mutex_lock(&rtwdev->mutex);
+       rtw89_chanctx_ops_change(rtwdev, ctx, changed);
+       mutex_unlock(&rtwdev->mutex);
+}
+
+static int rtw89_ops_assign_vif_chanctx(struct ieee80211_hw *hw,
+                                       struct ieee80211_vif *vif,
+                                       struct ieee80211_bss_conf *link_conf,
+                                       struct ieee80211_chanctx_conf *ctx)
+{
+       struct rtw89_dev *rtwdev = hw->priv;
+       struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+       int ret;
+
+       mutex_lock(&rtwdev->mutex);
+       ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif, ctx);
+       mutex_unlock(&rtwdev->mutex);
+
+       return ret;
+}
+
+static void rtw89_ops_unassign_vif_chanctx(struct ieee80211_hw *hw,
+                                          struct ieee80211_vif *vif,
+                                          struct ieee80211_bss_conf *link_conf,
+                                          struct ieee80211_chanctx_conf *ctx)
+{
+       struct rtw89_dev *rtwdev = hw->priv;
+       struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
+
+       mutex_lock(&rtwdev->mutex);
+       rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif, ctx);
+       mutex_unlock(&rtwdev->mutex);
+}
+
 const struct ieee80211_ops rtw89_ops = {
        .tx                     = rtw89_ops_tx,
        .wake_tx_queue          = rtw89_ops_wake_tx_queue,
@@ -800,6 +868,11 @@ const struct ieee80211_ops rtw89_ops = {
        .reconfig_complete      = rtw89_ops_reconfig_complete,
        .hw_scan                = rtw89_ops_hw_scan,
        .cancel_hw_scan         = rtw89_ops_cancel_hw_scan,
+       .add_chanctx            = rtw89_ops_add_chanctx,
+       .remove_chanctx         = rtw89_ops_remove_chanctx,
+       .change_chanctx         = rtw89_ops_change_chanctx,
+       .assign_vif_chanctx     = rtw89_ops_assign_vif_chanctx,
+       .unassign_vif_chanctx   = rtw89_ops_unassign_vif_chanctx,
        .set_sar_specs          = rtw89_ops_set_sar_specs,
        .sta_rc_update          = rtw89_ops_sta_rc_update,
 };
index c68fec9..d2cbe04 100644 (file)
@@ -760,7 +760,8 @@ static irqreturn_t rtw89_pci_interrupt_threadfn(int irq, void *dev)
 
 enable_intr:
        spin_lock_irqsave(&rtwpci->irq_lock, flags);
-       rtw89_chip_enable_intr(rtwdev, rtwpci);
+       if (likely(rtwpci->running))
+               rtw89_chip_enable_intr(rtwdev, rtwpci);
        spin_unlock_irqrestore(&rtwpci->irq_lock, flags);
        return IRQ_HANDLED;
 }
@@ -925,10 +926,12 @@ u32 __rtw89_pci_check_and_reclaim_tx_resource_noio(struct rtw89_dev *rtwdev,
 {
        struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
        struct rtw89_pci_tx_ring *tx_ring = &rtwpci->tx_rings[txch];
+       struct rtw89_pci_tx_wd_ring *wd_ring = &tx_ring->wd_ring;
        u32 cnt;
 
        spin_lock_bh(&rtwpci->trx_lock);
        cnt = rtw89_pci_get_avail_txbd_num(tx_ring);
+       cnt = min(cnt, wd_ring->curr_num);
        spin_unlock_bh(&rtwpci->trx_lock);
 
        return cnt;
@@ -1627,6 +1630,8 @@ static void rtw89_pci_ctrl_dma_all(struct rtw89_dev *rtwdev, bool enable)
                else
                        rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
                                          B_AX_STOP_AXI_MST);
+               rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
+                                 txhci_en | rxhci_en);
                if (chip_id == RTL8852C)
                        rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
                                          B_AX_STOP_AXI_MST);
@@ -3219,8 +3224,79 @@ static void rtw89_pci_free_irq(struct rtw89_dev *rtwdev,
        pci_free_irq_vectors(pdev);
 }
 
+static u16 gray_code_to_bin(u16 gray_code, u32 bit_num)
+{
+       u16 bin = 0, gray_bit;
+       u32 bit_idx;
+
+       for (bit_idx = 0; bit_idx < bit_num; bit_idx++) {
+               gray_bit = (gray_code >> bit_idx) & 0x1;
+               if (bit_num - bit_idx > 1)
+                       gray_bit ^= (gray_code >> (bit_idx + 1)) & 0x1;
+               bin |= (gray_bit << bit_idx);
+       }
+
+       return bin;
+}
+
+static int rtw89_pci_filter_out(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_pci *rtwpci = (struct rtw89_pci *)rtwdev->priv;
+       struct pci_dev *pdev = rtwpci->pdev;
+       u16 val16, filter_out_val;
+       u32 val, phy_offset;
+       int ret;
+
+       if (rtwdev->chip->chip_id != RTL8852C)
+               return 0;
+
+       val = rtw89_read32_mask(rtwdev, R_AX_PCIE_MIX_CFG_V1, B_AX_ASPM_CTRL_MASK);
+       if (val == B_AX_ASPM_CTRL_L1)
+               return 0;
+
+       ret = pci_read_config_dword(pdev, RTW89_PCIE_L1_STS_V1, &val);
+       if (ret)
+               return ret;
+
+       val = FIELD_GET(RTW89_BCFG_LINK_SPEED_MASK, val);
+       if (val == RTW89_PCIE_GEN1_SPEED) {
+               phy_offset = R_RAC_DIRECT_OFFSET_G1;
+       } else if (val == RTW89_PCIE_GEN2_SPEED) {
+               phy_offset = R_RAC_DIRECT_OFFSET_G2;
+               val16 = rtw89_read16(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT);
+               rtw89_write16_set(rtwdev, phy_offset + RAC_ANA10 * RAC_MULT,
+                                 val16 | B_PCIE_BIT_PINOUT_DIS);
+               rtw89_write16_set(rtwdev, phy_offset + RAC_ANA19 * RAC_MULT,
+                                 val16 & ~B_PCIE_BIT_RD_SEL);
+
+               val16 = rtw89_read16_mask(rtwdev,
+                                         phy_offset + RAC_ANA1F * RAC_MULT,
+                                         FILTER_OUT_EQ_MASK);
+               val16 = gray_code_to_bin(val16, hweight16(val16));
+               filter_out_val = rtw89_read16(rtwdev, phy_offset + RAC_ANA24 *
+                                             RAC_MULT);
+               filter_out_val &= ~REG_FILTER_OUT_MASK;
+               filter_out_val |= FIELD_PREP(REG_FILTER_OUT_MASK, val16);
+
+               rtw89_write16(rtwdev, phy_offset + RAC_ANA24 * RAC_MULT,
+                             filter_out_val);
+               rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0A * RAC_MULT,
+                                 B_BAC_EQ_SEL);
+               rtw89_write16_set(rtwdev,
+                                 R_RAC_DIRECT_OFFSET_G1 + RAC_ANA0C * RAC_MULT,
+                                 B_PCIE_BIT_PSAVE);
+       } else {
+               return -EOPNOTSUPP;
+       }
+       rtw89_write16_set(rtwdev, phy_offset + RAC_ANA0C * RAC_MULT,
+                         B_PCIE_BIT_PSAVE);
+
+       return 0;
+}
+
 static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable)
 {
+       enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
        int ret;
 
        if (rtw89_pci_disable_clkreq)
@@ -3231,19 +3307,33 @@ static void rtw89_pci_clkreq_set(struct rtw89_dev *rtwdev, bool enable)
        if (ret)
                rtw89_err(rtwdev, "failed to set CLKREQ Delay\n");
 
-       if (enable)
-               ret = rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL,
-                                               RTW89_PCIE_BIT_CLK);
-       else
-               ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1_CTRL,
-                                               RTW89_PCIE_BIT_CLK);
-       if (ret)
-               rtw89_err(rtwdev, "failed to %s CLKREQ_L1, ret=%d",
-                         enable ? "set" : "unset", ret);
+       if (chip_id == RTL8852A) {
+               if (enable)
+                       ret = rtw89_pci_config_byte_set(rtwdev,
+                                                       RTW89_PCIE_L1_CTRL,
+                                                       RTW89_PCIE_BIT_CLK);
+               else
+                       ret = rtw89_pci_config_byte_clr(rtwdev,
+                                                       RTW89_PCIE_L1_CTRL,
+                                                       RTW89_PCIE_BIT_CLK);
+               if (ret)
+                       rtw89_err(rtwdev, "failed to %s CLKREQ_L1, ret=%d",
+                                 enable ? "set" : "unset", ret);
+       } else if (chip_id == RTL8852C) {
+               rtw89_write32_set(rtwdev, R_AX_PCIE_LAT_CTRL,
+                                 B_AX_CLK_REQ_SEL_OPT | B_AX_CLK_REQ_SEL);
+               if (enable)
+                       rtw89_write32_set(rtwdev, R_AX_L1_CLK_CTRL,
+                                         B_AX_CLK_REQ_N);
+               else
+                       rtw89_write32_clr(rtwdev, R_AX_L1_CLK_CTRL,
+                                         B_AX_CLK_REQ_N);
+       }
 }
 
 static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable)
 {
+       enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
        u8 value = 0;
        int ret;
 
@@ -3262,12 +3352,23 @@ static void rtw89_pci_aspm_set(struct rtw89_dev *rtwdev, bool enable)
        if (ret)
                rtw89_err(rtwdev, "failed to read ASPM Delay\n");
 
-       if (enable)
-               ret = rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_L1_CTRL,
-                                               RTW89_PCIE_BIT_L1);
-       else
-               ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1_CTRL,
-                                               RTW89_PCIE_BIT_L1);
+       if (chip_id == RTL8852A || chip_id == RTL8852B) {
+               if (enable)
+                       ret = rtw89_pci_config_byte_set(rtwdev,
+                                                       RTW89_PCIE_L1_CTRL,
+                                                       RTW89_PCIE_BIT_L1);
+               else
+                       ret = rtw89_pci_config_byte_clr(rtwdev,
+                                                       RTW89_PCIE_L1_CTRL,
+                                                       RTW89_PCIE_BIT_L1);
+       } else if (chip_id == RTL8852C) {
+               if (enable)
+                       rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1,
+                                         B_AX_ASPM_CTRL_L1);
+               else
+                       rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1,
+                                         B_AX_ASPM_CTRL_L1);
+       }
        if (ret)
                rtw89_err(rtwdev, "failed to %s ASPM L1, ret=%d",
                          enable ? "set" : "unset", ret);
@@ -3328,17 +3429,34 @@ static void rtw89_pci_link_cfg(struct rtw89_dev *rtwdev)
 
 static void rtw89_pci_l1ss_set(struct rtw89_dev *rtwdev, bool enable)
 {
+       enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
        int ret;
 
-       if (enable)
-               ret = rtw89_pci_config_byte_set(rtwdev, RTW89_PCIE_TIMER_CTRL,
-                                               RTW89_PCIE_BIT_L1SUB);
-       else
-               ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_TIMER_CTRL,
-                                               RTW89_PCIE_BIT_L1SUB);
-       if (ret)
-               rtw89_err(rtwdev, "failed to %s L1SS, ret=%d",
-                         enable ? "set" : "unset", ret);
+       if (chip_id == RTL8852A || chip_id == RTL8852B) {
+               if (enable)
+                       ret = rtw89_pci_config_byte_set(rtwdev,
+                                                       RTW89_PCIE_TIMER_CTRL,
+                                                       RTW89_PCIE_BIT_L1SUB);
+               else
+                       ret = rtw89_pci_config_byte_clr(rtwdev,
+                                                       RTW89_PCIE_TIMER_CTRL,
+                                                       RTW89_PCIE_BIT_L1SUB);
+               if (ret)
+                       rtw89_err(rtwdev, "failed to %s L1SS, ret=%d",
+                                 enable ? "set" : "unset", ret);
+       } else if (chip_id == RTL8852C) {
+               ret = rtw89_pci_config_byte_clr(rtwdev, RTW89_PCIE_L1SS_STS_V1,
+                                               RTW89_PCIE_BIT_ASPM_L11 |
+                                               RTW89_PCIE_BIT_PCI_L11);
+               if (ret)
+                       rtw89_warn(rtwdev, "failed to unset ASPM L1.1, ret=%d", ret);
+               if (enable)
+                       rtw89_write32_clr(rtwdev, R_AX_PCIE_MIX_CFG_V1,
+                                         B_AX_L1SUB_DISABLE);
+               else
+                       rtw89_write32_set(rtwdev, R_AX_PCIE_MIX_CFG_V1,
+                                         B_AX_L1SUB_DISABLE);
+       }
 }
 
 static void rtw89_pci_l1ss_cfg(struct rtw89_dev *rtwdev)
@@ -3535,14 +3653,20 @@ static int __maybe_unused rtw89_pci_suspend(struct device *dev)
 {
        struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct rtw89_dev *rtwdev = hw->priv;
+       enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
 
-       rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL,
-                         B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
        rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
        rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
        rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
-       rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
-                         B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
+       if (chip_id == RTL8852A || chip_id == RTL8852B) {
+               rtw89_write32_clr(rtwdev, R_AX_SYS_SDIO_CTRL,
+                                 B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
+               rtw89_write32_set(rtwdev, R_AX_PCIE_INIT_CFG1,
+                                 B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
+       } else {
+               rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1,
+                                 B_AX_CMAC_EXIT_L1_EN | B_AX_DMAC0_EXIT_L1_EN);
+       }
 
        return 0;
 }
@@ -3563,15 +3687,24 @@ static int __maybe_unused rtw89_pci_resume(struct device *dev)
 {
        struct ieee80211_hw *hw = dev_get_drvdata(dev);
        struct rtw89_dev *rtwdev = hw->priv;
+       enum rtw89_core_chip_id chip_id = rtwdev->chip->chip_id;
 
-       rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL,
-                         B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
        rtw89_write32_set(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
        rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_R_DIS_PRST);
        rtw89_write32_clr(rtwdev, R_AX_RSV_CTRL, B_AX_WLOCK_1C_BIT6);
-       rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
-                         B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
+       if (chip_id == RTL8852A || chip_id == RTL8852B) {
+               rtw89_write32_set(rtwdev, R_AX_SYS_SDIO_CTRL,
+                                 B_AX_PCIE_DIS_L2_CTRL_LDO_HCI);
+               rtw89_write32_clr(rtwdev, R_AX_PCIE_INIT_CFG1,
+                                 B_AX_PCIE_PERST_KEEP_REG | B_AX_PCIE_TRAIN_KEEP_REG);
+       } else {
+               rtw89_write32_set(rtwdev, R_AX_PCIE_PS_CTRL_V1,
+                                 B_AX_CMAC_EXIT_L1_EN | B_AX_DMAC0_EXIT_L1_EN);
+               rtw89_write32_clr(rtwdev, R_AX_PCIE_PS_CTRL_V1,
+                                 B_AX_SEL_REQ_ENTR_L1);
+       }
        rtw89_pci_l2_hci_ldo(rtwdev);
+       rtw89_pci_filter_out(rtwdev);
        rtw89_pci_link_cfg(rtwdev);
        rtw89_pci_l1ss_cfg(rtwdev);
 
@@ -3614,27 +3747,23 @@ static const struct rtw89_hci_ops rtw89_pci_ops = {
 
 int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-       struct ieee80211_hw *hw;
        struct rtw89_dev *rtwdev;
        const struct rtw89_driver_info *info;
        const struct rtw89_pci_info *pci_info;
-       int driver_data_size;
        int ret;
 
-       driver_data_size = sizeof(struct rtw89_dev) + sizeof(struct rtw89_pci);
-       hw = ieee80211_alloc_hw(driver_data_size, &rtw89_ops);
-       if (!hw) {
+       info = (const struct rtw89_driver_info *)id->driver_data;
+
+       rtwdev = rtw89_alloc_ieee80211_hw(&pdev->dev,
+                                         sizeof(struct rtw89_pci),
+                                         info->chip);
+       if (!rtwdev) {
                dev_err(&pdev->dev, "failed to allocate hw\n");
                return -ENOMEM;
        }
 
-       info = (const struct rtw89_driver_info *)id->driver_data;
        pci_info = info->bus.pci;
 
-       rtwdev = hw->priv;
-       rtwdev->hw = hw;
-       rtwdev->dev = &pdev->dev;
-       rtwdev->chip = info->chip;
        rtwdev->pci_info = info->bus.pci;
        rtwdev->hci.ops = &rtw89_pci_ops;
        rtwdev->hci.type = RTW89_HCI_TYPE_PCIE;
@@ -3667,6 +3796,7 @@ int rtw89_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto err_clear_resource;
        }
 
+       rtw89_pci_filter_out(rtwdev);
        rtw89_pci_link_cfg(rtwdev);
        rtw89_pci_l1ss_cfg(rtwdev);
 
@@ -3696,7 +3826,7 @@ err_declaim_pci:
 err_core_deinit:
        rtw89_core_deinit(rtwdev);
 err_release_hw:
-       ieee80211_free_hw(hw);
+       rtw89_free_ieee80211_hw(rtwdev);
 
        return ret;
 }
@@ -3715,7 +3845,7 @@ void rtw89_pci_remove(struct pci_dev *pdev)
        rtw89_pci_clear_resource(rtwdev, pdev);
        rtw89_pci_declaim_device(rtwdev, pdev);
        rtw89_core_deinit(rtwdev);
-       ieee80211_free_hw(hw);
+       rtw89_free_ieee80211_hw(rtwdev);
 }
 EXPORT_SYMBOL(rtw89_pci_remove);
 
index a118647..63dc6d4 100644 (file)
 #define MDIO_PG1_G1 1
 #define MDIO_PG0_G2 2
 #define MDIO_PG1_G2 3
+#define RAC_CTRL_PPR                   0x00
+#define RAC_ANA0A                      0x0A
+#define B_BAC_EQ_SEL                   BIT(5)
+#define RAC_ANA0C                      0x0C
+#define B_PCIE_BIT_PSAVE               BIT(15)
 #define RAC_ANA10                      0x10
+#define B_PCIE_BIT_PINOUT_DIS          BIT(3)
 #define RAC_REG_REV2                   0x1B
 #define BAC_CMU_EN_DLY_MASK            GENMASK(15, 12)
 #define PCIE_DPHY_DLY_25US             0x1
 #define RAC_ANA19                      0x19
+#define B_PCIE_BIT_RD_SEL              BIT(2)
 #define RAC_ANA1F                      0x1F
 #define RAC_ANA24                      0x24
 #define B_AX_DEGLITCH                  GENMASK(11, 8)
 #define B_AX_SEL_REQ_ENTR_L1           BIT(2)
 #define B_AX_SEL_REQ_EXIT_L1           BIT(0)
 
+#define R_AX_PCIE_MIX_CFG_V1           0x300C
+#define B_AX_ASPM_CTRL_L1              BIT(17)
+#define B_AX_ASPM_CTRL_L0              BIT(16)
+#define B_AX_ASPM_CTRL_MASK            GENMASK(17, 16)
+#define B_AX_XFER_PENDING_FW           BIT(11)
+#define B_AX_XFER_PENDING              BIT(10)
+#define B_AX_REQ_EXIT_L1               BIT(9)
+#define B_AX_REQ_ENTR_L1               BIT(8)
+#define B_AX_L1SUB_DISABLE             BIT(0)
+
+#define R_AX_L1_CLK_CTRL               0x3010
+#define B_AX_CLK_REQ_N                 BIT(1)
+
 #define R_AX_PCIE_BG_CLR               0x303C
 #define B_AX_BG_CLR_ASYNC_M3           BIT(4)
 
+#define R_AX_PCIE_LAT_CTRL             0x3044
+#define B_AX_CLK_REQ_SEL_OPT           BIT(1)
+#define B_AX_CLK_REQ_SEL               BIT(0)
+
 #define R_AX_PCIE_IO_RCY_M1 0x3100
 #define B_AX_PCIE_IO_RCY_P_M1 BIT(5)
 #define B_AX_PCIE_IO_RCY_WDT_P_M1 BIT(4)
 #define B_AX_PCIE_WDT_TIMER_S1_MASK GENMASK(31, 0)
 
 #define R_RAC_DIRECT_OFFSET_G1 0x3800
+#define FILTER_OUT_EQ_MASK GENMASK(14, 10)
 #define R_RAC_DIRECT_OFFSET_G2 0x3880
+#define REG_FILTER_OUT_MASK GENMASK(6, 2)
+#define RAC_MULT 2
 
 #define RTW89_PCI_WR_RETRY_CNT         20
 
 #define RTW89_PCI_MULTITAG             8
 
 /* PCIE CFG register */
+#define RTW89_PCIE_L1_STS_V1           0x80
+#define RTW89_BCFG_LINK_SPEED_MASK     GENMASK(19, 16)
+#define RTW89_PCIE_GEN1_SPEED          0x01
+#define RTW89_PCIE_GEN2_SPEED          0x02
+#define RTW89_PCIE_PHY_RATE            0x82
+#define RTW89_PCIE_PHY_RATE_MASK       GENMASK(1, 0)
+#define RTW89_PCIE_L1SS_STS_V1         0x0168
+#define RTW89_PCIE_BIT_ASPM_L11                BIT(3)
+#define RTW89_PCIE_BIT_ASPM_L12                BIT(2)
+#define RTW89_PCIE_BIT_PCI_L11         BIT(1)
+#define RTW89_PCIE_BIT_PCI_L12         BIT(0)
 #define RTW89_PCIE_ASPM_CTRL           0x070F
 #define RTW89_L1DLY_MASK               GENMASK(5, 3)
 #define RTW89_L0DLY_MASK               GENMASK(2, 0)
 #define RTW89_PCIE_CLK_CTRL            0x0725
 #define RTW89_PCIE_RST_MSTATE          0x0B48
 #define RTW89_PCIE_BIT_CFG_RST_MSTATE  BIT(0)
-#define RTW89_PCIE_PHY_RATE            0x82
-#define RTW89_PCIE_PHY_RATE_MASK       GENMASK(1, 0)
+
 #define INTF_INTGRA_MINREF_V1  90
 #define INTF_INTGRA_HOSTREF_V1 100
 
index 1532c0a..4dfeede 100644 (file)
 static u16 get_max_amsdu_len(struct rtw89_dev *rtwdev,
                             const struct rtw89_ra_report *report)
 {
-       const struct rate_info *txrate = &report->txrate;
        u32 bit_rate = report->bit_rate;
-       u8 mcs;
 
        /* lower than ofdm, do not aggregate */
        if (bit_rate < 550)
                return 1;
 
-       /* prevent hardware rate fallback to G mode rate */
-       if (txrate->flags & RATE_INFO_FLAGS_MCS)
-               mcs = txrate->mcs & 0x07;
-       else if (txrate->flags & (RATE_INFO_FLAGS_VHT_MCS | RATE_INFO_FLAGS_HE_MCS))
-               mcs = txrate->mcs;
-       else
-               mcs = 0;
-
-       if (mcs <= 2)
+       /* avoid AMSDU for legacy rate */
+       if (report->might_fallback_legacy)
                return 1;
 
        /* lower than 20M vht 2ss mcs8, make it small */
@@ -142,8 +133,8 @@ static u64 rtw89_phy_ra_mask_recover(u64 ra_mask, u64 ra_mask_bak)
 
 static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtwsta)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
        struct ieee80211_sta *sta = rtwsta_to_sta(rtwsta);
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct cfg80211_bitrate_mask *mask = &rtwsta->mask;
        enum nl80211_band band;
        u64 cfg_mask;
@@ -151,7 +142,7 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw
        if (!rtwsta->use_cfg_mask)
                return -1;
 
-       switch (hal->current_band_type) {
+       switch (chan->band_type) {
        case RTW89_BAND_2G:
                band = NL80211_BAND_2GHZ;
                cfg_mask = u64_encode_bits(mask->control[NL80211_BAND_2GHZ].legacy,
@@ -168,7 +159,7 @@ static u64 rtw89_phy_ra_mask_cfg(struct rtw89_dev *rtwdev, struct rtw89_sta *rtw
                                           RA_MASK_OFDM_RATES);
                break;
        default:
-               rtw89_warn(rtwdev, "unhandled band type %d\n", hal->current_band_type);
+               rtw89_warn(rtwdev, "unhandled band type %d\n", chan->band_type);
                return -1;
        }
 
@@ -209,6 +200,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
        struct rtw89_vif *rtwvif = rtwsta->rtwvif;
        struct rtw89_phy_rate_pattern *rate_pattern = &rtwvif->rate_pattern;
        struct rtw89_ra_info *ra = &rtwsta->ra;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        const u64 *high_rate_masks = rtw89_ra_mask_ht_rates;
        u8 rssi = ewma_rssi_read(&rtwsta->avg_rssi);
        u64 ra_mask = 0;
@@ -260,7 +252,7 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
                        ldpc_en = 1;
        }
 
-       switch (rtwdev->hal.current_band_type) {
+       switch (chan->band_type) {
        case RTW89_BAND_2G:
                ra_mask |= sta->deflink.supp_rates[NL80211_BAND_2GHZ];
                if (sta->deflink.supp_rates[NL80211_BAND_2GHZ] <= 0xf)
@@ -416,6 +408,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
        struct ieee80211_supported_band *sband;
        struct rtw89_vif *rtwvif = (struct rtw89_vif *)vif->drv_priv;
        struct rtw89_phy_rate_pattern next_pattern = {0};
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        static const u16 hw_rate_he[] = {RTW89_HW_RATE_HE_NSS1_MCS0,
                                         RTW89_HW_RATE_HE_NSS2_MCS0,
                                         RTW89_HW_RATE_HE_NSS3_MCS0,
@@ -428,7 +421,7 @@ void rtw89_phy_rate_pattern_vif(struct rtw89_dev *rtwdev,
                                         RTW89_HW_RATE_MCS8,
                                         RTW89_HW_RATE_MCS16,
                                         RTW89_HW_RATE_MCS24};
-       u8 band = rtwdev->hal.current_band_type;
+       u8 band = chan->band_type;
        enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
        u8 tx_nss = rtwdev->hal.tx_nss;
        u8 i;
@@ -542,12 +535,12 @@ void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta)
 }
 
 u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
-                     struct rtw89_channel_params *param,
+                     const struct rtw89_chan *chan,
                      enum rtw89_bandwidth dbw)
 {
-       enum rtw89_bandwidth cbw = param->bandwidth;
-       u8 pri_ch = param->primary_chan;
-       u8 central_ch = param->center_chan;
+       enum rtw89_bandwidth cbw = chan->band_width;
+       u8 pri_ch = chan->primary_channel;
+       u8 central_ch = chan->channel;
        u8 txsc_idx = 0;
        u8 tmp = 0;
 
@@ -1468,10 +1461,9 @@ EXPORT_SYMBOL(rtw89_phy_load_txpwr_byrate);
        (txpwr_rf) >> (__c->txpwr_factor_rf - __c->txpwr_factor_mac);   \
 })
 
-s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev,
+s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band,
                               const struct rtw89_rate_desc *rate_desc)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
        s8 *byr;
        u8 idx;
 
@@ -1538,11 +1530,10 @@ static u8 rtw89_channel_to_idx(struct rtw89_dev *rtwdev, u8 band, u8 channel)
        }
 }
 
-s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
+s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
                              u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
-       u8 band = rtwdev->hal.current_band_type;
        u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
        u8 regd = rtw89_regd_get(rtwdev, band);
        s8 lmt = 0, sar;
@@ -1578,11 +1569,12 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
 }
 EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
 
-#define __fill_txpwr_limit_nonbf_bf(ptr, bw, ntx, rs, ch)              \
+#define __fill_txpwr_limit_nonbf_bf(ptr, band, bw, ntx, rs, ch)                \
        do {                                                            \
                u8 __i;                                                 \
                for (__i = 0; __i < RTW89_BF_NUM; __i++)                \
                        ptr[__i] = rtw89_phy_read_txpwr_limit(rtwdev,   \
+                                                             band,     \
                                                              bw, ntx,  \
                                                              rs, __i,  \
                                                              (ch));    \
@@ -1590,64 +1582,75 @@ EXPORT_SYMBOL(rtw89_phy_read_txpwr_limit);
 
 static void rtw89_phy_fill_txpwr_limit_20m(struct rtw89_dev *rtwdev,
                                           struct rtw89_txpwr_limit *lmt,
-                                          u8 ntx, u8 ch)
+                                          u8 band, u8 ntx, u8 ch)
 {
-       __fill_txpwr_limit_nonbf_bf(lmt->cck_20m, RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_CCK, ch);
-       __fill_txpwr_limit_nonbf_bf(lmt->cck_40m, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_CCK, ch);
-       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_OFDM, ch);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch);
 }
 
 static void rtw89_phy_fill_txpwr_limit_40m(struct rtw89_dev *rtwdev,
                                           struct rtw89_txpwr_limit *lmt,
-                                          u8 ntx, u8 ch, u8 pri_ch)
+                                          u8 band, u8 ntx, u8 ch, u8 pri_ch)
 {
-       __fill_txpwr_limit_nonbf_bf(lmt->cck_20m, RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->cck_20m, band, RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_CCK, ch - 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->cck_40m, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->cck_40m, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_CCK, ch);
-       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_OFDM, pri_ch);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch);
 }
 
 static void rtw89_phy_fill_txpwr_limit_80m(struct rtw89_dev *rtwdev,
                                           struct rtw89_txpwr_limit *lmt,
-                                          u8 ntx, u8 ch, u8 pri_ch)
+                                          u8 band, u8 ntx, u8 ch, u8 pri_ch)
 {
        s8 val_0p5_n[RTW89_BF_NUM];
        s8 val_0p5_p[RTW89_BF_NUM];
        u8 i;
 
-       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_OFDM, pri_ch);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 6);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 6);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch - 4);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch + 4);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], RTW89_CHANNEL_WIDTH_80,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
+                                   RTW89_CHANNEL_WIDTH_80,
                                    ntx, RTW89_RS_MCS, ch);
 
-       __fill_txpwr_limit_nonbf_bf(val_0p5_n, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch - 4);
-       __fill_txpwr_limit_nonbf_bf(val_0p5_p, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch + 4);
 
        for (i = 0; i < RTW89_BF_NUM; i++)
@@ -1656,7 +1659,7 @@ static void rtw89_phy_fill_txpwr_limit_80m(struct rtw89_dev *rtwdev,
 
 static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
                                            struct rtw89_txpwr_limit *lmt,
-                                           u8 ntx, u8 ch, u8 pri_ch)
+                                           u8 band, u8 ntx, u8 ch, u8 pri_ch)
 {
        s8 val_0p5_n[RTW89_BF_NUM];
        s8 val_0p5_p[RTW89_BF_NUM];
@@ -1665,60 +1668,75 @@ static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
        u8 i;
 
        /* fill ofdm section */
-       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->ofdm, band, RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_OFDM, pri_ch);
 
        /* fill mcs 20m section */
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[0], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 14);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[1], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 10);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[2], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 6);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[3], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch - 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[4], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[4], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 2);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[5], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[5], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 6);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[6], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[6], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 10);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[7], RTW89_CHANNEL_WIDTH_20,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_20m[7], band,
+                                   RTW89_CHANNEL_WIDTH_20,
                                    ntx, RTW89_RS_MCS, ch + 14);
 
        /* fill mcs 40m section */
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[0], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch - 12);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[1], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch - 4);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[2], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[2], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch + 4);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[3], RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_40m[3], band,
+                                   RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch + 12);
 
        /* fill mcs 80m section */
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], RTW89_CHANNEL_WIDTH_80,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[0], band,
+                                   RTW89_CHANNEL_WIDTH_80,
                                    ntx, RTW89_RS_MCS, ch - 8);
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[1], RTW89_CHANNEL_WIDTH_80,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_80m[1], band,
+                                   RTW89_CHANNEL_WIDTH_80,
                                    ntx, RTW89_RS_MCS, ch + 8);
 
        /* fill mcs 160m section */
-       __fill_txpwr_limit_nonbf_bf(lmt->mcs_160m, RTW89_CHANNEL_WIDTH_160,
+       __fill_txpwr_limit_nonbf_bf(lmt->mcs_160m, band,
+                                   RTW89_CHANNEL_WIDTH_160,
                                    ntx, RTW89_RS_MCS, ch);
 
        /* fill mcs 40m 0p5 section */
-       __fill_txpwr_limit_nonbf_bf(val_0p5_n, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(val_0p5_n, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch - 4);
-       __fill_txpwr_limit_nonbf_bf(val_0p5_p, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(val_0p5_p, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch + 4);
 
        for (i = 0; i < RTW89_BF_NUM; i++)
                lmt->mcs_40m_0p5[i] = min_t(s8, val_0p5_n[i], val_0p5_p[i]);
 
        /* fill mcs 40m 2p5 section */
-       __fill_txpwr_limit_nonbf_bf(val_2p5_n, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(val_2p5_n, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch - 8);
-       __fill_txpwr_limit_nonbf_bf(val_2p5_p, RTW89_CHANNEL_WIDTH_40,
+       __fill_txpwr_limit_nonbf_bf(val_2p5_p, band, RTW89_CHANNEL_WIDTH_40,
                                    ntx, RTW89_RS_MCS, ch + 8);
 
        for (i = 0; i < RTW89_BF_NUM; i++)
@@ -1726,37 +1744,41 @@ static void rtw89_phy_fill_txpwr_limit_160m(struct rtw89_dev *rtwdev,
 }
 
 void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
+                               const struct rtw89_chan *chan,
                                struct rtw89_txpwr_limit *lmt,
                                u8 ntx)
 {
-       u8 pri_ch = rtwdev->hal.current_primary_channel;
-       u8 ch = rtwdev->hal.current_channel;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 band = chan->band_type;
+       u8 pri_ch = chan->primary_channel;
+       u8 ch = chan->channel;
+       u8 bw = chan->band_width;
 
        memset(lmt, 0, sizeof(*lmt));
 
        switch (bw) {
        case RTW89_CHANNEL_WIDTH_20:
-               rtw89_phy_fill_txpwr_limit_20m(rtwdev, lmt, ntx, ch);
+               rtw89_phy_fill_txpwr_limit_20m(rtwdev, lmt, band, ntx, ch);
                break;
        case RTW89_CHANNEL_WIDTH_40:
-               rtw89_phy_fill_txpwr_limit_40m(rtwdev, lmt, ntx, ch, pri_ch);
+               rtw89_phy_fill_txpwr_limit_40m(rtwdev, lmt, band, ntx, ch,
+                                              pri_ch);
                break;
        case RTW89_CHANNEL_WIDTH_80:
-               rtw89_phy_fill_txpwr_limit_80m(rtwdev, lmt, ntx, ch, pri_ch);
+               rtw89_phy_fill_txpwr_limit_80m(rtwdev, lmt, band, ntx, ch,
+                                              pri_ch);
                break;
        case RTW89_CHANNEL_WIDTH_160:
-               rtw89_phy_fill_txpwr_limit_160m(rtwdev, lmt, ntx, ch, pri_ch);
+               rtw89_phy_fill_txpwr_limit_160m(rtwdev, lmt, band, ntx, ch,
+                                               pri_ch);
                break;
        }
 }
 EXPORT_SYMBOL(rtw89_phy_fill_txpwr_limit);
 
-static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev,
+static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
                                        u8 ru, u8 ntx, u8 ch)
 {
        const struct rtw89_chip_info *chip = rtwdev->chip;
-       u8 band = rtwdev->hal.current_band_type;
        u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
        u8 regd = rtw89_regd_get(rtwdev, band);
        s8 lmt_ru = 0, sar;
@@ -1794,85 +1816,106 @@ static s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev,
 static void
 rtw89_phy_fill_txpwr_limit_ru_20m(struct rtw89_dev *rtwdev,
                                  struct rtw89_txpwr_limit_ru *lmt_ru,
-                                 u8 ntx, u8 ch)
+                                 u8 band, u8 ntx, u8 ch)
 {
-       lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch);
-       lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch);
-       lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch);
 }
 
 static void
 rtw89_phy_fill_txpwr_limit_ru_40m(struct rtw89_dev *rtwdev,
                                  struct rtw89_txpwr_limit_ru *lmt_ru,
-                                 u8 ntx, u8 ch)
+                                 u8 band, u8 ntx, u8 ch)
 {
-       lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch - 2);
-       lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch + 2);
-       lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch - 2);
-       lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch + 2);
-       lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch - 2);
-       lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch + 2);
 }
 
 static void
 rtw89_phy_fill_txpwr_limit_ru_80m(struct rtw89_dev *rtwdev,
                                  struct rtw89_txpwr_limit_ru *lmt_ru,
-                                 u8 ntx, u8 ch)
+                                 u8 band, u8 ntx, u8 ch)
 {
-       lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch - 6);
-       lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch - 2);
-       lmt_ru->ru26[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch + 2);
-       lmt_ru->ru26[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU26,
+       lmt_ru->ru26[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU26,
                                                        ntx, ch + 6);
-       lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch - 6);
-       lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch - 2);
-       lmt_ru->ru52[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch + 2);
-       lmt_ru->ru52[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU52,
+       lmt_ru->ru52[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                       RTW89_RU52,
                                                        ntx, ch + 6);
-       lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[0] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch - 6);
-       lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[1] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch - 2);
-       lmt_ru->ru106[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[2] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch + 2);
-       lmt_ru->ru106[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, RTW89_RU106,
+       lmt_ru->ru106[3] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
+                                                        RTW89_RU106,
                                                         ntx, ch + 6);
 }
 
 static void
 rtw89_phy_fill_txpwr_limit_ru_160m(struct rtw89_dev *rtwdev,
                                   struct rtw89_txpwr_limit_ru *lmt_ru,
-                                  u8 ntx, u8 ch)
+                                  u8 band, u8 ntx, u8 ch)
 {
        static const int ofst[] = { -14, -10, -6, -2, 2, 6, 10, 14 };
        int i;
 
        static_assert(ARRAY_SIZE(ofst) == RTW89_RU_SEC_NUM);
        for (i = 0; i < RTW89_RU_SEC_NUM; i++) {
-               lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev,
+               lmt_ru->ru26[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
                                                                RTW89_RU26,
                                                                ntx,
                                                                ch + ofst[i]);
-               lmt_ru->ru52[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev,
+               lmt_ru->ru52[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
                                                                RTW89_RU52,
                                                                ntx,
                                                                ch + ofst[i]);
-               lmt_ru->ru106[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev,
+               lmt_ru->ru106[i] = rtw89_phy_read_txpwr_limit_ru(rtwdev, band,
                                                                 RTW89_RU106,
                                                                 ntx,
                                                                 ch + ofst[i]);
@@ -1880,26 +1923,32 @@ rtw89_phy_fill_txpwr_limit_ru_160m(struct rtw89_dev *rtwdev,
 }
 
 void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
+                                  const struct rtw89_chan *chan,
                                   struct rtw89_txpwr_limit_ru *lmt_ru,
                                   u8 ntx)
 {
-       u8 ch = rtwdev->hal.current_channel;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 band = chan->band_type;
+       u8 ch = chan->channel;
+       u8 bw = chan->band_width;
 
        memset(lmt_ru, 0, sizeof(*lmt_ru));
 
        switch (bw) {
        case RTW89_CHANNEL_WIDTH_20:
-               rtw89_phy_fill_txpwr_limit_ru_20m(rtwdev, lmt_ru, ntx, ch);
+               rtw89_phy_fill_txpwr_limit_ru_20m(rtwdev, lmt_ru, band, ntx,
+                                                 ch);
                break;
        case RTW89_CHANNEL_WIDTH_40:
-               rtw89_phy_fill_txpwr_limit_ru_40m(rtwdev, lmt_ru, ntx, ch);
+               rtw89_phy_fill_txpwr_limit_ru_40m(rtwdev, lmt_ru, band, ntx,
+                                                 ch);
                break;
        case RTW89_CHANNEL_WIDTH_80:
-               rtw89_phy_fill_txpwr_limit_ru_80m(rtwdev, lmt_ru, ntx, ch);
+               rtw89_phy_fill_txpwr_limit_ru_80m(rtwdev, lmt_ru, band, ntx,
+                                                 ch);
                break;
        case RTW89_CHANNEL_WIDTH_160:
-               rtw89_phy_fill_txpwr_limit_ru_160m(rtwdev, lmt_ru, ntx, ch);
+               rtw89_phy_fill_txpwr_limit_ru_160m(rtwdev, lmt_ru, band, ntx,
+                                                  ch);
                break;
        }
 }
@@ -1920,6 +1969,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
        u8 mode, rate, bw, giltf, mac_id;
        u16 legacy_bitrate;
        bool valid;
+       u8 mcs = 0;
 
        mac_id = RTW89_GET_PHY_C2H_RA_RPT_MACID(c2h->data);
        if (mac_id != rtwsta->mac_id)
@@ -1936,7 +1986,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
                        return;
        }
 
-       memset(ra_report, 0, sizeof(*ra_report));
+       memset(&ra_report->txrate, 0, sizeof(ra_report->txrate));
 
        switch (mode) {
        case RTW89_RA_RPT_MODE_LEGACY:
@@ -1952,6 +2002,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
                ra_report->txrate.mcs = rate;
                if (giltf)
                        ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+               mcs = ra_report->txrate.mcs & 0x07;
                break;
        case RTW89_RA_RPT_MODE_VHT:
                ra_report->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS;
@@ -1959,6 +2010,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
                ra_report->txrate.nss = FIELD_GET(RTW89_RA_RATE_MASK_NSS, rate) + 1;
                if (giltf)
                        ra_report->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
+               mcs = ra_report->txrate.mcs;
                break;
        case RTW89_RA_RPT_MODE_HE:
                ra_report->txrate.flags |= RATE_INFO_FLAGS_HE_MCS;
@@ -1970,6 +2022,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
                        ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_1_6;
                else
                        ra_report->txrate.he_gi = NL80211_RATE_INFO_HE_GI_3_2;
+               mcs = ra_report->txrate.mcs;
                break;
        }
 
@@ -1977,6 +2030,7 @@ static void rtw89_phy_c2h_ra_rpt_iter(void *data, struct ieee80211_sta *sta)
        ra_report->bit_rate = cfg80211_calculate_bitrate(&ra_report->txrate);
        ra_report->hw_rate = FIELD_PREP(RTW89_HW_RATE_MASK_MOD, mode) |
                             FIELD_PREP(RTW89_HW_RATE_MASK_VAL, rate);
+       ra_report->might_fallback_legacy = mcs <= 2;
        sta->max_rc_amsdu_len = get_max_amsdu_len(rtwdev, ra_report);
        rtwsta->max_agg_wait = sta->max_rc_amsdu_len / 1500 - 1;
 }
@@ -3247,10 +3301,11 @@ static void rtw89_phy_dig_update_rssi_info(struct rtw89_dev *rtwdev)
 static void rtw89_phy_dig_update_para(struct rtw89_dev *rtwdev)
 {
        struct rtw89_dig_info *dig = &rtwdev->dig;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        bool is_linked = rtwdev->total_sta_assoc > 0;
        const u16 *fa_th_src = NULL;
 
-       switch (rtwdev->hal.current_band_type) {
+       switch (chan->band_type) {
        case RTW89_BAND_2G:
                dig->lna_gain = dig->lna_gain_g;
                dig->tia_gain = dig->tia_gain_g;
@@ -3483,7 +3538,8 @@ static void rtw89_phy_dig_config_igi(struct rtw89_dev *rtwdev)
 static void rtw89_phy_dig_dyn_pd_th(struct rtw89_dev *rtwdev, u8 rssi,
                                    bool enable)
 {
-       enum rtw89_bandwidth cbw = rtwdev->hal.current_band_width;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_bandwidth cbw = chan->band_width;
        struct rtw89_dig_info *dig = &rtwdev->dig;
        u8 final_rssi = 0, under_region = dig->pd_low_th_ofst;
        u8 ofdm_cca_th;
index e20636f..0eeab18 100644 (file)
@@ -56,7 +56,7 @@
 #define CFO_TRK_STOP_TH (2 << 2)
 #define CFO_SW_COMP_FINE_TUNE (2 << 2)
 #define CFO_PERIOD_CNT 15
-#define CFO_BOUND 32
+#define CFO_BOUND 64
 #define CFO_TP_UPPER 100
 #define CFO_TP_LOWER 50
 #define CFO_COMP_PERIOD 250
@@ -439,7 +439,7 @@ rtw89_rfk_parser(struct rtw89_dev *rtwdev, const struct rtw89_rfk_tbl *tbl);
 void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
                              const struct rtw89_phy_reg3_tbl *tbl);
 u8 rtw89_phy_get_txsc(struct rtw89_dev *rtwdev,
-                     struct rtw89_channel_params *param,
+                     const struct rtw89_chan *chan,
                      enum rtw89_bandwidth dbw);
 u32 rtw89_phy_read_rf(struct rtw89_dev *rtwdev, enum rtw89_rf_path rf_path,
                      u32 addr, u32 mask);
@@ -460,15 +460,17 @@ void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
                           u32 data, enum rtw89_phy_idx phy_idx);
 void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
                                 const struct rtw89_txpwr_table *tbl);
-s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev,
+s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band,
                               const struct rtw89_rate_desc *rate_desc);
 void rtw89_phy_fill_txpwr_limit(struct rtw89_dev *rtwdev,
+                               const struct rtw89_chan *chan,
                                struct rtw89_txpwr_limit *lmt,
                                u8 ntx);
 void rtw89_phy_fill_txpwr_limit_ru(struct rtw89_dev *rtwdev,
+                                  const struct rtw89_chan *chan,
                                   struct rtw89_txpwr_limit_ru *lmt_ru,
                                   u8 ntx);
-s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev,
+s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
                              u8 bw, u8 ntx, u8 rs, u8 bf, u8 ch);
 void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta);
 void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
index a90b337..ea32601 100644 (file)
@@ -127,7 +127,6 @@ static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwv
        if (rtwvif->wifi_role != RTW89_WIFI_ROLE_STATION)
                return;
 
-       __rtw89_leave_ps_mode(rtwdev);
        __rtw89_leave_lps(rtwdev, rtwvif->mac_id);
 }
 
@@ -140,6 +139,8 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev)
        if (!test_and_clear_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
                return;
 
+       __rtw89_leave_ps_mode(rtwdev);
+
        rtw89_for_each_rtwvif(rtwdev, rtwvif)
                rtw89_leave_lps_vif(rtwdev, rtwvif);
 }
index ebf2871..38139ff 100644 (file)
 #define R_AX_PMC_DBG_CTRL2 0x00CC
 #define B_AX_SYSON_DIS_PMCR_AX_WRMSK BIT(2)
 
+#define R_AX_PCIE_MIO_INTF 0x00E4
+#define B_AX_PCIE_MIO_ADDR_PAGE_V1_MASK GENMASK(20, 16)
+#define B_AX_PCIE_MIO_BYIOREG BIT(13)
+#define B_AX_PCIE_MIO_RE BIT(12)
+#define B_AX_PCIE_MIO_WE_MASK GENMASK(11, 8)
+#define MIO_WRITE_BYTE_ALL 0xF
+#define B_AX_PCIE_MIO_ADDR_MASK GENMASK(7, 0)
+#define MIO_ADDR_PAGE_MASK GENMASK(12, 8)
+
+#define R_AX_PCIE_MIO_INTD 0x00E8
+#define B_AX_PCIE_MIO_DATA_MASK GENMASK(31, 0)
+
 #define R_AX_SYS_CFG1 0x00F0
 #define B_AX_CHIP_VER_MASK GENMASK(15, 12)
 
                          B_AX_WDE_DATCHN_NULLPG_ERR_INT_EN | \
                          B_AX_WDE_DATCHN_FRZTO_ERR_INT_EN)
 #define B_AX_WDE_IMR_SET (B_AX_WDE_BUFREQ_QTAID_ERR_INT_EN | \
-                         B_AX_WDE_BUFREQ_SIZE0_INT_EN | \
-                         B_AX_WDE_BUFREQ_SIZELMT_INT_EN | \
-                         B_AX_WDE_BUFREQ_UNAVAL_ERR_INT_EN_V1 | \
-                         B_AX_WDE_BUFRTN_INVLD_PKTID_ERR_INT_EN_V1 | \
-                         B_AX_WDE_BUFRTN_SIZE_ERR_INT_EN_V1 | \
-                         B_AX_WDE_BUFREQ_SRCHTAILPG_ERR_INT_EN_V1 | \
-                         B_AX_WDE_GETNPG_STRPG_ERR_INT_EN_V1 | \
-                         B_AX_WDE_GETNPG_PGOFST_ERR_INT_EN_V1 | \
-                         B_AX_WDE_BUFMGN_FRZTO_ERR_INT_EN_V1 | \
+                         B_AX_WDE_BUFREQ_UNAVAL_ERR_INT_EN | \
+                         B_AX_WDE_BUFRTN_INVLD_PKTID_ERR_INT_EN | \
+                         B_AX_WDE_BUFRTN_SIZE_ERR_INT_EN | \
+                         B_AX_WDE_BUFREQ_SRCHTAILPG_ERR_INT_EN | \
+                         B_AX_WDE_GETNPG_STRPG_ERR_INT_EN | \
+                         B_AX_WDE_GETNPG_PGOFST_ERR_INT_EN | \
+                         B_AX_WDE_BUFMGN_FRZTO_ERR_INT_EN | \
                          B_AX_WDE_QUE_CMDTYPE_ERR_INT_EN | \
                          B_AX_WDE_QUE_DSTQUEID_ERR_INT_EN | \
                          B_AX_WDE_QUE_SRCQUEID_ERR_INT_EN | \
                          B_AX_WDE_QUEMGN_FRZTO_ERR_INT_EN | \
                          B_AX_WDE_DATCHN_ARBT_ERR_INT_EN | \
                          B_AX_WDE_DATCHN_NULLPG_ERR_INT_EN | \
-                         B_AX_WDE_DATCHN_FRZTO_ERR_INT_EN | \
-                         B_AX_WDE_DATCHN_RRDY_ERR_INT_EN | \
-                         B_AX_WDE_DATCHN_ADRERR_ERR_INT_EN | \
-                         B_AX_WDE_DATCHN_CAMREQ_ERR_INT_EN)
+                         B_AX_WDE_DATCHN_FRZTO_ERR_INT_EN)
 
 #define B_AX_WDE_DATCHN_CAMREQ_ERR_INT_EN BIT(29)
 #define B_AX_WDE_DATCHN_ADRERR_ERR_INT_EN BIT(28)
 #define B_AX_SIFS_TIMEOUT_T2_MASK GENMASK(14, 8)
 #define B_AX_SIFS_MACTXEN_T1_MASK GENMASK(6, 0)
 #define SIFS_MACTXEN_T1 0x47
+#define SIFS_MACTXEN_T1_V1 0x41
 
 #define R_AX_CCA_CFG_0 0xC340
 #define R_AX_CCA_CFG_0_C1 0xE340
 #define R_AX_TBTT_SHIFT_P3 0xC4E8
 #define R_AX_TBTT_SHIFT_P4 0xC528
 #define B_AX_TBTT_SHIFT_OFST_MASK GENMASK(11, 0)
+#define B_AX_TBTT_SHIFT_OFST_SIGN BIT(11)
+#define B_AX_TBTT_SHIFT_OFST_MAG GENMASK(10, 0)
 
 #define R_AX_BCN_CNT_TMR_P0 0xC434
 #define R_AX_BCN_CNT_TMR_P1 0xC474
 #define R_MAC_PIN_SEL 0x0734
 #define B_CH_IDX_SEG0 GENMASK(23, 16)
 #define R_PLCP_HISTOGRAM 0x0738
-#define B_STS_DIS_TRIG_BY_BRK BIT(2)
+#define B_STS_PARSING_TIME GENMASK(19, 16)
 #define B_STS_DIS_TRIG_BY_FAIL BIT(3)
+#define B_STS_DIS_TRIG_BY_BRK BIT(2)
 #define R_PHY_STS_BITMAP_ADDR_START R_PHY_STS_BITMAP_SEARCH_FAIL
 #define B_PHY_STS_BITMAP_ADDR_MASK GENMASK(6, 2)
 #define R_PHY_STS_BITMAP_SEARCH_FAIL 0x073C
index 20c7afd..6e5a740 100644 (file)
@@ -346,7 +346,7 @@ void rtw89_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request
        rtw89_debug_regd(rtwdev, rtwdev->regd, "get from initiator %d, alpha2",
                         request->initiator);
 
-       rtw89_chip_set_txpwr(rtwdev);
+       rtw89_core_set_chip_txpwr(rtwdev);
 
 exit:
        mutex_unlock(&rtwdev->mutex);
index 81bd0c4..c872c8b 100644 (file)
@@ -660,7 +660,7 @@ static void rtw8852a_power_trim(struct rtw89_dev *rtwdev)
 }
 
 static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
-                                    struct rtw89_channel_params *param,
+                                    const struct rtw89_chan *chan,
                                     u8 mac_idx)
 {
        u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
@@ -669,20 +669,20 @@ static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
        u32 chk_rate = rtw89_mac_reg_by_idx(R_AX_TXRATE_CHK, mac_idx);
        u8 txsc20 = 0, txsc40 = 0;
 
-       switch (param->bandwidth) {
+       switch (chan->band_width) {
        case RTW89_CHANNEL_WIDTH_80:
-               txsc40 = rtw89_phy_get_txsc(rtwdev, param,
+               txsc40 = rtw89_phy_get_txsc(rtwdev, chan,
                                            RTW89_CHANNEL_WIDTH_40);
                fallthrough;
        case RTW89_CHANNEL_WIDTH_40:
-               txsc20 = rtw89_phy_get_txsc(rtwdev, param,
+               txsc20 = rtw89_phy_get_txsc(rtwdev, chan,
                                            RTW89_CHANNEL_WIDTH_20);
                break;
        default:
                break;
        }
 
-       switch (param->bandwidth) {
+       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));
@@ -699,7 +699,7 @@ static void rtw8852a_set_channel_mac(struct rtw89_dev *rtwdev,
                break;
        }
 
-       if (param->center_chan > 14)
+       if (chan->channel > 14)
                rtw89_write8_set(rtwdev, chk_rate,
                                 B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6);
        else
@@ -1102,11 +1102,12 @@ static void rtw8852a_bb_sethw(struct rtw89_dev *rtwdev)
        if (rtwdev->hal.cv <= CHIP_CCV) {
                rtw89_phy_write32_set(rtwdev, R_RSTB_WATCH_DOG, B_P0_RSTB_WATCH_DOG);
                rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_1, 0x864FA000);
-               rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_2, 0x3F);
+               rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_2, 0x43F);
                rtw89_phy_write32(rtwdev, R_BRK_ASYNC_RST_EN_3, 0x7FFF);
                rtw89_phy_write32_set(rtwdev, R_SPOOF_ASYNC_RST, B_SPOOF_ASYNC_RST);
                rtw89_phy_write32_set(rtwdev, R_P0_TXPW_RSTB, B_P0_TXPW_RSTB_MANON);
                rtw89_phy_write32_set(rtwdev, R_P1_TXPW_RSTB, B_P1_TXPW_RSTB_MANON);
+               rtw89_phy_write32_set(rtwdev, R_PLCP_HISTOGRAM, B_STS_PARSING_TIME);
        }
        rtw89_phy_write32_mask(rtwdev, R_CFO_TRK0, B_CFO_TRK_MSK, 0x1f);
        rtw89_phy_write32_mask(rtwdev, R_CFO_TRK1, B_CFO_TRK_MSK, 0x0c);
@@ -1130,35 +1131,38 @@ static void rtw8852a_bbrst_for_rfk(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852a_set_channel_bb(struct rtw89_dev *rtwdev,
-                                   struct rtw89_channel_params *param,
+                                   const struct rtw89_chan *chan,
                                    enum rtw89_phy_idx phy_idx)
 {
-       bool cck_en = param->center_chan <= 14;
-       u8 pri_ch_idx = param->pri_ch_idx;
+       bool cck_en = chan->channel <= 14;
+       u8 pri_ch_idx = chan->pri_ch_idx;
 
        if (cck_en)
-               rtw8852a_ctrl_sco_cck(rtwdev, param->center_chan,
-                                     param->primary_chan, param->bandwidth);
+               rtw8852a_ctrl_sco_cck(rtwdev, chan->channel,
+                                     chan->primary_channel,
+                                     chan->band_width);
 
-       rtw8852a_ctrl_ch(rtwdev, param->center_chan, phy_idx);
-       rtw8852a_ctrl_bw(rtwdev, pri_ch_idx, param->bandwidth, phy_idx);
+       rtw8852a_ctrl_ch(rtwdev, chan->channel, phy_idx);
+       rtw8852a_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
        if (cck_en) {
                rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 0);
        } else {
                rtw89_phy_write32_mask(rtwdev, R_RXCCA, B_RXCCA_DIS, 1);
                rtw8852a_bbrst_for_rfk(rtwdev, phy_idx);
        }
-       rtw8852a_spur_elimination(rtwdev, param->center_chan);
+       rtw8852a_spur_elimination(rtwdev, chan->channel);
        rtw89_phy_write32_mask(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0,
-                              param->primary_chan);
+                              chan->primary_channel);
        rtw8852a_bb_reset_all(rtwdev, phy_idx);
 }
 
 static void rtw8852a_set_channel(struct rtw89_dev *rtwdev,
-                                struct rtw89_channel_params *params)
+                                const struct rtw89_chan *chan,
+                                enum rtw89_mac_idx mac_idx,
+                                enum rtw89_phy_idx phy_idx)
 {
-       rtw8852a_set_channel_mac(rtwdev, params, RTW89_MAC_0);
-       rtw8852a_set_channel_bb(rtwdev, params, RTW89_PHY_0);
+       rtw8852a_set_channel_mac(rtwdev, chan, mac_idx);
+       rtw8852a_set_channel_bb(rtwdev, chan, phy_idx);
 }
 
 static void rtw8852a_dfs_en(struct rtw89_dev *rtwdev, bool en)
@@ -1209,25 +1213,27 @@ static void rtw8852a_adc_en(struct rtw89_dev *rtwdev, bool en)
 }
 
 static void rtw8852a_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
-                                     struct rtw89_channel_help_params *p)
+                                     struct rtw89_channel_help_params *p,
+                                     const struct rtw89_chan *chan,
+                                     enum rtw89_mac_idx mac_idx,
+                                     enum rtw89_phy_idx phy_idx)
 {
-       u8 phy_idx = RTW89_PHY_0;
-
        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);
+               rtw89_chip_stop_sch_tx(rtwdev, mac_idx, &p->tx_en,
+                                      RTW89_SCH_TX_SEL_ALL);
+               rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, false);
                rtw8852a_dfs_en(rtwdev, false);
-               rtw8852a_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
+               rtw8852a_tssi_cont_en_phyidx(rtwdev, false, phy_idx);
                rtw8852a_adc_en(rtwdev, false);
                fsleep(40);
                rtw8852a_bb_reset_en(rtwdev, phy_idx, false);
        } else {
-               rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
+               rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, true);
                rtw8852a_adc_en(rtwdev, true);
                rtw8852a_dfs_en(rtwdev, true);
-               rtw8852a_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
+               rtw8852a_tssi_cont_en_phyidx(rtwdev, true, phy_idx);
                rtw8852a_bb_reset_en(rtwdev, phy_idx, true);
-               rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
+               rtw89_chip_resume_sch_tx(rtwdev, mac_idx, p->tx_en);
        }
 }
 
@@ -1277,9 +1283,10 @@ static void rtw8852a_rfk_channel(struct rtw89_dev *rtwdev)
        rtw8852a_dpk(rtwdev, phy_idx);
 }
 
-static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev)
+static void rtw8852a_rfk_band_changed(struct rtw89_dev *rtwdev,
+                                     enum rtw89_phy_idx phy_idx)
 {
-       rtw8852a_tssi_scan(rtwdev, RTW89_PHY_0);
+       rtw8852a_tssi_scan(rtwdev, phy_idx);
 }
 
 static void rtw8852a_rfk_scan(struct rtw89_dev *rtwdev, bool start)
@@ -1378,9 +1385,11 @@ static void rtw8852a_set_txpwr_ref(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852a_set_txpwr_byrate(struct rtw89_dev *rtwdev,
+                                     const struct rtw89_chan *chan,
                                      enum rtw89_phy_idx phy_idx)
 {
-       u8 ch = rtwdev->hal.current_channel;
+       u8 band = chan->band_type;
+       u8 ch = chan->channel;
        static const u8 rs[] = {
                RTW89_RS_CCK,
                RTW89_RS_OFDM,
@@ -1406,7 +1415,8 @@ static void rtw8852a_set_txpwr_byrate(struct rtw89_dev *rtwdev,
                        for (j = 0; j < rtw89_rs_idx_max[rs[i]]; j++) {
                                cur.idx = j;
                                shf = (j % 4) * 8;
-                               tmp = rtw89_phy_read_txpwr_byrate(rtwdev, &cur);
+                               tmp = rtw89_phy_read_txpwr_byrate(rtwdev, band,
+                                                                 &cur);
                                val |= (tmp << shf);
 
                                if ((j + 1) % 4)
@@ -1421,8 +1431,10 @@ static void rtw8852a_set_txpwr_byrate(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852a_set_txpwr_offset(struct rtw89_dev *rtwdev,
+                                     const struct rtw89_chan *chan,
                                      enum rtw89_phy_idx phy_idx)
 {
+       u8 band = chan->band_type;
        struct rtw89_rate_desc desc = {
                .nss = RTW89_NSS_1,
                .rs = RTW89_RS_OFFSET,
@@ -1433,7 +1445,7 @@ static void rtw8852a_set_txpwr_offset(struct rtw89_dev *rtwdev,
        rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
 
        for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++) {
-               v = rtw89_phy_read_txpwr_byrate(rtwdev, &desc);
+               v = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc);
                val |= ((v & 0xf) << (4 * desc.idx));
        }
 
@@ -1442,29 +1454,31 @@ static void rtw8852a_set_txpwr_offset(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852a_set_txpwr_limit(struct rtw89_dev *rtwdev,
+                                    const struct rtw89_chan *chan,
                                     enum rtw89_phy_idx phy_idx)
 {
 #define __MAC_TXPWR_LMT_PAGE_SIZE 40
-       u8 ch = rtwdev->hal.current_channel;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 ch = chan->channel;
+       u8 bw = chan->band_width;
        struct rtw89_txpwr_limit lmt[NTX_NUM_8852A];
        u32 addr, val;
        const s8 *ptr;
-       u8 i, j, k;
+       u8 i, j;
 
        rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
                    "[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
 
        for (i = 0; i < NTX_NUM_8852A; i++) {
-               rtw89_phy_fill_txpwr_limit(rtwdev, &lmt[i], i);
+               rtw89_phy_fill_txpwr_limit(rtwdev, chan, &lmt[i], i);
 
                for (j = 0; j < __MAC_TXPWR_LMT_PAGE_SIZE; j += 4) {
                        addr = R_AX_PWR_LMT + j + __MAC_TXPWR_LMT_PAGE_SIZE * i;
                        ptr = (s8 *)&lmt[i] + j;
-                       val = 0;
 
-                       for (k = 0; k < 4; k++)
-                               val |= (ptr[k] << (8 * k));
+                       val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
+                             FIELD_PREP(GENMASK(15, 8), ptr[1]) |
+                             FIELD_PREP(GENMASK(23, 16), ptr[2]) |
+                             FIELD_PREP(GENMASK(31, 24), ptr[3]);
 
                        rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
                }
@@ -1473,30 +1487,32 @@ static void rtw8852a_set_txpwr_limit(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852a_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
+                                       const struct rtw89_chan *chan,
                                        enum rtw89_phy_idx phy_idx)
 {
 #define __MAC_TXPWR_LMT_RU_PAGE_SIZE 24
-       u8 ch = rtwdev->hal.current_channel;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 ch = chan->channel;
+       u8 bw = chan->band_width;
        struct rtw89_txpwr_limit_ru lmt_ru[NTX_NUM_8852A];
        u32 addr, val;
        const s8 *ptr;
-       u8 i, j, k;
+       u8 i, j;
 
        rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
                    "[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
 
        for (i = 0; i < NTX_NUM_8852A; i++) {
-               rtw89_phy_fill_txpwr_limit_ru(rtwdev, &lmt_ru[i], i);
+               rtw89_phy_fill_txpwr_limit_ru(rtwdev, chan, &lmt_ru[i], i);
 
                for (j = 0; j < __MAC_TXPWR_LMT_RU_PAGE_SIZE; j += 4) {
                        addr = R_AX_PWR_RU_LMT + j +
                               __MAC_TXPWR_LMT_RU_PAGE_SIZE * i;
                        ptr = (s8 *)&lmt_ru[i] + j;
-                       val = 0;
 
-                       for (k = 0; k < 4; k++)
-                               val |= (ptr[k] << (8 * k));
+                       val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
+                             FIELD_PREP(GENMASK(15, 8), ptr[1]) |
+                             FIELD_PREP(GENMASK(23, 16), ptr[2]) |
+                             FIELD_PREP(GENMASK(31, 24), ptr[3]);
 
                        rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
                }
@@ -1505,17 +1521,20 @@ static void rtw8852a_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
 #undef __MAC_TXPWR_LMT_RU_PAGE_SIZE
 }
 
-static void rtw8852a_set_txpwr(struct rtw89_dev *rtwdev)
+static void rtw8852a_set_txpwr(struct rtw89_dev *rtwdev,
+                              const struct rtw89_chan *chan,
+                              enum rtw89_phy_idx phy_idx)
 {
-       rtw8852a_set_txpwr_byrate(rtwdev, RTW89_PHY_0);
-       rtw8852a_set_txpwr_limit(rtwdev, RTW89_PHY_0);
-       rtw8852a_set_txpwr_limit_ru(rtwdev, RTW89_PHY_0);
+       rtw8852a_set_txpwr_byrate(rtwdev, chan, phy_idx);
+       rtw8852a_set_txpwr_offset(rtwdev, chan, phy_idx);
+       rtw8852a_set_txpwr_limit(rtwdev, chan, phy_idx);
+       rtw8852a_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
 }
 
-static void rtw8852a_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
+static void rtw8852a_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
+                                   enum rtw89_phy_idx phy_idx)
 {
-       rtw8852a_set_txpwr_ref(rtwdev, RTW89_PHY_0);
-       rtw8852a_set_txpwr_offset(rtwdev, RTW89_PHY_0);
+       rtw8852a_set_txpwr_ref(rtwdev, phy_idx);
 }
 
 static int
@@ -1592,10 +1611,12 @@ void rtw8852a_bb_set_pmac_tx(struct rtw89_dev *rtwdev,
                             struct rtw8852a_bb_pmac_info *tx_info,
                             enum rtw89_phy_idx idx)
 {
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+
        if (!tx_info->en_pmac_tx) {
                rtw8852a_stop_pmac_tx(rtwdev, tx_info, idx);
                rtw89_phy_write32_idx(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0, idx);
-               if (rtwdev->hal.current_band_type == RTW89_BAND_2G)
+               if (chan->band_type == RTW89_BAND_2G)
                        rtw89_phy_write32_clr(rtwdev, R_RXCCA, B_RXCCA_DIS);
                return;
        }
@@ -2086,6 +2107,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
        .btc_bt_aci_imp         = rtw8852a_btc_bt_aci_imp,
        .btc_update_bt_cnt      = rtw8852a_btc_update_bt_cnt,
        .btc_wl_s1_standby      = rtw8852a_btc_wl_s1_standby,
+       .btc_set_policy         = rtw89_btc_set_policy,
 };
 
 const struct rtw89_chip_info rtw8852a_chip_info = {
@@ -2115,6 +2137,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
        .txpwr_factor_mac       = 1,
        .dig_table              = &rtw89_8852a_phy_dig_table,
        .tssi_dbw_table         = NULL,
+       .support_chanctx_num    = 1,
        .support_bands          = BIT(NL80211_BAND_2GHZ) |
                                  BIT(NL80211_BAND_5GHZ),
        .support_bw160          = false,
@@ -2125,6 +2148,9 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
        .acam_num               = 128,
        .bcam_num               = 10,
        .scam_num               = 128,
+       .bacam_num              = 2,
+       .bacam_dynamic_num      = 4,
+       .bacam_v1               = false,
        .sec_ctrl_efuse_size    = 4,
        .physical_efuse_size    = 1216,
        .logical_efuse_size     = 1536,
@@ -2138,6 +2164,20 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
        .btcx_desired           = 0x5,
        .scbd                   = 0x1,
        .mailbox                = 0x1,
+
+       .fcxbtcrpt_ver          = 1,
+       .fcxtdma_ver            = 1,
+       .fcxslots_ver           = 1,
+       .fcxcysta_ver           = 2,
+       .fcxstep_ver            = 2,
+       .fcxnullsta_ver         = 1,
+       .fcxmreg_ver            = 1,
+       .fcxgpiodbg_ver         = 1,
+       .fcxbtver_ver           = 1,
+       .fcxbtscan_ver          = 1,
+       .fcxbtafh_ver           = 1,
+       .fcxbtdevinfo_ver       = 1,
+
        .afh_guard_ch           = 6,
        .wl_rssi_thres          = rtw89_btc_8852a_wl_rssi_thres,
        .bt_rssi_thres          = rtw89_btc_8852a_bt_rssi_thres,
index 3d60feb..582ff0d 100644 (file)
@@ -1359,7 +1359,7 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
                             enum rtw89_phy_idx phy, u8 path)
 {
        struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u32 reg_rf18 = 0x0, reg_35c = 0x0;
        u8 idx = 0;
        u8 get_empty_table = false;
@@ -1380,9 +1380,9 @@ static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
        rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]cfg ch = %d\n", reg_rf18);
        reg_35c = rtw89_phy_read32_mask(rtwdev, 0x35c, 0x00000c00);
 
-       iqk_info->iqk_band[path] = hal->current_band_type;
-       iqk_info->iqk_bw[path] = hal->current_band_width;
-       iqk_info->iqk_ch[path] = hal->current_channel;
+       iqk_info->iqk_band[path] = chan->band_type;
+       iqk_info->iqk_bw[path] = chan->band_width;
+       iqk_info->iqk_ch[path] = chan->channel;
 
        rtw89_debug(rtwdev, RTW89_DBG_RFK,
                    "[IQK]iqk_info->iqk_band[%x] = 0x%x\n", path,
@@ -1879,13 +1879,12 @@ static void _dpk_information(struct rtw89_dev *rtwdev,
                             enum rtw89_rf_path path)
 {
        struct rtw89_dpk_info *dpk = &rtwdev->dpk;
-       struct rtw89_hal *hal = &rtwdev->hal;
-
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u8 kidx = dpk->cur_idx[path];
 
-       dpk->bp[path][kidx].band = hal->current_band_type;
-       dpk->bp[path][kidx].ch = hal->current_channel;
-       dpk->bp[path][kidx].bw = hal->current_band_width;
+       dpk->bp[path][kidx].band = chan->band_type;
+       dpk->bp[path][kidx].ch = chan->channel;
+       dpk->bp[path][kidx].bw = chan->band_width;
 
        rtw89_debug(rtwdev, RTW89_DBG_RFK,
                    "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n",
@@ -2358,6 +2357,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
 #define DPK_RXBB_UPPER 0x1f
 #define DPK_RXBB_LOWER 0
 #define DPK_GL_CRIT 7
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        u8 tmp_txagc, tmp_rxbb = 0, tmp_gl_idx = 0;
        u8 agc_cnt = 0;
        bool limited_rxbb = false;
@@ -2404,7 +2404,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                                    "[DPK] Adjust RXBB (%d) = 0x%x\n", offset,
                                    tmp_rxbb);
                        if (offset != 0 || agc_cnt == 0) {
-                               if (rtwdev->hal.current_band_width < RTW89_CHANNEL_WIDTH_80)
+                               if (chan->band_width < RTW89_CHANNEL_WIDTH_80)
                                        _dpk_bypass_rxcfir(rtwdev, path, true);
                                else
                                        _dpk_lbk_rxiqk(rtwdev, phy, path);
@@ -2548,11 +2548,12 @@ static bool _dpk_reload_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                              enum rtw89_rf_path path)
 {
        struct rtw89_dpk_info *dpk = &rtwdev->dpk;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        bool is_reload = false;
        u8 idx, cur_band, cur_ch;
 
-       cur_band = rtwdev->hal.current_band_type;
-       cur_ch = rtwdev->hal.current_channel;
+       cur_band = chan->band_type;
+       cur_ch = chan->channel;
 
        for (idx = 0; idx < RTW89_DPK_BKUP_NUM; idx++) {
                if (cur_band != dpk->bp[path][idx].band ||
@@ -2681,12 +2682,13 @@ static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force,
 static bool _dpk_bypass_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
 {
        struct rtw89_fem_info *fem = &rtwdev->fem;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
 
-       if (fem->epa_2g && rtwdev->hal.current_band_type == RTW89_BAND_2G) {
+       if (fem->epa_2g && chan->band_type == RTW89_BAND_2G) {
                rtw89_debug(rtwdev, RTW89_DBG_RFK,
                            "[DPK] Skip DPK due to 2G_ext_PA exist!!\n");
                return true;
-       } else if (fem->epa_5g && rtwdev->hal.current_band_type == RTW89_BAND_5G) {
+       } else if (fem->epa_5g && chan->band_type == RTW89_BAND_5G) {
                rtw89_debug(rtwdev, RTW89_DBG_RFK,
                            "[DPK] Skip DPK due to 5G_ext_PA exist!!\n");
                return true;
@@ -2842,7 +2844,8 @@ static void _dpk_track(struct rtw89_dev *rtwdev)
 static void _tssi_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                             enum rtw89_rf_path path)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
 
        if (band == RTW89_BAND_2G)
                rtw89_write_rf(rtwdev, path, RR_TXPOW, RR_TXPOW_TXG, 0x1);
@@ -2852,7 +2855,8 @@ static void _tssi_rf_setting(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
 
 static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
 
        rtw89_rfk_parser(rtwdev, &rtw8852a_tssi_sys_defs_tbl);
        rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
@@ -2863,7 +2867,8 @@ static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
 static void _tssi_ini_txpwr_ctrl_bb(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                                    enum rtw89_rf_path path)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       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, path == RF_PATH_A,
                                 &rtw8852a_tssi_txpwr_ctrl_bb_defs_a_tbl,
@@ -2905,8 +2910,9 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
        __val;                                          \
 })
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
-       u8 ch = rtwdev->hal.current_channel;
-       u8 subband = rtwdev->hal.current_subband;
+       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;
        const s8 *thm_up_b = NULL;
@@ -3099,7 +3105,8 @@ static void _tssi_set_txagc_offset_mv_avg(struct rtw89_dev *rtwdev,
 static void _tssi_pak(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                      enum rtw89_rf_path path)
 {
-       u8 subband = rtwdev->hal.current_subband;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 subband = chan->subband_type;
 
        switch (subband) {
        default:
@@ -3275,7 +3282,8 @@ 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;
-       u8 ch = rtwdev->hal.current_channel;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 ch = chan->channel;
        u32 gidx, gidx_1st, gidx_2nd;
        s8 de_1st = 0;
        s8 de_2nd = 0;
@@ -3312,7 +3320,8 @@ static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev,
                                 enum rtw89_rf_path path)
 {
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
-       u8 ch = rtwdev->hal.current_channel;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 ch = chan->channel;
        u32 tgidx, tgidx_1st, tgidx_2nd;
        s8 tde_1st = 0;
        s8 tde_2nd = 0;
@@ -3350,6 +3359,7 @@ static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev,
 {
 #define __DE_MASK 0x003ff000
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        static const u32 r_cck_long[RF_PATH_NUM_8852A] = {0x5858, 0x7858};
        static const u32 r_cck_short[RF_PATH_NUM_8852A] = {0x5860, 0x7860};
        static const u32 r_mcs_20m[RF_PATH_NUM_8852A] = {0x5838, 0x7838};
@@ -3358,7 +3368,7 @@ static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev,
        static const u32 r_mcs_80m_80m[RF_PATH_NUM_8852A] = {0x5850, 0x7850};
        static const u32 r_mcs_5m[RF_PATH_NUM_8852A] = {0x5828, 0x7828};
        static const u32 r_mcs_10m[RF_PATH_NUM_8852A] = {0x5830, 0x7830};
-       u8 ch = rtwdev->hal.current_channel;
+       u8 ch = chan->channel;
        u8 i, gidx;
        s8 ofdm_de;
        s8 trim_de;
@@ -3478,9 +3488,11 @@ static void _tssi_track(struct rtw89_dev *rtwdev)
 static void _tssi_high_power(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
 {
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
-       u8 ch = rtwdev->hal.current_channel, ch_tmp;
-       u8 bw = rtwdev->hal.current_band_width;
-       u8 subband = rtwdev->hal.current_subband;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 ch = chan->channel, ch_tmp;
+       u8 bw = chan->band_width;
+       u8 band = chan->band_type;
+       u8 subband = chan->subband_type;
        s8 power;
        s32 xdbm;
 
@@ -3491,7 +3503,7 @@ static void _tssi_high_power(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
        else
                ch_tmp = ch;
 
-       power = rtw89_phy_read_txpwr_limit(rtwdev, bw, RTW89_1TX,
+       power = rtw89_phy_read_txpwr_limit(rtwdev, band, bw, RTW89_1TX,
                                           RTW89_RS_MCS, RTW89_NONBF, ch_tmp);
 
        xdbm = power * 100 / 4;
@@ -3523,9 +3535,11 @@ static void _tssi_hw_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
 static void _tssi_pre_tx(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);
        const struct rtw89_chip_info *mac_reg = rtwdev->chip;
-       u8 ch = rtwdev->hal.current_channel, ch_tmp;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 ch = chan->channel, ch_tmp;
+       u8 bw = chan->band_width;
+       u8 band = chan->band_type;
        u32 tx_en;
        u8 phy_map = rtw89_btc_phymap(rtwdev, phy, 0);
        s8 power;
@@ -3539,8 +3553,9 @@ static void _tssi_pre_tx(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
        else
                ch_tmp = ch;
 
-       power = rtw89_phy_read_txpwr_limit(rtwdev, RTW89_CHANNEL_WIDTH_20, RTW89_1TX,
-                                          RTW89_RS_OFDM, RTW89_NONBF, ch_tmp);
+       power = rtw89_phy_read_txpwr_limit(rtwdev, band, RTW89_CHANNEL_WIDTH_20,
+                                          RTW89_1TX, RTW89_RS_OFDM,
+                                          RTW89_NONBF, ch_tmp);
 
        xdbm = (power * 100) >> mac_reg->txpwr_factor_mac;
 
index b697aef..ac02561 100644 (file)
@@ -567,7 +567,7 @@ static void rtw8852c_power_trim(struct rtw89_dev *rtwdev)
 }
 
 static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
-                                    struct rtw89_channel_params *param,
+                                    const struct rtw89_chan *chan,
                                     u8 mac_idx)
 {
        u32 rf_mod = rtw89_mac_reg_by_idx(R_AX_WMAC_RFMOD, mac_idx);
@@ -578,24 +578,24 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
        u8 rf_mod_val = 0, chk_rate_mask = 0;
        u32 txsc;
 
-       switch (param->bandwidth) {
+       switch (chan->band_width) {
        case RTW89_CHANNEL_WIDTH_160:
-               txsc80 = rtw89_phy_get_txsc(rtwdev, param,
+               txsc80 = rtw89_phy_get_txsc(rtwdev, chan,
                                            RTW89_CHANNEL_WIDTH_80);
                fallthrough;
        case RTW89_CHANNEL_WIDTH_80:
-               txsc40 = rtw89_phy_get_txsc(rtwdev, param,
+               txsc40 = rtw89_phy_get_txsc(rtwdev, chan,
                                            RTW89_CHANNEL_WIDTH_40);
                fallthrough;
        case RTW89_CHANNEL_WIDTH_40:
-               txsc20 = rtw89_phy_get_txsc(rtwdev, param,
+               txsc20 = rtw89_phy_get_txsc(rtwdev, chan,
                                            RTW89_CHANNEL_WIDTH_20);
                break;
        default:
                break;
        }
 
-       switch (param->bandwidth) {
+       switch (chan->band_width) {
        case RTW89_CHANNEL_WIDTH_160:
                rf_mod_val = AX_WMAC_RFMOD_160M;
                txsc = FIELD_PREP(B_AX_TXSC_20M_MASK, txsc20) |
@@ -620,7 +620,7 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
        rtw89_write8_mask(rtwdev, rf_mod, B_AX_WMAC_RFMOD_MASK, rf_mod_val);
        rtw89_write32(rtwdev, sub_carr, txsc);
 
-       switch (param->band_type) {
+       switch (chan->band_type) {
        case RTW89_BAND_2G:
                chk_rate_mask = B_AX_BAND_MODE;
                break;
@@ -629,7 +629,7 @@ static void rtw8852c_set_channel_mac(struct rtw89_dev *rtwdev,
                chk_rate_mask = B_AX_CHECK_CCK_EN | B_AX_RTS_LIMIT_IN_OFDM6;
                break;
        default:
-               rtw89_warn(rtwdev, "Invalid band_type:%d\n", param->band_type);
+               rtw89_warn(rtwdev, "Invalid band_type:%d\n", chan->band_type);
                return;
        }
        rtw89_write8_clr(rtwdev, chk_rate, B_AX_BAND_MODE | B_AX_CHECK_CCK_EN |
@@ -920,7 +920,7 @@ static void rtw8852c_decode_chan_idx(struct rtw89_dev *rtwdev, u8 chan_idx,
 }
 
 static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
-                                    const struct rtw89_channel_params *param,
+                                    const struct rtw89_chan *chan,
                                     enum rtw89_phy_idx phy_idx,
                                     enum rtw89_rf_path path)
 {
@@ -939,7 +939,7 @@ static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
        if (rtwdev->dbcc_en && path == RF_PATH_B)
                phy_idx = RTW89_PHY_1;
 
-       if (param->band_type == RTW89_BAND_2G) {
+       if (chan->band_type == RTW89_BAND_2G) {
                offset_q0 = efuse_gain->offset[path][RTW89_GAIN_OFFSET_2G_CCK];
                offset_base_q4 = efuse_gain->offset_base[phy_idx];
 
@@ -948,7 +948,7 @@ static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
                rtw89_phy_write32_mask(rtwdev, R_RPL_OFST, B_RPL_OFST_MASK, tmp & 0x7f);
        }
 
-       switch (param->subband_type) {
+       switch (chan->subband_type) {
        default:
        case RTW89_CH_2G:
                gain_band = RTW89_GAIN_OFFSET_2G_OFDM;
@@ -977,14 +977,14 @@ static void rtw8852c_set_gain_offset(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
-                            const struct rtw89_channel_params *param,
+                            const struct rtw89_chan *chan,
                             enum rtw89_phy_idx phy_idx)
 {
        u8 sco;
-       u16 central_freq = param->center_freq;
-       u8 central_ch = param->center_chan;
-       u8 band = param->band_type;
-       u8 subband = param->subband_type;
+       u16 central_freq = chan->freq;
+       u8 central_ch = chan->channel;
+       u8 band = chan->band_type;
+       u8 subband = chan->subband_type;
        bool is_2g = band == RTW89_BAND_2G;
        u8 chan_idx;
 
@@ -996,7 +996,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
        if (phy_idx == RTW89_PHY_0) {
                /* Path A */
                rtw8852c_set_gain_error(rtwdev, subband, RF_PATH_A);
-               rtw8852c_set_gain_offset(rtwdev, param, phy_idx, RF_PATH_A);
+               rtw8852c_set_gain_offset(rtwdev, chan, phy_idx, RF_PATH_A);
 
                if (is_2g)
                        rtw89_phy_write32_idx(rtwdev, R_PATH0_BAND_SEL_V1,
@@ -1009,7 +1009,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
                /* Path B */
                if (!rtwdev->dbcc_en) {
                        rtw8852c_set_gain_error(rtwdev, subband, RF_PATH_B);
-                       rtw8852c_set_gain_offset(rtwdev, param, phy_idx, RF_PATH_B);
+                       rtw8852c_set_gain_offset(rtwdev, chan, phy_idx, RF_PATH_B);
 
                        if (is_2g)
                                rtw89_phy_write32_idx(rtwdev,
@@ -1038,7 +1038,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
        } else {
                /* Path B */
                rtw8852c_set_gain_error(rtwdev, subband, RF_PATH_B);
-               rtw8852c_set_gain_offset(rtwdev, param, phy_idx, RF_PATH_B);
+               rtw8852c_set_gain_offset(rtwdev, chan, phy_idx, RF_PATH_B);
 
                if (is_2g)
                        rtw89_phy_write32_idx(rtwdev, R_PATH1_BAND_SEL_V1,
@@ -1095,7 +1095,7 @@ static void rtw8852c_ctrl_ch(struct rtw89_dev *rtwdev,
                }
        }
 
-       chan_idx = rtw8852c_encode_chan_idx(rtwdev, param->primary_chan, band);
+       chan_idx = rtw8852c_encode_chan_idx(rtwdev, chan->primary_channel, band);
        rtw89_phy_write32_idx(rtwdev, R_MAC_PIN_SEL, B_CH_IDX_SEG0, chan_idx, phy_idx);
 }
 
@@ -1246,12 +1246,12 @@ rtw8852c_ctrl_bw(struct rtw89_dev *rtwdev, u8 pri_ch, u8 bw,
 }
 
 static u32 rtw8852c_spur_freq(struct rtw89_dev *rtwdev,
-                             struct rtw89_channel_params *param)
+                             const struct rtw89_chan *chan)
 {
-       u8 center_chan = param->center_chan;
-       u8 bw = param->bandwidth;
+       u8 center_chan = chan->channel;
+       u8 bw = chan->band_width;
 
-       switch (param->band_type) {
+       switch (chan->band_type) {
        case RTW89_BAND_2G:
                if (bw == RTW89_CHANNEL_WIDTH_20) {
                        if (center_chan >= 5 && center_chan <= 8)
@@ -1285,19 +1285,19 @@ static u32 rtw8852c_spur_freq(struct rtw89_dev *rtwdev,
 #define MAX_TONE_NUM 2048
 
 static void rtw8852c_set_csi_tone_idx(struct rtw89_dev *rtwdev,
-                                     struct rtw89_channel_params *param,
+                                     const struct rtw89_chan *chan,
                                      enum rtw89_phy_idx phy_idx)
 {
        u32 spur_freq;
        s32 freq_diff, csi_idx, csi_tone_idx;
 
-       spur_freq = rtw8852c_spur_freq(rtwdev, param);
+       spur_freq = rtw8852c_spur_freq(rtwdev, chan);
        if (spur_freq == 0) {
                rtw89_phy_write32_idx(rtwdev, R_SEG0CSI_EN, B_SEG0CSI_EN, 0, phy_idx);
                return;
        }
 
-       freq_diff = (spur_freq - param->center_freq) * 1000000;
+       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);
 
@@ -1325,7 +1325,7 @@ static const struct rtw89_nbi_reg_def rtw8852c_nbi_reg_def[] = {
 };
 
 static void rtw8852c_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
-                                     struct rtw89_channel_params *param,
+                                     const struct rtw89_chan *chan,
                                      enum rtw89_rf_path path)
 {
        const struct rtw89_nbi_reg_def *nbi = &rtw8852c_nbi_reg_def[path];
@@ -1335,34 +1335,37 @@ static void rtw8852c_set_nbi_tone_idx(struct rtw89_dev *rtwdev,
        s32 nbi_frac_idx, nbi_frac_tone_idx;
        bool notch2_chk = false;
 
-       spur_freq = rtw8852c_spur_freq(rtwdev, param);
+       spur_freq = rtw8852c_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->notch1_en.addr, nbi->notch1_en.mask, 0);
                return;
        }
 
-       fc = param->center_freq;
-       if (param->bandwidth == RTW89_CHANNEL_WIDTH_160) {
+       fc = chan->freq;
+       if (chan->band_width == RTW89_CHANNEL_WIDTH_160) {
                fc = (spur_freq > fc) ? fc + 40 : fc - 40;
-               if ((fc > spur_freq && param->center_chan < param->primary_chan) ||
-                   (fc < spur_freq && param->center_chan > param->primary_chan))
+               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 (param->bandwidth == RTW89_CHANNEL_WIDTH_20) {
+       if (chan->band_width == RTW89_CHANNEL_WIDTH_20) {
                s32_div_u32_round_down(nbi_idx + 32, 64, &nbi_tone_idx);
        } else {
-               u16 tone_para = (param->bandwidth == RTW89_CHANNEL_WIDTH_40) ? 128 : 256;
+               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 (param->bandwidth == RTW89_CHANNEL_WIDTH_160 && notch2_chk) {
+       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,
@@ -1404,42 +1407,42 @@ static void rtw8852c_spur_notch(struct rtw89_dev *rtwdev, u32 val,
 }
 
 static void rtw8852c_spur_elimination(struct rtw89_dev *rtwdev,
-                                     struct rtw89_channel_params *param,
+                                     const struct rtw89_chan *chan,
                                      u8 pri_ch_idx,
                                      enum rtw89_phy_idx phy_idx)
 {
-       rtw8852c_set_csi_tone_idx(rtwdev, param, phy_idx);
+       rtw8852c_set_csi_tone_idx(rtwdev, chan, phy_idx);
 
        if (phy_idx == RTW89_PHY_0) {
-               if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
+               if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
                    (pri_ch_idx == RTW89_SC_20_LOWER ||
                     pri_ch_idx == RTW89_SC_20_UP3X)) {
                        rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_0);
                        if (!rtwdev->dbcc_en)
                                rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_1);
-               } else if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
+               } else if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
                           (pri_ch_idx == RTW89_SC_20_UPPER ||
                            pri_ch_idx == RTW89_SC_20_LOW3X)) {
                        rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_0);
                        if (!rtwdev->dbcc_en)
                                rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_1);
                } else {
-                       rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_A);
+                       rtw8852c_set_nbi_tone_idx(rtwdev, chan, RF_PATH_A);
                        if (!rtwdev->dbcc_en)
-                               rtw8852c_set_nbi_tone_idx(rtwdev, param,
+                               rtw8852c_set_nbi_tone_idx(rtwdev, chan,
                                                          RF_PATH_B);
                }
        } else {
-               if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
+               if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
                    (pri_ch_idx == RTW89_SC_20_LOWER ||
                     pri_ch_idx == RTW89_SC_20_UP3X)) {
                        rtw8852c_spur_notch(rtwdev, 0xe7f, RTW89_PHY_1);
-               } else if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
+               } else if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
                           (pri_ch_idx == RTW89_SC_20_UPPER ||
                            pri_ch_idx == RTW89_SC_20_LOW3X)) {
                        rtw8852c_spur_notch(rtwdev, 0x280, RTW89_PHY_1);
                } else {
-                       rtw8852c_set_nbi_tone_idx(rtwdev, param, RF_PATH_B);
+                       rtw8852c_set_nbi_tone_idx(rtwdev, chan, RF_PATH_B);
                }
        }
 
@@ -1450,14 +1453,14 @@ static void rtw8852c_spur_elimination(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_5m_mask(struct rtw89_dev *rtwdev,
-                            struct rtw89_channel_params *param,
+                            const struct rtw89_chan *chan,
                             enum rtw89_phy_idx phy_idx)
 {
-       u8 pri_ch = param->primary_chan;
+       u8 pri_ch = chan->primary_channel;
        bool mask_5m_low;
        bool mask_5m_en;
 
-       switch (param->bandwidth) {
+       switch (chan->band_width) {
        case RTW89_CHANNEL_WIDTH_40:
                mask_5m_en = true;
                mask_5m_low = pri_ch == 2;
@@ -1526,11 +1529,9 @@ static void rtw8852c_bb_reset_all(struct rtw89_dev *rtwdev,
                              phy_idx);
 }
 
-static void rtw8852c_bb_reset_en(struct rtw89_dev *rtwdev,
+static void rtw8852c_bb_reset_en(struct rtw89_dev *rtwdev, enum rtw89_band band,
                                 enum rtw89_phy_idx phy_idx, bool en)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
-
        if (en) {
                rtw89_phy_write32_idx(rtwdev, R_S0_HW_SI_DIS,
                                      B_S0_HW_SI_DIS_W_R_TRIG, 0x0, phy_idx);
@@ -1538,7 +1539,7 @@ static void rtw8852c_bb_reset_en(struct rtw89_dev *rtwdev,
                                      B_S1_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 (hal->current_band_type == RTW89_BAND_2G)
+               if (band == RTW89_BAND_2G)
                        rtw89_phy_write32_mask(rtwdev, R_RXCCA_V1, B_RXCCA_DIS_V1, 0x0);
                rtw89_phy_write32_mask(rtwdev, R_PD_CTRL, B_PD_HIT_DIS, 0x0);
        } else {
@@ -1690,21 +1691,22 @@ static void rtw8852c_bb_sethw(struct rtw89_dev *rtwdev)
 }
 
 static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
-                                   struct rtw89_channel_params *param,
+                                   const struct rtw89_chan *chan,
                                    enum rtw89_phy_idx phy_idx)
 {
-       bool cck_en = param->band_type == RTW89_BAND_2G;
-       u8 pri_ch_idx = param->pri_ch_idx;
+       bool cck_en = chan->band_type == RTW89_BAND_2G;
+       u8 pri_ch_idx = chan->pri_ch_idx;
        u32 mask, reg;
        u32 ru_alloc_msk[2] = {B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY0,
                               B_P80_AT_HIGH_FREQ_RU_ALLOC_PHY1};
 
-       if (param->band_type == RTW89_BAND_2G)
-               rtw8852c_ctrl_sco_cck(rtwdev, param->center_chan,
-                                     param->primary_chan, param->bandwidth);
+       if (chan->band_type == RTW89_BAND_2G)
+               rtw8852c_ctrl_sco_cck(rtwdev, chan->channel,
+                                     chan->primary_channel,
+                                     chan->band_width);
 
-       rtw8852c_ctrl_ch(rtwdev, param, phy_idx);
-       rtw8852c_ctrl_bw(rtwdev, pri_ch_idx, param->bandwidth, phy_idx);
+       rtw8852c_ctrl_ch(rtwdev, chan, phy_idx);
+       rtw8852c_ctrl_bw(rtwdev, pri_ch_idx, chan->band_width, phy_idx);
        if (cck_en) {
                rtw89_phy_write32_mask(rtwdev, R_UPD_CLK_ADC, B_ENABLE_CCK, 1);
                rtw89_phy_write32_mask(rtwdev, R_RXCCA_V1, B_RXCCA_DIS_V1, 0);
@@ -1717,17 +1719,17 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
                                      B_PD_ARBITER_OFF, 0x1, phy_idx);
        }
 
-       rtw8852c_spur_elimination(rtwdev, param, pri_ch_idx, phy_idx);
-       rtw8852c_ctrl_btg(rtwdev, param->band_type == RTW89_BAND_2G);
-       rtw8852c_5m_mask(rtwdev, param, phy_idx);
+       rtw8852c_spur_elimination(rtwdev, chan, pri_ch_idx, phy_idx);
+       rtw8852c_ctrl_btg(rtwdev, chan->band_type == RTW89_BAND_2G);
+       rtw8852c_5m_mask(rtwdev, chan, phy_idx);
 
-       if (param->bandwidth == RTW89_CHANNEL_WIDTH_160 &&
+       if (chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
            rtwdev->hal.cv != CHIP_CAV) {
                rtw89_phy_write32_idx(rtwdev, R_P80_AT_HIGH_FREQ,
                                      B_P80_AT_HIGH_FREQ, 0x0, phy_idx);
                reg = rtw89_mac_reg_by_idx(R_P80_AT_HIGH_FREQ_BB_WRP,
                                           phy_idx);
-               if (param->primary_chan > param->center_chan) {
+               if (chan->primary_channel > chan->channel) {
                        rtw89_phy_write32_mask(rtwdev,
                                               R_P80_AT_HIGH_FREQ_RU_ALLOC,
                                               ru_alloc_msk[phy_idx], 1);
@@ -1742,8 +1744,8 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
                }
        }
 
-       if (param->band_type == RTW89_BAND_6G &&
-           param->bandwidth == RTW89_CHANNEL_WIDTH_160)
+       if (chan->band_type == RTW89_BAND_6G &&
+           chan->band_width == RTW89_CHANNEL_WIDTH_160)
                rtw89_phy_write32_idx(rtwdev, R_CDD_EVM_CHK_EN,
                                      B_CDD_EVM_CHK_EN, 0, phy_idx);
        else
@@ -1773,11 +1775,13 @@ static void rtw8852c_set_channel_bb(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_set_channel(struct rtw89_dev *rtwdev,
-                                struct rtw89_channel_params *params)
+                                const struct rtw89_chan *chan,
+                                enum rtw89_mac_idx mac_idx,
+                                enum rtw89_phy_idx phy_idx)
 {
-       rtw8852c_set_channel_mac(rtwdev, params, RTW89_MAC_0);
-       rtw8852c_set_channel_bb(rtwdev, params, RTW89_PHY_0);
-       rtw8852c_set_channel_rf(rtwdev, params, RTW89_PHY_0);
+       rtw8852c_set_channel_mac(rtwdev, chan, mac_idx);
+       rtw8852c_set_channel_bb(rtwdev, chan, phy_idx);
+       rtw8852c_set_channel_rf(rtwdev, chan, phy_idx);
 }
 
 static void rtw8852c_dfs_en(struct rtw89_dev *rtwdev, bool en)
@@ -1799,25 +1803,27 @@ static void rtw8852c_adc_en(struct rtw89_dev *rtwdev, bool en)
 }
 
 static void rtw8852c_set_channel_help(struct rtw89_dev *rtwdev, bool enter,
-                                     struct rtw89_channel_help_params *p)
+                                     struct rtw89_channel_help_params *p,
+                                     const struct rtw89_chan *chan,
+                                     enum rtw89_mac_idx mac_idx,
+                                     enum rtw89_phy_idx phy_idx)
 {
-       u8 phy_idx = RTW89_PHY_0;
-
        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);
+               rtw89_chip_stop_sch_tx(rtwdev, mac_idx, &p->tx_en,
+                                      RTW89_SCH_TX_SEL_ALL);
+               rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, false);
                rtw8852c_dfs_en(rtwdev, false);
-               rtw8852c_tssi_cont_en_phyidx(rtwdev, false, RTW89_PHY_0);
+               rtw8852c_tssi_cont_en_phyidx(rtwdev, false, phy_idx);
                rtw8852c_adc_en(rtwdev, false);
                fsleep(40);
-               rtw8852c_bb_reset_en(rtwdev, phy_idx, false);
+               rtw8852c_bb_reset_en(rtwdev, chan->band_type, phy_idx, false);
        } else {
-               rtw89_mac_cfg_ppdu_status(rtwdev, RTW89_MAC_0, true);
+               rtw89_mac_cfg_ppdu_status(rtwdev, mac_idx, true);
                rtw8852c_adc_en(rtwdev, true);
                rtw8852c_dfs_en(rtwdev, true);
-               rtw8852c_tssi_cont_en_phyidx(rtwdev, true, RTW89_PHY_0);
-               rtw8852c_bb_reset_en(rtwdev, phy_idx, true);
-               rtw89_chip_resume_sch_tx(rtwdev, RTW89_MAC_0, p->tx_en);
+               rtw8852c_tssi_cont_en_phyidx(rtwdev, true, phy_idx);
+               rtw8852c_bb_reset_en(rtwdev, chan->band_type, phy_idx, true);
+               rtw89_chip_resume_sch_tx(rtwdev, mac_idx, p->tx_en);
        }
 }
 
@@ -1847,9 +1853,10 @@ static void rtw8852c_rfk_channel(struct rtw89_dev *rtwdev)
        rtw89_fw_h2c_rf_ntfy_mcc(rtwdev);
 }
 
-static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev)
+static void rtw8852c_rfk_band_changed(struct rtw89_dev *rtwdev,
+                                     enum rtw89_phy_idx phy_idx)
 {
-       rtw8852c_tssi_scan(rtwdev, RTW89_PHY_0);
+       rtw8852c_tssi_scan(rtwdev, phy_idx);
 }
 
 static void rtw8852c_rfk_scan(struct rtw89_dev *rtwdev, bool start)
@@ -1958,9 +1965,11 @@ static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
+                                     const struct rtw89_chan *chan,
                                      enum rtw89_phy_idx phy_idx)
 {
-       u8 ch = rtwdev->hal.current_channel;
+       u8 band = chan->band_type;
+       u8 ch = chan->channel;
        static const u8 rs[] = {
                RTW89_RS_CCK,
                RTW89_RS_OFDM,
@@ -1986,7 +1995,8 @@ static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
                        for (j = 0; j < rtw89_rs_idx_max[rs[i]]; j++) {
                                cur.idx = j;
                                shf = (j % 4) * 8;
-                               tmp = rtw89_phy_read_txpwr_byrate(rtwdev, &cur);
+                               tmp = rtw89_phy_read_txpwr_byrate(rtwdev, band,
+                                                                 &cur);
                                val |= (tmp << shf);
 
                                if ((j + 1) % 4)
@@ -2001,8 +2011,10 @@ static void rtw8852c_set_txpwr_byrate(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_set_txpwr_offset(struct rtw89_dev *rtwdev,
+                                     const struct rtw89_chan *chan,
                                      enum rtw89_phy_idx phy_idx)
 {
+       u8 band = chan->band_type;
        struct rtw89_rate_desc desc = {
                .nss = RTW89_NSS_1,
                .rs = RTW89_RS_OFFSET,
@@ -2013,7 +2025,7 @@ static void rtw8852c_set_txpwr_offset(struct rtw89_dev *rtwdev,
        rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set txpwr offset\n");
 
        for (desc.idx = 0; desc.idx < RTW89_RATE_OFFSET_MAX; desc.idx++) {
-               v = rtw89_phy_read_txpwr_byrate(rtwdev, &desc);
+               v = rtw89_phy_read_txpwr_byrate(rtwdev, band, &desc);
                val |= ((v & 0xf) << (4 * desc.idx));
        }
 
@@ -2045,7 +2057,8 @@ static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
        __DECL_DFIR_ADDR(filter,
                         0x45BC, 0x45CC, 0x45D0, 0x45D4, 0x45D8, 0x45C0,
                         0x45C4, 0x45C8);
-       u8 ch = rtwdev->hal.current_channel;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 ch = chan->channel;
        const u32 *param;
        int i;
 
@@ -2076,9 +2089,10 @@ static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
+                                 const struct rtw89_chan *chan,
                                  enum rtw89_phy_idx phy_idx)
 {
-       u8 band = rtwdev->hal.current_band_type;
+       u8 band = chan->band_type;
        u8 regd = rtw89_regd_get(rtwdev, band);
        u8 tx_shape_cck = rtw89_8852c_tx_shape[band][RTW89_RS_CCK][regd];
        u8 tx_shape_ofdm = rtw89_8852c_tx_shape[band][RTW89_RS_OFDM][regd];
@@ -2092,29 +2106,31 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_set_txpwr_limit(struct rtw89_dev *rtwdev,
+                                    const struct rtw89_chan *chan,
                                     enum rtw89_phy_idx phy_idx)
 {
 #define __MAC_TXPWR_LMT_PAGE_SIZE 40
-       u8 ch = rtwdev->hal.current_channel;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 ch = chan->channel;
+       u8 bw = chan->band_width;
        struct rtw89_txpwr_limit lmt[NTX_NUM_8852C];
        u32 addr, val;
        const s8 *ptr;
-       u8 i, j, k;
+       u8 i, j;
 
        rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
                    "[TXPWR] set txpwr limit with ch=%d bw=%d\n", ch, bw);
 
        for (i = 0; i < NTX_NUM_8852C; i++) {
-               rtw89_phy_fill_txpwr_limit(rtwdev, &lmt[i], i);
+               rtw89_phy_fill_txpwr_limit(rtwdev, chan, &lmt[i], i);
 
                for (j = 0; j < __MAC_TXPWR_LMT_PAGE_SIZE; j += 4) {
                        addr = R_AX_PWR_LMT + j + __MAC_TXPWR_LMT_PAGE_SIZE * i;
                        ptr = (s8 *)&lmt[i] + j;
-                       val = 0;
 
-                       for (k = 0; k < 4; k++)
-                               val |= (ptr[k] << (8 * k));
+                       val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
+                             FIELD_PREP(GENMASK(15, 8), ptr[1]) |
+                             FIELD_PREP(GENMASK(23, 16), ptr[2]) |
+                             FIELD_PREP(GENMASK(31, 24), ptr[3]);
 
                        rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
                }
@@ -2123,30 +2139,32 @@ static void rtw8852c_set_txpwr_limit(struct rtw89_dev *rtwdev,
 }
 
 static void rtw8852c_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
+                                       const struct rtw89_chan *chan,
                                        enum rtw89_phy_idx phy_idx)
 {
 #define __MAC_TXPWR_LMT_RU_PAGE_SIZE 24
-       u8 ch = rtwdev->hal.current_channel;
-       u8 bw = rtwdev->hal.current_band_width;
+       u8 ch = chan->channel;
+       u8 bw = chan->band_width;
        struct rtw89_txpwr_limit_ru lmt_ru[NTX_NUM_8852C];
        u32 addr, val;
        const s8 *ptr;
-       u8 i, j, k;
+       u8 i, j;
 
        rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
                    "[TXPWR] set txpwr limit ru with ch=%d bw=%d\n", ch, bw);
 
        for (i = 0; i < NTX_NUM_8852C; i++) {
-               rtw89_phy_fill_txpwr_limit_ru(rtwdev, &lmt_ru[i], i);
+               rtw89_phy_fill_txpwr_limit_ru(rtwdev, chan, &lmt_ru[i], i);
 
                for (j = 0; j < __MAC_TXPWR_LMT_RU_PAGE_SIZE; j += 4) {
                        addr = R_AX_PWR_RU_LMT + j +
                               __MAC_TXPWR_LMT_RU_PAGE_SIZE * i;
                        ptr = (s8 *)&lmt_ru[i] + j;
-                       val = 0;
 
-                       for (k = 0; k < 4; k++)
-                               val |= (ptr[k] << (8 * k));
+                       val = FIELD_PREP(GENMASK(7, 0), ptr[0]) |
+                             FIELD_PREP(GENMASK(15, 8), ptr[1]) |
+                             FIELD_PREP(GENMASK(23, 16), ptr[2]) |
+                             FIELD_PREP(GENMASK(31, 24), ptr[3]);
 
                        rtw89_mac_txpwr_write32(rtwdev, phy_idx, addr, val);
                }
@@ -2155,18 +2173,21 @@ static void rtw8852c_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
 #undef __MAC_TXPWR_LMT_RU_PAGE_SIZE
 }
 
-static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev)
+static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
+                              const struct rtw89_chan *chan,
+                              enum rtw89_phy_idx phy_idx)
 {
-       rtw8852c_set_txpwr_byrate(rtwdev, RTW89_PHY_0);
-       rtw8852c_set_txpwr_offset(rtwdev, RTW89_PHY_0);
-       rtw8852c_set_tx_shape(rtwdev, RTW89_PHY_0);
-       rtw8852c_set_txpwr_limit(rtwdev, RTW89_PHY_0);
-       rtw8852c_set_txpwr_limit_ru(rtwdev, RTW89_PHY_0);
+       rtw8852c_set_txpwr_byrate(rtwdev, chan, phy_idx);
+       rtw8852c_set_txpwr_offset(rtwdev, chan, phy_idx);
+       rtw8852c_set_tx_shape(rtwdev, chan, phy_idx);
+       rtw8852c_set_txpwr_limit(rtwdev, chan, phy_idx);
+       rtw8852c_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
 }
 
-static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev)
+static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
+                                   enum rtw89_phy_idx phy_idx)
 {
-       rtw8852c_set_txpwr_ref(rtwdev, RTW89_PHY_0);
+       rtw8852c_set_txpwr_ref(rtwdev, phy_idx);
 }
 
 static void
@@ -2222,7 +2243,8 @@ rtw8852c_init_txpwr_unit(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
 
 static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path)
 {
-       struct rtw89_hal *hal = &rtwdev->hal;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 band = chan->band_type;
        u32 rst_mask0 = B_P0_TXPW_RSTB_MANON | B_P0_TXPW_RSTB_TSSI;
        u32 rst_mask1 = B_P1_TXPW_RSTB_MANON | B_P1_TXPW_RSTB_TSSI;
 
@@ -2316,7 +2338,7 @@ static void rtw8852c_bb_cfg_rx_path(struct rtw89_dev *rtwdev, u8 rx_path)
                                               1);
                        rtw89_phy_write32_mask(rtwdev, R_RXHE, B_RXHETB_MAX_NSS,
                                               1);
-                       rtw8852c_ctrl_btg(rtwdev, hal->current_band_type == RTW89_BAND_2G);
+                       rtw8852c_ctrl_btg(rtwdev, band == RTW89_BAND_2G);
                        rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
                                               rst_mask0, 1);
                        rtw89_phy_write32_mask(rtwdev, R_P0_TXPW_RSTB,
@@ -2773,23 +2795,7 @@ void rtw8852c_btc_bt_aci_imp(struct rtw89_dev *rtwdev)
 static
 void rtw8852c_btc_update_bt_cnt(struct rtw89_dev *rtwdev)
 {
-       struct rtw89_btc *btc = &rtwdev->btc;
-       struct rtw89_btc_cx *cx = &btc->cx;
-       u32 val;
-
-       val = rtw89_read32(rtwdev, R_BTC_BT_CNT_HIGH);
-       cx->cnt_bt[BTC_BCNT_HIPRI_TX] = FIELD_GET(B_AX_STATIS_BT_HI_TX_MASK, val);
-       cx->cnt_bt[BTC_BCNT_HIPRI_RX] = FIELD_GET(B_AX_STATIS_BT_HI_RX_MASK, val);
-
-       val = rtw89_read32(rtwdev, R_BTC_BT_CNT_LOW);
-       cx->cnt_bt[BTC_BCNT_LOPRI_TX] = FIELD_GET(B_AX_STATIS_BT_LO_TX_1_MASK, val);
-       cx->cnt_bt[BTC_BCNT_LOPRI_RX] = FIELD_GET(B_AX_STATIS_BT_LO_RX_1_MASK, val);
-
-       /* clock-gate off before reset counter*/
-       rtw89_write32_set(rtwdev, R_AX_BTC_CFG, B_AX_DIS_BTC_CLK_G);
-       rtw89_write32_clr(rtwdev, R_AX_BT_CNT_CFG, B_AX_BT_CNT_RST);
-       rtw89_write32_set(rtwdev, R_AX_BT_CNT_CFG, B_AX_BT_CNT_RST);
-       rtw89_write32_clr(rtwdev, R_AX_BTC_CFG, B_AX_DIS_BTC_CLK_G);
+       /* Feature move to firmware */
 }
 
 static
@@ -2930,6 +2936,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
        .btc_bt_aci_imp         = rtw8852c_btc_bt_aci_imp,
        .btc_update_bt_cnt      = rtw8852c_btc_update_bt_cnt,
        .btc_wl_s1_standby      = rtw8852c_btc_wl_s1_standby,
+       .btc_set_policy         = rtw89_btc_set_policy_v1,
 };
 
 const struct rtw89_chip_info rtw8852c_chip_info = {
@@ -2961,6 +2968,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
        .txpwr_factor_mac       = 1,
        .dig_table              = NULL,
        .tssi_dbw_table         = &rtw89_8852c_tssi_dbw_table,
+       .support_chanctx_num    = 1,
        .support_bands          = BIT(NL80211_BAND_2GHZ) |
                                  BIT(NL80211_BAND_5GHZ) |
                                  BIT(NL80211_BAND_6GHZ),
@@ -2972,6 +2980,9 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
        .acam_num               = 128,
        .bcam_num               = 20,
        .scam_num               = 128,
+       .bacam_num              = 8,
+       .bacam_dynamic_num      = 8,
+       .bacam_v1               = true,
        .sec_ctrl_efuse_size    = 4,
        .physical_efuse_size    = 1216,
        .logical_efuse_size     = 2048,
@@ -2985,6 +2996,20 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
        .btcx_desired           = 0x5,
        .scbd                   = 0x1,
        .mailbox                = 0x1,
+
+       .fcxbtcrpt_ver          = 4,
+       .fcxtdma_ver            = 3,
+       .fcxslots_ver           = 1,
+       .fcxcysta_ver           = 3,
+       .fcxstep_ver            = 3,
+       .fcxnullsta_ver         = 2,
+       .fcxmreg_ver            = 1,
+       .fcxgpiodbg_ver         = 1,
+       .fcxbtver_ver           = 1,
+       .fcxbtscan_ver          = 1,
+       .fcxbtafh_ver           = 1,
+       .fcxbtdevinfo_ver       = 1,
+
        .afh_guard_ch           = 6,
        .wl_rssi_thres          = rtw89_btc_8852c_wl_rssi_thres,
        .bt_rssi_thres          = rtw89_btc_8852c_bt_rssi_thres,
index 4186d82..478a36d 100644 (file)
@@ -1294,14 +1294,14 @@ static void _iqk_by_path(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx, u
 static void _iqk_get_ch_info(struct rtw89_dev *rtwdev,
                             enum rtw89_phy_idx phy, u8 path)
 {
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct rtw89_iqk_info *iqk_info = &rtwdev->iqk;
-       struct rtw89_hal *hal = &rtwdev->hal;
 
        rtw89_debug(rtwdev, RTW89_DBG_RFK, "[IQK]===>%s\n", __func__);
 
-       iqk_info->iqk_band[path] = hal->current_band_type;
-       iqk_info->iqk_bw[path] = hal->current_band_width;
-       iqk_info->iqk_ch[path] = hal->current_channel;
+       iqk_info->iqk_band[path] = chan->band_type;
+       iqk_info->iqk_bw[path] = chan->band_width;
+       iqk_info->iqk_ch[path] = chan->channel;
 
        rtw89_debug(rtwdev, RTW89_DBG_RFK,
                    "[IQK]iqk_info->iqk_band[%x] = 0x%x\n", path,
@@ -1691,14 +1691,14 @@ 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;
-       struct rtw89_hal *hal = &rtwdev->hal;
 
        u8 kidx = dpk->cur_idx[path];
 
-       dpk->bp[path][kidx].band = hal->current_band_type;
-       dpk->bp[path][kidx].ch = hal->current_channel;
-       dpk->bp[path][kidx].bw = hal->current_band_width;
+       dpk->bp[path][kidx].band = chan->band_type;
+       dpk->bp[path][kidx].ch = chan->channel;
+       dpk->bp[path][kidx].bw = chan->band_width;
 
        rtw89_debug(rtwdev, RTW89_DBG_RFK,
                    "[DPK] S%d[%d] (PHY%d): TSSI %s/ DBCC %s/ %s/ CH%d/ %s\n",
@@ -2272,12 +2272,13 @@ static void _dpk_idl_mpa(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
 static bool _dpk_reload_check(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;
        bool is_reload = false;
        u8 idx, cur_band, cur_ch;
 
-       cur_band = rtwdev->hal.current_band_type;
-       cur_ch = rtwdev->hal.current_channel;
+       cur_band = chan->band_type;
+       cur_ch = chan->channel;
 
        for (idx = 0; idx < RTW89_DPK_BKUP_NUM; idx++) {
                if (cur_band != dpk->bp[path][idx].band ||
@@ -2530,17 +2531,19 @@ static void _dpk_cal_select(struct rtw89_dev *rtwdev, bool force,
 static bool _dpk_bypass_check(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy)
 {
        struct rtw89_fem_info *fem = &rtwdev->fem;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       u8 band = chan->band_type;
 
-       if (rtwdev->hal.cv == CHIP_CAV && rtwdev->hal.current_band_type != RTW89_BAND_2G) {
+       if (rtwdev->hal.cv == CHIP_CAV && band != RTW89_BAND_2G) {
                rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to CAV & not 2G!!\n");
                return true;
-       } else if (fem->epa_2g && rtwdev->hal.current_band_type == RTW89_BAND_2G) {
+       } else if (fem->epa_2g && band == RTW89_BAND_2G) {
                rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to 2G_ext_PA exist!!\n");
                return true;
-       } else if (fem->epa_5g && rtwdev->hal.current_band_type == RTW89_BAND_5G) {
+       } else if (fem->epa_5g && band == RTW89_BAND_5G) {
                rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to 5G_ext_PA exist!!\n");
                return true;
-       } else if (fem->epa_6g && rtwdev->hal.current_band_type == RTW89_BAND_6G) {
+       } else if (fem->epa_6g && band == RTW89_BAND_6G) {
                rtw89_debug(rtwdev, RTW89_DBG_RFK, "[DPK] Skip DPK due to 6G_ext_PA exist!!\n");
                return true;
        }
@@ -2663,7 +2666,8 @@ static void _dpk_track(struct rtw89_dev *rtwdev)
 static void _tssi_set_sys(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                          enum rtw89_rf_path path)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
 
        rtw89_rfk_parser(rtwdev, &rtw8852c_tssi_sys_defs_tbl);
 
@@ -2697,7 +2701,8 @@ static void _tssi_ini_txpwr_ctrl_bb_he_tb(struct rtw89_dev *rtwdev,
 static void _tssi_set_dck(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                          enum rtw89_rf_path path)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
 
        if (path == RF_PATH_A) {
                rtw89_rfk_parser(rtwdev, &rtw8852c_tssi_dck_defs_a_tbl);
@@ -2735,8 +2740,9 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
        __val;                                          \
 })
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
-       u8 ch = rtwdev->hal.current_channel;
-       u8 subband = rtwdev->hal.current_subband;
+       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;
        const s8 *thm_up_b = NULL;
@@ -2908,7 +2914,8 @@ static void _tssi_set_tmeter_tbl(struct rtw89_dev *rtwdev, enum rtw89_phy_idx ph
 static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                                enum rtw89_rf_path path)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
 
        if (path == RF_PATH_A) {
                rtw89_rfk_parser_by_cond(rtwdev, band == RTW89_BAND_2G,
@@ -2924,7 +2931,8 @@ static void _tssi_slope_cal_org(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy
 static void _tssi_set_aligk_default(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
                                    enum rtw89_rf_path path)
 {
-       enum rtw89_band band = rtwdev->hal.current_band_type;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
        const struct rtw89_rfk_tbl *tbl;
 
        if (path == RF_PATH_A) {
@@ -3335,8 +3343,9 @@ 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;
-       enum rtw89_band band = rtwdev->hal.current_band_type;
-       u8 ch = rtwdev->hal.current_channel;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
+       u8 ch = chan->channel;
        u32 gidx, gidx_1st, gidx_2nd;
        s8 de_1st;
        s8 de_2nd;
@@ -3398,8 +3407,9 @@ static s8 _tssi_get_ofdm_trim_de(struct rtw89_dev *rtwdev,
                                 enum rtw89_rf_path path)
 {
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
-       enum rtw89_band band = rtwdev->hal.current_band_type;
-       u8 ch = rtwdev->hal.current_channel;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
+       u8 ch = chan->channel;
        u32 tgidx, tgidx_1st, tgidx_2nd;
        s8 tde_1st = 0;
        s8 tde_2nd = 0;
@@ -3462,7 +3472,8 @@ static void _tssi_set_efuse_to_de(struct rtw89_dev *rtwdev,
                                  enum rtw89_phy_idx phy)
 {
        struct rtw89_tssi_info *tssi_info = &rtwdev->tssi;
-       u8 ch = rtwdev->hal.current_channel;
+       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;
@@ -3802,15 +3813,17 @@ void rtw8852c_ctrl_bw_ch(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
 }
 
 void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
-                            struct rtw89_channel_params *param,
+                            const struct rtw89_chan *chan,
                             enum rtw89_phy_idx phy_idx)
 {
-       rtw8852c_ctrl_bw_ch(rtwdev, phy_idx, param->center_chan, param->band_type,
-                           param->bandwidth);
+       rtw8852c_ctrl_bw_ch(rtwdev, phy_idx, chan->channel,
+                           chan->band_type,
+                           chan->band_width);
 }
 
 void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
 {
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
        struct rtw89_mcc_info *mcc_info = &rtwdev->mcc;
        u8 idx = mcc_info->table_idx;
        int i;
@@ -3823,8 +3836,8 @@ void rtw8852c_mcc_get_ch_info(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_i
        }
 
        mcc_info->table_idx = idx;
-       mcc_info->ch[idx] = rtwdev->hal.current_channel;
-       mcc_info->band[idx] = rtwdev->hal.current_band_type;
+       mcc_info->ch[idx] = chan->channel;
+       mcc_info->band[idx] = chan->band_type;
 }
 
 void rtw8852c_rck(struct rtw89_dev *rtwdev)
index 5118a49..928a587 100644 (file)
@@ -21,7 +21,7 @@ void rtw8852c_tssi_cont_en_phyidx(struct rtw89_dev *rtwdev, bool en, u8 phy_idx)
 void rtw8852c_wifi_scan_notify(struct rtw89_dev *rtwdev, bool scan_start,
                               enum rtw89_phy_idx phy_idx);
 void rtw8852c_set_channel_rf(struct rtw89_dev *rtwdev,
-                            struct rtw89_channel_params *param,
+                            const struct rtw89_chan *chan,
                             enum rtw89_phy_idx phy_idx);
 void rtw8852c_lck_init(struct rtw89_dev *rtwdev);
 void rtw8852c_lck_track(struct rtw89_dev *rtwdev);
index feaa83b..11f35e7 100644 (file)
@@ -1767,7 +1767,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_bb_reg_gain[] = {
        {0x3070103, 0x34343C3C},
 };
 
-static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
+static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] = {
        {0xF0010000, 0x00000000},
        {0xF0020000, 0x00000001},
        {0xF0320000, 0x00000002},
@@ -1777,13 +1777,17 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0xF0360000, 0x00000006},
        {0xF0010001, 0x00000007},
        {0xF0020001, 0x00000008},
-       {0xF0320001, 0x00000009},
-       {0xF0330001, 0x0000000A},
-       {0xF0340001, 0x0000000B},
-       {0xF0350001, 0x0000000C},
-       {0xF0360001, 0x0000000D},
-       {0xF03F0001, 0x0000000E},
-       {0xF0400001, 0x0000000F},
+       {0xF0030001, 0x00000009},
+       {0xF0040001, 0x0000000A},
+       {0xF0050001, 0x0000000B},
+       {0xF0070001, 0x0000000C},
+       {0xF0320001, 0x0000000D},
+       {0xF0330001, 0x0000000E},
+       {0xF0340001, 0x0000000F},
+       {0xF0350001, 0x00000010},
+       {0xF0360001, 0x00000011},
+       {0xF03F0001, 0x00000012},
+       {0xF0400001, 0x00000013},
        {0x005, 0x00000000},
        {0x10005, 0x00000000},
        {0x000, 0x00030001},
@@ -1795,7 +1799,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03E, 0x00000620},
        {0x03F, 0x0000020C},
        {0x0EF, 0x00000000},
-       {0x05F, 0x00000032},
+       {0x05F, 0x00000038},
        {0x097, 0x00043200},
        {0x0A6, 0x00066DB7},
        {0x0EF, 0x00004000},
@@ -1821,8 +1825,8 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x000, 0x00033C01},
        {0x10000, 0x00033C00},
        {0x01A, 0x00040004},
-       {0x0FE, 0x00000000},
        {0x096, 0x00015200},
+       {0x10055, 0x00080080},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x067, 0x0004D000},
        {0x0DA, 0x000D4009},
@@ -1850,6 +1854,18 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x067, 0x0000D300},
        {0x0DA, 0x000D4000},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x067, 0x0000D300},
        {0x0DA, 0x000D4000},
@@ -1922,6 +1938,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000CC},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000CC},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000CC},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000CC},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000CC},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000CC},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000CC},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -1958,6 +1982,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000C4},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000C4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000C4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000C4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000C4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000C4},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000C4},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -1994,6 +2026,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000BC},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000BC},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000BC},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2030,6 +2070,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000B4},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000B4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000B4},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2066,6 +2114,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000AC},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000AC},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000AC},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2102,6 +2158,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000A4},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000A4},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2138,6 +2202,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000009C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000009C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000009C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2174,6 +2246,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000094},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000094},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000094},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2210,6 +2290,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000008C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000008C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000008C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2246,6 +2334,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000084},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000084},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000084},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2282,6 +2378,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000BC},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000BC},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000BC},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000BC},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2318,6 +2422,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000B4},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000B4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000B4},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000B4},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2354,6 +2466,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000AC},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000AC},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000AC},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000AC},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2390,6 +2510,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000000A4},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000000A4},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000000A4},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2426,6 +2554,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000009C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000009C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000009C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2462,6 +2598,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000094},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000094},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000094},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000094},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2498,6 +2642,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000008C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000008C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000008C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000008C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2534,6 +2686,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000084},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000084},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000084},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000084},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2570,6 +2730,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000003C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000003C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000003C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000003C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000003C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000003C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000003C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2606,6 +2774,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000034},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000034},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000034},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000034},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000034},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000034},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000034},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2642,6 +2818,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000002C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000002C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000002C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000002C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000002C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000002C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000002C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2678,6 +2862,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000024},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000024},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000024},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000024},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000024},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000024},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000024},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2714,6 +2906,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000001C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000001C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000001C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000001C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000001C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000001C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000001C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2750,6 +2950,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000014},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000014},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000014},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000014},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000014},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000014},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000014},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2786,6 +2994,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000000C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000000C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000000C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000000C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000000C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000000C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000000C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2822,6 +3038,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000004},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000004},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000004},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000004},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000004},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000004},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000004},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2871,6 +3095,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x08F, 0x000D1352},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x08F, 0x000D1352},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x08F, 0x000D1352},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -2905,6 +3137,52 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000015},
        {0x033, 0x00000001},
        {0x03F, 0x00000017},
+       {0x033, 0x00000002},
+       {0x03F, 0x00000017},
+       {0x033, 0x00000003},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0xB0000000, 0x00000000},
        {0x0EF, 0x00000000},
        {0x0EF, 0x00008000},
        {0x033, 0x00000020},
@@ -3416,6 +3694,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000EFFF},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000EFFF},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000EFFF},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3522,7 +3808,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x033, 0x00000005},
        {0x03F, 0x00004344},
        {0x033, 0x00000006},
-       {0x03F, 0x00004324},
+       {0x03F, 0x00004344},
        {0x033, 0x00000007},
        {0x03F, 0x00004344},
        {0x033, 0x00000008},
@@ -3585,6 +3871,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x00000200},
        {0x0EF, 0x00000000},
        {0x0EF, 0x00000010},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x030, 0x000084DC},
        {0x030, 0x000103C9},
        {0x030, 0x00018399},
@@ -3597,98 +3884,359 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x030, 0x00050011},
        {0x030, 0x00058000},
        {0x030, 0x00060000},
-       {0x030, 0x00068000},
-       {0x030, 0x00070000},
-       {0x0EF, 0x00000000},
-       {0x0EF, 0x00000080},
-       {0x033, 0x00000004},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x00000005},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x00000006},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00021C58},
-       {0x033, 0x00000007},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022B58},
-       {0x033, 0x00000008},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x00000009},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x0000000A},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00021C58},
-       {0x033, 0x0000000B},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022B58},
-       {0x033, 0x0000000C},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x0000000D},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x0000000E},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00021C58},
-       {0x033, 0x0000000F},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022B58},
-       {0x033, 0x00000010},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x00000011},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00023C58},
-       {0x033, 0x00000012},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00021C58},
-       {0x033, 0x00000013},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022B58},
-       {0x033, 0x00000014},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023C58},
-       {0x033, 0x00000015},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00025A58},
-       {0x033, 0x00000016},
-       {0x03E, 0x0000001C},
-       {0x03F, 0x00021C58},
-       {0x033, 0x00000017},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000018},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00025A58},
-       {0x033, 0x00000019},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00025A58},
-       {0x033, 0x0000001A},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022A58},
-       {0x033, 0x0000001B},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00022A58},
-       {0x033, 0x0000001C},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002CD58},
-       {0x033, 0x0000001D},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00025A58},
-       {0x033, 0x0000001E},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00021E58},
-       {0x033, 0x0000001F},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000020},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002CD58},
-       {0x033, 0x00000021},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90010001, 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},
+       {0x90020001, 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},
+       {0x90030001, 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},
+       {0x90040001, 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},
+       {0x90050001, 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},
+       {0x90070001, 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},
+       {0x030, 0x000184AA},
+       {0x030, 0x00020388},
+       {0x030, 0x00028377},
+       {0x030, 0x00030377},
+       {0x030, 0x00038255},
+       {0x030, 0x00040244},
+       {0x030, 0x00048133},
+       {0x030, 0x00050112},
+       {0x030, 0x00058101},
+       {0x030, 0x00060001},
+       {0x90330001, 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},
+       {0x90340001, 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},
+       {0x90350001, 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},
+       {0x90360001, 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},
+       {0x903f0001, 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},
+       {0x90400001, 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},
+       {0xA0000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0xB0000000, 0x00000000},
+       {0x030, 0x00068000},
+       {0x030, 0x00070000},
+       {0x0EF, 0x00000000},
+       {0x0EF, 0x00000080},
+       {0x033, 0x00000004},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x00000005},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x00000006},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00021C58},
+       {0x033, 0x00000007},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022B58},
+       {0x033, 0x00000008},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x00000009},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x0000000A},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00021C58},
+       {0x033, 0x0000000B},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022B58},
+       {0x033, 0x0000000C},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x0000000D},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x0000000E},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00021C58},
+       {0x033, 0x0000000F},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022B58},
+       {0x033, 0x00000010},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x00000011},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00023C58},
+       {0x033, 0x00000012},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00021C58},
+       {0x033, 0x00000013},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022B58},
+       {0x033, 0x00000014},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023C58},
+       {0x033, 0x00000015},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00025A58},
+       {0x033, 0x00000016},
+       {0x03E, 0x0000001C},
+       {0x03F, 0x00021C58},
+       {0x033, 0x00000017},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022A58},
+       {0x033, 0x00000018},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00025A58},
+       {0x033, 0x00000019},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00025A58},
+       {0x033, 0x0000001A},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022A58},
+       {0x033, 0x0000001B},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00022A58},
+       {0x033, 0x0000001C},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002CD58},
+       {0x033, 0x0000001D},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00025A58},
+       {0x033, 0x0000001E},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00021E58},
+       {0x033, 0x0000001F},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
+       {0x033, 0x00000020},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002CD58},
+       {0x033, 0x00000021},
        {0x03E, 0x0000001C},
        {0x03F, 0x0002CD58},
        {0x033, 0x00000022},
@@ -3831,6 +4379,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x030, 0x000300FF},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x030, 0x000300FF},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000300FF},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000300FF},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000300FF},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000300FF},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x030, 0x000300FF},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3901,6 +4457,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {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},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x095, 0x00000008},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -3920,109 +4484,13 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0xB0000000, 0x00000000},
        {0x0EE, 0x00001000},
        {0x033, 0x00000020},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000052},
-       {0x033, 0x00000024},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000028},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000002C},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000030},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000034},
-       {0x03F, 0x000001E7},
-       {0x033, 0x00000038},
-       {0x03F, 0x000002E7},
-       {0x033, 0x0000003C},
-       {0x03F, 0x000003E7},
-       {0x033, 0x00000021},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000052},
-       {0x033, 0x00000025},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000029},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000002D},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000031},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000035},
-       {0x03F, 0x000001E6},
-       {0x033, 0x00000039},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000003D},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000022},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000052},
-       {0x033, 0x00000026},
-       {0x03F, 0x0000005A},
-       {0x033, 0x0000002A},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000002E},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000032},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000036},
-       {0x03F, 0x000001E6},
-       {0x033, 0x0000003A},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000003E},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000060},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000064},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000068},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000006C},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000070},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000074},
-       {0x03F, 0x000001E6},
-       {0x033, 0x00000078},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000007C},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000061},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000065},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000069},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000006D},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000071},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000075},
-       {0x03F, 0x000001E6},
-       {0x033, 0x00000079},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000007D},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000062},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000066},
-       {0x03F, 0x0000005A},
-       {0x033, 0x0000006A},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000006E},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000072},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000076},
-       {0x03F, 0x000001E6},
-       {0x033, 0x0000007A},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000007E},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000063},
-       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
-       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
-       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
-       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000052},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000052},
@@ -4034,24 +4502,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {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},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000152},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x03F, 0x00000052},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x03F, 0x00000052},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x03F, 0x00000052},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x03F, 0x00000052},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x03F, 0x00000052},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x03F, 0x00000052},
        {0xA0000000, 0x00000000},
        {0x03F, 0x00000052},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000067},
+       {0x033, 0x00000024},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000005A},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
@@ -4070,24 +4546,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {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},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000015A},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x0000005A},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x0000005A},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x0000005A},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x0000005A},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x0000005A},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x0000005A},
        {0xA0000000, 0x00000000},
        {0x03F, 0x0000005A},
        {0xB0000000, 0x00000000},
-       {0x033, 0x0000006B},
+       {0x033, 0x00000028},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000009C},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
@@ -4106,24 +4590,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x0000019C},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000019C},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x0000009C},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x0000009C},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x0000009C},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x0000009C},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x0000009C},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x0000009C},
        {0xA0000000, 0x00000000},
        {0x03F, 0x0000009C},
        {0xB0000000, 0x00000000},
-       {0x033, 0x0000006F},
+       {0x033, 0x0000002C},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x0000019C},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
@@ -4142,24 +4634,32 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000001A4},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000001A4},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x0000019C},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x0000019C},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x0000019C},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x0000019C},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x0000019C},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x0000019C},
        {0xA0000000, 0x00000000},
        {0x03F, 0x0000019C},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000073},
+       {0x033, 0x00000030},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000001A4},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
@@ -4178,2976 +4678,8760 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x03F, 0x000001E6},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000001E6},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001A4},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001A4},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001A4},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001A4},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001A4},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001A4},
        {0xA0000000, 0x00000000},
        {0x03F, 0x000001A4},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000077},
+       {0x033, 0x00000034},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000002E6},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x000002E6},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x000001E7},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x000001E7},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x000001E7},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x000001E7},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x000001E7},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x000001E7},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x000001E7},
        {0xB0000000, 0x00000000},
-       {0x033, 0x0000007B},
+       {0x033, 0x00000038},
        {0x03F, 0x000002E7},
-       {0x033, 0x0000007F},
+       {0x033, 0x0000003C},
        {0x03F, 0x000003E7},
-       {0x0EE, 0x00000000},
-       {0x100EE, 0x00004000},
+       {0x033, 0x00000021},
        {0x80010000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90020000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90320000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90010001, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781EF},
-       {0x10030, 0x000785E9},
-       {0x10030, 0x000789E3},
-       {0x10030, 0x00078DA3},
-       {0x10030, 0x00079161},
-       {0x10030, 0x0007955B},
-       {0x10030, 0x00079921},
-       {0x10030, 0x00079D1B},
-       {0x10030, 0x0007A0E1},
-       {0x10030, 0x0007A4DB},
-       {0x10030, 0x0007A8A1},
-       {0x10030, 0x0007AC9B},
-       {0x10030, 0x0007B061},
-       {0x10030, 0x0007B45B},
-       {0x10030, 0x0007B821},
-       {0x10030, 0x0007BC1B},
-       {0x10030, 0x0007C015},
-       {0x10030, 0x0007C40F},
+       {0x03F, 0x00000152},
        {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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781EF},
-       {0x10030, 0x000785E9},
-       {0x10030, 0x000789E3},
-       {0x10030, 0x00078DA3},
-       {0x10030, 0x00079161},
-       {0x10030, 0x0007955B},
-       {0x10030, 0x00079921},
-       {0x10030, 0x00079D1B},
-       {0x10030, 0x0007A0E1},
-       {0x10030, 0x0007A4DB},
-       {0x10030, 0x0007A8A1},
-       {0x10030, 0x0007AC9B},
-       {0x10030, 0x0007B061},
-       {0x10030, 0x0007B45B},
-       {0x10030, 0x0007B821},
-       {0x10030, 0x0007BC1B},
-       {0x10030, 0x0007C015},
-       {0x10030, 0x0007C40F},
+       {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},
        {0x90320001, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781EF},
-       {0x10030, 0x000785E9},
-       {0x10030, 0x000789E3},
-       {0x10030, 0x00078DA3},
-       {0x10030, 0x00079161},
-       {0x10030, 0x0007955B},
-       {0x10030, 0x00079921},
-       {0x10030, 0x00079D1B},
-       {0x10030, 0x0007A0E1},
-       {0x10030, 0x0007A4DB},
-       {0x10030, 0x0007A8A1},
-       {0x10030, 0x0007AC9B},
-       {0x10030, 0x0007B061},
-       {0x10030, 0x0007B45B},
-       {0x10030, 0x0007B821},
-       {0x10030, 0x0007BC1B},
-       {0x10030, 0x0007C015},
-       {0x10030, 0x0007C40F},
+       {0x03F, 0x00000152},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0xA0000000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000052},
        {0xB0000000, 0x00000000},
-       {0x100EE, 0x00000000},
-       {0x100EE, 0x00002000},
-       {0x10030, 0x000000FC},
-       {0x10030, 0x000004F9},
-       {0x10030, 0x000008F6},
-       {0x10030, 0x00000CF3},
-       {0x10030, 0x000010F0},
-       {0x10030, 0x000014ED},
-       {0x10030, 0x000018AC},
-       {0x10030, 0x00001CA9},
-       {0x10030, 0x00002069},
-       {0x10030, 0x00002466},
-       {0x10030, 0x00002829},
-       {0x10030, 0x00002C26},
-       {0x10030, 0x00003023},
-       {0x10030, 0x00003420},
-       {0x10030, 0x0000381D},
-       {0x10030, 0x00003C1A},
-       {0x10030, 0x00004017},
-       {0x100EE, 0x00000000},
-       {0x100EE, 0x00002000},
-       {0x10030, 0x000780F4},
-       {0x10030, 0x000784F1},
-       {0x10030, 0x000788EE},
-       {0x10030, 0x00078CEB},
-       {0x10030, 0x000790E8},
-       {0x10030, 0x000794E5},
-       {0x10030, 0x000798E2},
-       {0x10030, 0x00079CDF},
-       {0x10030, 0x0007A0DC},
-       {0x10030, 0x0007A4D9},
-       {0x10030, 0x0007A8D6},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B0D0},
-       {0x10030, 0x0007B4CD},
-       {0x10030, 0x0007B8CA},
-       {0x10030, 0x0007BC07},
-       {0x10030, 0x0007C004},
-       {0x100EE, 0x00000000},
-       {0x0EF, 0x00002000},
-       {0x033, 0x00000008},
-       {0x03F, 0x00000004},
-       {0x033, 0x00000009},
-       {0x03F, 0x00000003},
-       {0x033, 0x0000000A},
-       {0x03F, 0x00000003},
-       {0x033, 0x0000000B},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000C},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000D},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000E},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000F},
-       {0x03F, 0x00000002},
-       {0x0EF, 0x00000000},
-       {0x0EB, 0x00040000},
-       {0x030, 0x000109B7},
-       {0x0EB, 0x00000000},
-       {0x0EF, 0x00008000},
-       {0x033, 0x00000020},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000021},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000022},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000023},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000024},
-       {0x03F, 0x00008001},
        {0x033, 0x00000025},
-       {0x03F, 0x00008002},
-       {0x033, 0x00000026},
-       {0x03F, 0x00000003},
-       {0x033, 0x00000027},
-       {0x03F, 0x00000003},
-       {0x033, 0x00000028},
-       {0x03F, 0x00050002},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000029},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000002A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000002B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000002C},
-       {0x03F, 0x00008001},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
        {0x033, 0x0000002D},
-       {0x03F, 0x00008002},
-       {0x033, 0x0000002E},
-       {0x03F, 0x00000003},
-       {0x033, 0x0000002F},
-       {0x03F, 0x00000003},
-       {0x033, 0x00000030},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000031},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000032},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000033},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000034},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000035},
-       {0x03F, 0x00008002},
-       {0x033, 0x00000036},
-       {0x03F, 0x00000003},
-       {0x033, 0x00000037},
-       {0x03F, 0x00000003},
-       {0x033, 0x00000060},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000061},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000062},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000063},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000064},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000065},
-       {0x03F, 0x00008002},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000031},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000035},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000039},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000003D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000022},
+       {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},
+       {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, 0x00000026},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000002A},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000002E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000032},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000036},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000003A},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000003E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000060},
+       {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},
+       {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, 0x00000064},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000068},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006C},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000070},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000074},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000078},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007C},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000061},
+       {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},
+       {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, 0x00000065},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000069},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000071},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000075},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000079},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000062},
+       {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},
+       {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, 0x00000066},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006A},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000072},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000076},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007A},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000063},
+       {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},
+       {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, 0x00000067},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006B},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000073},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000077},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007B},
+       {0x03F, 0x000002E7},
+       {0x033, 0x0000007F},
+       {0x03F, 0x000003E7},
+       {0x0EE, 0x00000000},
+       {0x100EE, 0x00004000},
+       {0x80010000, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90020000, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90320000, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x90010001, 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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {0x90040001, 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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {0x90050001, 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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {0x90070001, 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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {0x90320001, 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, 0x000701EF},
+       {0x10030, 0x000705E7},
+       {0x10030, 0x000709A7},
+       {0x10030, 0x00070D61},
+       {0x10030, 0x0007115B},
+       {0x10030, 0x00071523},
+       {0x10030, 0x0007191D},
+       {0x10030, 0x00071D17},
+       {0x10030, 0x000720DF},
+       {0x10030, 0x000724D9},
+       {0x10030, 0x000728A1},
+       {0x10030, 0x00072C67},
+       {0x10030, 0x00073061},
+       {0x10030, 0x00073427},
+       {0x10030, 0x00073821},
+       {0x10030, 0x00073C1B},
+       {0x10030, 0x00074015},
+       {0x10030, 0x0007440D},
+       {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},
+       {0x90330001, 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, 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, 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, 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},
+       {0x90340001, 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, 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, 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, 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},
+       {0x90350001, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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},
+       {0xA0000000, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0xB0000000, 0x00000000},
+       {0x100EE, 0x00000000},
+       {0x100EE, 0x00002000},
+       {0x10030, 0x000000FC},
+       {0x10030, 0x000004F9},
+       {0x10030, 0x000008F6},
+       {0x10030, 0x00000CF3},
+       {0x10030, 0x000010F0},
+       {0x10030, 0x000014ED},
+       {0x10030, 0x000018AC},
+       {0x10030, 0x00001CA9},
+       {0x10030, 0x00002069},
+       {0x10030, 0x00002466},
+       {0x10030, 0x00002829},
+       {0x10030, 0x00002C26},
+       {0x10030, 0x00003023},
+       {0x10030, 0x00003420},
+       {0x10030, 0x0000381D},
+       {0x10030, 0x00003C1A},
+       {0x10030, 0x00004017},
+       {0x100EE, 0x00000000},
+       {0x100EE, 0x00002000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
+       {0xA0000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0xB0000000, 0x00000000},
+       {0x10030, 0x000600F6},
+       {0x10030, 0x000604F3},
+       {0x10030, 0x000608F0},
+       {0x10030, 0x00060CED},
+       {0x10030, 0x000610EA},
+       {0x10030, 0x000614E7},
+       {0x10030, 0x000618E4},
+       {0x10030, 0x00061CE1},
+       {0x10030, 0x000620DE},
+       {0x10030, 0x000624DB},
+       {0x10030, 0x000628D8},
+       {0x10030, 0x00062CD5},
+       {0x10030, 0x000630D2},
+       {0x10030, 0x000634CF},
+       {0x10030, 0x000638CC},
+       {0x10030, 0x00063C09},
+       {0x10030, 0x00064006},
+       {0x10030, 0x000680F5},
+       {0x10030, 0x000684F2},
+       {0x10030, 0x000688EF},
+       {0x10030, 0x00068CEC},
+       {0x10030, 0x000690E9},
+       {0x10030, 0x000694E6},
+       {0x10030, 0x000698E3},
+       {0x10030, 0x00069CE0},
+       {0x10030, 0x0006A0DD},
+       {0x10030, 0x0006A4DA},
+       {0x10030, 0x0006A8D7},
+       {0x10030, 0x0006ACD4},
+       {0x10030, 0x0006B0D1},
+       {0x10030, 0x0006B4CE},
+       {0x10030, 0x0006B8CB},
+       {0x10030, 0x0006BC08},
+       {0x10030, 0x0006C005},
+       {0x10030, 0x000700F5},
+       {0x10030, 0x000704F2},
+       {0x10030, 0x000708EF},
+       {0x10030, 0x00070CEC},
+       {0x10030, 0x000710E9},
+       {0x10030, 0x000714E6},
+       {0x10030, 0x000718E3},
+       {0x10030, 0x00071CE0},
+       {0x10030, 0x000720DD},
+       {0x10030, 0x000724DA},
+       {0x10030, 0x000728D7},
+       {0x10030, 0x00072CD4},
+       {0x10030, 0x000730D1},
+       {0x10030, 0x000734CE},
+       {0x10030, 0x000738CB},
+       {0x10030, 0x00073C08},
+       {0x10030, 0x00074005},
+       {0x10030, 0x000780F4},
+       {0x10030, 0x000784F1},
+       {0x10030, 0x000788EE},
+       {0x10030, 0x00078CEB},
+       {0x10030, 0x000790E8},
+       {0x10030, 0x000794E5},
+       {0x10030, 0x000798E2},
+       {0x10030, 0x00079CDF},
+       {0x10030, 0x0007A0DC},
+       {0x10030, 0x0007A4D9},
+       {0x10030, 0x0007A8D6},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B0D0},
+       {0x10030, 0x0007B4CD},
+       {0x10030, 0x0007B8CA},
+       {0x10030, 0x0007BC07},
+       {0x10030, 0x0007C004},
+       {0x100EE, 0x00000000},
+       {0x0EF, 0x00002000},
+       {0x033, 0x00000008},
+       {0x03F, 0x00000004},
+       {0x033, 0x00000009},
+       {0x03F, 0x00000003},
+       {0x033, 0x0000000A},
+       {0x03F, 0x00000003},
+       {0x033, 0x0000000B},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000C},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000D},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000E},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000F},
+       {0x03F, 0x00000002},
+       {0x0EF, 0x00000000},
+       {0x0EB, 0x00040000},
+       {0x030, 0x000109B7},
+       {0x0EB, 0x00000000},
+       {0x0EF, 0x00008000},
+       {0x033, 0x00000020},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000021},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000022},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000023},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000024},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000025},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000026},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000027},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000028},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000029},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000002A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000002B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000002C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000002D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000002E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000002F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000030},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000031},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000032},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000033},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000034},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000035},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000036},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000037},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000060},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000061},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000062},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000063},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000064},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000065},
+       {0x03F, 0x00008002},
        {0x033, 0x00000066},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000067},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000068},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000069},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000006A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000006B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000006C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000006D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000006E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000070},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000071},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000072},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000073},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000074},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000075},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000076},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000077},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000078},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000079},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000007A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000007B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000007C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000007D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000007E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000A0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000A1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000A2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000A3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000A4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000A5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000A6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000A7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000A8},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000A9},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000AA},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000AB},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000AC},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000AD},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000AE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000AF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000B0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000B1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000B2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000B3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000B4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000B5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000B6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000B7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000E0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000E1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000E2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000E3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000E4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000E5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000E6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000E7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000E8},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000E9},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000EA},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000EB},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000EC},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000ED},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000EE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000EF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000F0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000F1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000F2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000F3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000F4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000F5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000F6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000F7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000F8},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000F9},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000FA},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000FB},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000FC},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000FD},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000FE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000FF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000120},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000121},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000122},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000123},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000124},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000125},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000126},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000127},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000128},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000129},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000012A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000012B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000012C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000012D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000012E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000012F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000130},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000131},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000132},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000133},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000134},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000135},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000136},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000137},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000160},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000161},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000162},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000163},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000164},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000165},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000166},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000167},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000168},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000169},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000016A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000016B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000016C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000016D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000016E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000016F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000170},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000171},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000172},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000173},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000174},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000175},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000176},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000177},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000067},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000068},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000178},
        {0x03F, 0x00050002},
-       {0x033, 0x00000069},
+       {0x033, 0x00000179},
        {0x03F, 0x00060032},
-       {0x033, 0x0000006A},
+       {0x033, 0x0000017A},
        {0x03F, 0x00050042},
-       {0x033, 0x0000006B},
+       {0x033, 0x0000017B},
        {0x03F, 0x00040042},
-       {0x033, 0x0000006C},
+       {0x033, 0x0000017C},
        {0x03F, 0x00008001},
-       {0x033, 0x0000006D},
+       {0x033, 0x0000017D},
        {0x03F, 0x00008002},
-       {0x033, 0x0000006E},
+       {0x033, 0x0000017E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000006F},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000070},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000071},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000072},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000073},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000074},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000075},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000076},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000077},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000078},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000079},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000007A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000007B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000007C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000007D},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x0000007E},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000007F},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000017F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000A0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000A1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000A2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000A3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000A4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000A5},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000A6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000A7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000A8},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001A0},
        {0x03F, 0x00050002},
-       {0x033, 0x000000A9},
+       {0x033, 0x000001A1},
        {0x03F, 0x00060032},
-       {0x033, 0x000000AA},
+       {0x033, 0x000001A2},
        {0x03F, 0x00050042},
-       {0x033, 0x000000AB},
+       {0x033, 0x000001A3},
        {0x03F, 0x00040042},
-       {0x033, 0x000000AC},
+       {0x033, 0x000001A4},
        {0x03F, 0x00008001},
-       {0x033, 0x000000AD},
+       {0x033, 0x000001A5},
        {0x03F, 0x00008002},
-       {0x033, 0x000000AE},
+       {0x033, 0x000001A6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000AF},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000B0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000B1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000B2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000B3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000B4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000B5},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000B6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000B7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000E0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000E1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000E2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000E3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000E4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000E5},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000E7},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001A7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000E8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000E9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000EA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000EB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000EC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000ED},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000EE},
-       {0x03F, 0x00000003},
-       {0x033, 0x000000EF},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000F0},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001A8},
        {0x03F, 0x00050002},
-       {0x033, 0x000000F1},
+       {0x033, 0x000001A9},
        {0x03F, 0x00060032},
-       {0x033, 0x000000F2},
+       {0x033, 0x000001AA},
        {0x03F, 0x00050042},
-       {0x033, 0x000000F3},
+       {0x033, 0x000001AB},
        {0x03F, 0x00040042},
-       {0x033, 0x000000F4},
+       {0x033, 0x000001AC},
        {0x03F, 0x00008001},
-       {0x033, 0x000000F5},
+       {0x033, 0x000001AD},
        {0x03F, 0x00008002},
-       {0x033, 0x000000F6},
+       {0x033, 0x000001AE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000F7},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000F8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000F9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000FA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000FB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000FC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000FD},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000FE},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000FF},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000120},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000121},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000122},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000123},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000124},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000125},
-       {0x03F, 0x00008002},
-       {0x033, 0x00000126},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000127},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000128},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000129},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000012A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000012B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000012C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000012D},
-       {0x03F, 0x00008002},
-       {0x033, 0x0000012E},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000012F},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000130},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000131},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000132},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000133},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000134},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000135},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000136},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000137},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001AF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000160},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000161},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000162},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000163},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000164},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000165},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000166},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000167},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000168},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001B0},
        {0x03F, 0x00050002},
-       {0x033, 0x00000169},
+       {0x033, 0x000001B1},
        {0x03F, 0x00060032},
-       {0x033, 0x0000016A},
+       {0x033, 0x000001B2},
        {0x03F, 0x00050042},
-       {0x033, 0x0000016B},
+       {0x033, 0x000001B3},
        {0x03F, 0x00040042},
-       {0x033, 0x0000016C},
+       {0x033, 0x000001B4},
        {0x03F, 0x00008001},
-       {0x033, 0x0000016D},
+       {0x033, 0x000001B5},
        {0x03F, 0x00008002},
-       {0x033, 0x0000016E},
+       {0x033, 0x000001B6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000016F},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000170},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000171},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000172},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000173},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000174},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000175},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000176},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000177},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000178},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000179},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000017A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000017B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000017C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000017D},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x0000017E},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000017F},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001B7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001A0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001A1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001A2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001A3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001A4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001A5},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000001A6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001A7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001A8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001A9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001AA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001AB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001AC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001AD},
-       {0x03F, 0x00008002},
-       {0x033, 0x000001AE},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001AF},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001B0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001B1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001B2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001B3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001B4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001B5},
-       {0x03F, 0x00008002},
-       {0x033, 0x000001B6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001B7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001E0},
        {0x03F, 0x00050002},
        {0x033, 0x000001E1},
@@ -7161,9 +13445,93 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x033, 0x000001E5},
        {0x03F, 0x00008002},
        {0x033, 0x000001E6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001E7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001E8},
        {0x03F, 0x00050002},
        {0x033, 0x000001E9},
@@ -7177,9 +13545,93 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x033, 0x000001ED},
        {0x03F, 0x00008002},
        {0x033, 0x000001EE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001EF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001F0},
        {0x03F, 0x00050002},
        {0x033, 0x000001F1},
@@ -7193,9 +13645,93 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x033, 0x000001F5},
        {0x03F, 0x00008002},
        {0x033, 0x000001F6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001F7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001F7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001F8},
        {0x03F, 0x00050002},
        {0x033, 0x000001F9},
@@ -7209,9 +13745,93 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x033, 0x000001FD},
        {0x03F, 0x00008002},
        {0x033, 0x000001FE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x033, 0x000001FF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x0EF, 0x00000000},
        {0x005, 0x00000001},
        {0x10005, 0x00000001},
@@ -7253,7 +13873,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x10030, 0x00022000},
        {0x10030, 0x00023000},
        {0x10030, 0x00024000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x10030, 0x00025000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0xA0000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00026003},
        {0x10030, 0x00027003},
        {0x10030, 0x00028000},
@@ -7261,7 +13923,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x10030, 0x0002A000},
        {0x10030, 0x0002B000},
        {0x10030, 0x0002C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0002D000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0002E003},
        {0x10030, 0x0002F003},
        {0x10030, 0x00030000},
@@ -7269,7 +13973,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x10030, 0x00032000},
        {0x10030, 0x00033000},
        {0x10030, 0x00034000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x00035000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00036003},
        {0x10030, 0x00037003},
        {0x10030, 0x00038000},
@@ -7277,7 +14023,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x10030, 0x0003A000},
        {0x10030, 0x0003B000},
        {0x10030, 0x0003C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0003D000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0003E003},
        {0x10030, 0x0003F003},
        {0x10030, 0x00060000},
@@ -7285,35 +14073,283 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radioa_regs[] =  {
        {0x10030, 0x00062000},
        {0x10030, 0x00063000},
        {0x10030, 0x00064000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x00065000},
        {0x10030, 0x00066000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00067003},
        {0x10030, 0x00068000},
        {0x10030, 0x00069000},
        {0x10030, 0x0006A000},
        {0x10030, 0x0006B000},
        {0x10030, 0x0006C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0006D000},
        {0x10030, 0x0006E000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0006F003},
        {0x10030, 0x00070000},
        {0x10030, 0x00071000},
        {0x10030, 0x00072000},
        {0x10030, 0x00073000},
        {0x10030, 0x00074000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x00075000},
        {0x10030, 0x00076000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00077003},
        {0x10030, 0x00078000},
        {0x10030, 0x00079000},
        {0x10030, 0x0007A000},
        {0x10030, 0x0007B000},
        {0x10030, 0x0007C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0007D000},
        {0x10030, 0x0007E000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0007F003},
        {0x100EE, 0x00000000},
-       {0x0FE, 0x00000031},
+       {0x0FE, 0x00000048},
 };
 
 static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
@@ -7326,13 +14362,17 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0xF0360000, 0x00000006},
        {0xF0010001, 0x00000007},
        {0xF0020001, 0x00000008},
-       {0xF0320001, 0x00000009},
-       {0xF0330001, 0x0000000A},
-       {0xF0340001, 0x0000000B},
-       {0xF0350001, 0x0000000C},
-       {0xF0360001, 0x0000000D},
-       {0xF03F0001, 0x0000000E},
-       {0xF0400001, 0x0000000F},
+       {0xF0030001, 0x00000009},
+       {0xF0040001, 0x0000000A},
+       {0xF0050001, 0x0000000B},
+       {0xF0070001, 0x0000000C},
+       {0xF0320001, 0x0000000D},
+       {0xF0330001, 0x0000000E},
+       {0xF0340001, 0x0000000F},
+       {0xF0350001, 0x00000010},
+       {0xF0360001, 0x00000011},
+       {0xF03F0001, 0x00000012},
+       {0xF0400001, 0x00000013},
        {0x005, 0x00000000},
        {0x10005, 0x00000000},
        {0x0B9, 0x00020440},
@@ -7340,42 +14380,69 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x10000, 0x00030000},
        {0x018, 0x00011124},
        {0x10018, 0x00011124},
-       {0x05F, 0x00000032},
+       {0x05F, 0x00000038},
        {0x097, 0x00043200},
        {0x0A6, 0x00066DB7},
        {0x0EF, 0x00004000},
        {0x033, 0x00000005},
        {0x03E, 0x00000000},
        {0x03F, 0x00010500},
+       {0x033, 0x00000004},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00000400},
        {0x033, 0x00000003},
        {0x03E, 0x00000000},
        {0x03F, 0x00028B00},
        {0x033, 0x00000002},
        {0x03E, 0x00000000},
        {0x03F, 0x0009AB00},
+       {0x033, 0x00000001},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00001A00},
+       {0x033, 0x00000000},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00002900},
        {0x033, 0x0000000D},
        {0x03E, 0x00000000},
        {0x03F, 0x00010500},
+       {0x033, 0x0000000C},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00000400},
        {0x033, 0x0000000B},
        {0x03E, 0x00000000},
        {0x03F, 0x00028B00},
        {0x033, 0x0000000A},
        {0x03E, 0x00000000},
        {0x03F, 0x0009AB00},
+       {0x033, 0x00000009},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00001A00},
+       {0x033, 0x00000008},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00002900},
        {0x033, 0x00000015},
        {0x03E, 0x00000000},
        {0x03F, 0x00010500},
+       {0x033, 0x00000014},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00000400},
        {0x033, 0x00000013},
        {0x03E, 0x00000000},
        {0x03F, 0x00028B00},
        {0x033, 0x00000012},
        {0x03E, 0x00000000},
        {0x03F, 0x0009AB00},
+       {0x033, 0x00000011},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00001A00},
+       {0x033, 0x00000010},
+       {0x03E, 0x00000000},
+       {0x03F, 0x00002900},
        {0x0EF, 0x00000000},
+       {0x10055, 0x00080080},
        {0x000, 0x00033C01},
        {0x10000, 0x00033C00},
        {0x01A, 0x00040004},
-       {0x0FE, 0x00000000},
        {0x096, 0x00015200},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x067, 0x0004D000},
@@ -7404,6 +14471,18 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x067, 0x0000D300},
        {0x0DA, 0x000D4000},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x067, 0x0000D300},
+       {0x0DA, 0x000D4000},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x067, 0x0000D300},
        {0x0DA, 0x000D4000},
@@ -7430,7 +14509,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x0DA, 0x000D4009},
        {0xB0000000, 0x00000000},
        {0x057, 0x0000D589},
-       {0x05A, 0x0007FFFF},
+       {0x05A, 0x0007F0F8},
        {0x043, 0x00005000},
        {0x018, 0x00001001},
        {0x10018, 0x00001001},
@@ -7462,6 +14541,14 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x08F, 0x000D1352},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x08F, 0x000D1352},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x08F, 0x000D1352},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
        {0x08F, 0x000D1352},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
@@ -7496,6 +14583,52 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x03F, 0x00000015},
        {0x033, 0x00000001},
        {0x03F, 0x00000017},
+       {0x033, 0x00000004},
+       {0x03F, 0x00000017},
+       {0x033, 0x00000005},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000017},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000007},
+       {0xB0000000, 0x00000000},
        {0x0EF, 0x00000000},
        {0x0EF, 0x00008000},
        {0x033, 0x00000020},
@@ -7947,3828 +15080,10246 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x033, 0x000001FF},
        {0x03F, 0x00000003},
        {0x0EF, 0x00000000},
-       {0x0EF, 0x00000100},
+       {0x0EF, 0x00000100},
+       {0x033, 0x00000001},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000002},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000003},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000004},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000005},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000006},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000007},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000008},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000009},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000000A},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000000B},
+       {0x03F, 0x0000AFFF},
+       {0x033, 0x0000000C},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000000D},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000000E},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000000F},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000010},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000011},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000012},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000013},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000014},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000015},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000EFFF},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000E3FF},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000016},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000017},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000018},
+       {0x03F, 0x0000FBFF},
+       {0x033, 0x00000019},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000001A},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000001B},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000001C},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000001D},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000001E},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000001F},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000020},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000021},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000022},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000023},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000024},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000025},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000026},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000027},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000028},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000029},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000002A},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000002B},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000002C},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000002D},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000002E},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000002F},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000030},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000031},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000032},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000033},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000034},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000035},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000036},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000037},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000038},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x00000039},
+       {0x03F, 0x0000EFFF},
+       {0x033, 0x0000003A},
+       {0x03F, 0x0000EFFF},
+       {0x0EF, 0x00000000},
+       {0x0EF, 0x00000040},
+       {0x033, 0x00000000},
+       {0x03F, 0x00004344},
        {0x033, 0x00000001},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000002},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000003},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000004},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000005},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000006},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000007},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000008},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x00000009},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
        {0x033, 0x0000000A},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000000B},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000010},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000011},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000012},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000013},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000014},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000015},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000016},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000017},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000018},
+       {0x03F, 0x00004344},
+       {0x033, 0x00000019},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000001A},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000001B},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000001C},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000001D},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000001E},
+       {0x03F, 0x00004344},
+       {0x033, 0x0000001F},
+       {0x03F, 0x00004344},
+       {0x0EF, 0x00000000},
+       {0x0EF, 0x00000020},
+       {0x033, 0x00000010},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000011},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000012},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000013},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000020},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000021},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000022},
+       {0x03F, 0x00000200},
+       {0x033, 0x00000023},
+       {0x03F, 0x00000200},
+       {0x0EF, 0x00000000},
+       {0x0EF, 0x00000010},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0x90010001, 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},
+       {0x90020001, 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},
+       {0x90030001, 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},
+       {0x90040001, 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},
+       {0x90050001, 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},
+       {0x90070001, 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},
+       {0x030, 0x000184AA},
+       {0x030, 0x00020388},
+       {0x030, 0x00028377},
+       {0x030, 0x00030377},
+       {0x030, 0x00038255},
+       {0x030, 0x00040244},
+       {0x030, 0x00048133},
+       {0x030, 0x00050112},
+       {0x030, 0x00058101},
+       {0x030, 0x00060001},
+       {0x90330001, 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},
+       {0x90340001, 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},
+       {0x90350001, 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},
+       {0x90360001, 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},
+       {0x903f0001, 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},
+       {0x90400001, 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},
+       {0xA0000000, 0x00000000},
+       {0x030, 0x000084DC},
+       {0x030, 0x000103C9},
+       {0x030, 0x00018399},
+       {0x030, 0x00020287},
+       {0x030, 0x00028277},
+       {0x030, 0x00030165},
+       {0x030, 0x00038144},
+       {0x030, 0x00040044},
+       {0x030, 0x00048022},
+       {0x030, 0x00050011},
+       {0x030, 0x00058000},
+       {0x030, 0x00060000},
+       {0xB0000000, 0x00000000},
+       {0x030, 0x00068000},
+       {0x030, 0x00070000},
+       {0x0EF, 0x00000000},
+       {0x0EF, 0x00000080},
+       {0x033, 0x00000004},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
+       {0x033, 0x00000005},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
+       {0x033, 0x00000006},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023958},
+       {0x033, 0x00000007},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000008},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
+       {0x033, 0x00000009},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
+       {0x033, 0x0000000A},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023958},
        {0x033, 0x0000000B},
-       {0x03F, 0x0000AFFF},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
        {0x033, 0x0000000C},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
        {0x033, 0x0000000D},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
        {0x033, 0x0000000E},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023958},
        {0x033, 0x0000000F},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
        {0x033, 0x00000010},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
        {0x033, 0x00000011},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00022A58},
        {0x033, 0x00000012},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023958},
        {0x033, 0x00000013},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
        {0x033, 0x00000014},
-       {0x03F, 0x0000EFFF},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00022A58},
        {0x033, 0x00000015},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00029858},
+       {0x033, 0x00000016},
+       {0x03E, 0x0000001C},
+       {0x03F, 0x00023958},
+       {0x033, 0x00000017},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000018},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00029858},
+       {0x033, 0x00000019},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00029858},
+       {0x033, 0x0000001A},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000001B},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000001C},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000001D},
+       {0x03E, 0x0000001B},
+       {0x03F, 0x00029858},
+       {0x033, 0x0000001E},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000001F},
+       {0x03E, 0x00000013},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000020},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000021},
+       {0x03E, 0x0000001C},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000022},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000023},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000024},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000025},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000026},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000027},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000028},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000029},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000002A},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000002B},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000002C},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000002D},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000002E},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000002F},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000030},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000031},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000032},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000033},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000034},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000035},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000036},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000037},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x00000038},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x00000039},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000003A},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000003B},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000003C},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000003D},
+       {0x03E, 0x00000014},
+       {0x03F, 0x0002AC58},
+       {0x033, 0x0000003E},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x033, 0x0000003F},
+       {0x03E, 0x00000014},
+       {0x03F, 0x00023A58},
+       {0x0EF, 0x00000000},
+       {0x0EE, 0x00000800},
+       {0x033, 0x00000000},
+       {0x03F, 0x00000031},
+       {0x033, 0x00000001},
+       {0x03F, 0x00000023},
+       {0x033, 0x00000002},
+       {0x03F, 0x00000015},
+       {0x033, 0x00000003},
+       {0x03F, 0x00000007},
+       {0x0EE, 0x00000000},
+       {0x0EC, 0x00000400},
+       {0x033, 0x00000003},
+       {0x03F, 0x00000030},
+       {0x033, 0x00000004},
+       {0x03F, 0x00000021},
+       {0x0EC, 0x00000000},
+       {0x0DE, 0x00000000},
+       {0x0EF, 0x00000000},
+       {0x033, 0x00000000},
+       {0x008, 0x00060280},
+       {0x009, 0x00030400},
+       {0x0EF, 0x00000000},
+       {0x0A7, 0x00080308},
+       {0x066, 0x00006000},
+       {0x0EF, 0x00000400},
+       {0x030, 0x000001FF},
+       {0x030, 0x000081FF},
+       {0x030, 0x000101FF},
+       {0x030, 0x000181FF},
+       {0x030, 0x000201FF},
+       {0x030, 0x000281FF},
+       {0x030, 0x0003017F},
+       {0x030, 0x000380FB},
+       {0x0EF, 0x00000000},
+       {0x06E, 0x00077A18},
+       {0x06D, 0x00000C31},
+       {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},
+       {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},
+       {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, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000152},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {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},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000152},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000052},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000052},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000052},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000052},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000052},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000EFFF},
+       {0x03F, 0x00000052},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x0000E3FF},
+       {0x03F, 0x00000052},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000016},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000017},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000018},
-       {0x03F, 0x0000FBFF},
-       {0x033, 0x00000019},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000001A},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000001B},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000001C},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000001D},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000001E},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000001F},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000020},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000021},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000022},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000023},
-       {0x03F, 0x0000EFFF},
        {0x033, 0x00000024},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000025},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000026},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000027},
-       {0x03F, 0x0000EFFF},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000028},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000029},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000002A},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000002B},
-       {0x03F, 0x0000EFFF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
        {0x033, 0x0000002C},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000002D},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000002E},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000002F},
-       {0x03F, 0x0000EFFF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000030},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000031},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000032},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000033},
-       {0x03F, 0x0000EFFF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000034},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000035},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000036},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000037},
-       {0x03F, 0x0000EFFF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E7},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000038},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x00000039},
-       {0x03F, 0x0000EFFF},
-       {0x033, 0x0000003A},
-       {0x03F, 0x0000EFFF},
-       {0x0EF, 0x00000000},
-       {0x0EF, 0x00000040},
-       {0x033, 0x00000000},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000001},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000002},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000003},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000004},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000005},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000006},
-       {0x03F, 0x00004324},
-       {0x033, 0x00000007},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000008},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000009},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000000A},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000000B},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000010},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000011},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000012},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000013},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000014},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000015},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000016},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000017},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000018},
-       {0x03F, 0x00004344},
-       {0x033, 0x00000019},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000001A},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000001B},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000001C},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000001D},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000001E},
-       {0x03F, 0x00004344},
-       {0x033, 0x0000001F},
-       {0x03F, 0x00004344},
-       {0x0EF, 0x00000000},
-       {0x0EF, 0x00000020},
-       {0x033, 0x00000010},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000011},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000012},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000013},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000020},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000021},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000022},
-       {0x03F, 0x00000200},
-       {0x033, 0x00000023},
-       {0x03F, 0x00000200},
-       {0x0EF, 0x00000000},
-       {0x0EF, 0x00000010},
-       {0x030, 0x000084DC},
-       {0x030, 0x000103C9},
-       {0x030, 0x00018399},
-       {0x030, 0x00020287},
-       {0x030, 0x00028277},
-       {0x030, 0x00030165},
-       {0x030, 0x00038144},
-       {0x030, 0x00040044},
-       {0x030, 0x00048022},
-       {0x030, 0x00050011},
-       {0x030, 0x00058000},
-       {0x030, 0x00060000},
-       {0x030, 0x00068000},
-       {0x030, 0x00070000},
-       {0x0EF, 0x00000000},
-       {0x0EF, 0x00000080},
-       {0x033, 0x00000004},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000005},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000006},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023958},
-       {0x033, 0x00000007},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000008},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000009},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x0000000A},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023958},
-       {0x033, 0x0000000B},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000000C},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x0000000D},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x0000000E},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023958},
-       {0x033, 0x0000000F},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000010},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000011},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000012},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023958},
-       {0x033, 0x00000013},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000014},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00022A58},
-       {0x033, 0x00000015},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00029858},
-       {0x033, 0x00000016},
-       {0x03E, 0x0000001C},
-       {0x03F, 0x00023958},
-       {0x033, 0x00000017},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000018},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00029858},
-       {0x033, 0x00000019},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00029858},
-       {0x033, 0x0000001A},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000001B},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000001C},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x0000001D},
-       {0x03E, 0x0000001B},
-       {0x03F, 0x00029858},
-       {0x033, 0x0000001E},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000001F},
-       {0x03E, 0x00000013},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000020},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000003C},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000021},
-       {0x03E, 0x0000001C},
-       {0x03F, 0x0002AC58},
+       {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},
+       {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, 0x00000025},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000029},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000002D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000031},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000035},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000039},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000003D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000022},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000023},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000024},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x00000025},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {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},
+       {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, 0x00000026},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000027},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000028},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x00000029},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
        {0x033, 0x0000002A},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000002B},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000002C},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x0000002D},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
        {0x033, 0x0000002E},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000002F},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000030},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x00000031},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000032},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000033},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000034},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x00000035},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
        {0x033, 0x00000036},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000037},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x00000038},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x00000039},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
        {0x033, 0x0000003A},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000003B},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000003C},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
-       {0x033, 0x0000003D},
-       {0x03E, 0x00000014},
-       {0x03F, 0x0002AC58},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
        {0x033, 0x0000003E},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x033, 0x0000003F},
-       {0x03E, 0x00000014},
-       {0x03F, 0x00023A58},
-       {0x0EF, 0x00000000},
-       {0x0EE, 0x00000800},
-       {0x033, 0x00000000},
-       {0x03F, 0x00000031},
-       {0x033, 0x00000001},
-       {0x03F, 0x00000023},
-       {0x033, 0x00000002},
-       {0x03F, 0x00000015},
-       {0x033, 0x00000003},
-       {0x03F, 0x00000007},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000060},
+       {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},
+       {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, 0x00000064},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000068},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006C},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000070},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000074},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000078},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007C},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000061},
+       {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},
+       {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, 0x00000065},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000069},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000071},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000075},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000079},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007D},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000062},
+       {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},
+       {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, 0x00000066},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006A},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000072},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000076},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007A},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E7},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000003E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000063},
+       {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},
+       {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, 0x00000067},
+       {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},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000015A},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000005A},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006B},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000009C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x0000019C},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000073},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001A4},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000077},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000002E6},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x000001E6},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007B},
+       {0x03F, 0x000002E7},
+       {0x033, 0x0000007F},
+       {0x03F, 0x000003E7},
        {0x0EE, 0x00000000},
-       {0x0EC, 0x00000400},
-       {0x033, 0x00000003},
-       {0x03F, 0x00000030},
-       {0x033, 0x00000004},
-       {0x03F, 0x00000021},
-       {0x0EC, 0x00000000},
-       {0x0DE, 0x00000000},
-       {0x0EF, 0x00000000},
-       {0x033, 0x00000000},
-       {0x008, 0x00060280},
-       {0x009, 0x00030400},
-       {0x0EF, 0x00000000},
-       {0x0A7, 0x00080308},
-       {0x066, 0x00006000},
-       {0x0EF, 0x00000400},
-       {0x030, 0x000001FF},
-       {0x030, 0x000081FF},
-       {0x030, 0x000101FF},
-       {0x030, 0x000181FF},
-       {0x030, 0x000201FF},
-       {0x030, 0x000281FF},
-       {0x030, 0x0003017F},
-       {0x030, 0x000380FB},
-       {0x0EF, 0x00000000},
-       {0x06E, 0x00077A18},
-       {0x06D, 0x00000C31},
-       {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},
+       {0x100EE, 0x00004000},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000000},
+       {0x10030, 0x000201DF},
+       {0x10030, 0x000205D9},
+       {0x10030, 0x000209D3},
+       {0x10030, 0x00020D99},
+       {0x10030, 0x00021193},
+       {0x10030, 0x0002155F},
+       {0x10030, 0x00021959},
+       {0x10030, 0x00021D21},
+       {0x10030, 0x00022119},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228D9},
+       {0x10030, 0x00022C9F},
+       {0x10030, 0x00023099},
+       {0x10030, 0x0002345F},
+       {0x10030, 0x00023859},
+       {0x10030, 0x00023C1F},
+       {0x10030, 0x00024019},
+       {0x10030, 0x00024413},
+       {0x10030, 0x000281CD},
+       {0x10030, 0x000285DB},
+       {0x10030, 0x000289D5},
+       {0x10030, 0x00028D9B},
+       {0x10030, 0x0002918D},
+       {0x10030, 0x00029555},
+       {0x10030, 0x00029957},
+       {0x10030, 0x00029D1F},
+       {0x10030, 0x0002A119},
+       {0x10030, 0x0002A4DF},
+       {0x10030, 0x0002A8D9},
+       {0x10030, 0x0002AC9F},
+       {0x10030, 0x0002B099},
+       {0x10030, 0x0002B45F},
+       {0x10030, 0x0002B859},
+       {0x10030, 0x0002BC1F},
+       {0x10030, 0x0002C019},
+       {0x10030, 0x0002C413},
+       {0x10030, 0x000301D9},
+       {0x10030, 0x000305DB},
+       {0x10030, 0x000309D5},
+       {0x10030, 0x00030D9B},
+       {0x10030, 0x00031195},
+       {0x10030, 0x0003155D},
+       {0x10030, 0x00031955},
+       {0x10030, 0x00031D1D},
+       {0x10030, 0x00032119},
+       {0x10030, 0x000324DF},
+       {0x10030, 0x000328D9},
+       {0x10030, 0x00032C9F},
+       {0x10030, 0x00033099},
+       {0x10030, 0x0003345F},
+       {0x10030, 0x00033859},
+       {0x10030, 0x00033C1F},
+       {0x10030, 0x00034019},
+       {0x10030, 0x00034413},
+       {0x10030, 0x000601E1},
+       {0x10030, 0x000605DB},
+       {0x10030, 0x000609D5},
+       {0x10030, 0x00060D9B},
+       {0x10030, 0x00061195},
+       {0x10030, 0x0006155B},
+       {0x10030, 0x00061957},
+       {0x10030, 0x00061D1F},
+       {0x10030, 0x00062119},
+       {0x10030, 0x000624DF},
+       {0x10030, 0x000628D9},
+       {0x10030, 0x00062C9F},
+       {0x10030, 0x00063099},
+       {0x10030, 0x0006345F},
+       {0x10030, 0x00063859},
+       {0x10030, 0x00063C1F},
+       {0x10030, 0x00064019},
+       {0x10030, 0x00064413},
+       {0x10030, 0x000681E1},
+       {0x10030, 0x000685DB},
+       {0x10030, 0x000689D5},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955B},
+       {0x10030, 0x00069957},
+       {0x10030, 0x00069D1F},
+       {0x10030, 0x0006A119},
+       {0x10030, 0x0006A4DF},
+       {0x10030, 0x0006A8D9},
+       {0x10030, 0x0006AC9F},
+       {0x10030, 0x0006B099},
+       {0x10030, 0x0006B45F},
+       {0x10030, 0x0006B859},
+       {0x10030, 0x0006BC1F},
+       {0x10030, 0x0006C019},
+       {0x10030, 0x0006C413},
+       {0x10030, 0x000701E1},
+       {0x10030, 0x000705DB},
+       {0x10030, 0x000709D5},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071957},
+       {0x10030, 0x00071D1F},
+       {0x10030, 0x00072119},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072C9F},
+       {0x10030, 0x00073099},
+       {0x10030, 0x0007345F},
+       {0x10030, 0x00073859},
+       {0x10030, 0x00073C1F},
+       {0x10030, 0x00074019},
+       {0x10030, 0x00074413},
+       {0x10030, 0x000781DF},
+       {0x10030, 0x000785D9},
+       {0x10030, 0x000789D3},
+       {0x10030, 0x00078D99},
+       {0x10030, 0x00079193},
+       {0x10030, 0x0007955F},
+       {0x10030, 0x00079959},
+       {0x10030, 0x00079D21},
+       {0x10030, 0x0007A115},
+       {0x10030, 0x0007A4DF},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007AC9F},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B45F},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC1F},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0x10030, 0x00000000},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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},
+       {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},
+       {0x90050001, 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},
+       {0x90070001, 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},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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, 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},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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, 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},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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, 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},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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, 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},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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, 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},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x095, 0x00000008},
+       {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, 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},
        {0xA0000000, 0x00000000},
-       {0x095, 0x00000000},
-       {0xB0000000, 0x00000000},
-       {0x0EE, 0x00001000},
-       {0x033, 0x00000020},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000024},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000028},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000002C},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000030},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000034},
-       {0x03F, 0x000001E7},
-       {0x033, 0x00000038},
-       {0x03F, 0x000002E7},
-       {0x033, 0x0000003C},
-       {0x03F, 0x000003E7},
-       {0x033, 0x00000021},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000025},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000029},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000002D},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000031},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000035},
-       {0x03F, 0x000001E6},
-       {0x033, 0x00000039},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000003D},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000022},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000026},
-       {0x03F, 0x0000005A},
-       {0x033, 0x0000002A},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000002E},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000032},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000036},
-       {0x03F, 0x000001E6},
-       {0x033, 0x0000003A},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000003E},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000060},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000064},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000068},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000006C},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000070},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000074},
-       {0x03F, 0x000001E6},
-       {0x033, 0x00000078},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000007C},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000061},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000065},
-       {0x03F, 0x0000005A},
-       {0x033, 0x00000069},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000006D},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000071},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000075},
-       {0x03F, 0x000001E6},
-       {0x033, 0x00000079},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000007D},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000062},
-       {0x03F, 0x00000052},
-       {0x033, 0x00000066},
-       {0x03F, 0x0000005A},
-       {0x033, 0x0000006A},
-       {0x03F, 0x0000009C},
-       {0x033, 0x0000006E},
-       {0x03F, 0x0000019C},
-       {0x033, 0x00000072},
-       {0x03F, 0x000001A4},
-       {0x033, 0x00000076},
-       {0x03F, 0x000001E6},
-       {0x033, 0x0000007A},
-       {0x03F, 0x000002E6},
-       {0x033, 0x0000007E},
-       {0x03F, 0x000003E6},
-       {0x033, 0x00000063},
+       {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, 0x000201ED},
+       {0x10030, 0x000205AD},
+       {0x10030, 0x000209A7},
+       {0x10030, 0x00020DA1},
+       {0x10030, 0x0002119B},
+       {0x10030, 0x00021561},
+       {0x10030, 0x0002195B},
+       {0x10030, 0x00021D27},
+       {0x10030, 0x00022121},
+       {0x10030, 0x000224E9},
+       {0x10030, 0x000228E3},
+       {0x10030, 0x00022CA9},
+       {0x10030, 0x000230A3},
+       {0x10030, 0x00023469},
+       {0x10030, 0x00023863},
+       {0x10030, 0x00023C29},
+       {0x10030, 0x00024023},
+       {0x10030, 0x0002441D},
+       {0x10030, 0x000281EF},
+       {0x10030, 0x000285AF},
+       {0x10030, 0x000289A9},
+       {0x10030, 0x00028DA3},
+       {0x10030, 0x0002919D},
+       {0x10030, 0x00029563},
+       {0x10030, 0x0002995D},
+       {0x10030, 0x00029D25},
+       {0x10030, 0x0002A11F},
+       {0x10030, 0x0002A4E7},
+       {0x10030, 0x0002A8E1},
+       {0x10030, 0x0002ACA7},
+       {0x10030, 0x0002B0A1},
+       {0x10030, 0x0002B467},
+       {0x10030, 0x0002B861},
+       {0x10030, 0x0002BC27},
+       {0x10030, 0x0002C021},
+       {0x10030, 0x0002C41B},
+       {0x10030, 0x000301EF},
+       {0x10030, 0x000305AF},
+       {0x10030, 0x000309A9},
+       {0x10030, 0x00030DA3},
+       {0x10030, 0x0003119D},
+       {0x10030, 0x00031563},
+       {0x10030, 0x0003195D},
+       {0x10030, 0x00031D25},
+       {0x10030, 0x0003211F},
+       {0x10030, 0x000324E7},
+       {0x10030, 0x000328E1},
+       {0x10030, 0x00032CA7},
+       {0x10030, 0x000330A1},
+       {0x10030, 0x00033467},
+       {0x10030, 0x00033861},
+       {0x10030, 0x00033C27},
+       {0x10030, 0x00034021},
+       {0x10030, 0x0003441B},
+       {0x10030, 0x000601EB},
+       {0x10030, 0x000605AB},
+       {0x10030, 0x000609A5},
+       {0x10030, 0x00060D9F},
+       {0x10030, 0x00061199},
+       {0x10030, 0x00061593},
+       {0x10030, 0x00061959},
+       {0x10030, 0x00061D53},
+       {0x10030, 0x0006211B},
+       {0x10030, 0x00062515},
+       {0x10030, 0x000628DD},
+       {0x10030, 0x00062CD7},
+       {0x10030, 0x0006309D},
+       {0x10030, 0x00063497},
+       {0x10030, 0x0006385D},
+       {0x10030, 0x00063C57},
+       {0x10030, 0x0006401D},
+       {0x10030, 0x00064417},
+       {0x10030, 0x000681E7},
+       {0x10030, 0x000685A7},
+       {0x10030, 0x000689A1},
+       {0x10030, 0x00068D9B},
+       {0x10030, 0x00069195},
+       {0x10030, 0x0006955F},
+       {0x10030, 0x00069959},
+       {0x10030, 0x00069D21},
+       {0x10030, 0x0006A11B},
+       {0x10030, 0x0006A4E3},
+       {0x10030, 0x0006A8DD},
+       {0x10030, 0x0006ACA5},
+       {0x10030, 0x0006B09F},
+       {0x10030, 0x0006B465},
+       {0x10030, 0x0006B85F},
+       {0x10030, 0x0006BC25},
+       {0x10030, 0x0006C01F},
+       {0x10030, 0x0006C419},
+       {0x10030, 0x000701E7},
+       {0x10030, 0x000705A7},
+       {0x10030, 0x000709A1},
+       {0x10030, 0x00070D9B},
+       {0x10030, 0x00071195},
+       {0x10030, 0x0007155B},
+       {0x10030, 0x00071955},
+       {0x10030, 0x00071D1D},
+       {0x10030, 0x00072117},
+       {0x10030, 0x000724DF},
+       {0x10030, 0x000728D9},
+       {0x10030, 0x00072CA1},
+       {0x10030, 0x0007309B},
+       {0x10030, 0x00073461},
+       {0x10030, 0x0007385B},
+       {0x10030, 0x00073C21},
+       {0x10030, 0x0007401B},
+       {0x10030, 0x0007441B},
+       {0x10030, 0x000781E9},
+       {0x10030, 0x000785A9},
+       {0x10030, 0x000789A3},
+       {0x10030, 0x00078D9D},
+       {0x10030, 0x00079197},
+       {0x10030, 0x00079591},
+       {0x10030, 0x00079957},
+       {0x10030, 0x00079D51},
+       {0x10030, 0x0007A119},
+       {0x10030, 0x0007A513},
+       {0x10030, 0x0007A8D9},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B099},
+       {0x10030, 0x0007B493},
+       {0x10030, 0x0007B859},
+       {0x10030, 0x0007BC53},
+       {0x10030, 0x0007C019},
+       {0x10030, 0x0007C413},
+       {0xB0000000, 0x00000000},
+       {0x100EE, 0x00000000},
+       {0x100EE, 0x00002000},
+       {0x10030, 0x000000FC},
+       {0x10030, 0x000004F9},
+       {0x10030, 0x000008F6},
+       {0x10030, 0x00000CF3},
+       {0x10030, 0x000010F0},
+       {0x10030, 0x000014ED},
+       {0x10030, 0x000018AC},
+       {0x10030, 0x00001CA9},
+       {0x10030, 0x00002069},
+       {0x10030, 0x00002466},
+       {0x10030, 0x00002829},
+       {0x10030, 0x00002C26},
+       {0x10030, 0x00003023},
+       {0x10030, 0x00003420},
+       {0x10030, 0x0000381D},
+       {0x10030, 0x00003C1A},
+       {0x10030, 0x00004017},
+       {0x100EE, 0x00000000},
+       {0x100EE, 0x00002000},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x00000152},
+       {0x10030, 0x000200E8},
+       {0x10030, 0x000204E5},
+       {0x10030, 0x000208E2},
+       {0x10030, 0x00020CDF},
+       {0x10030, 0x000210DC},
+       {0x10030, 0x000214D9},
+       {0x10030, 0x000218D6},
+       {0x10030, 0x00021CD3},
+       {0x10030, 0x000220D0},
+       {0x10030, 0x000224CD},
+       {0x10030, 0x000228CD},
+       {0x10030, 0x00022CCD},
+       {0x10030, 0x000230CD},
+       {0x10030, 0x000234CD},
+       {0x10030, 0x000238CD},
+       {0x10030, 0x00023CCD},
+       {0x10030, 0x000240CD},
+       {0x10030, 0x000280E8},
+       {0x10030, 0x000284E5},
+       {0x10030, 0x000288E2},
+       {0x10030, 0x00028CDF},
+       {0x10030, 0x000290DC},
+       {0x10030, 0x000294D9},
+       {0x10030, 0x000298D6},
+       {0x10030, 0x00029CD3},
+       {0x10030, 0x0002A0D0},
+       {0x10030, 0x0002A4CD},
+       {0x10030, 0x0002A8CD},
+       {0x10030, 0x0002ACCD},
+       {0x10030, 0x0002B0CD},
+       {0x10030, 0x0002B4CD},
+       {0x10030, 0x0002B8CD},
+       {0x10030, 0x0002BCCD},
+       {0x10030, 0x0002C0CD},
+       {0x10030, 0x000300E8},
+       {0x10030, 0x000304E5},
+       {0x10030, 0x000308E2},
+       {0x10030, 0x00030CDF},
+       {0x10030, 0x000310DC},
+       {0x10030, 0x000314D9},
+       {0x10030, 0x000318D6},
+       {0x10030, 0x00031CD3},
+       {0x10030, 0x000320D0},
+       {0x10030, 0x000324CD},
+       {0x10030, 0x000328CD},
+       {0x10030, 0x00032CCD},
+       {0x10030, 0x000330CD},
+       {0x10030, 0x000334CD},
+       {0x10030, 0x000338CD},
+       {0x10030, 0x00033CCD},
+       {0x10030, 0x000340CD},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x00000052},
+       {0x10030, 0x000200FA},
+       {0x10030, 0x000204F7},
+       {0x10030, 0x000208F4},
+       {0x10030, 0x00020CF1},
+       {0x10030, 0x000210EE},
+       {0x10030, 0x000214EB},
+       {0x10030, 0x000218E8},
+       {0x10030, 0x00021CE5},
+       {0x10030, 0x000220E2},
+       {0x10030, 0x000224DF},
+       {0x10030, 0x000228DC},
+       {0x10030, 0x00022CD9},
+       {0x10030, 0x000230D6},
+       {0x10030, 0x000234D3},
+       {0x10030, 0x000238D0},
+       {0x10030, 0x00023C0D},
+       {0x10030, 0x0002400A},
+       {0x10030, 0x000280F9},
+       {0x10030, 0x000284F6},
+       {0x10030, 0x000288F3},
+       {0x10030, 0x00028CF0},
+       {0x10030, 0x000290ED},
+       {0x10030, 0x000294EA},
+       {0x10030, 0x000298E7},
+       {0x10030, 0x00029CE4},
+       {0x10030, 0x0002A0E1},
+       {0x10030, 0x0002A4DE},
+       {0x10030, 0x0002A8DB},
+       {0x10030, 0x0002ACD8},
+       {0x10030, 0x0002B0D5},
+       {0x10030, 0x0002B4D2},
+       {0x10030, 0x0002B8CF},
+       {0x10030, 0x0002BC0C},
+       {0x10030, 0x0002C009},
+       {0x10030, 0x000300F6},
+       {0x10030, 0x000304F3},
+       {0x10030, 0x000308F0},
+       {0x10030, 0x00030CED},
+       {0x10030, 0x000310EA},
+       {0x10030, 0x000314E7},
+       {0x10030, 0x000318E4},
+       {0x10030, 0x00031CE1},
+       {0x10030, 0x000320DE},
+       {0x10030, 0x000324DB},
+       {0x10030, 0x000328D8},
+       {0x10030, 0x00032CD5},
+       {0x10030, 0x000330D2},
+       {0x10030, 0x000334CF},
+       {0x10030, 0x000338CC},
+       {0x10030, 0x00033C09},
+       {0x10030, 0x00034006},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000067},
+       {0x10030, 0x000600F6},
+       {0x10030, 0x000604F3},
+       {0x10030, 0x000608F0},
+       {0x10030, 0x00060CED},
+       {0x10030, 0x000610EA},
+       {0x10030, 0x000614E7},
+       {0x10030, 0x000618E4},
+       {0x10030, 0x00061CE1},
+       {0x10030, 0x000620DE},
+       {0x10030, 0x000624DB},
+       {0x10030, 0x000628D8},
+       {0x10030, 0x00062CD5},
+       {0x10030, 0x000630D2},
+       {0x10030, 0x000634CF},
+       {0x10030, 0x000638CC},
+       {0x10030, 0x00063C09},
+       {0x10030, 0x00064006},
+       {0x10030, 0x000680F5},
+       {0x10030, 0x000684F2},
+       {0x10030, 0x000688EF},
+       {0x10030, 0x00068CEC},
+       {0x10030, 0x000690E9},
+       {0x10030, 0x000694E6},
+       {0x10030, 0x000698E3},
+       {0x10030, 0x00069CE0},
+       {0x10030, 0x0006A0DD},
+       {0x10030, 0x0006A4DA},
+       {0x10030, 0x0006A8D7},
+       {0x10030, 0x0006ACD4},
+       {0x10030, 0x0006B0D1},
+       {0x10030, 0x0006B4CE},
+       {0x10030, 0x0006B8CB},
+       {0x10030, 0x0006BC08},
+       {0x10030, 0x0006C005},
+       {0x10030, 0x000700F5},
+       {0x10030, 0x000704F2},
+       {0x10030, 0x000708EF},
+       {0x10030, 0x00070CEC},
+       {0x10030, 0x000710E9},
+       {0x10030, 0x000714E6},
+       {0x10030, 0x000718E3},
+       {0x10030, 0x00071CE0},
+       {0x10030, 0x000720DD},
+       {0x10030, 0x000724DA},
+       {0x10030, 0x000728D7},
+       {0x10030, 0x00072CD4},
+       {0x10030, 0x000730D1},
+       {0x10030, 0x000734CE},
+       {0x10030, 0x000738CB},
+       {0x10030, 0x00073C08},
+       {0x10030, 0x00074005},
+       {0x10030, 0x000780F4},
+       {0x10030, 0x000784F1},
+       {0x10030, 0x000788EE},
+       {0x10030, 0x00078CEB},
+       {0x10030, 0x000790E8},
+       {0x10030, 0x000794E5},
+       {0x10030, 0x000798E2},
+       {0x10030, 0x00079CDF},
+       {0x10030, 0x0007A0DC},
+       {0x10030, 0x0007A4D9},
+       {0x10030, 0x0007A8D6},
+       {0x10030, 0x0007ACD3},
+       {0x10030, 0x0007B0D0},
+       {0x10030, 0x0007B4CD},
+       {0x10030, 0x0007B8CA},
+       {0x10030, 0x0007BC07},
+       {0x10030, 0x0007C004},
+       {0x100EE, 0x00000000},
+       {0x0EF, 0x00002000},
+       {0x033, 0x00000008},
+       {0x03F, 0x00000004},
+       {0x033, 0x00000009},
+       {0x03F, 0x00000003},
+       {0x033, 0x0000000A},
+       {0x03F, 0x00000003},
+       {0x033, 0x0000000B},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000C},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000D},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000E},
+       {0x03F, 0x00000002},
+       {0x033, 0x0000000F},
+       {0x03F, 0x00000002},
+       {0x0EF, 0x00000000},
+       {0x0EB, 0x00040000},
+       {0x030, 0x000109B7},
+       {0x0EB, 0x00000000},
+       {0x0EF, 0x00008000},
+       {0x033, 0x00000020},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000021},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000022},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000023},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000024},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000025},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000026},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00000003},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00000003},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00000003},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00008002},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00008002},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00008002},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00008002},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00000003},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00000003},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00008002},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00008002},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00008002},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00008002},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00008002},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000015A},
+       {0x03F, 0x00008002},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x0000005A},
+       {0x03F, 0x00000003},
        {0xB0000000, 0x00000000},
-       {0x033, 0x0000006B},
+       {0x033, 0x00000027},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00000003},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00000003},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00000003},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00008002},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00008002},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00008002},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00008002},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x0000009C},
+       {0x03F, 0x00000003},
        {0xB0000000, 0x00000000},
-       {0x033, 0x0000006F},
+       {0x033, 0x00000028},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000029},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000002A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000002B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000002C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000002D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000002E},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00008002},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x0000019C},
+       {0x03F, 0x00000003},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000073},
+       {0x033, 0x0000002F},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00008002},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00000003},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00000003},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0xA0000000, 0x00000000},
-       {0x03F, 0x000001A4},
+       {0x03F, 0x00000003},
        {0xB0000000, 0x00000000},
-       {0x033, 0x00000077},
+       {0x033, 0x00000030},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000031},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000032},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000033},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000034},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000035},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000036},
        {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00000003},
        {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00000003},
        {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00000003},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000001E6},
+       {0x03F, 0x00008002},
        {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x00000003},
        {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x00000003},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x00008002},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
+       {0x03F, 0x00008002},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
-       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
-       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
-       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x03F, 0x000002E6},
-       {0xA0000000, 0x00000000},
-       {0x03F, 0x000001E6},
-       {0xB0000000, 0x00000000},
-       {0x033, 0x0000007B},
-       {0x03F, 0x000002E7},
-       {0x033, 0x0000007F},
-       {0x03F, 0x000003E7},
-       {0x0EE, 0x00000000},
-       {0x100EE, 0x00004000},
-       {0x80010000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000037},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90020000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000060},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000061},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000062},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000063},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000064},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000065},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000066},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000067},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000068},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000069},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000006A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000006B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000006C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000006D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000006E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000006F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000070},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000071},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000072},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000073},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000074},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000075},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000076},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000077},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000078},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000079},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000007A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000007B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000007C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000007D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000007E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000007F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000A0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000A1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000A2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000A3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000A4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000A5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000A6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000A7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000A8},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000A9},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000AA},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000AB},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000AC},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000AD},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000AE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000AF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000B0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000B1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000B2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000B3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000B4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000B5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000B6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000B7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000E0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000E1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000E2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000E3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000E4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000E5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000E6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90010001, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781EF},
-       {0x10030, 0x000785E9},
-       {0x10030, 0x000789E3},
-       {0x10030, 0x00078DA3},
-       {0x10030, 0x00079161},
-       {0x10030, 0x0007955B},
-       {0x10030, 0x00079921},
-       {0x10030, 0x00079D1B},
-       {0x10030, 0x0007A0E1},
-       {0x10030, 0x0007A4DB},
-       {0x10030, 0x0007A8A1},
-       {0x10030, 0x0007AC9B},
-       {0x10030, 0x0007B061},
-       {0x10030, 0x0007B45B},
-       {0x10030, 0x0007B821},
-       {0x10030, 0x0007BC1B},
-       {0x10030, 0x0007C015},
-       {0x10030, 0x0007C40F},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000E7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000E8},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000E9},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000EA},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000EB},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000EC},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000ED},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000EE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781EF},
-       {0x10030, 0x000785E9},
-       {0x10030, 0x000789E3},
-       {0x10030, 0x00078DA3},
-       {0x10030, 0x00079161},
-       {0x10030, 0x0007955B},
-       {0x10030, 0x00079921},
-       {0x10030, 0x00079D1B},
-       {0x10030, 0x0007A0E1},
-       {0x10030, 0x0007A4DB},
-       {0x10030, 0x0007A8A1},
-       {0x10030, 0x0007AC9B},
-       {0x10030, 0x0007B061},
-       {0x10030, 0x0007B45B},
-       {0x10030, 0x0007B821},
-       {0x10030, 0x0007BC1B},
-       {0x10030, 0x0007C015},
-       {0x10030, 0x0007C40F},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000EF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000F0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000F1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000F2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000F3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000F4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000F5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000F6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000F7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90320001, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781EF},
-       {0x10030, 0x000785E9},
-       {0x10030, 0x000789E3},
-       {0x10030, 0x00078DA3},
-       {0x10030, 0x00079161},
-       {0x10030, 0x0007955B},
-       {0x10030, 0x00079921},
-       {0x10030, 0x00079D1B},
-       {0x10030, 0x0007A0E1},
-       {0x10030, 0x0007A4DB},
-       {0x10030, 0x0007A8A1},
-       {0x10030, 0x0007AC9B},
-       {0x10030, 0x0007B061},
-       {0x10030, 0x0007B45B},
-       {0x10030, 0x0007B821},
-       {0x10030, 0x0007BC1B},
-       {0x10030, 0x0007C015},
-       {0x10030, 0x0007C40F},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000F8},
+       {0x03F, 0x00050002},
+       {0x033, 0x000000F9},
+       {0x03F, 0x00060032},
+       {0x033, 0x000000FA},
+       {0x03F, 0x00050042},
+       {0x033, 0x000000FB},
+       {0x03F, 0x00040042},
+       {0x033, 0x000000FC},
+       {0x03F, 0x00008001},
+       {0x033, 0x000000FD},
+       {0x03F, 0x00008002},
+       {0x033, 0x000000FE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000000FF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
        {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000120},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000121},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000122},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000123},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000124},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000125},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000126},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000127},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000128},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000129},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000012A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000012B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000012C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000012D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000012E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000012F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000130},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000131},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000132},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000133},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000134},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000135},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000136},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000137},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000160},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000161},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000162},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000163},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000164},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000165},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000166},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000167},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000168},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000169},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000016A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000016B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000016C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000016D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000016E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000016F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000170},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000171},
+       {0x03F, 0x00060032},
+       {0x033, 0x00000172},
+       {0x03F, 0x00050042},
+       {0x033, 0x00000173},
+       {0x03F, 0x00040042},
+       {0x033, 0x00000174},
+       {0x03F, 0x00008001},
+       {0x033, 0x00000175},
+       {0x03F, 0x00008002},
+       {0x033, 0x00000176},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000177},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
-       {0x10030, 0x000201DF},
-       {0x10030, 0x000205D9},
-       {0x10030, 0x000209D3},
-       {0x10030, 0x00020D99},
-       {0x10030, 0x00021193},
-       {0x10030, 0x0002155F},
-       {0x10030, 0x00021959},
-       {0x10030, 0x00021D21},
-       {0x10030, 0x00022119},
-       {0x10030, 0x000224DF},
-       {0x10030, 0x000228D9},
-       {0x10030, 0x00022C9F},
-       {0x10030, 0x00023099},
-       {0x10030, 0x0002345F},
-       {0x10030, 0x00023859},
-       {0x10030, 0x00023C1F},
-       {0x10030, 0x00024019},
-       {0x10030, 0x00024413},
-       {0x10030, 0x000281CD},
-       {0x10030, 0x000285DB},
-       {0x10030, 0x000289D5},
-       {0x10030, 0x00028D9B},
-       {0x10030, 0x0002918D},
-       {0x10030, 0x00029555},
-       {0x10030, 0x00029957},
-       {0x10030, 0x00029D1F},
-       {0x10030, 0x0002A119},
-       {0x10030, 0x0002A4DF},
-       {0x10030, 0x0002A8D9},
-       {0x10030, 0x0002AC9F},
-       {0x10030, 0x0002B099},
-       {0x10030, 0x0002B45F},
-       {0x10030, 0x0002B859},
-       {0x10030, 0x0002BC1F},
-       {0x10030, 0x0002C019},
-       {0x10030, 0x0002C413},
-       {0x10030, 0x000301D9},
-       {0x10030, 0x000305DB},
-       {0x10030, 0x000309D5},
-       {0x10030, 0x00030D9B},
-       {0x10030, 0x00031195},
-       {0x10030, 0x0003155D},
-       {0x10030, 0x00031955},
-       {0x10030, 0x00031D1D},
-       {0x10030, 0x00032119},
-       {0x10030, 0x000324DF},
-       {0x10030, 0x000328D9},
-       {0x10030, 0x00032C9F},
-       {0x10030, 0x00033099},
-       {0x10030, 0x0003345F},
-       {0x10030, 0x00033859},
-       {0x10030, 0x00033C1F},
-       {0x10030, 0x00034019},
-       {0x10030, 0x00034413},
-       {0x10030, 0x000601E1},
-       {0x10030, 0x000605DB},
-       {0x10030, 0x000609D5},
-       {0x10030, 0x00060D9B},
-       {0x10030, 0x00061195},
-       {0x10030, 0x0006155B},
-       {0x10030, 0x00061957},
-       {0x10030, 0x00061D1F},
-       {0x10030, 0x00062119},
-       {0x10030, 0x000624DF},
-       {0x10030, 0x000628D9},
-       {0x10030, 0x00062C9F},
-       {0x10030, 0x00063099},
-       {0x10030, 0x0006345F},
-       {0x10030, 0x00063859},
-       {0x10030, 0x00063C1F},
-       {0x10030, 0x00064019},
-       {0x10030, 0x00064413},
-       {0x10030, 0x000681E1},
-       {0x10030, 0x000685DB},
-       {0x10030, 0x000689D5},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955B},
-       {0x10030, 0x00069957},
-       {0x10030, 0x00069D1F},
-       {0x10030, 0x0006A119},
-       {0x10030, 0x0006A4DF},
-       {0x10030, 0x0006A8D9},
-       {0x10030, 0x0006AC9F},
-       {0x10030, 0x0006B099},
-       {0x10030, 0x0006B45F},
-       {0x10030, 0x0006B859},
-       {0x10030, 0x0006BC1F},
-       {0x10030, 0x0006C019},
-       {0x10030, 0x0006C413},
-       {0x10030, 0x000701E1},
-       {0x10030, 0x000705DB},
-       {0x10030, 0x000709D5},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071957},
-       {0x10030, 0x00071D1F},
-       {0x10030, 0x00072119},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072C9F},
-       {0x10030, 0x00073099},
-       {0x10030, 0x0007345F},
-       {0x10030, 0x00073859},
-       {0x10030, 0x00073C1F},
-       {0x10030, 0x00074019},
-       {0x10030, 0x00074413},
-       {0x10030, 0x000781DF},
-       {0x10030, 0x000785D9},
-       {0x10030, 0x000789D3},
-       {0x10030, 0x00078D99},
-       {0x10030, 0x00079193},
-       {0x10030, 0x0007955F},
-       {0x10030, 0x00079959},
-       {0x10030, 0x00079D21},
-       {0x10030, 0x0007A115},
-       {0x10030, 0x0007A4DF},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007AC9F},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B45F},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC1F},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
-       {0x10030, 0x00000000},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x00000178},
+       {0x03F, 0x00050002},
+       {0x033, 0x00000179},
+       {0x03F, 0x00060032},
+       {0x033, 0x0000017A},
+       {0x03F, 0x00050042},
+       {0x033, 0x0000017B},
+       {0x03F, 0x00040042},
+       {0x033, 0x0000017C},
+       {0x03F, 0x00008001},
+       {0x033, 0x0000017D},
+       {0x03F, 0x00008002},
+       {0x033, 0x0000017E},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x0000017F},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001A0},
+       {0x03F, 0x00050002},
+       {0x033, 0x000001A1},
+       {0x03F, 0x00060032},
+       {0x033, 0x000001A2},
+       {0x03F, 0x00050042},
+       {0x033, 0x000001A3},
+       {0x03F, 0x00040042},
+       {0x033, 0x000001A4},
+       {0x03F, 0x00008001},
+       {0x033, 0x000001A5},
+       {0x03F, 0x00008002},
+       {0x033, 0x000001A6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
        {0xA0000000, 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, 0x000201ED},
-       {0x10030, 0x000205AD},
-       {0x10030, 0x000209A7},
-       {0x10030, 0x00020DA1},
-       {0x10030, 0x0002119B},
-       {0x10030, 0x00021561},
-       {0x10030, 0x0002195B},
-       {0x10030, 0x00021D27},
-       {0x10030, 0x00022121},
-       {0x10030, 0x000224E9},
-       {0x10030, 0x000228E3},
-       {0x10030, 0x00022CA9},
-       {0x10030, 0x000230A3},
-       {0x10030, 0x00023469},
-       {0x10030, 0x00023863},
-       {0x10030, 0x00023C29},
-       {0x10030, 0x00024023},
-       {0x10030, 0x0002441D},
-       {0x10030, 0x000281EF},
-       {0x10030, 0x000285AF},
-       {0x10030, 0x000289A9},
-       {0x10030, 0x00028DA3},
-       {0x10030, 0x0002919D},
-       {0x10030, 0x00029563},
-       {0x10030, 0x0002995D},
-       {0x10030, 0x00029D25},
-       {0x10030, 0x0002A11F},
-       {0x10030, 0x0002A4E7},
-       {0x10030, 0x0002A8E1},
-       {0x10030, 0x0002ACA7},
-       {0x10030, 0x0002B0A1},
-       {0x10030, 0x0002B467},
-       {0x10030, 0x0002B861},
-       {0x10030, 0x0002BC27},
-       {0x10030, 0x0002C021},
-       {0x10030, 0x0002C41B},
-       {0x10030, 0x000301EF},
-       {0x10030, 0x000305AF},
-       {0x10030, 0x000309A9},
-       {0x10030, 0x00030DA3},
-       {0x10030, 0x0003119D},
-       {0x10030, 0x00031563},
-       {0x10030, 0x0003195D},
-       {0x10030, 0x00031D25},
-       {0x10030, 0x0003211F},
-       {0x10030, 0x000324E7},
-       {0x10030, 0x000328E1},
-       {0x10030, 0x00032CA7},
-       {0x10030, 0x000330A1},
-       {0x10030, 0x00033467},
-       {0x10030, 0x00033861},
-       {0x10030, 0x00033C27},
-       {0x10030, 0x00034021},
-       {0x10030, 0x0003441B},
-       {0x10030, 0x000601EB},
-       {0x10030, 0x000605AB},
-       {0x10030, 0x000609A5},
-       {0x10030, 0x00060D9F},
-       {0x10030, 0x00061199},
-       {0x10030, 0x00061593},
-       {0x10030, 0x00061959},
-       {0x10030, 0x00061D53},
-       {0x10030, 0x0006211B},
-       {0x10030, 0x00062515},
-       {0x10030, 0x000628DD},
-       {0x10030, 0x00062CD7},
-       {0x10030, 0x0006309D},
-       {0x10030, 0x00063497},
-       {0x10030, 0x0006385D},
-       {0x10030, 0x00063C57},
-       {0x10030, 0x0006401D},
-       {0x10030, 0x00064417},
-       {0x10030, 0x000681E7},
-       {0x10030, 0x000685A7},
-       {0x10030, 0x000689A1},
-       {0x10030, 0x00068D9B},
-       {0x10030, 0x00069195},
-       {0x10030, 0x0006955F},
-       {0x10030, 0x00069959},
-       {0x10030, 0x00069D21},
-       {0x10030, 0x0006A11B},
-       {0x10030, 0x0006A4E3},
-       {0x10030, 0x0006A8DD},
-       {0x10030, 0x0006ACA5},
-       {0x10030, 0x0006B09F},
-       {0x10030, 0x0006B465},
-       {0x10030, 0x0006B85F},
-       {0x10030, 0x0006BC25},
-       {0x10030, 0x0006C01F},
-       {0x10030, 0x0006C419},
-       {0x10030, 0x000701E7},
-       {0x10030, 0x000705A7},
-       {0x10030, 0x000709A1},
-       {0x10030, 0x00070D9B},
-       {0x10030, 0x00071195},
-       {0x10030, 0x0007155B},
-       {0x10030, 0x00071955},
-       {0x10030, 0x00071D1D},
-       {0x10030, 0x00072117},
-       {0x10030, 0x000724DF},
-       {0x10030, 0x000728D9},
-       {0x10030, 0x00072CA1},
-       {0x10030, 0x0007309B},
-       {0x10030, 0x00073461},
-       {0x10030, 0x0007385B},
-       {0x10030, 0x00073C21},
-       {0x10030, 0x0007401B},
-       {0x10030, 0x0007441B},
-       {0x10030, 0x000781E9},
-       {0x10030, 0x000785A9},
-       {0x10030, 0x000789A3},
-       {0x10030, 0x00078D9D},
-       {0x10030, 0x00079197},
-       {0x10030, 0x00079591},
-       {0x10030, 0x00079957},
-       {0x10030, 0x00079D51},
-       {0x10030, 0x0007A119},
-       {0x10030, 0x0007A513},
-       {0x10030, 0x0007A8D9},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B099},
-       {0x10030, 0x0007B493},
-       {0x10030, 0x0007B859},
-       {0x10030, 0x0007BC53},
-       {0x10030, 0x0007C019},
-       {0x10030, 0x0007C413},
+       {0x03F, 0x00000003},
        {0xB0000000, 0x00000000},
-       {0x100EE, 0x00000000},
-       {0x100EE, 0x00002000},
-       {0x10030, 0x000000FC},
-       {0x10030, 0x000004F9},
-       {0x10030, 0x000008F6},
-       {0x10030, 0x00000CF3},
-       {0x10030, 0x000010F0},
-       {0x10030, 0x000014ED},
-       {0x10030, 0x000018AC},
-       {0x10030, 0x00001CA9},
-       {0x10030, 0x00002069},
-       {0x10030, 0x00002466},
-       {0x10030, 0x00002829},
-       {0x10030, 0x00002C26},
-       {0x10030, 0x00003023},
-       {0x10030, 0x00003420},
-       {0x10030, 0x0000381D},
-       {0x10030, 0x00003C1A},
-       {0x10030, 0x00004017},
-       {0x100EE, 0x00000000},
-       {0x100EE, 0x00002000},
-       {0x10030, 0x000780F4},
-       {0x10030, 0x000784F1},
-       {0x10030, 0x000788EE},
-       {0x10030, 0x00078CEB},
-       {0x10030, 0x000790E8},
-       {0x10030, 0x000794E5},
-       {0x10030, 0x000798E2},
-       {0x10030, 0x00079CDF},
-       {0x10030, 0x0007A0DC},
-       {0x10030, 0x0007A4D9},
-       {0x10030, 0x0007A8D6},
-       {0x10030, 0x0007ACD3},
-       {0x10030, 0x0007B0D0},
-       {0x10030, 0x0007B4CD},
-       {0x10030, 0x0007B8CA},
-       {0x10030, 0x0007BC07},
-       {0x10030, 0x0007C004},
-       {0x100EE, 0x00000000},
-       {0x0EF, 0x00002000},
-       {0x033, 0x00000008},
-       {0x03F, 0x00000004},
-       {0x033, 0x00000009},
+       {0x033, 0x000001A7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000000A},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000000B},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000C},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000D},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000E},
-       {0x03F, 0x00000002},
-       {0x033, 0x0000000F},
-       {0x03F, 0x00000002},
-       {0x0EF, 0x00000000},
-       {0x0EB, 0x00040000},
-       {0x030, 0x000109B7},
-       {0x0EB, 0x00000000},
-       {0x0EF, 0x00008000},
-       {0x033, 0x00000020},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001A8},
        {0x03F, 0x00050002},
-       {0x033, 0x00000021},
+       {0x033, 0x000001A9},
        {0x03F, 0x00060032},
-       {0x033, 0x00000022},
+       {0x033, 0x000001AA},
        {0x03F, 0x00050042},
-       {0x033, 0x00000023},
+       {0x033, 0x000001AB},
        {0x03F, 0x00040042},
-       {0x033, 0x00000024},
+       {0x033, 0x000001AC},
        {0x03F, 0x00008001},
-       {0x033, 0x00000025},
+       {0x033, 0x000001AD},
        {0x03F, 0x00008002},
-       {0x033, 0x00000026},
+       {0x033, 0x000001AE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000027},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000028},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000029},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000002A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000002B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000002C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000002D},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x0000002E},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000002F},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000030},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000031},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000032},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000033},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000034},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000035},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000036},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000037},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001AF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000060},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000061},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000062},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000063},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000064},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000065},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000066},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000067},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000068},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001B0},
        {0x03F, 0x00050002},
-       {0x033, 0x00000069},
+       {0x033, 0x000001B1},
        {0x03F, 0x00060032},
-       {0x033, 0x0000006A},
+       {0x033, 0x000001B2},
        {0x03F, 0x00050042},
-       {0x033, 0x0000006B},
+       {0x033, 0x000001B3},
        {0x03F, 0x00040042},
-       {0x033, 0x0000006C},
+       {0x033, 0x000001B4},
        {0x03F, 0x00008001},
-       {0x033, 0x0000006D},
+       {0x033, 0x000001B5},
        {0x03F, 0x00008002},
-       {0x033, 0x0000006E},
+       {0x033, 0x000001B6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000006F},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000070},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000071},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000072},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000073},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000074},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000075},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000076},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000077},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000078},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000079},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000007A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000007B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000007C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000007D},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x0000007E},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000007F},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001B7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000A0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000A1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000A2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000A3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000A4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000A5},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000A6},
-       {0x03F, 0x00000003},
-       {0x033, 0x000000A7},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000A8},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001E0},
        {0x03F, 0x00050002},
-       {0x033, 0x000000A9},
+       {0x033, 0x000001E1},
        {0x03F, 0x00060032},
-       {0x033, 0x000000AA},
+       {0x033, 0x000001E2},
        {0x03F, 0x00050042},
-       {0x033, 0x000000AB},
+       {0x033, 0x000001E3},
        {0x03F, 0x00040042},
-       {0x033, 0x000000AC},
+       {0x033, 0x000001E4},
        {0x03F, 0x00008001},
-       {0x033, 0x000000AD},
+       {0x033, 0x000001E5},
        {0x03F, 0x00008002},
-       {0x033, 0x000000AE},
+       {0x033, 0x000001E6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000AF},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000B0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000B1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000B2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000B3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000B4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000B5},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000B6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000B7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000E0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000E1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000E2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000E3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000E4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000E5},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000E6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000E7},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001E7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000E8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000E9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000EA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000EB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000EC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000ED},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000EE},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000EF},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000F0},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001E8},
        {0x03F, 0x00050002},
-       {0x033, 0x000000F1},
+       {0x033, 0x000001E9},
        {0x03F, 0x00060032},
-       {0x033, 0x000000F2},
+       {0x033, 0x000001EA},
        {0x03F, 0x00050042},
-       {0x033, 0x000000F3},
+       {0x033, 0x000001EB},
        {0x03F, 0x00040042},
-       {0x033, 0x000000F4},
+       {0x033, 0x000001EC},
        {0x03F, 0x00008001},
-       {0x033, 0x000000F5},
+       {0x033, 0x000001ED},
        {0x03F, 0x00008002},
-       {0x033, 0x000000F6},
+       {0x033, 0x000001EE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000F7},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000F8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000000F9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000000FA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000000FB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000000FC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000000FD},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000000FE},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000000FF},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000120},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000121},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000122},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000123},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000124},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000125},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000126},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000127},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001EF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000128},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000129},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000012A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000012B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000012C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000012D},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x0000012E},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000012F},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000130},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000131},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000132},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000133},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000134},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000135},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x00000136},
-       {0x03F, 0x00000003},
-       {0x033, 0x00000137},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000160},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001F0},
        {0x03F, 0x00050002},
-       {0x033, 0x00000161},
+       {0x033, 0x000001F1},
        {0x03F, 0x00060032},
-       {0x033, 0x00000162},
+       {0x033, 0x000001F2},
        {0x03F, 0x00050042},
-       {0x033, 0x00000163},
+       {0x033, 0x000001F3},
        {0x03F, 0x00040042},
-       {0x033, 0x00000164},
+       {0x033, 0x000001F4},
        {0x03F, 0x00008001},
-       {0x033, 0x00000165},
+       {0x033, 0x000001F5},
        {0x03F, 0x00008002},
-       {0x033, 0x00000166},
+       {0x033, 0x000001F6},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000167},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000168},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000169},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000016A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000016B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000016C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000016D},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x0000016E},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000016F},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000170},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000171},
-       {0x03F, 0x00060032},
-       {0x033, 0x00000172},
-       {0x03F, 0x00050042},
-       {0x033, 0x00000173},
-       {0x03F, 0x00040042},
-       {0x033, 0x00000174},
-       {0x03F, 0x00008001},
-       {0x033, 0x00000175},
-       {0x03F, 0x00008002},
-       {0x033, 0x00000176},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000177},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x00000178},
-       {0x03F, 0x00050002},
-       {0x033, 0x00000179},
-       {0x03F, 0x00060032},
-       {0x033, 0x0000017A},
-       {0x03F, 0x00050042},
-       {0x033, 0x0000017B},
-       {0x03F, 0x00040042},
-       {0x033, 0x0000017C},
-       {0x03F, 0x00008001},
-       {0x033, 0x0000017D},
-       {0x03F, 0x00008002},
-       {0x033, 0x0000017E},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x0000017F},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001A0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001A1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001A2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001A3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001A4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001A5},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000001A6},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001A7},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001F7},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001A8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001A9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001AA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001AB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001AC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001AD},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000001AE},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001AF},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001B0},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001F8},
        {0x03F, 0x00050002},
-       {0x033, 0x000001B1},
+       {0x033, 0x000001F9},
        {0x03F, 0x00060032},
-       {0x033, 0x000001B2},
+       {0x033, 0x000001FA},
        {0x03F, 0x00050042},
-       {0x033, 0x000001B3},
+       {0x033, 0x000001FB},
        {0x03F, 0x00040042},
-       {0x033, 0x000001B4},
+       {0x033, 0x000001FC},
        {0x03F, 0x00008001},
-       {0x033, 0x000001B5},
+       {0x033, 0x000001FD},
        {0x03F, 0x00008002},
-       {0x033, 0x000001B6},
+       {0x033, 0x000001FE},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001B7},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001E0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001E1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001E2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001E3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001E4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001E5},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000001E6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001E7},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001E8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001E9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001EA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001EB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001EC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001ED},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000001EE},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001EF},
+       {0xB0000000, 0x00000000},
+       {0x033, 0x000001FF},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001F0},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001F1},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001F2},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001F3},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001F4},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001F5},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00008002},
-       {0x033, 0x000001F6},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001F7},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001F8},
-       {0x03F, 0x00050002},
-       {0x033, 0x000001F9},
-       {0x03F, 0x00060032},
-       {0x033, 0x000001FA},
-       {0x03F, 0x00050042},
-       {0x033, 0x000001FB},
-       {0x03F, 0x00040042},
-       {0x033, 0x000001FC},
-       {0x03F, 0x00008001},
-       {0x033, 0x000001FD},
-       {0x03F, 0x00008002},
-       {0x033, 0x000001FE},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
        {0x03F, 0x00000003},
-       {0x033, 0x000001FF},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00000003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x03F, 0x00008002},
+       {0xA0000000, 0x00000000},
        {0x03F, 0x00000003},
+       {0xB0000000, 0x00000000},
        {0x0EF, 0x00000000},
        {0x005, 0x00000001},
        {0x10005, 0x00000001},
@@ -11810,7 +25361,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x10030, 0x00022000},
        {0x10030, 0x00023000},
        {0x10030, 0x00024000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00025003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x00025000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00026003},
        {0x10030, 0x00027003},
        {0x10030, 0x00028000},
@@ -11818,7 +25411,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x10030, 0x0002A000},
        {0x10030, 0x0002B000},
        {0x10030, 0x0002C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0002D003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0002D000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0002E003},
        {0x10030, 0x0002F003},
        {0x10030, 0x00030000},
@@ -11826,7 +25461,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x10030, 0x00032000},
        {0x10030, 0x00033000},
        {0x10030, 0x00034000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
        {0x10030, 0x00035000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00035003},
+       {0xA0000000, 0x00000000},
+       {0x10030, 0x00035000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00036003},
        {0x10030, 0x00037003},
        {0x10030, 0x00038000},
@@ -11834,7 +25511,49 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x10030, 0x0003A000},
        {0x10030, 0x0003B000},
        {0x10030, 0x0003C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0003D003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0003D000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0003E003},
        {0x10030, 0x0003F003},
        {0x10030, 0x00060000},
@@ -11842,32 +25561,280 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x10030, 0x00062000},
        {0x10030, 0x00063000},
        {0x10030, 0x00064000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065000},
+       {0x10030, 0x00066000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00065003},
+       {0x10030, 0x00066003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x00065000},
        {0x10030, 0x00066000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00067003},
        {0x10030, 0x00068000},
        {0x10030, 0x00069000},
        {0x10030, 0x0006A000},
        {0x10030, 0x0006B000},
        {0x10030, 0x0006C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D000},
+       {0x10030, 0x0006E000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0006D003},
+       {0x10030, 0x0006E003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0006D000},
        {0x10030, 0x0006E000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0006F003},
        {0x10030, 0x00070000},
        {0x10030, 0x00071000},
        {0x10030, 0x00072000},
        {0x10030, 0x00073000},
        {0x10030, 0x00074000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075000},
+       {0x10030, 0x00076000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x00075003},
+       {0x10030, 0x00076003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x00075000},
        {0x10030, 0x00076000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x00077003},
        {0x10030, 0x00078000},
        {0x10030, 0x00079000},
        {0x10030, 0x0007A000},
        {0x10030, 0x0007B000},
        {0x10030, 0x0007C000},
+       {0x80010000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90020000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90320000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90330000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90340000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90350000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90360000, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D000},
+       {0x10030, 0x0007E000},
+       {0x90010001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90020001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90030001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90040001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90050001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90070001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90320001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90330001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90340001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90350001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90360001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x903f0001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0x90400001, 0x00000000}, {0x40000000, 0x00000000},
+       {0x10030, 0x0007D003},
+       {0x10030, 0x0007E003},
+       {0xA0000000, 0x00000000},
        {0x10030, 0x0007D000},
        {0x10030, 0x0007E000},
+       {0xB0000000, 0x00000000},
        {0x10030, 0x0007F003},
        {0x0ED, 0x00000010},
        {0x033, 0x00000001},
@@ -11884,7 +25851,7 @@ static const struct rtw89_reg2_def rtw89_8852c_phy_radiob_regs[] = {
        {0x03F, 0x0000000A},
        {0x0ED, 0x00000000},
        {0x100EE, 0x00000000},
-       {0x0FE, 0x00000031},
+       {0x0FE, 0x00000048},
 };
 
 static const struct rtw89_reg2_def rtw89_8852c_phy_nctl_regs[] = {
@@ -13825,1207 +27792,1722 @@ 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_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_MKK] = 0,
+       [0][0][RTW89_UK] = 0,
        [0][1][RTW89_ACMA] = 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_MKK] = 0,
+       [0][1][RTW89_UK] = 0,
        [1][1][RTW89_ACMA] = 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_MKK] = 0,
-       [2][1][RTW89_FCC] = 1,
+       [1][1][RTW89_UK] = 0,
+       [2][1][RTW89_ETSI] = 0,
+       [2][1][RTW89_FCC] = 0,
+       [2][1][RTW89_KCC] = 0,
 };
 
 const s8 rtw89_8852c_txpwr_lmt_2g[RTW89_2G_BW_NUM][RTW89_NTX_NUM]
                                 [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
                                 [RTW89_REGD_NUM][RTW89_2G_CH_NUM] = {
-       [0][0][0][0][RTW89_WW][0] = 60,
-       [0][0][0][0][RTW89_WW][1] = 60,
-       [0][0][0][0][RTW89_WW][2] = 60,
-       [0][0][0][0][RTW89_WW][3] = 60,
-       [0][0][0][0][RTW89_WW][4] = 60,
-       [0][0][0][0][RTW89_WW][5] = 60,
-       [0][0][0][0][RTW89_WW][6] = 60,
-       [0][0][0][0][RTW89_WW][7] = 60,
-       [0][0][0][0][RTW89_WW][8] = 60,
-       [0][0][0][0][RTW89_WW][9] = 60,
-       [0][0][0][0][RTW89_WW][10] = 60,
-       [0][0][0][0][RTW89_WW][11] = 60,
-       [0][0][0][0][RTW89_WW][12] = 48,
+       [0][0][0][0][RTW89_WW][0] = 58,
+       [0][0][0][0][RTW89_WW][1] = 58,
+       [0][0][0][0][RTW89_WW][2] = 58,
+       [0][0][0][0][RTW89_WW][3] = 58,
+       [0][0][0][0][RTW89_WW][4] = 58,
+       [0][0][0][0][RTW89_WW][5] = 58,
+       [0][0][0][0][RTW89_WW][6] = 58,
+       [0][0][0][0][RTW89_WW][7] = 58,
+       [0][0][0][0][RTW89_WW][8] = 58,
+       [0][0][0][0][RTW89_WW][9] = 58,
+       [0][0][0][0][RTW89_WW][10] = 58,
+       [0][0][0][0][RTW89_WW][11] = 58,
+       [0][0][0][0][RTW89_WW][12] = 46,
        [0][0][0][0][RTW89_WW][13] = 72,
-       [0][1][0][0][RTW89_WW][0] = 48,
-       [0][1][0][0][RTW89_WW][1] = 48,
-       [0][1][0][0][RTW89_WW][2] = 48,
-       [0][1][0][0][RTW89_WW][3] = 48,
-       [0][1][0][0][RTW89_WW][4] = 48,
-       [0][1][0][0][RTW89_WW][5] = 48,
-       [0][1][0][0][RTW89_WW][6] = 48,
-       [0][1][0][0][RTW89_WW][7] = 48,
-       [0][1][0][0][RTW89_WW][8] = 48,
-       [0][1][0][0][RTW89_WW][9] = 48,
-       [0][1][0][0][RTW89_WW][10] = 48,
-       [0][1][0][0][RTW89_WW][11] = 46,
-       [0][1][0][0][RTW89_WW][12] = 34,
+       [0][1][0][0][RTW89_WW][0] = 42,
+       [0][1][0][0][RTW89_WW][1] = 42,
+       [0][1][0][0][RTW89_WW][2] = 42,
+       [0][1][0][0][RTW89_WW][3] = 42,
+       [0][1][0][0][RTW89_WW][4] = 42,
+       [0][1][0][0][RTW89_WW][5] = 42,
+       [0][1][0][0][RTW89_WW][6] = 42,
+       [0][1][0][0][RTW89_WW][7] = 42,
+       [0][1][0][0][RTW89_WW][8] = 42,
+       [0][1][0][0][RTW89_WW][9] = 42,
+       [0][1][0][0][RTW89_WW][10] = 42,
+       [0][1][0][0][RTW89_WW][11] = 42,
+       [0][1][0][0][RTW89_WW][12] = 18,
        [0][1][0][0][RTW89_WW][13] = 60,
        [1][0][0][0][RTW89_WW][0] = 0,
        [1][0][0][0][RTW89_WW][1] = 0,
-       [1][0][0][0][RTW89_WW][2] = 42,
-       [1][0][0][0][RTW89_WW][3] = 42,
-       [1][0][0][0][RTW89_WW][4] = 42,
+       [1][0][0][0][RTW89_WW][2] = 44,
+       [1][0][0][0][RTW89_WW][3] = 58,
+       [1][0][0][0][RTW89_WW][4] = 58,
        [1][0][0][0][RTW89_WW][5] = 58,
-       [1][0][0][0][RTW89_WW][6] = 42,
-       [1][0][0][0][RTW89_WW][7] = 42,
-       [1][0][0][0][RTW89_WW][8] = 42,
-       [1][0][0][0][RTW89_WW][9] = 34,
-       [1][0][0][0][RTW89_WW][10] = 22,
+       [1][0][0][0][RTW89_WW][6] = 46,
+       [1][0][0][0][RTW89_WW][7] = 46,
+       [1][0][0][0][RTW89_WW][8] = 28,
+       [1][0][0][0][RTW89_WW][9] = 26,
+       [1][0][0][0][RTW89_WW][10] = 26,
        [1][0][0][0][RTW89_WW][11] = 0,
        [1][0][0][0][RTW89_WW][12] = 0,
        [1][0][0][0][RTW89_WW][13] = 0,
        [1][1][0][0][RTW89_WW][0] = 0,
        [1][1][0][0][RTW89_WW][1] = 0,
-       [1][1][0][0][RTW89_WW][2] = 38,
-       [1][1][0][0][RTW89_WW][3] = 38,
-       [1][1][0][0][RTW89_WW][4] = 38,
-       [1][1][0][0][RTW89_WW][5] = 48,
-       [1][1][0][0][RTW89_WW][6] = 26,
-       [1][1][0][0][RTW89_WW][7] = 26,
-       [1][1][0][0][RTW89_WW][8] = 26,
-       [1][1][0][0][RTW89_WW][9] = 22,
-       [1][1][0][0][RTW89_WW][10] = 22,
+       [1][1][0][0][RTW89_WW][2] = 46,
+       [1][1][0][0][RTW89_WW][3] = 46,
+       [1][1][0][0][RTW89_WW][4] = 46,
+       [1][1][0][0][RTW89_WW][5] = 46,
+       [1][1][0][0][RTW89_WW][6] = 40,
+       [1][1][0][0][RTW89_WW][7] = 40,
+       [1][1][0][0][RTW89_WW][8] = 14,
+       [1][1][0][0][RTW89_WW][9] = 14,
+       [1][1][0][0][RTW89_WW][10] = 12,
        [1][1][0][0][RTW89_WW][11] = 0,
        [1][1][0][0][RTW89_WW][12] = 0,
        [1][1][0][0][RTW89_WW][13] = 0,
-       [0][0][1][0][RTW89_WW][0] = 60,
-       [0][0][1][0][RTW89_WW][1] = 60,
-       [0][0][1][0][RTW89_WW][2] = 60,
-       [0][0][1][0][RTW89_WW][3] = 60,
-       [0][0][1][0][RTW89_WW][4] = 60,
-       [0][0][1][0][RTW89_WW][5] = 60,
-       [0][0][1][0][RTW89_WW][6] = 60,
-       [0][0][1][0][RTW89_WW][7] = 60,
-       [0][0][1][0][RTW89_WW][8] = 60,
-       [0][0][1][0][RTW89_WW][9] = 60,
-       [0][0][1][0][RTW89_WW][10] = 60,
-       [0][0][1][0][RTW89_WW][11] = 46,
-       [0][0][1][0][RTW89_WW][12] = 42,
+       [0][0][1][0][RTW89_WW][0] = 58,
+       [0][0][1][0][RTW89_WW][1] = 58,
+       [0][0][1][0][RTW89_WW][2] = 58,
+       [0][0][1][0][RTW89_WW][3] = 58,
+       [0][0][1][0][RTW89_WW][4] = 58,
+       [0][0][1][0][RTW89_WW][5] = 58,
+       [0][0][1][0][RTW89_WW][6] = 58,
+       [0][0][1][0][RTW89_WW][7] = 58,
+       [0][0][1][0][RTW89_WW][8] = 58,
+       [0][0][1][0][RTW89_WW][9] = 58,
+       [0][0][1][0][RTW89_WW][10] = 58,
+       [0][0][1][0][RTW89_WW][11] = 58,
+       [0][0][1][0][RTW89_WW][12] = 58,
        [0][0][1][0][RTW89_WW][13] = 0,
-       [0][1][1][0][RTW89_WW][0] = 48,
-       [0][1][1][0][RTW89_WW][1] = 48,
-       [0][1][1][0][RTW89_WW][2] = 48,
-       [0][1][1][0][RTW89_WW][3] = 48,
-       [0][1][1][0][RTW89_WW][4] = 48,
-       [0][1][1][0][RTW89_WW][5] = 48,
-       [0][1][1][0][RTW89_WW][6] = 48,
-       [0][1][1][0][RTW89_WW][7] = 48,
-       [0][1][1][0][RTW89_WW][8] = 48,
-       [0][1][1][0][RTW89_WW][9] = 48,
-       [0][1][1][0][RTW89_WW][10] = 48,
-       [0][1][1][0][RTW89_WW][11] = 38,
-       [0][1][1][0][RTW89_WW][12] = 34,
+       [0][1][1][0][RTW89_WW][0] = 46,
+       [0][1][1][0][RTW89_WW][1] = 46,
+       [0][1][1][0][RTW89_WW][2] = 46,
+       [0][1][1][0][RTW89_WW][3] = 46,
+       [0][1][1][0][RTW89_WW][4] = 46,
+       [0][1][1][0][RTW89_WW][5] = 46,
+       [0][1][1][0][RTW89_WW][6] = 46,
+       [0][1][1][0][RTW89_WW][7] = 46,
+       [0][1][1][0][RTW89_WW][8] = 46,
+       [0][1][1][0][RTW89_WW][9] = 46,
+       [0][1][1][0][RTW89_WW][10] = 46,
+       [0][1][1][0][RTW89_WW][11] = 46,
+       [0][1][1][0][RTW89_WW][12] = 36,
        [0][1][1][0][RTW89_WW][13] = 0,
-       [0][0][2][0][RTW89_WW][0] = 60,
-       [0][0][2][0][RTW89_WW][1] = 60,
-       [0][0][2][0][RTW89_WW][2] = 60,
-       [0][0][2][0][RTW89_WW][3] = 60,
-       [0][0][2][0][RTW89_WW][4] = 60,
-       [0][0][2][0][RTW89_WW][5] = 60,
-       [0][0][2][0][RTW89_WW][6] = 60,
-       [0][0][2][0][RTW89_WW][7] = 60,
-       [0][0][2][0][RTW89_WW][8] = 60,
-       [0][0][2][0][RTW89_WW][9] = 60,
-       [0][0][2][0][RTW89_WW][10] = 60,
-       [0][0][2][0][RTW89_WW][11] = 46,
-       [0][0][2][0][RTW89_WW][12] = 42,
+       [0][0][2][0][RTW89_WW][0] = 58,
+       [0][0][2][0][RTW89_WW][1] = 58,
+       [0][0][2][0][RTW89_WW][2] = 58,
+       [0][0][2][0][RTW89_WW][3] = 58,
+       [0][0][2][0][RTW89_WW][4] = 58,
+       [0][0][2][0][RTW89_WW][5] = 58,
+       [0][0][2][0][RTW89_WW][6] = 58,
+       [0][0][2][0][RTW89_WW][7] = 58,
+       [0][0][2][0][RTW89_WW][8] = 58,
+       [0][0][2][0][RTW89_WW][9] = 58,
+       [0][0][2][0][RTW89_WW][10] = 58,
+       [0][0][2][0][RTW89_WW][11] = 58,
+       [0][0][2][0][RTW89_WW][12] = 38,
        [0][0][2][0][RTW89_WW][13] = 0,
-       [0][1][2][0][RTW89_WW][0] = 48,
-       [0][1][2][0][RTW89_WW][1] = 48,
-       [0][1][2][0][RTW89_WW][2] = 48,
-       [0][1][2][0][RTW89_WW][3] = 48,
-       [0][1][2][0][RTW89_WW][4] = 48,
-       [0][1][2][0][RTW89_WW][5] = 48,
-       [0][1][2][0][RTW89_WW][6] = 48,
-       [0][1][2][0][RTW89_WW][7] = 48,
-       [0][1][2][0][RTW89_WW][8] = 48,
-       [0][1][2][0][RTW89_WW][9] = 48,
-       [0][1][2][0][RTW89_WW][10] = 48,
-       [0][1][2][0][RTW89_WW][11] = 38,
-       [0][1][2][0][RTW89_WW][12] = 34,
+       [0][1][2][0][RTW89_WW][0] = 46,
+       [0][1][2][0][RTW89_WW][1] = 46,
+       [0][1][2][0][RTW89_WW][2] = 46,
+       [0][1][2][0][RTW89_WW][3] = 46,
+       [0][1][2][0][RTW89_WW][4] = 46,
+       [0][1][2][0][RTW89_WW][5] = 46,
+       [0][1][2][0][RTW89_WW][6] = 46,
+       [0][1][2][0][RTW89_WW][7] = 46,
+       [0][1][2][0][RTW89_WW][8] = 46,
+       [0][1][2][0][RTW89_WW][9] = 46,
+       [0][1][2][0][RTW89_WW][10] = 46,
+       [0][1][2][0][RTW89_WW][11] = 46,
+       [0][1][2][0][RTW89_WW][12] = 16,
        [0][1][2][0][RTW89_WW][13] = 0,
        [0][1][2][1][RTW89_WW][0] = 36,
-       [0][1][2][1][RTW89_WW][1] = 36,
-       [0][1][2][1][RTW89_WW][2] = 36,
-       [0][1][2][1][RTW89_WW][3] = 36,
-       [0][1][2][1][RTW89_WW][4] = 36,
-       [0][1][2][1][RTW89_WW][5] = 36,
-       [0][1][2][1][RTW89_WW][6] = 36,
-       [0][1][2][1][RTW89_WW][7] = 36,
-       [0][1][2][1][RTW89_WW][8] = 36,
-       [0][1][2][1][RTW89_WW][9] = 36,
-       [0][1][2][1][RTW89_WW][10] = 36,
-       [0][1][2][1][RTW89_WW][11] = 36,
-       [0][1][2][1][RTW89_WW][12] = 34,
+       [0][1][2][1][RTW89_WW][1] = 34,
+       [0][1][2][1][RTW89_WW][2] = 34,
+       [0][1][2][1][RTW89_WW][3] = 34,
+       [0][1][2][1][RTW89_WW][4] = 34,
+       [0][1][2][1][RTW89_WW][5] = 34,
+       [0][1][2][1][RTW89_WW][6] = 34,
+       [0][1][2][1][RTW89_WW][7] = 34,
+       [0][1][2][1][RTW89_WW][8] = 34,
+       [0][1][2][1][RTW89_WW][9] = 34,
+       [0][1][2][1][RTW89_WW][10] = 34,
+       [0][1][2][1][RTW89_WW][11] = 34,
+       [0][1][2][1][RTW89_WW][12] = 16,
        [0][1][2][1][RTW89_WW][13] = 0,
        [1][0][2][0][RTW89_WW][0] = 0,
        [1][0][2][0][RTW89_WW][1] = 0,
-       [1][0][2][0][RTW89_WW][2] = 60,
-       [1][0][2][0][RTW89_WW][3] = 60,
-       [1][0][2][0][RTW89_WW][4] = 60,
-       [1][0][2][0][RTW89_WW][5] = 60,
-       [1][0][2][0][RTW89_WW][6] = 60,
-       [1][0][2][0][RTW89_WW][7] = 60,
-       [1][0][2][0][RTW89_WW][8] = 60,
-       [1][0][2][0][RTW89_WW][9] = 60,
-       [1][0][2][0][RTW89_WW][10] = 58,
+       [1][0][2][0][RTW89_WW][2] = 58,
+       [1][0][2][0][RTW89_WW][3] = 58,
+       [1][0][2][0][RTW89_WW][4] = 58,
+       [1][0][2][0][RTW89_WW][5] = 58,
+       [1][0][2][0][RTW89_WW][6] = 58,
+       [1][0][2][0][RTW89_WW][7] = 58,
+       [1][0][2][0][RTW89_WW][8] = 58,
+       [1][0][2][0][RTW89_WW][9] = 58,
+       [1][0][2][0][RTW89_WW][10] = 56,
        [1][0][2][0][RTW89_WW][11] = 0,
        [1][0][2][0][RTW89_WW][12] = 0,
        [1][0][2][0][RTW89_WW][13] = 0,
        [1][1][2][0][RTW89_WW][0] = 0,
        [1][1][2][0][RTW89_WW][1] = 0,
-       [1][1][2][0][RTW89_WW][2] = 46,
-       [1][1][2][0][RTW89_WW][3] = 46,
-       [1][1][2][0][RTW89_WW][4] = 48,
-       [1][1][2][0][RTW89_WW][5] = 48,
-       [1][1][2][0][RTW89_WW][6] = 48,
-       [1][1][2][0][RTW89_WW][7] = 46,
-       [1][1][2][0][RTW89_WW][8] = 46,
+       [1][1][2][0][RTW89_WW][2] = 34,
+       [1][1][2][0][RTW89_WW][3] = 34,
+       [1][1][2][0][RTW89_WW][4] = 34,
+       [1][1][2][0][RTW89_WW][5] = 34,
+       [1][1][2][0][RTW89_WW][6] = 34,
+       [1][1][2][0][RTW89_WW][7] = 34,
+       [1][1][2][0][RTW89_WW][8] = 34,
        [1][1][2][0][RTW89_WW][9] = 34,
-       [1][1][2][0][RTW89_WW][10] = 30,
+       [1][1][2][0][RTW89_WW][10] = 34,
        [1][1][2][0][RTW89_WW][11] = 0,
        [1][1][2][0][RTW89_WW][12] = 0,
        [1][1][2][0][RTW89_WW][13] = 0,
        [1][1][2][1][RTW89_WW][0] = 0,
        [1][1][2][1][RTW89_WW][1] = 0,
-       [1][1][2][1][RTW89_WW][2] = 36,
-       [1][1][2][1][RTW89_WW][3] = 36,
-       [1][1][2][1][RTW89_WW][4] = 36,
-       [1][1][2][1][RTW89_WW][5] = 36,
-       [1][1][2][1][RTW89_WW][6] = 36,
-       [1][1][2][1][RTW89_WW][7] = 36,
-       [1][1][2][1][RTW89_WW][8] = 36,
+       [1][1][2][1][RTW89_WW][2] = 34,
+       [1][1][2][1][RTW89_WW][3] = 34,
+       [1][1][2][1][RTW89_WW][4] = 34,
+       [1][1][2][1][RTW89_WW][5] = 34,
+       [1][1][2][1][RTW89_WW][6] = 34,
+       [1][1][2][1][RTW89_WW][7] = 34,
+       [1][1][2][1][RTW89_WW][8] = 34,
        [1][1][2][1][RTW89_WW][9] = 34,
-       [1][1][2][1][RTW89_WW][10] = 30,
+       [1][1][2][1][RTW89_WW][10] = 36,
        [1][1][2][1][RTW89_WW][11] = 0,
        [1][1][2][1][RTW89_WW][12] = 0,
        [1][1][2][1][RTW89_WW][13] = 0,
-       [0][0][0][0][RTW89_FCC][0] = 70,
+       [0][0][0][0][RTW89_FCC][0] = 76,
        [0][0][0][0][RTW89_ETSI][0] = 60,
        [0][0][0][0][RTW89_MKK][0] = 68,
-       [0][0][0][0][RTW89_IC][0] = 74,
+       [0][0][0][0][RTW89_IC][0] = 76,
+       [0][0][0][0][RTW89_KCC][0] = 68,
        [0][0][0][0][RTW89_ACMA][0] = 60,
-       [0][0][0][0][RTW89_FCC][1] = 70,
+       [0][0][0][0][RTW89_CN][0] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][1] = 74,
+       [0][0][0][0][RTW89_IC][1] = 76,
+       [0][0][0][0][RTW89_KCC][1] = 68,
        [0][0][0][0][RTW89_ACMA][1] = 60,
-       [0][0][0][0][RTW89_FCC][2] = 70,
+       [0][0][0][0][RTW89_CN][1] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][2] = 74,
+       [0][0][0][0][RTW89_IC][2] = 76,
+       [0][0][0][0][RTW89_KCC][2] = 68,
        [0][0][0][0][RTW89_ACMA][2] = 60,
-       [0][0][0][0][RTW89_FCC][3] = 70,
+       [0][0][0][0][RTW89_CN][2] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][3] = 74,
+       [0][0][0][0][RTW89_IC][3] = 76,
+       [0][0][0][0][RTW89_KCC][3] = 68,
        [0][0][0][0][RTW89_ACMA][3] = 60,
-       [0][0][0][0][RTW89_FCC][4] = 70,
+       [0][0][0][0][RTW89_CN][3] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][4] = 74,
+       [0][0][0][0][RTW89_IC][4] = 76,
+       [0][0][0][0][RTW89_KCC][4] = 68,
        [0][0][0][0][RTW89_ACMA][4] = 60,
-       [0][0][0][0][RTW89_FCC][5] = 70,
+       [0][0][0][0][RTW89_CN][4] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][5] = 74,
+       [0][0][0][0][RTW89_IC][5] = 76,
+       [0][0][0][0][RTW89_KCC][5] = 68,
        [0][0][0][0][RTW89_ACMA][5] = 60,
-       [0][0][0][0][RTW89_FCC][6] = 70,
+       [0][0][0][0][RTW89_CN][5] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][6] = 74,
+       [0][0][0][0][RTW89_IC][6] = 76,
+       [0][0][0][0][RTW89_KCC][6] = 68,
        [0][0][0][0][RTW89_ACMA][6] = 60,
-       [0][0][0][0][RTW89_FCC][7] = 70,
+       [0][0][0][0][RTW89_CN][6] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][7] = 74,
+       [0][0][0][0][RTW89_IC][7] = 76,
+       [0][0][0][0][RTW89_KCC][7] = 68,
        [0][0][0][0][RTW89_ACMA][7] = 60,
-       [0][0][0][0][RTW89_FCC][8] = 70,
+       [0][0][0][0][RTW89_CN][7] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][8] = 74,
+       [0][0][0][0][RTW89_IC][8] = 76,
+       [0][0][0][0][RTW89_KCC][8] = 68,
        [0][0][0][0][RTW89_ACMA][8] = 60,
-       [0][0][0][0][RTW89_FCC][9] = 70,
+       [0][0][0][0][RTW89_CN][8] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][9] = 74,
+       [0][0][0][0][RTW89_IC][9] = 76,
+       [0][0][0][0][RTW89_KCC][9] = 70,
        [0][0][0][0][RTW89_ACMA][9] = 60,
-       [0][0][0][0][RTW89_FCC][10] = 70,
+       [0][0][0][0][RTW89_CN][9] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][10] = 74,
+       [0][0][0][0][RTW89_IC][10] = 76,
+       [0][0][0][0][RTW89_KCC][10] = 70,
        [0][0][0][0][RTW89_ACMA][10] = 60,
-       [0][0][0][0][RTW89_FCC][11] = 62,
+       [0][0][0][0][RTW89_CN][10] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][11] = 72,
+       [0][0][0][0][RTW89_IC][11] = 58,
+       [0][0][0][0][RTW89_KCC][11] = 70,
        [0][0][0][0][RTW89_ACMA][11] = 60,
-       [0][0][0][0][RTW89_FCC][12] = 48,
+       [0][0][0][0][RTW89_CN][11] = 58,
+       [0][0][0][0][RTW89_UK][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,
-       [0][0][0][0][RTW89_IC][12] = 58,
+       [0][0][0][0][RTW89_IC][12] = 46,
+       [0][0][0][0][RTW89_KCC][12] = 70,
        [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_FCC][13] = 127,
        [0][0][0][0][RTW89_ETSI][13] = 127,
        [0][0][0][0][RTW89_MKK][13] = 72,
        [0][0][0][0][RTW89_IC][13] = 127,
+       [0][0][0][0][RTW89_KCC][13] = 127,
        [0][0][0][0][RTW89_ACMA][13] = 127,
-       [0][1][0][0][RTW89_FCC][0] = 66,
+       [0][0][0][0][RTW89_CN][13] = 127,
+       [0][0][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][0] = 74,
+       [0][1][0][0][RTW89_IC][0] = 76,
+       [0][1][0][0][RTW89_KCC][0] = 56,
        [0][1][0][0][RTW89_ACMA][0] = 48,
-       [0][1][0][0][RTW89_FCC][1] = 66,
+       [0][1][0][0][RTW89_CN][0] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][1] = 74,
+       [0][1][0][0][RTW89_IC][1] = 76,
+       [0][1][0][0][RTW89_KCC][1] = 56,
        [0][1][0][0][RTW89_ACMA][1] = 48,
-       [0][1][0][0][RTW89_FCC][2] = 66,
+       [0][1][0][0][RTW89_CN][1] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][2] = 74,
+       [0][1][0][0][RTW89_IC][2] = 76,
+       [0][1][0][0][RTW89_KCC][2] = 56,
        [0][1][0][0][RTW89_ACMA][2] = 48,
-       [0][1][0][0][RTW89_FCC][3] = 66,
+       [0][1][0][0][RTW89_CN][2] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][3] = 74,
+       [0][1][0][0][RTW89_IC][3] = 76,
+       [0][1][0][0][RTW89_KCC][3] = 56,
        [0][1][0][0][RTW89_ACMA][3] = 48,
-       [0][1][0][0][RTW89_FCC][4] = 66,
+       [0][1][0][0][RTW89_CN][3] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][4] = 74,
+       [0][1][0][0][RTW89_IC][4] = 76,
+       [0][1][0][0][RTW89_KCC][4] = 56,
        [0][1][0][0][RTW89_ACMA][4] = 48,
-       [0][1][0][0][RTW89_FCC][5] = 66,
+       [0][1][0][0][RTW89_CN][4] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][5] = 74,
+       [0][1][0][0][RTW89_IC][5] = 76,
+       [0][1][0][0][RTW89_KCC][5] = 56,
        [0][1][0][0][RTW89_ACMA][5] = 48,
-       [0][1][0][0][RTW89_FCC][6] = 66,
+       [0][1][0][0][RTW89_CN][5] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][6] = 74,
+       [0][1][0][0][RTW89_IC][6] = 76,
+       [0][1][0][0][RTW89_KCC][6] = 56,
        [0][1][0][0][RTW89_ACMA][6] = 48,
-       [0][1][0][0][RTW89_FCC][7] = 66,
+       [0][1][0][0][RTW89_CN][6] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][7] = 74,
+       [0][1][0][0][RTW89_IC][7] = 76,
+       [0][1][0][0][RTW89_KCC][7] = 56,
        [0][1][0][0][RTW89_ACMA][7] = 48,
-       [0][1][0][0][RTW89_FCC][8] = 66,
+       [0][1][0][0][RTW89_CN][7] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][8] = 74,
+       [0][1][0][0][RTW89_IC][8] = 76,
+       [0][1][0][0][RTW89_KCC][8] = 56,
        [0][1][0][0][RTW89_ACMA][8] = 48,
-       [0][1][0][0][RTW89_FCC][9] = 66,
+       [0][1][0][0][RTW89_CN][8] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][9] = 74,
+       [0][1][0][0][RTW89_IC][9] = 70,
+       [0][1][0][0][RTW89_KCC][9] = 56,
        [0][1][0][0][RTW89_ACMA][9] = 48,
-       [0][1][0][0][RTW89_FCC][10] = 66,
+       [0][1][0][0][RTW89_CN][9] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][10] = 74,
+       [0][1][0][0][RTW89_IC][10] = 72,
+       [0][1][0][0][RTW89_KCC][10] = 56,
        [0][1][0][0][RTW89_ACMA][10] = 48,
-       [0][1][0][0][RTW89_FCC][11] = 46,
+       [0][1][0][0][RTW89_CN][10] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][11] = 56,
+       [0][1][0][0][RTW89_IC][11] = 44,
+       [0][1][0][0][RTW89_KCC][11] = 56,
        [0][1][0][0][RTW89_ACMA][11] = 48,
-       [0][1][0][0][RTW89_FCC][12] = 34,
+       [0][1][0][0][RTW89_CN][11] = 42,
+       [0][1][0][0][RTW89_UK][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,
-       [0][1][0][0][RTW89_IC][12] = 44,
+       [0][1][0][0][RTW89_IC][12] = 18,
+       [0][1][0][0][RTW89_KCC][12] = 56,
        [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_FCC][13] = 127,
        [0][1][0][0][RTW89_ETSI][13] = 127,
        [0][1][0][0][RTW89_MKK][13] = 60,
        [0][1][0][0][RTW89_IC][13] = 127,
+       [0][1][0][0][RTW89_KCC][13] = 127,
        [0][1][0][0][RTW89_ACMA][13] = 127,
+       [0][1][0][0][RTW89_CN][13] = 127,
+       [0][1][0][0][RTW89_UK][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,
        [1][0][0][0][RTW89_IC][0] = 127,
+       [1][0][0][0][RTW89_KCC][0] = 127,
        [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_FCC][1] = 127,
        [1][0][0][0][RTW89_ETSI][1] = 127,
        [1][0][0][0][RTW89_MKK][1] = 127,
        [1][0][0][0][RTW89_IC][1] = 127,
+       [1][0][0][0][RTW89_KCC][1] = 127,
        [1][0][0][0][RTW89_ACMA][1] = 127,
-       [1][0][0][0][RTW89_FCC][2] = 42,
+       [1][0][0][0][RTW89_CN][1] = 127,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][2] = 52,
+       [1][0][0][0][RTW89_IC][2] = 44,
+       [1][0][0][0][RTW89_KCC][2] = 68,
        [1][0][0][0][RTW89_ACMA][2] = 60,
-       [1][0][0][0][RTW89_FCC][3] = 42,
+       [1][0][0][0][RTW89_CN][2] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][3] = 52,
+       [1][0][0][0][RTW89_IC][3] = 60,
+       [1][0][0][0][RTW89_KCC][3] = 68,
        [1][0][0][0][RTW89_ACMA][3] = 60,
-       [1][0][0][0][RTW89_FCC][4] = 42,
+       [1][0][0][0][RTW89_CN][3] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][4] = 52,
+       [1][0][0][0][RTW89_IC][4] = 60,
+       [1][0][0][0][RTW89_KCC][4] = 68,
        [1][0][0][0][RTW89_ACMA][4] = 60,
-       [1][0][0][0][RTW89_FCC][5] = 58,
+       [1][0][0][0][RTW89_CN][4] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][5] = 68,
+       [1][0][0][0][RTW89_IC][5] = 62,
+       [1][0][0][0][RTW89_KCC][5] = 68,
        [1][0][0][0][RTW89_ACMA][5] = 60,
-       [1][0][0][0][RTW89_FCC][6] = 42,
+       [1][0][0][0][RTW89_CN][5] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][6] = 52,
+       [1][0][0][0][RTW89_IC][6] = 46,
+       [1][0][0][0][RTW89_KCC][6] = 68,
        [1][0][0][0][RTW89_ACMA][6] = 60,
-       [1][0][0][0][RTW89_FCC][7] = 42,
+       [1][0][0][0][RTW89_CN][6] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][7] = 52,
+       [1][0][0][0][RTW89_IC][7] = 46,
+       [1][0][0][0][RTW89_KCC][7] = 68,
        [1][0][0][0][RTW89_ACMA][7] = 60,
-       [1][0][0][0][RTW89_FCC][8] = 42,
+       [1][0][0][0][RTW89_CN][7] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][8] = 52,
+       [1][0][0][0][RTW89_IC][8] = 28,
+       [1][0][0][0][RTW89_KCC][8] = 70,
        [1][0][0][0][RTW89_ACMA][8] = 60,
-       [1][0][0][0][RTW89_FCC][9] = 34,
+       [1][0][0][0][RTW89_CN][8] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][9] = 44,
+       [1][0][0][0][RTW89_IC][9] = 26,
+       [1][0][0][0][RTW89_KCC][9] = 70,
        [1][0][0][0][RTW89_ACMA][9] = 60,
-       [1][0][0][0][RTW89_FCC][10] = 22,
+       [1][0][0][0][RTW89_CN][9] = 58,
+       [1][0][0][0][RTW89_UK][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,
-       [1][0][0][0][RTW89_IC][10] = 32,
+       [1][0][0][0][RTW89_IC][10] = 26,
+       [1][0][0][0][RTW89_KCC][10] = 70,
        [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_FCC][11] = 127,
        [1][0][0][0][RTW89_ETSI][11] = 127,
        [1][0][0][0][RTW89_MKK][11] = 127,
        [1][0][0][0][RTW89_IC][11] = 127,
+       [1][0][0][0][RTW89_KCC][11] = 127,
        [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_FCC][12] = 127,
        [1][0][0][0][RTW89_ETSI][12] = 127,
        [1][0][0][0][RTW89_MKK][12] = 127,
        [1][0][0][0][RTW89_IC][12] = 127,
+       [1][0][0][0][RTW89_KCC][12] = 127,
        [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_FCC][13] = 127,
        [1][0][0][0][RTW89_ETSI][13] = 127,
        [1][0][0][0][RTW89_MKK][13] = 127,
        [1][0][0][0][RTW89_IC][13] = 127,
+       [1][0][0][0][RTW89_KCC][13] = 127,
        [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][1][0][0][RTW89_FCC][0] = 127,
        [1][1][0][0][RTW89_ETSI][0] = 127,
        [1][1][0][0][RTW89_MKK][0] = 127,
        [1][1][0][0][RTW89_IC][0] = 127,
+       [1][1][0][0][RTW89_KCC][0] = 127,
        [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_FCC][1] = 127,
        [1][1][0][0][RTW89_ETSI][1] = 127,
        [1][1][0][0][RTW89_MKK][1] = 127,
        [1][1][0][0][RTW89_IC][1] = 127,
+       [1][1][0][0][RTW89_KCC][1] = 127,
        [1][1][0][0][RTW89_ACMA][1] = 127,
-       [1][1][0][0][RTW89_FCC][2] = 38,
+       [1][1][0][0][RTW89_CN][1] = 127,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][2] = 48,
+       [1][1][0][0][RTW89_IC][2] = 46,
+       [1][1][0][0][RTW89_KCC][2] = 56,
        [1][1][0][0][RTW89_ACMA][2] = 48,
-       [1][1][0][0][RTW89_FCC][3] = 38,
+       [1][1][0][0][RTW89_CN][2] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][3] = 48,
+       [1][1][0][0][RTW89_IC][3] = 46,
+       [1][1][0][0][RTW89_KCC][3] = 56,
        [1][1][0][0][RTW89_ACMA][3] = 48,
-       [1][1][0][0][RTW89_FCC][4] = 38,
+       [1][1][0][0][RTW89_CN][3] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][4] = 48,
+       [1][1][0][0][RTW89_IC][4] = 46,
+       [1][1][0][0][RTW89_KCC][4] = 56,
        [1][1][0][0][RTW89_ACMA][4] = 48,
-       [1][1][0][0][RTW89_FCC][5] = 54,
+       [1][1][0][0][RTW89_CN][4] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][5] = 64,
+       [1][1][0][0][RTW89_IC][5] = 48,
+       [1][1][0][0][RTW89_KCC][5] = 56,
        [1][1][0][0][RTW89_ACMA][5] = 48,
-       [1][1][0][0][RTW89_FCC][6] = 26,
+       [1][1][0][0][RTW89_CN][5] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][6] = 36,
+       [1][1][0][0][RTW89_IC][6] = 40,
+       [1][1][0][0][RTW89_KCC][6] = 56,
        [1][1][0][0][RTW89_ACMA][6] = 48,
-       [1][1][0][0][RTW89_FCC][7] = 26,
+       [1][1][0][0][RTW89_CN][6] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][7] = 36,
+       [1][1][0][0][RTW89_IC][7] = 40,
+       [1][1][0][0][RTW89_KCC][7] = 56,
        [1][1][0][0][RTW89_ACMA][7] = 48,
-       [1][1][0][0][RTW89_FCC][8] = 26,
+       [1][1][0][0][RTW89_CN][7] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][8] = 36,
+       [1][1][0][0][RTW89_IC][8] = 14,
+       [1][1][0][0][RTW89_KCC][8] = 58,
        [1][1][0][0][RTW89_ACMA][8] = 48,
-       [1][1][0][0][RTW89_FCC][9] = 22,
+       [1][1][0][0][RTW89_CN][8] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][9] = 32,
+       [1][1][0][0][RTW89_IC][9] = 14,
+       [1][1][0][0][RTW89_KCC][9] = 58,
        [1][1][0][0][RTW89_ACMA][9] = 48,
-       [1][1][0][0][RTW89_FCC][10] = 22,
+       [1][1][0][0][RTW89_CN][9] = 46,
+       [1][1][0][0][RTW89_UK][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,
-       [1][1][0][0][RTW89_IC][10] = 32,
+       [1][1][0][0][RTW89_IC][10] = 12,
+       [1][1][0][0][RTW89_KCC][10] = 58,
        [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_FCC][11] = 127,
        [1][1][0][0][RTW89_ETSI][11] = 127,
        [1][1][0][0][RTW89_MKK][11] = 127,
        [1][1][0][0][RTW89_IC][11] = 127,
+       [1][1][0][0][RTW89_KCC][11] = 127,
        [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_FCC][12] = 127,
        [1][1][0][0][RTW89_ETSI][12] = 127,
        [1][1][0][0][RTW89_MKK][12] = 127,
        [1][1][0][0][RTW89_IC][12] = 127,
+       [1][1][0][0][RTW89_KCC][12] = 127,
        [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_FCC][13] = 127,
        [1][1][0][0][RTW89_ETSI][13] = 127,
        [1][1][0][0][RTW89_MKK][13] = 127,
        [1][1][0][0][RTW89_IC][13] = 127,
+       [1][1][0][0][RTW89_KCC][13] = 127,
        [1][1][0][0][RTW89_ACMA][13] = 127,
-       [0][0][1][0][RTW89_FCC][0] = 68,
+       [1][1][0][0][RTW89_CN][13] = 127,
+       [1][1][0][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][0] = 78,
+       [0][0][1][0][RTW89_IC][0] = 66,
+       [0][0][1][0][RTW89_KCC][0] = 68,
        [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_FCC][1] = 68,
        [0][0][1][0][RTW89_ETSI][1] = 60,
        [0][0][1][0][RTW89_MKK][1] = 78,
-       [0][0][1][0][RTW89_IC][1] = 78,
+       [0][0][1][0][RTW89_IC][1] = 68,
+       [0][0][1][0][RTW89_KCC][1] = 68,
        [0][0][1][0][RTW89_ACMA][1] = 60,
-       [0][0][1][0][RTW89_FCC][2] = 70,
+       [0][0][1][0][RTW89_CN][1] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][2] = 78,
+       [0][0][1][0][RTW89_IC][2] = 72,
+       [0][0][1][0][RTW89_KCC][2] = 68,
        [0][0][1][0][RTW89_ACMA][2] = 60,
-       [0][0][1][0][RTW89_FCC][3] = 70,
+       [0][0][1][0][RTW89_CN][2] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][3] = 78,
+       [0][0][1][0][RTW89_IC][3] = 76,
+       [0][0][1][0][RTW89_KCC][3] = 68,
        [0][0][1][0][RTW89_ACMA][3] = 60,
-       [0][0][1][0][RTW89_FCC][4] = 70,
+       [0][0][1][0][RTW89_CN][3] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][4] = 78,
+       [0][0][1][0][RTW89_IC][4] = 80,
+       [0][0][1][0][RTW89_KCC][4] = 76,
        [0][0][1][0][RTW89_ACMA][4] = 60,
-       [0][0][1][0][RTW89_FCC][5] = 70,
+       [0][0][1][0][RTW89_CN][4] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][5] = 78,
+       [0][0][1][0][RTW89_IC][5] = 80,
+       [0][0][1][0][RTW89_KCC][5] = 76,
        [0][0][1][0][RTW89_ACMA][5] = 60,
-       [0][0][1][0][RTW89_FCC][6] = 70,
+       [0][0][1][0][RTW89_CN][5] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][6] = 78,
+       [0][0][1][0][RTW89_IC][6] = 80,
+       [0][0][1][0][RTW89_KCC][6] = 76,
        [0][0][1][0][RTW89_ACMA][6] = 60,
-       [0][0][1][0][RTW89_FCC][7] = 70,
+       [0][0][1][0][RTW89_CN][6] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][7] = 78,
+       [0][0][1][0][RTW89_IC][7] = 80,
+       [0][0][1][0][RTW89_KCC][7] = 76,
        [0][0][1][0][RTW89_ACMA][7] = 60,
-       [0][0][1][0][RTW89_FCC][8] = 70,
+       [0][0][1][0][RTW89_CN][7] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][8] = 78,
+       [0][0][1][0][RTW89_IC][8] = 80,
+       [0][0][1][0][RTW89_KCC][8] = 76,
        [0][0][1][0][RTW89_ACMA][8] = 60,
-       [0][0][1][0][RTW89_FCC][9] = 66,
+       [0][0][1][0][RTW89_CN][8] = 58,
+       [0][0][1][0][RTW89_UK][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,
        [0][0][1][0][RTW89_IC][9] = 76,
+       [0][0][1][0][RTW89_KCC][9] = 70,
        [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_FCC][10] = 66,
        [0][0][1][0][RTW89_ETSI][10] = 60,
        [0][0][1][0][RTW89_MKK][10] = 78,
-       [0][0][1][0][RTW89_IC][10] = 76,
+       [0][0][1][0][RTW89_IC][10] = 66,
+       [0][0][1][0][RTW89_KCC][10] = 70,
        [0][0][1][0][RTW89_ACMA][10] = 60,
-       [0][0][1][0][RTW89_FCC][11] = 46,
+       [0][0][1][0][RTW89_CN][10] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][11] = 56,
+       [0][0][1][0][RTW89_IC][11] = 62,
+       [0][0][1][0][RTW89_KCC][11] = 70,
        [0][0][1][0][RTW89_ACMA][11] = 60,
-       [0][0][1][0][RTW89_FCC][12] = 42,
+       [0][0][1][0][RTW89_CN][11] = 58,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][12] = 52,
+       [0][0][1][0][RTW89_IC][12] = 60,
+       [0][0][1][0][RTW89_KCC][12] = 70,
        [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_FCC][13] = 127,
        [0][0][1][0][RTW89_ETSI][13] = 127,
        [0][0][1][0][RTW89_MKK][13] = 127,
        [0][0][1][0][RTW89_IC][13] = 127,
+       [0][0][1][0][RTW89_KCC][13] = 127,
        [0][0][1][0][RTW89_ACMA][13] = 127,
-       [0][1][1][0][RTW89_FCC][0] = 54,
+       [0][0][1][0][RTW89_CN][13] = 127,
+       [0][0][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][0] = 64,
+       [0][1][1][0][RTW89_IC][0] = 66,
+       [0][1][1][0][RTW89_KCC][0] = 64,
        [0][1][1][0][RTW89_ACMA][0] = 48,
-       [0][1][1][0][RTW89_FCC][1] = 54,
+       [0][1][1][0][RTW89_CN][0] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][1] = 64,
+       [0][1][1][0][RTW89_IC][1] = 68,
+       [0][1][1][0][RTW89_KCC][1] = 64,
        [0][1][1][0][RTW89_ACMA][1] = 48,
-       [0][1][1][0][RTW89_FCC][2] = 58,
+       [0][1][1][0][RTW89_CN][1] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][2] = 68,
+       [0][1][1][0][RTW89_IC][2] = 72,
+       [0][1][1][0][RTW89_KCC][2] = 64,
        [0][1][1][0][RTW89_ACMA][2] = 48,
-       [0][1][1][0][RTW89_FCC][3] = 62,
+       [0][1][1][0][RTW89_CN][2] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][3] = 72,
+       [0][1][1][0][RTW89_IC][3] = 76,
+       [0][1][1][0][RTW89_KCC][3] = 64,
        [0][1][1][0][RTW89_ACMA][3] = 48,
-       [0][1][1][0][RTW89_FCC][4] = 70,
+       [0][1][1][0][RTW89_CN][3] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][4] = 78,
+       [0][1][1][0][RTW89_IC][4] = 80,
+       [0][1][1][0][RTW89_KCC][4] = 66,
        [0][1][1][0][RTW89_ACMA][4] = 48,
-       [0][1][1][0][RTW89_FCC][5] = 70,
+       [0][1][1][0][RTW89_CN][4] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][5] = 78,
+       [0][1][1][0][RTW89_IC][5] = 80,
+       [0][1][1][0][RTW89_KCC][5] = 66,
        [0][1][1][0][RTW89_ACMA][5] = 48,
-       [0][1][1][0][RTW89_FCC][6] = 70,
+       [0][1][1][0][RTW89_CN][5] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][6] = 78,
+       [0][1][1][0][RTW89_IC][6] = 80,
+       [0][1][1][0][RTW89_KCC][6] = 66,
        [0][1][1][0][RTW89_ACMA][6] = 48,
-       [0][1][1][0][RTW89_FCC][7] = 62,
+       [0][1][1][0][RTW89_CN][6] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][7] = 72,
+       [0][1][1][0][RTW89_IC][7] = 78,
+       [0][1][1][0][RTW89_KCC][7] = 66,
        [0][1][1][0][RTW89_ACMA][7] = 48,
-       [0][1][1][0][RTW89_FCC][8] = 58,
+       [0][1][1][0][RTW89_CN][7] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][8] = 68,
+       [0][1][1][0][RTW89_IC][8] = 74,
+       [0][1][1][0][RTW89_KCC][8] = 66,
        [0][1][1][0][RTW89_ACMA][8] = 48,
-       [0][1][1][0][RTW89_FCC][9] = 54,
+       [0][1][1][0][RTW89_CN][8] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][9] = 64,
+       [0][1][1][0][RTW89_IC][9] = 70,
+       [0][1][1][0][RTW89_KCC][9] = 64,
        [0][1][1][0][RTW89_ACMA][9] = 48,
-       [0][1][1][0][RTW89_FCC][10] = 54,
+       [0][1][1][0][RTW89_CN][9] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][10] = 64,
+       [0][1][1][0][RTW89_IC][10] = 62,
+       [0][1][1][0][RTW89_KCC][10] = 64,
        [0][1][1][0][RTW89_ACMA][10] = 48,
-       [0][1][1][0][RTW89_FCC][11] = 38,
+       [0][1][1][0][RTW89_CN][10] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][11] = 48,
+       [0][1][1][0][RTW89_IC][11] = 60,
+       [0][1][1][0][RTW89_KCC][11] = 64,
        [0][1][1][0][RTW89_ACMA][11] = 48,
-       [0][1][1][0][RTW89_FCC][12] = 34,
+       [0][1][1][0][RTW89_CN][11] = 46,
+       [0][1][1][0][RTW89_UK][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,
-       [0][1][1][0][RTW89_IC][12] = 44,
+       [0][1][1][0][RTW89_IC][12] = 36,
+       [0][1][1][0][RTW89_KCC][12] = 64,
        [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_FCC][13] = 127,
        [0][1][1][0][RTW89_ETSI][13] = 127,
        [0][1][1][0][RTW89_MKK][13] = 127,
        [0][1][1][0][RTW89_IC][13] = 127,
+       [0][1][1][0][RTW89_KCC][13] = 127,
        [0][1][1][0][RTW89_ACMA][13] = 127,
-       [0][0][2][0][RTW89_FCC][0] = 68,
+       [0][1][1][0][RTW89_CN][13] = 127,
+       [0][1][1][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][0] = 78,
+       [0][0][2][0][RTW89_IC][0] = 66,
+       [0][0][2][0][RTW89_KCC][0] = 70,
        [0][0][2][0][RTW89_ACMA][0] = 60,
-       [0][0][2][0][RTW89_FCC][1] = 68,
+       [0][0][2][0][RTW89_CN][0] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][1] = 78,
+       [0][0][2][0][RTW89_IC][1] = 70,
+       [0][0][2][0][RTW89_KCC][1] = 70,
        [0][0][2][0][RTW89_ACMA][1] = 60,
-       [0][0][2][0][RTW89_FCC][2] = 70,
+       [0][0][2][0][RTW89_CN][1] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][2] = 78,
+       [0][0][2][0][RTW89_IC][2] = 74,
+       [0][0][2][0][RTW89_KCC][2] = 70,
        [0][0][2][0][RTW89_ACMA][2] = 60,
-       [0][0][2][0][RTW89_FCC][3] = 70,
+       [0][0][2][0][RTW89_CN][2] = 58,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][3] = 78,
+       [0][0][2][0][RTW89_KCC][3] = 70,
        [0][0][2][0][RTW89_ACMA][3] = 60,
-       [0][0][2][0][RTW89_FCC][4] = 70,
+       [0][0][2][0][RTW89_CN][3] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][4] = 78,
+       [0][0][2][0][RTW89_IC][4] = 80,
+       [0][0][2][0][RTW89_KCC][4] = 78,
        [0][0][2][0][RTW89_ACMA][4] = 60,
-       [0][0][2][0][RTW89_FCC][5] = 70,
+       [0][0][2][0][RTW89_CN][4] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][5] = 78,
+       [0][0][2][0][RTW89_IC][5] = 80,
+       [0][0][2][0][RTW89_KCC][5] = 78,
        [0][0][2][0][RTW89_ACMA][5] = 60,
-       [0][0][2][0][RTW89_FCC][6] = 70,
+       [0][0][2][0][RTW89_CN][5] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][6] = 78,
+       [0][0][2][0][RTW89_IC][6] = 80,
+       [0][0][2][0][RTW89_KCC][6] = 78,
        [0][0][2][0][RTW89_ACMA][6] = 60,
-       [0][0][2][0][RTW89_FCC][7] = 70,
+       [0][0][2][0][RTW89_CN][6] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][7] = 78,
+       [0][0][2][0][RTW89_IC][7] = 80,
+       [0][0][2][0][RTW89_KCC][7] = 78,
        [0][0][2][0][RTW89_ACMA][7] = 60,
-       [0][0][2][0][RTW89_FCC][8] = 68,
+       [0][0][2][0][RTW89_CN][7] = 58,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][8] = 78,
+       [0][0][2][0][RTW89_KCC][8] = 78,
        [0][0][2][0][RTW89_ACMA][8] = 60,
-       [0][0][2][0][RTW89_FCC][9] = 64,
+       [0][0][2][0][RTW89_CN][8] = 58,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][9] = 74,
+       [0][0][2][0][RTW89_KCC][9] = 66,
        [0][0][2][0][RTW89_ACMA][9] = 60,
-       [0][0][2][0][RTW89_FCC][10] = 64,
+       [0][0][2][0][RTW89_CN][9] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][10] = 74,
+       [0][0][2][0][RTW89_IC][10] = 62,
+       [0][0][2][0][RTW89_KCC][10] = 66,
        [0][0][2][0][RTW89_ACMA][10] = 60,
-       [0][0][2][0][RTW89_FCC][11] = 46,
+       [0][0][2][0][RTW89_CN][10] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][11] = 56,
+       [0][0][2][0][RTW89_IC][11] = 60,
+       [0][0][2][0][RTW89_KCC][11] = 66,
        [0][0][2][0][RTW89_ACMA][11] = 60,
-       [0][0][2][0][RTW89_FCC][12] = 42,
+       [0][0][2][0][RTW89_CN][11] = 58,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][12] = 52,
+       [0][0][2][0][RTW89_IC][12] = 38,
+       [0][0][2][0][RTW89_KCC][12] = 66,
        [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_FCC][13] = 127,
        [0][0][2][0][RTW89_ETSI][13] = 127,
        [0][0][2][0][RTW89_MKK][13] = 127,
        [0][0][2][0][RTW89_IC][13] = 127,
+       [0][0][2][0][RTW89_KCC][13] = 127,
        [0][0][2][0][RTW89_ACMA][13] = 127,
-       [0][1][2][0][RTW89_FCC][0] = 50,
+       [0][0][2][0][RTW89_CN][13] = 127,
+       [0][0][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][0] = 60,
+       [0][1][2][0][RTW89_IC][0] = 64,
+       [0][1][2][0][RTW89_KCC][0] = 66,
        [0][1][2][0][RTW89_ACMA][0] = 48,
-       [0][1][2][0][RTW89_FCC][1] = 50,
+       [0][1][2][0][RTW89_CN][0] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][1] = 60,
+       [0][1][2][0][RTW89_IC][1] = 70,
+       [0][1][2][0][RTW89_KCC][1] = 66,
        [0][1][2][0][RTW89_ACMA][1] = 48,
-       [0][1][2][0][RTW89_FCC][2] = 54,
+       [0][1][2][0][RTW89_CN][1] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][2] = 64,
+       [0][1][2][0][RTW89_IC][2] = 74,
+       [0][1][2][0][RTW89_KCC][2] = 66,
        [0][1][2][0][RTW89_ACMA][2] = 48,
-       [0][1][2][0][RTW89_FCC][3] = 58,
+       [0][1][2][0][RTW89_CN][2] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][3] = 68,
+       [0][1][2][0][RTW89_IC][3] = 78,
+       [0][1][2][0][RTW89_KCC][3] = 66,
        [0][1][2][0][RTW89_ACMA][3] = 48,
-       [0][1][2][0][RTW89_FCC][4] = 64,
+       [0][1][2][0][RTW89_CN][3] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][4] = 74,
+       [0][1][2][0][RTW89_IC][4] = 80,
+       [0][1][2][0][RTW89_KCC][4] = 66,
        [0][1][2][0][RTW89_ACMA][4] = 48,
-       [0][1][2][0][RTW89_FCC][5] = 70,
+       [0][1][2][0][RTW89_CN][4] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][5] = 78,
+       [0][1][2][0][RTW89_IC][5] = 80,
+       [0][1][2][0][RTW89_KCC][5] = 66,
        [0][1][2][0][RTW89_ACMA][5] = 48,
-       [0][1][2][0][RTW89_FCC][6] = 66,
+       [0][1][2][0][RTW89_CN][5] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][6] = 76,
+       [0][1][2][0][RTW89_IC][6] = 80,
+       [0][1][2][0][RTW89_KCC][6] = 66,
        [0][1][2][0][RTW89_ACMA][6] = 48,
-       [0][1][2][0][RTW89_FCC][7] = 58,
+       [0][1][2][0][RTW89_CN][6] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][7] = 68,
+       [0][1][2][0][RTW89_IC][7] = 74,
+       [0][1][2][0][RTW89_KCC][7] = 66,
        [0][1][2][0][RTW89_ACMA][7] = 48,
-       [0][1][2][0][RTW89_FCC][8] = 54,
+       [0][1][2][0][RTW89_CN][7] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][8] = 64,
+       [0][1][2][0][RTW89_IC][8] = 70,
+       [0][1][2][0][RTW89_KCC][8] = 66,
        [0][1][2][0][RTW89_ACMA][8] = 48,
-       [0][1][2][0][RTW89_FCC][9] = 50,
+       [0][1][2][0][RTW89_CN][8] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][9] = 60,
+       [0][1][2][0][RTW89_IC][9] = 66,
+       [0][1][2][0][RTW89_KCC][9] = 64,
        [0][1][2][0][RTW89_ACMA][9] = 48,
-       [0][1][2][0][RTW89_FCC][10] = 50,
+       [0][1][2][0][RTW89_CN][9] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][10] = 60,
+       [0][1][2][0][RTW89_IC][10] = 58,
+       [0][1][2][0][RTW89_KCC][10] = 64,
        [0][1][2][0][RTW89_ACMA][10] = 48,
-       [0][1][2][0][RTW89_FCC][11] = 38,
+       [0][1][2][0][RTW89_CN][10] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][11] = 48,
+       [0][1][2][0][RTW89_IC][11] = 58,
+       [0][1][2][0][RTW89_KCC][11] = 64,
        [0][1][2][0][RTW89_ACMA][11] = 48,
-       [0][1][2][0][RTW89_FCC][12] = 34,
+       [0][1][2][0][RTW89_CN][11] = 46,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][0][RTW89_IC][12] = 44,
+       [0][1][2][0][RTW89_IC][12] = 16,
+       [0][1][2][0][RTW89_KCC][12] = 64,
        [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_FCC][13] = 127,
        [0][1][2][0][RTW89_ETSI][13] = 127,
        [0][1][2][0][RTW89_MKK][13] = 127,
        [0][1][2][0][RTW89_IC][13] = 127,
+       [0][1][2][0][RTW89_KCC][13] = 127,
        [0][1][2][0][RTW89_ACMA][13] = 127,
-       [0][1][2][1][RTW89_FCC][0] = 50,
+       [0][1][2][0][RTW89_CN][13] = 127,
+       [0][1][2][0][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][0] = 60,
+       [0][1][2][1][RTW89_IC][0] = 64,
+       [0][1][2][1][RTW89_KCC][0] = 66,
        [0][1][2][1][RTW89_ACMA][0] = 36,
-       [0][1][2][1][RTW89_FCC][1] = 50,
+       [0][1][2][1][RTW89_CN][0] = 36,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][1] = 60,
+       [0][1][2][1][RTW89_IC][1] = 70,
+       [0][1][2][1][RTW89_KCC][1] = 66,
        [0][1][2][1][RTW89_ACMA][1] = 36,
-       [0][1][2][1][RTW89_FCC][2] = 54,
+       [0][1][2][1][RTW89_CN][1] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][2] = 64,
+       [0][1][2][1][RTW89_IC][2] = 74,
+       [0][1][2][1][RTW89_KCC][2] = 66,
        [0][1][2][1][RTW89_ACMA][2] = 36,
-       [0][1][2][1][RTW89_FCC][3] = 58,
+       [0][1][2][1][RTW89_CN][2] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][3] = 68,
+       [0][1][2][1][RTW89_IC][3] = 78,
+       [0][1][2][1][RTW89_KCC][3] = 66,
        [0][1][2][1][RTW89_ACMA][3] = 36,
-       [0][1][2][1][RTW89_FCC][4] = 64,
+       [0][1][2][1][RTW89_CN][3] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][4] = 74,
+       [0][1][2][1][RTW89_IC][4] = 80,
+       [0][1][2][1][RTW89_KCC][4] = 66,
        [0][1][2][1][RTW89_ACMA][4] = 36,
-       [0][1][2][1][RTW89_FCC][5] = 70,
+       [0][1][2][1][RTW89_CN][4] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][5] = 78,
+       [0][1][2][1][RTW89_IC][5] = 80,
+       [0][1][2][1][RTW89_KCC][5] = 66,
        [0][1][2][1][RTW89_ACMA][5] = 36,
-       [0][1][2][1][RTW89_FCC][6] = 66,
+       [0][1][2][1][RTW89_CN][5] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][6] = 76,
+       [0][1][2][1][RTW89_IC][6] = 80,
+       [0][1][2][1][RTW89_KCC][6] = 66,
        [0][1][2][1][RTW89_ACMA][6] = 36,
-       [0][1][2][1][RTW89_FCC][7] = 58,
+       [0][1][2][1][RTW89_CN][6] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][7] = 68,
+       [0][1][2][1][RTW89_IC][7] = 74,
+       [0][1][2][1][RTW89_KCC][7] = 66,
        [0][1][2][1][RTW89_ACMA][7] = 36,
-       [0][1][2][1][RTW89_FCC][8] = 54,
+       [0][1][2][1][RTW89_CN][7] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][8] = 64,
+       [0][1][2][1][RTW89_IC][8] = 70,
+       [0][1][2][1][RTW89_KCC][8] = 66,
        [0][1][2][1][RTW89_ACMA][8] = 36,
-       [0][1][2][1][RTW89_FCC][9] = 50,
+       [0][1][2][1][RTW89_CN][8] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][9] = 60,
+       [0][1][2][1][RTW89_IC][9] = 66,
+       [0][1][2][1][RTW89_KCC][9] = 64,
        [0][1][2][1][RTW89_ACMA][9] = 36,
-       [0][1][2][1][RTW89_FCC][10] = 50,
+       [0][1][2][1][RTW89_CN][9] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][10] = 60,
+       [0][1][2][1][RTW89_IC][10] = 58,
+       [0][1][2][1][RTW89_KCC][10] = 64,
        [0][1][2][1][RTW89_ACMA][10] = 36,
-       [0][1][2][1][RTW89_FCC][11] = 38,
+       [0][1][2][1][RTW89_CN][10] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][11] = 48,
+       [0][1][2][1][RTW89_IC][11] = 58,
+       [0][1][2][1][RTW89_KCC][11] = 64,
        [0][1][2][1][RTW89_ACMA][11] = 36,
-       [0][1][2][1][RTW89_FCC][12] = 34,
+       [0][1][2][1][RTW89_CN][11] = 34,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][12] = 44,
+       [0][1][2][1][RTW89_IC][12] = 16,
+       [0][1][2][1][RTW89_KCC][12] = 64,
        [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_FCC][13] = 127,
        [0][1][2][1][RTW89_ETSI][13] = 127,
        [0][1][2][1][RTW89_MKK][13] = 127,
        [0][1][2][1][RTW89_IC][13] = 127,
+       [0][1][2][1][RTW89_KCC][13] = 127,
        [0][1][2][1][RTW89_ACMA][13] = 127,
+       [0][1][2][1][RTW89_CN][13] = 127,
+       [0][1][2][1][RTW89_UK][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,
        [1][0][2][0][RTW89_IC][0] = 127,
+       [1][0][2][0][RTW89_KCC][0] = 127,
        [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_FCC][1] = 127,
        [1][0][2][0][RTW89_ETSI][1] = 127,
        [1][0][2][0][RTW89_MKK][1] = 127,
        [1][0][2][0][RTW89_IC][1] = 127,
+       [1][0][2][0][RTW89_KCC][1] = 127,
        [1][0][2][0][RTW89_ACMA][1] = 127,
-       [1][0][2][0][RTW89_FCC][2] = 62,
+       [1][0][2][0][RTW89_CN][1] = 127,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][2] = 72,
+       [1][0][2][0][RTW89_IC][2] = 64,
+       [1][0][2][0][RTW89_KCC][2] = 68,
        [1][0][2][0][RTW89_ACMA][2] = 60,
-       [1][0][2][0][RTW89_FCC][3] = 62,
+       [1][0][2][0][RTW89_CN][2] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][3] = 72,
+       [1][0][2][0][RTW89_IC][3] = 64,
+       [1][0][2][0][RTW89_KCC][3] = 68,
        [1][0][2][0][RTW89_ACMA][3] = 60,
-       [1][0][2][0][RTW89_FCC][4] = 64,
+       [1][0][2][0][RTW89_CN][3] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][4] = 74,
+       [1][0][2][0][RTW89_IC][4] = 68,
+       [1][0][2][0][RTW89_KCC][4] = 68,
        [1][0][2][0][RTW89_ACMA][4] = 60,
-       [1][0][2][0][RTW89_FCC][5] = 64,
+       [1][0][2][0][RTW89_CN][4] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][5] = 74,
+       [1][0][2][0][RTW89_IC][5] = 68,
+       [1][0][2][0][RTW89_KCC][5] = 74,
        [1][0][2][0][RTW89_ACMA][5] = 60,
-       [1][0][2][0][RTW89_FCC][6] = 64,
+       [1][0][2][0][RTW89_CN][5] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][6] = 74,
+       [1][0][2][0][RTW89_IC][6] = 66,
+       [1][0][2][0][RTW89_KCC][6] = 74,
        [1][0][2][0][RTW89_ACMA][6] = 60,
-       [1][0][2][0][RTW89_FCC][7] = 60,
+       [1][0][2][0][RTW89_CN][6] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][7] = 70,
+       [1][0][2][0][RTW89_IC][7] = 62,
+       [1][0][2][0][RTW89_KCC][7] = 74,
        [1][0][2][0][RTW89_ACMA][7] = 60,
-       [1][0][2][0][RTW89_FCC][8] = 60,
+       [1][0][2][0][RTW89_CN][7] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][8] = 70,
+       [1][0][2][0][RTW89_IC][8] = 62,
+       [1][0][2][0][RTW89_KCC][8] = 68,
        [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_FCC][9] = 60,
        [1][0][2][0][RTW89_ETSI][9] = 60,
        [1][0][2][0][RTW89_MKK][9] = 74,
-       [1][0][2][0][RTW89_IC][9] = 70,
+       [1][0][2][0][RTW89_IC][9] = 60,
+       [1][0][2][0][RTW89_KCC][9] = 68,
        [1][0][2][0][RTW89_ACMA][9] = 60,
-       [1][0][2][0][RTW89_FCC][10] = 58,
+       [1][0][2][0][RTW89_CN][9] = 58,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][10] = 68,
+       [1][0][2][0][RTW89_IC][10] = 56,
+       [1][0][2][0][RTW89_KCC][10] = 68,
        [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_FCC][11] = 127,
        [1][0][2][0][RTW89_ETSI][11] = 127,
        [1][0][2][0][RTW89_MKK][11] = 127,
        [1][0][2][0][RTW89_IC][11] = 127,
+       [1][0][2][0][RTW89_KCC][11] = 127,
        [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_FCC][12] = 127,
        [1][0][2][0][RTW89_ETSI][12] = 127,
        [1][0][2][0][RTW89_MKK][12] = 127,
        [1][0][2][0][RTW89_IC][12] = 127,
+       [1][0][2][0][RTW89_KCC][12] = 127,
        [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_FCC][13] = 127,
        [1][0][2][0][RTW89_ETSI][13] = 127,
        [1][0][2][0][RTW89_MKK][13] = 127,
        [1][0][2][0][RTW89_IC][13] = 127,
+       [1][0][2][0][RTW89_KCC][13] = 127,
        [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][1][2][0][RTW89_FCC][0] = 127,
        [1][1][2][0][RTW89_ETSI][0] = 127,
        [1][1][2][0][RTW89_MKK][0] = 127,
        [1][1][2][0][RTW89_IC][0] = 127,
+       [1][1][2][0][RTW89_KCC][0] = 127,
        [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_FCC][1] = 127,
        [1][1][2][0][RTW89_ETSI][1] = 127,
        [1][1][2][0][RTW89_MKK][1] = 127,
        [1][1][2][0][RTW89_IC][1] = 127,
+       [1][1][2][0][RTW89_KCC][1] = 127,
        [1][1][2][0][RTW89_ACMA][1] = 127,
-       [1][1][2][0][RTW89_FCC][2] = 46,
+       [1][1][2][0][RTW89_CN][1] = 127,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][2] = 56,
+       [1][1][2][0][RTW89_IC][2] = 60,
+       [1][1][2][0][RTW89_KCC][2] = 64,
        [1][1][2][0][RTW89_ACMA][2] = 48,
-       [1][1][2][0][RTW89_FCC][3] = 46,
+       [1][1][2][0][RTW89_CN][2] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][3] = 56,
+       [1][1][2][0][RTW89_IC][3] = 60,
+       [1][1][2][0][RTW89_KCC][3] = 64,
        [1][1][2][0][RTW89_ACMA][3] = 48,
-       [1][1][2][0][RTW89_FCC][4] = 50,
+       [1][1][2][0][RTW89_CN][3] = 34,
+       [1][1][2][0][RTW89_UK][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,
        [1][1][2][0][RTW89_IC][4] = 60,
+       [1][1][2][0][RTW89_KCC][4] = 64,
        [1][1][2][0][RTW89_ACMA][4] = 48,
-       [1][1][2][0][RTW89_FCC][5] = 58,
+       [1][1][2][0][RTW89_CN][4] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][5] = 68,
+       [1][1][2][0][RTW89_IC][5] = 60,
+       [1][1][2][0][RTW89_KCC][5] = 66,
        [1][1][2][0][RTW89_ACMA][5] = 48,
-       [1][1][2][0][RTW89_FCC][6] = 50,
+       [1][1][2][0][RTW89_CN][5] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][6] = 60,
+       [1][1][2][0][RTW89_IC][6] = 58,
+       [1][1][2][0][RTW89_KCC][6] = 66,
        [1][1][2][0][RTW89_ACMA][6] = 48,
-       [1][1][2][0][RTW89_FCC][7] = 46,
+       [1][1][2][0][RTW89_CN][6] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][7] = 56,
+       [1][1][2][0][RTW89_IC][7] = 54,
+       [1][1][2][0][RTW89_KCC][7] = 66,
        [1][1][2][0][RTW89_ACMA][7] = 48,
-       [1][1][2][0][RTW89_FCC][8] = 46,
+       [1][1][2][0][RTW89_CN][7] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][8] = 56,
+       [1][1][2][0][RTW89_IC][8] = 54,
+       [1][1][2][0][RTW89_KCC][8] = 64,
        [1][1][2][0][RTW89_ACMA][8] = 48,
-       [1][1][2][0][RTW89_FCC][9] = 34,
+       [1][1][2][0][RTW89_CN][8] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][9] = 44,
+       [1][1][2][0][RTW89_IC][9] = 54,
+       [1][1][2][0][RTW89_KCC][9] = 64,
        [1][1][2][0][RTW89_ACMA][9] = 48,
-       [1][1][2][0][RTW89_FCC][10] = 30,
+       [1][1][2][0][RTW89_CN][9] = 34,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][10] = 40,
+       [1][1][2][0][RTW89_IC][10] = 46,
+       [1][1][2][0][RTW89_KCC][10] = 64,
        [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_FCC][11] = 127,
        [1][1][2][0][RTW89_ETSI][11] = 127,
        [1][1][2][0][RTW89_MKK][11] = 127,
        [1][1][2][0][RTW89_IC][11] = 127,
+       [1][1][2][0][RTW89_KCC][11] = 127,
        [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_FCC][12] = 127,
        [1][1][2][0][RTW89_ETSI][12] = 127,
        [1][1][2][0][RTW89_MKK][12] = 127,
        [1][1][2][0][RTW89_IC][12] = 127,
+       [1][1][2][0][RTW89_KCC][12] = 127,
        [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_FCC][13] = 127,
        [1][1][2][0][RTW89_ETSI][13] = 127,
        [1][1][2][0][RTW89_MKK][13] = 127,
        [1][1][2][0][RTW89_IC][13] = 127,
+       [1][1][2][0][RTW89_KCC][13] = 127,
        [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][1][RTW89_FCC][0] = 127,
        [1][1][2][1][RTW89_ETSI][0] = 127,
        [1][1][2][1][RTW89_MKK][0] = 127,
        [1][1][2][1][RTW89_IC][0] = 127,
+       [1][1][2][1][RTW89_KCC][0] = 127,
        [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_FCC][1] = 127,
        [1][1][2][1][RTW89_ETSI][1] = 127,
        [1][1][2][1][RTW89_MKK][1] = 127,
        [1][1][2][1][RTW89_IC][1] = 127,
+       [1][1][2][1][RTW89_KCC][1] = 127,
        [1][1][2][1][RTW89_ACMA][1] = 127,
-       [1][1][2][1][RTW89_FCC][2] = 46,
+       [1][1][2][1][RTW89_CN][1] = 127,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][2] = 56,
+       [1][1][2][1][RTW89_IC][2] = 60,
+       [1][1][2][1][RTW89_KCC][2] = 64,
        [1][1][2][1][RTW89_ACMA][2] = 36,
-       [1][1][2][1][RTW89_FCC][3] = 46,
+       [1][1][2][1][RTW89_CN][2] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][3] = 56,
+       [1][1][2][1][RTW89_IC][3] = 60,
+       [1][1][2][1][RTW89_KCC][3] = 64,
        [1][1][2][1][RTW89_ACMA][3] = 36,
-       [1][1][2][1][RTW89_FCC][4] = 50,
+       [1][1][2][1][RTW89_CN][3] = 34,
+       [1][1][2][1][RTW89_UK][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,
        [1][1][2][1][RTW89_IC][4] = 60,
+       [1][1][2][1][RTW89_KCC][4] = 64,
        [1][1][2][1][RTW89_ACMA][4] = 36,
-       [1][1][2][1][RTW89_FCC][5] = 58,
+       [1][1][2][1][RTW89_CN][4] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][5] = 68,
+       [1][1][2][1][RTW89_IC][5] = 60,
+       [1][1][2][1][RTW89_KCC][5] = 66,
        [1][1][2][1][RTW89_ACMA][5] = 36,
-       [1][1][2][1][RTW89_FCC][6] = 50,
+       [1][1][2][1][RTW89_CN][5] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][6] = 60,
+       [1][1][2][1][RTW89_IC][6] = 58,
+       [1][1][2][1][RTW89_KCC][6] = 66,
        [1][1][2][1][RTW89_ACMA][6] = 36,
-       [1][1][2][1][RTW89_FCC][7] = 46,
+       [1][1][2][1][RTW89_CN][6] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][7] = 56,
+       [1][1][2][1][RTW89_IC][7] = 54,
+       [1][1][2][1][RTW89_KCC][7] = 66,
        [1][1][2][1][RTW89_ACMA][7] = 36,
-       [1][1][2][1][RTW89_FCC][8] = 46,
+       [1][1][2][1][RTW89_CN][7] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][8] = 56,
+       [1][1][2][1][RTW89_IC][8] = 54,
+       [1][1][2][1][RTW89_KCC][8] = 64,
        [1][1][2][1][RTW89_ACMA][8] = 36,
-       [1][1][2][1][RTW89_FCC][9] = 34,
+       [1][1][2][1][RTW89_CN][8] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][9] = 44,
+       [1][1][2][1][RTW89_IC][9] = 54,
+       [1][1][2][1][RTW89_KCC][9] = 64,
        [1][1][2][1][RTW89_ACMA][9] = 36,
-       [1][1][2][1][RTW89_FCC][10] = 30,
+       [1][1][2][1][RTW89_CN][9] = 34,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][10] = 40,
+       [1][1][2][1][RTW89_IC][10] = 46,
+       [1][1][2][1][RTW89_KCC][10] = 64,
        [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_FCC][11] = 127,
        [1][1][2][1][RTW89_ETSI][11] = 127,
        [1][1][2][1][RTW89_MKK][11] = 127,
        [1][1][2][1][RTW89_IC][11] = 127,
+       [1][1][2][1][RTW89_KCC][11] = 127,
        [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_FCC][12] = 127,
        [1][1][2][1][RTW89_ETSI][12] = 127,
        [1][1][2][1][RTW89_MKK][12] = 127,
        [1][1][2][1][RTW89_IC][12] = 127,
+       [1][1][2][1][RTW89_KCC][12] = 127,
        [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_FCC][13] = 127,
        [1][1][2][1][RTW89_ETSI][13] = 127,
        [1][1][2][1][RTW89_MKK][13] = 127,
        [1][1][2][1][RTW89_IC][13] = 127,
+       [1][1][2][1][RTW89_KCC][13] = 127,
        [1][1][2][1][RTW89_ACMA][13] = 127,
+       [1][1][2][1][RTW89_CN][13] = 127,
+       [1][1][2][1][RTW89_UK][13] = 127,
 };
 
 const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
                                 [RTW89_RS_LMT_NUM][RTW89_BF_NUM]
                                 [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
-       [0][0][1][0][RTW89_WW][0] = 60,
-       [0][0][1][0][RTW89_WW][2] = 60,
-       [0][0][1][0][RTW89_WW][4] = 60,
-       [0][0][1][0][RTW89_WW][6] = 60,
-       [0][0][1][0][RTW89_WW][8] = 60,
-       [0][0][1][0][RTW89_WW][10] = 60,
-       [0][0][1][0][RTW89_WW][12] = 60,
-       [0][0][1][0][RTW89_WW][14] = 60,
-       [0][0][1][0][RTW89_WW][15] = 60,
-       [0][0][1][0][RTW89_WW][17] = 60,
-       [0][0][1][0][RTW89_WW][19] = 60,
-       [0][0][1][0][RTW89_WW][21] = 60,
-       [0][0][1][0][RTW89_WW][23] = 60,
+       [0][0][1][0][RTW89_WW][0] = 50,
+       [0][0][1][0][RTW89_WW][2] = 50,
+       [0][0][1][0][RTW89_WW][4] = 50,
+       [0][0][1][0][RTW89_WW][6] = 50,
+       [0][0][1][0][RTW89_WW][8] = 50,
+       [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] = 60,
-       [0][0][1][0][RTW89_WW][33] = 60,
+       [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][37] = 70,
+       [0][0][1][0][RTW89_WW][37] = 64,
        [0][0][1][0][RTW89_WW][38] = 30,
        [0][0][1][0][RTW89_WW][40] = 30,
        [0][0][1][0][RTW89_WW][42] = 30,
        [0][0][1][0][RTW89_WW][44] = 30,
        [0][0][1][0][RTW89_WW][46] = 30,
-       [0][0][1][0][RTW89_WW][48] = 70,
-       [0][0][1][0][RTW89_WW][50] = 70,
-       [0][0][1][0][RTW89_WW][52] = 70,
-       [0][1][1][0][RTW89_WW][0] = 42,
-       [0][1][1][0][RTW89_WW][2] = 42,
-       [0][1][1][0][RTW89_WW][4] = 42,
-       [0][1][1][0][RTW89_WW][6] = 42,
-       [0][1][1][0][RTW89_WW][8] = 48,
-       [0][1][1][0][RTW89_WW][10] = 48,
-       [0][1][1][0][RTW89_WW][12] = 48,
-       [0][1][1][0][RTW89_WW][14] = 48,
-       [0][1][1][0][RTW89_WW][15] = 48,
-       [0][1][1][0][RTW89_WW][17] = 48,
-       [0][1][1][0][RTW89_WW][19] = 48,
-       [0][1][1][0][RTW89_WW][21] = 48,
-       [0][1][1][0][RTW89_WW][23] = 48,
+       [0][0][1][0][RTW89_WW][48] = 72,
+       [0][0][1][0][RTW89_WW][50] = 72,
+       [0][0][1][0][RTW89_WW][52] = 72,
+       [0][1][1][0][RTW89_WW][0] = 34,
+       [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] = 48,
-       [0][1][1][0][RTW89_WW][33] = 48,
-       [0][1][1][0][RTW89_WW][35] = 48,
-       [0][1][1][0][RTW89_WW][37] = 60,
+       [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][37] = 52,
        [0][1][1][0][RTW89_WW][38] = 18,
-       [0][1][1][0][RTW89_WW][40] = 16,
+       [0][1][1][0][RTW89_WW][40] = 18,
        [0][1][1][0][RTW89_WW][42] = 18,
-       [0][1][1][0][RTW89_WW][44] = 16,
+       [0][1][1][0][RTW89_WW][44] = 18,
        [0][1][1][0][RTW89_WW][46] = 18,
        [0][1][1][0][RTW89_WW][48] = 48,
        [0][1][1][0][RTW89_WW][50] = 48,
        [0][1][1][0][RTW89_WW][52] = 48,
-       [0][0][2][0][RTW89_WW][0] = 62,
-       [0][0][2][0][RTW89_WW][2] = 62,
-       [0][0][2][0][RTW89_WW][4] = 62,
-       [0][0][2][0][RTW89_WW][6] = 60,
-       [0][0][2][0][RTW89_WW][8] = 58,
-       [0][0][2][0][RTW89_WW][10] = 62,
-       [0][0][2][0][RTW89_WW][12] = 62,
-       [0][0][2][0][RTW89_WW][14] = 62,
-       [0][0][2][0][RTW89_WW][15] = 62,
-       [0][0][2][0][RTW89_WW][17] = 62,
-       [0][0][2][0][RTW89_WW][19] = 62,
-       [0][0][2][0][RTW89_WW][21] = 62,
-       [0][0][2][0][RTW89_WW][23] = 62,
+       [0][0][2][0][RTW89_WW][0] = 52,
+       [0][0][2][0][RTW89_WW][2] = 52,
+       [0][0][2][0][RTW89_WW][4] = 52,
+       [0][0][2][0][RTW89_WW][6] = 52,
+       [0][0][2][0][RTW89_WW][8] = 52,
+       [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] = 62,
-       [0][0][2][0][RTW89_WW][33] = 62,
-       [0][0][2][0][RTW89_WW][35] = 62,
-       [0][0][2][0][RTW89_WW][37] = 70,
+       [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][37] = 64,
        [0][0][2][0][RTW89_WW][38] = 30,
        [0][0][2][0][RTW89_WW][40] = 30,
        [0][0][2][0][RTW89_WW][42] = 30,
        [0][0][2][0][RTW89_WW][44] = 30,
        [0][0][2][0][RTW89_WW][46] = 30,
-       [0][0][2][0][RTW89_WW][48] = 70,
-       [0][0][2][0][RTW89_WW][50] = 70,
-       [0][0][2][0][RTW89_WW][52] = 70,
-       [0][1][2][0][RTW89_WW][0] = 44,
-       [0][1][2][0][RTW89_WW][2] = 44,
-       [0][1][2][0][RTW89_WW][4] = 44,
-       [0][1][2][0][RTW89_WW][6] = 44,
-       [0][1][2][0][RTW89_WW][8] = 42,
-       [0][1][2][0][RTW89_WW][10] = 50,
-       [0][1][2][0][RTW89_WW][12] = 50,
-       [0][1][2][0][RTW89_WW][14] = 50,
-       [0][1][2][0][RTW89_WW][15] = 50,
-       [0][1][2][0][RTW89_WW][17] = 50,
-       [0][1][2][0][RTW89_WW][19] = 50,
-       [0][1][2][0][RTW89_WW][21] = 50,
-       [0][1][2][0][RTW89_WW][23] = 50,
+       [0][0][2][0][RTW89_WW][48] = 72,
+       [0][0][2][0][RTW89_WW][50] = 72,
+       [0][0][2][0][RTW89_WW][52] = 72,
+       [0][1][2][0][RTW89_WW][0] = 36,
+       [0][1][2][0][RTW89_WW][2] = 36,
+       [0][1][2][0][RTW89_WW][4] = 36,
+       [0][1][2][0][RTW89_WW][6] = 38,
+       [0][1][2][0][RTW89_WW][8] = 40,
+       [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] = 50,
-       [0][1][2][0][RTW89_WW][33] = 50,
-       [0][1][2][0][RTW89_WW][35] = 50,
-       [0][1][2][0][RTW89_WW][37] = 62,
+       [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][37] = 52,
        [0][1][2][0][RTW89_WW][38] = 18,
        [0][1][2][0][RTW89_WW][40] = 18,
        [0][1][2][0][RTW89_WW][42] = 18,
        [0][1][2][0][RTW89_WW][44] = 18,
        [0][1][2][0][RTW89_WW][46] = 18,
-       [0][1][2][0][RTW89_WW][48] = 50,
+       [0][1][2][0][RTW89_WW][48] = 48,
        [0][1][2][0][RTW89_WW][50] = 50,
-       [0][1][2][0][RTW89_WW][52] = 50,
-       [0][1][2][1][RTW89_WW][0] = 38,
-       [0][1][2][1][RTW89_WW][2] = 38,
-       [0][1][2][1][RTW89_WW][4] = 38,
-       [0][1][2][1][RTW89_WW][6] = 38,
-       [0][1][2][1][RTW89_WW][8] = 38,
-       [0][1][2][1][RTW89_WW][10] = 38,
-       [0][1][2][1][RTW89_WW][12] = 38,
-       [0][1][2][1][RTW89_WW][14] = 38,
-       [0][1][2][1][RTW89_WW][15] = 38,
-       [0][1][2][1][RTW89_WW][17] = 38,
-       [0][1][2][1][RTW89_WW][19] = 38,
-       [0][1][2][1][RTW89_WW][21] = 38,
-       [0][1][2][1][RTW89_WW][23] = 38,
+       [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] = 38,
-       [0][1][2][1][RTW89_WW][33] = 38,
-       [0][1][2][1][RTW89_WW][35] = 38,
-       [0][1][2][1][RTW89_WW][37] = 60,
+       [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][37] = 40,
        [0][1][2][1][RTW89_WW][38] = 6,
        [0][1][2][1][RTW89_WW][40] = 6,
        [0][1][2][1][RTW89_WW][42] = 6,
        [0][1][2][1][RTW89_WW][44] = 6,
        [0][1][2][1][RTW89_WW][46] = 6,
-       [0][1][2][1][RTW89_WW][48] = 50,
+       [0][1][2][1][RTW89_WW][48] = 48,
        [0][1][2][1][RTW89_WW][50] = 50,
-       [0][1][2][1][RTW89_WW][52] = 50,
-       [1][0][2][0][RTW89_WW][1] = 58,
-       [1][0][2][0][RTW89_WW][5] = 66,
-       [1][0][2][0][RTW89_WW][9] = 66,
-       [1][0][2][0][RTW89_WW][13] = 58,
+       [0][1][2][1][RTW89_WW][52] = 48,
+       [1][0][2][0][RTW89_WW][1] = 54,
+       [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] = 66,
-       [1][0][2][0][RTW89_WW][24] = 66,
+       [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] = 66,
-       [1][0][2][0][RTW89_WW][36] = 66,
+       [1][0][2][0][RTW89_WW][32] = 62,
+       [1][0][2][0][RTW89_WW][36] = 64,
        [1][0][2][0][RTW89_WW][39] = 30,
        [1][0][2][0][RTW89_WW][43] = 30,
        [1][0][2][0][RTW89_WW][47] = 68,
        [1][0][2][0][RTW89_WW][51] = 68,
-       [1][1][2][0][RTW89_WW][1] = 48,
-       [1][1][2][0][RTW89_WW][5] = 52,
-       [1][1][2][0][RTW89_WW][9] = 52,
-       [1][1][2][0][RTW89_WW][13] = 52,
-       [1][1][2][0][RTW89_WW][16] = 48,
+       [1][1][2][0][RTW89_WW][1] = 42,
+       [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][36] = 66,
+       [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] = 60,
-       [1][1][2][0][RTW89_WW][51] = 58,
+       [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,
@@ -15035,2082 +29517,3694 @@ const s8 rtw89_8852c_txpwr_lmt_5g[RTW89_5G_BW_NUM][RTW89_NTX_NUM]
        [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][36] = 60,
+       [1][1][2][1][RTW89_WW][36] = 40,
        [1][1][2][1][RTW89_WW][39] = 6,
        [1][1][2][1][RTW89_WW][43] = 6,
-       [1][1][2][1][RTW89_WW][47] = 60,
-       [1][1][2][1][RTW89_WW][51] = 58,
-       [2][0][2][0][RTW89_WW][3] = 56,
-       [2][0][2][0][RTW89_WW][11] = 58,
-       [2][0][2][0][RTW89_WW][18] = 54,
+       [1][1][2][1][RTW89_WW][47] = 62,
+       [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][34] = 60,
        [2][0][2][0][RTW89_WW][41] = 30,
-       [2][0][2][0][RTW89_WW][49] = 56,
-       [2][1][2][0][RTW89_WW][3] = 48,
-       [2][1][2][0][RTW89_WW][11] = 52,
-       [2][1][2][0][RTW89_WW][18] = 48,
-       [2][1][2][0][RTW89_WW][26] = 54,
-       [2][1][2][0][RTW89_WW][34] = 60,
+       [2][0][2][0][RTW89_WW][49] = 62,
+       [2][1][2][0][RTW89_WW][3] = 46,
+       [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][34] = 52,
        [2][1][2][0][RTW89_WW][41] = 18,
-       [2][1][2][0][RTW89_WW][49] = 50,
+       [2][1][2][0][RTW89_WW][49] = 62,
        [2][1][2][1][RTW89_WW][3] = 40,
-       [2][1][2][1][RTW89_WW][11] = 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][34] = 60,
+       [2][1][2][1][RTW89_WW][34] = 40,
        [2][1][2][1][RTW89_WW][41] = 6,
-       [2][1][2][1][RTW89_WW][49] = 50,
-       [3][0][2][0][RTW89_WW][7] = 38,
-       [3][0][2][0][RTW89_WW][22] = 50,
-       [3][0][2][0][RTW89_WW][45] = 0,
-       [3][1][2][0][RTW89_WW][7] = 26,
-       [3][1][2][0][RTW89_WW][22] = 42,
-       [3][1][2][0][RTW89_WW][45] = 0,
-       [3][1][2][1][RTW89_WW][7] = 14,
-       [3][1][2][1][RTW89_WW][22] = 30,
-       [3][1][2][1][RTW89_WW][45] = 0,
-       [0][0][1][0][RTW89_FCC][0] = 70,
+       [2][1][2][1][RTW89_WW][49] = 62,
+       [3][0][2][0][RTW89_WW][7] = 40,
+       [3][0][2][0][RTW89_WW][22] = 42,
+       [3][0][2][0][RTW89_WW][45] = 52,
+       [3][1][2][0][RTW89_WW][7] = 32,
+       [3][1][2][0][RTW89_WW][22] = 36,
+       [3][1][2][0][RTW89_WW][45] = 46,
+       [3][1][2][1][RTW89_WW][7] = 32,
+       [3][1][2][1][RTW89_WW][22] = 36,
+       [3][1][2][1][RTW89_WW][45] = 46,
+       [0][0][1][0][RTW89_FCC][0] = 72,
        [0][0][1][0][RTW89_ETSI][0] = 66,
        [0][0][1][0][RTW89_MKK][0] = 66,
-       [0][0][1][0][RTW89_IC][0] = 62,
-       [0][0][1][0][RTW89_ACMA][0] = 60,
-       [0][0][1][0][RTW89_FCC][2] = 70,
+       [0][0][1][0][RTW89_IC][0] = 60,
+       [0][0][1][0][RTW89_KCC][0] = 52,
+       [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_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] = 62,
-       [0][0][1][0][RTW89_ACMA][2] = 60,
-       [0][0][1][0][RTW89_FCC][4] = 70,
+       [0][0][1][0][RTW89_IC][2] = 60,
+       [0][0][1][0][RTW89_KCC][2] = 52,
+       [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_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] = 62,
-       [0][0][1][0][RTW89_ACMA][4] = 60,
-       [0][0][1][0][RTW89_FCC][6] = 70,
+       [0][0][1][0][RTW89_IC][4] = 60,
+       [0][0][1][0][RTW89_KCC][4] = 52,
+       [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_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] = 62,
-       [0][0][1][0][RTW89_ACMA][6] = 60,
-       [0][0][1][0][RTW89_FCC][8] = 70,
+       [0][0][1][0][RTW89_IC][6] = 58,
+       [0][0][1][0][RTW89_KCC][6] = 62,
+       [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_FCC][8] = 72,
        [0][0][1][0][RTW89_ETSI][8] = 66,
        [0][0][1][0][RTW89_MKK][8] = 66,
-       [0][0][1][0][RTW89_IC][8] = 66,
-       [0][0][1][0][RTW89_ACMA][8] = 60,
-       [0][0][1][0][RTW89_FCC][10] = 70,
+       [0][0][1][0][RTW89_IC][8] = 64,
+       [0][0][1][0][RTW89_KCC][8] = 70,
+       [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_FCC][10] = 72,
        [0][0][1][0][RTW89_ETSI][10] = 66,
        [0][0][1][0][RTW89_MKK][10] = 66,
-       [0][0][1][0][RTW89_IC][10] = 66,
-       [0][0][1][0][RTW89_ACMA][10] = 60,
-       [0][0][1][0][RTW89_FCC][12] = 70,
+       [0][0][1][0][RTW89_IC][10] = 64,
+       [0][0][1][0][RTW89_KCC][10] = 70,
+       [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_FCC][12] = 72,
        [0][0][1][0][RTW89_ETSI][12] = 66,
        [0][0][1][0][RTW89_MKK][12] = 66,
-       [0][0][1][0][RTW89_IC][12] = 66,
-       [0][0][1][0][RTW89_ACMA][12] = 60,
+       [0][0][1][0][RTW89_IC][12] = 64,
+       [0][0][1][0][RTW89_KCC][12] = 66,
+       [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_FCC][14] = 70,
        [0][0][1][0][RTW89_ETSI][14] = 66,
        [0][0][1][0][RTW89_MKK][14] = 66,
-       [0][0][1][0][RTW89_IC][14] = 66,
-       [0][0][1][0][RTW89_ACMA][14] = 60,
-       [0][0][1][0][RTW89_FCC][15] = 68,
+       [0][0][1][0][RTW89_IC][14] = 64,
+       [0][0][1][0][RTW89_KCC][14] = 66,
+       [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_FCC][15] = 72,
        [0][0][1][0][RTW89_ETSI][15] = 66,
        [0][0][1][0][RTW89_MKK][15] = 70,
-       [0][0][1][0][RTW89_IC][15] = 70,
-       [0][0][1][0][RTW89_ACMA][15] = 60,
-       [0][0][1][0][RTW89_FCC][17] = 70,
+       [0][0][1][0][RTW89_IC][15] = 72,
+       [0][0][1][0][RTW89_KCC][15] = 70,
+       [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_FCC][17] = 72,
        [0][0][1][0][RTW89_ETSI][17] = 66,
        [0][0][1][0][RTW89_MKK][17] = 70,
-       [0][0][1][0][RTW89_IC][17] = 70,
-       [0][0][1][0][RTW89_ACMA][17] = 60,
-       [0][0][1][0][RTW89_FCC][19] = 70,
+       [0][0][1][0][RTW89_IC][17] = 72,
+       [0][0][1][0][RTW89_KCC][17] = 70,
+       [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_FCC][19] = 72,
        [0][0][1][0][RTW89_ETSI][19] = 66,
        [0][0][1][0][RTW89_MKK][19] = 70,
-       [0][0][1][0][RTW89_IC][19] = 70,
-       [0][0][1][0][RTW89_ACMA][19] = 60,
-       [0][0][1][0][RTW89_FCC][21] = 70,
+       [0][0][1][0][RTW89_IC][19] = 72,
+       [0][0][1][0][RTW89_KCC][19] = 70,
+       [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_FCC][21] = 72,
        [0][0][1][0][RTW89_ETSI][21] = 66,
        [0][0][1][0][RTW89_MKK][21] = 70,
-       [0][0][1][0][RTW89_IC][21] = 70,
-       [0][0][1][0][RTW89_ACMA][21] = 60,
-       [0][0][1][0][RTW89_FCC][23] = 70,
+       [0][0][1][0][RTW89_IC][21] = 72,
+       [0][0][1][0][RTW89_KCC][21] = 70,
+       [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_FCC][23] = 72,
        [0][0][1][0][RTW89_ETSI][23] = 66,
        [0][0][1][0][RTW89_MKK][23] = 70,
-       [0][0][1][0][RTW89_IC][23] = 70,
-       [0][0][1][0][RTW89_ACMA][23] = 60,
-       [0][0][1][0][RTW89_FCC][25] = 70,
+       [0][0][1][0][RTW89_IC][23] = 72,
+       [0][0][1][0][RTW89_KCC][23] = 70,
+       [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_FCC][25] = 72,
        [0][0][1][0][RTW89_ETSI][25] = 66,
        [0][0][1][0][RTW89_MKK][25] = 70,
        [0][0][1][0][RTW89_IC][25] = 127,
+       [0][0][1][0][RTW89_KCC][25] = 70,
        [0][0][1][0][RTW89_ACMA][25] = 127,
-       [0][0][1][0][RTW89_FCC][27] = 70,
+       [0][0][1][0][RTW89_CN][25] = 127,
+       [0][0][1][0][RTW89_UK][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,
        [0][0][1][0][RTW89_IC][27] = 127,
+       [0][0][1][0][RTW89_KCC][27] = 70,
        [0][0][1][0][RTW89_ACMA][27] = 127,
-       [0][0][1][0][RTW89_FCC][29] = 70,
+       [0][0][1][0][RTW89_CN][27] = 127,
+       [0][0][1][0][RTW89_UK][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,
        [0][0][1][0][RTW89_IC][29] = 127,
+       [0][0][1][0][RTW89_KCC][29] = 70,
        [0][0][1][0][RTW89_ACMA][29] = 127,
-       [0][0][1][0][RTW89_FCC][31] = 70,
+       [0][0][1][0][RTW89_CN][29] = 127,
+       [0][0][1][0][RTW89_UK][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,
-       [0][0][1][0][RTW89_IC][31] = 70,
-       [0][0][1][0][RTW89_ACMA][31] = 60,
-       [0][0][1][0][RTW89_FCC][33] = 70,
+       [0][0][1][0][RTW89_IC][31] = 72,
+       [0][0][1][0][RTW89_KCC][31] = 70,
+       [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_FCC][33] = 72,
        [0][0][1][0][RTW89_ETSI][33] = 66,
        [0][0][1][0][RTW89_MKK][33] = 70,
-       [0][0][1][0][RTW89_IC][33] = 70,
-       [0][0][1][0][RTW89_ACMA][33] = 60,
-       [0][0][1][0][RTW89_FCC][35] = 62,
+       [0][0][1][0][RTW89_IC][33] = 72,
+       [0][0][1][0][RTW89_KCC][33] = 70,
+       [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_FCC][35] = 60,
        [0][0][1][0][RTW89_ETSI][35] = 66,
        [0][0][1][0][RTW89_MKK][35] = 70,
-       [0][0][1][0][RTW89_IC][35] = 70,
-       [0][0][1][0][RTW89_ACMA][35] = 60,
-       [0][0][1][0][RTW89_FCC][37] = 70,
+       [0][0][1][0][RTW89_IC][35] = 60,
+       [0][0][1][0][RTW89_KCC][35] = 70,
+       [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_FCC][37] = 72,
        [0][0][1][0][RTW89_ETSI][37] = 127,
        [0][0][1][0][RTW89_MKK][37] = 70,
-       [0][0][1][0][RTW89_IC][37] = 70,
+       [0][0][1][0][RTW89_IC][37] = 72,
+       [0][0][1][0][RTW89_KCC][37] = 70,
        [0][0][1][0][RTW89_ACMA][37] = 70,
-       [0][0][1][0][RTW89_FCC][38] = 70,
+       [0][0][1][0][RTW89_CN][37] = 127,
+       [0][0][1][0][RTW89_UK][37] = 64,
+       [0][0][1][0][RTW89_FCC][38] = 72,
        [0][0][1][0][RTW89_ETSI][38] = 30,
        [0][0][1][0][RTW89_MKK][38] = 127,
-       [0][0][1][0][RTW89_IC][38] = 70,
+       [0][0][1][0][RTW89_IC][38] = 72,
+       [0][0][1][0][RTW89_KCC][38] = 62,
        [0][0][1][0][RTW89_ACMA][38] = 70,
-       [0][0][1][0][RTW89_FCC][40] = 70,
+       [0][0][1][0][RTW89_CN][38] = 68,
+       [0][0][1][0][RTW89_UK][38] = 64,
+       [0][0][1][0][RTW89_FCC][40] = 72,
        [0][0][1][0][RTW89_ETSI][40] = 30,
        [0][0][1][0][RTW89_MKK][40] = 127,
-       [0][0][1][0][RTW89_IC][40] = 70,
+       [0][0][1][0][RTW89_IC][40] = 72,
+       [0][0][1][0][RTW89_KCC][40] = 62,
        [0][0][1][0][RTW89_ACMA][40] = 70,
-       [0][0][1][0][RTW89_FCC][42] = 70,
+       [0][0][1][0][RTW89_CN][40] = 68,
+       [0][0][1][0][RTW89_UK][40] = 64,
+       [0][0][1][0][RTW89_FCC][42] = 72,
        [0][0][1][0][RTW89_ETSI][42] = 30,
        [0][0][1][0][RTW89_MKK][42] = 127,
-       [0][0][1][0][RTW89_IC][42] = 70,
+       [0][0][1][0][RTW89_IC][42] = 72,
+       [0][0][1][0][RTW89_KCC][42] = 62,
        [0][0][1][0][RTW89_ACMA][42] = 70,
-       [0][0][1][0][RTW89_FCC][44] = 70,
+       [0][0][1][0][RTW89_CN][42] = 68,
+       [0][0][1][0][RTW89_UK][42] = 64,
+       [0][0][1][0][RTW89_FCC][44] = 72,
        [0][0][1][0][RTW89_ETSI][44] = 30,
        [0][0][1][0][RTW89_MKK][44] = 127,
-       [0][0][1][0][RTW89_IC][44] = 70,
+       [0][0][1][0][RTW89_IC][44] = 72,
+       [0][0][1][0][RTW89_KCC][44] = 62,
        [0][0][1][0][RTW89_ACMA][44] = 70,
-       [0][0][1][0][RTW89_FCC][46] = 70,
+       [0][0][1][0][RTW89_CN][44] = 68,
+       [0][0][1][0][RTW89_UK][44] = 64,
+       [0][0][1][0][RTW89_FCC][46] = 72,
        [0][0][1][0][RTW89_ETSI][46] = 30,
        [0][0][1][0][RTW89_MKK][46] = 127,
-       [0][0][1][0][RTW89_IC][46] = 70,
+       [0][0][1][0][RTW89_IC][46] = 72,
+       [0][0][1][0][RTW89_KCC][46] = 62,
        [0][0][1][0][RTW89_ACMA][46] = 70,
-       [0][0][1][0][RTW89_FCC][48] = 70,
+       [0][0][1][0][RTW89_CN][46] = 68,
+       [0][0][1][0][RTW89_UK][46] = 64,
+       [0][0][1][0][RTW89_FCC][48] = 72,
        [0][0][1][0][RTW89_ETSI][48] = 127,
        [0][0][1][0][RTW89_MKK][48] = 127,
        [0][0][1][0][RTW89_IC][48] = 127,
+       [0][0][1][0][RTW89_KCC][48] = 127,
        [0][0][1][0][RTW89_ACMA][48] = 127,
-       [0][0][1][0][RTW89_FCC][50] = 70,
+       [0][0][1][0][RTW89_CN][48] = 127,
+       [0][0][1][0][RTW89_UK][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,
        [0][0][1][0][RTW89_IC][50] = 127,
+       [0][0][1][0][RTW89_KCC][50] = 127,
        [0][0][1][0][RTW89_ACMA][50] = 127,
-       [0][0][1][0][RTW89_FCC][52] = 70,
+       [0][0][1][0][RTW89_CN][50] = 127,
+       [0][0][1][0][RTW89_UK][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,
        [0][0][1][0][RTW89_IC][52] = 127,
+       [0][0][1][0][RTW89_KCC][52] = 127,
        [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][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] = 42,
-       [0][1][1][0][RTW89_ACMA][0] = 48,
+       [0][1][1][0][RTW89_IC][0] = 34,
+       [0][1][1][0][RTW89_KCC][0] = 40,
+       [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_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] = 42,
-       [0][1][1][0][RTW89_ACMA][2] = 48,
+       [0][1][1][0][RTW89_IC][2] = 34,
+       [0][1][1][0][RTW89_KCC][2] = 40,
+       [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_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] = 42,
-       [0][1][1][0][RTW89_ACMA][4] = 48,
+       [0][1][1][0][RTW89_IC][4] = 34,
+       [0][1][1][0][RTW89_KCC][4] = 40,
+       [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_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] = 42,
-       [0][1][1][0][RTW89_ACMA][6] = 48,
-       [0][1][1][0][RTW89_FCC][8] = 60,
+       [0][1][1][0][RTW89_IC][6] = 36,
+       [0][1][1][0][RTW89_KCC][6] = 60,
+       [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_FCC][8] = 62,
        [0][1][1][0][RTW89_ETSI][8] = 54,
        [0][1][1][0][RTW89_MKK][8] = 52,
-       [0][1][1][0][RTW89_IC][8] = 54,
-       [0][1][1][0][RTW89_ACMA][8] = 48,
-       [0][1][1][0][RTW89_FCC][10] = 60,
+       [0][1][1][0][RTW89_IC][8] = 52,
+       [0][1][1][0][RTW89_KCC][8] = 60,
+       [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_FCC][10] = 62,
        [0][1][1][0][RTW89_ETSI][10] = 54,
        [0][1][1][0][RTW89_MKK][10] = 54,
-       [0][1][1][0][RTW89_IC][10] = 54,
-       [0][1][1][0][RTW89_ACMA][10] = 48,
-       [0][1][1][0][RTW89_FCC][12] = 60,
+       [0][1][1][0][RTW89_IC][10] = 52,
+       [0][1][1][0][RTW89_KCC][10] = 60,
+       [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_FCC][12] = 62,
        [0][1][1][0][RTW89_ETSI][12] = 54,
        [0][1][1][0][RTW89_MKK][12] = 54,
-       [0][1][1][0][RTW89_IC][12] = 54,
-       [0][1][1][0][RTW89_ACMA][12] = 48,
+       [0][1][1][0][RTW89_IC][12] = 52,
+       [0][1][1][0][RTW89_KCC][12] = 60,
+       [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_FCC][14] = 60,
        [0][1][1][0][RTW89_ETSI][14] = 54,
        [0][1][1][0][RTW89_MKK][14] = 54,
-       [0][1][1][0][RTW89_IC][14] = 54,
-       [0][1][1][0][RTW89_ACMA][14] = 48,
-       [0][1][1][0][RTW89_FCC][15] = 58,
+       [0][1][1][0][RTW89_IC][14] = 52,
+       [0][1][1][0][RTW89_KCC][14] = 60,
+       [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_FCC][15] = 60,
        [0][1][1][0][RTW89_ETSI][15] = 54,
        [0][1][1][0][RTW89_MKK][15] = 70,
-       [0][1][1][0][RTW89_IC][15] = 68,
-       [0][1][1][0][RTW89_ACMA][15] = 48,
+       [0][1][1][0][RTW89_IC][15] = 60,
+       [0][1][1][0][RTW89_KCC][15] = 60,
+       [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_FCC][17] = 60,
        [0][1][1][0][RTW89_ETSI][17] = 54,
        [0][1][1][0][RTW89_MKK][17] = 70,
-       [0][1][1][0][RTW89_IC][17] = 70,
-       [0][1][1][0][RTW89_ACMA][17] = 48,
+       [0][1][1][0][RTW89_IC][17] = 60,
+       [0][1][1][0][RTW89_KCC][17] = 60,
+       [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_FCC][19] = 60,
        [0][1][1][0][RTW89_ETSI][19] = 54,
        [0][1][1][0][RTW89_MKK][19] = 70,
-       [0][1][1][0][RTW89_IC][19] = 70,
-       [0][1][1][0][RTW89_ACMA][19] = 48,
+       [0][1][1][0][RTW89_IC][19] = 60,
+       [0][1][1][0][RTW89_KCC][19] = 60,
+       [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_FCC][21] = 60,
        [0][1][1][0][RTW89_ETSI][21] = 54,
        [0][1][1][0][RTW89_MKK][21] = 70,
-       [0][1][1][0][RTW89_IC][21] = 70,
-       [0][1][1][0][RTW89_ACMA][21] = 48,
+       [0][1][1][0][RTW89_IC][21] = 60,
+       [0][1][1][0][RTW89_KCC][21] = 60,
+       [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_FCC][23] = 60,
        [0][1][1][0][RTW89_ETSI][23] = 54,
        [0][1][1][0][RTW89_MKK][23] = 70,
-       [0][1][1][0][RTW89_IC][23] = 70,
-       [0][1][1][0][RTW89_ACMA][23] = 48,
+       [0][1][1][0][RTW89_IC][23] = 60,
+       [0][1][1][0][RTW89_KCC][23] = 60,
+       [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_FCC][25] = 60,
        [0][1][1][0][RTW89_ETSI][25] = 54,
        [0][1][1][0][RTW89_MKK][25] = 70,
        [0][1][1][0][RTW89_IC][25] = 127,
+       [0][1][1][0][RTW89_KCC][25] = 60,
        [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_FCC][27] = 60,
        [0][1][1][0][RTW89_ETSI][27] = 54,
        [0][1][1][0][RTW89_MKK][27] = 70,
        [0][1][1][0][RTW89_IC][27] = 127,
+       [0][1][1][0][RTW89_KCC][27] = 60,
        [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_FCC][29] = 60,
        [0][1][1][0][RTW89_ETSI][29] = 54,
        [0][1][1][0][RTW89_MKK][29] = 70,
        [0][1][1][0][RTW89_IC][29] = 127,
+       [0][1][1][0][RTW89_KCC][29] = 60,
        [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_FCC][31] = 60,
        [0][1][1][0][RTW89_ETSI][31] = 54,
        [0][1][1][0][RTW89_MKK][31] = 70,
-       [0][1][1][0][RTW89_IC][31] = 70,
-       [0][1][1][0][RTW89_ACMA][31] = 48,
+       [0][1][1][0][RTW89_IC][31] = 60,
+       [0][1][1][0][RTW89_KCC][31] = 58,
+       [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_FCC][33] = 60,
        [0][1][1][0][RTW89_ETSI][33] = 54,
        [0][1][1][0][RTW89_MKK][33] = 70,
-       [0][1][1][0][RTW89_IC][33] = 70,
-       [0][1][1][0][RTW89_ACMA][33] = 48,
-       [0][1][1][0][RTW89_FCC][35] = 58,
+       [0][1][1][0][RTW89_IC][33] = 60,
+       [0][1][1][0][RTW89_KCC][33] = 58,
+       [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_FCC][35] = 52,
        [0][1][1][0][RTW89_ETSI][35] = 54,
        [0][1][1][0][RTW89_MKK][35] = 70,
-       [0][1][1][0][RTW89_IC][35] = 68,
-       [0][1][1][0][RTW89_ACMA][35] = 48,
-       [0][1][1][0][RTW89_FCC][37] = 60,
+       [0][1][1][0][RTW89_IC][35] = 52,
+       [0][1][1][0][RTW89_KCC][35] = 58,
+       [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_FCC][37] = 62,
        [0][1][1][0][RTW89_ETSI][37] = 127,
        [0][1][1][0][RTW89_MKK][37] = 70,
-       [0][1][1][0][RTW89_IC][37] = 70,
-       [0][1][1][0][RTW89_ACMA][37] = 70,
-       [0][1][1][0][RTW89_FCC][38] = 70,
+       [0][1][1][0][RTW89_IC][37] = 62,
+       [0][1][1][0][RTW89_KCC][37] = 58,
+       [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_FCC][38] = 72,
        [0][1][1][0][RTW89_ETSI][38] = 18,
        [0][1][1][0][RTW89_MKK][38] = 127,
-       [0][1][1][0][RTW89_IC][38] = 70,
+       [0][1][1][0][RTW89_IC][38] = 72,
+       [0][1][1][0][RTW89_KCC][38] = 60,
        [0][1][1][0][RTW89_ACMA][38] = 70,
-       [0][1][1][0][RTW89_FCC][40] = 70,
+       [0][1][1][0][RTW89_CN][38] = 64,
+       [0][1][1][0][RTW89_UK][38] = 52,
+       [0][1][1][0][RTW89_FCC][40] = 72,
        [0][1][1][0][RTW89_ETSI][40] = 18,
        [0][1][1][0][RTW89_MKK][40] = 127,
-       [0][1][1][0][RTW89_IC][40] = 70,
-       [0][1][1][0][RTW89_ACMA][40] = 16,
-       [0][1][1][0][RTW89_FCC][42] = 70,
+       [0][1][1][0][RTW89_IC][40] = 72,
+       [0][1][1][0][RTW89_KCC][40] = 60,
+       [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_FCC][42] = 72,
        [0][1][1][0][RTW89_ETSI][42] = 18,
        [0][1][1][0][RTW89_MKK][42] = 127,
-       [0][1][1][0][RTW89_IC][42] = 70,
+       [0][1][1][0][RTW89_IC][42] = 72,
+       [0][1][1][0][RTW89_KCC][42] = 60,
        [0][1][1][0][RTW89_ACMA][42] = 70,
-       [0][1][1][0][RTW89_FCC][44] = 70,
+       [0][1][1][0][RTW89_CN][42] = 64,
+       [0][1][1][0][RTW89_UK][42] = 52,
+       [0][1][1][0][RTW89_FCC][44] = 72,
        [0][1][1][0][RTW89_ETSI][44] = 18,
        [0][1][1][0][RTW89_MKK][44] = 127,
-       [0][1][1][0][RTW89_IC][44] = 70,
-       [0][1][1][0][RTW89_ACMA][44] = 16,
-       [0][1][1][0][RTW89_FCC][46] = 70,
+       [0][1][1][0][RTW89_IC][44] = 72,
+       [0][1][1][0][RTW89_KCC][44] = 60,
+       [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_FCC][46] = 72,
        [0][1][1][0][RTW89_ETSI][46] = 18,
        [0][1][1][0][RTW89_MKK][46] = 127,
-       [0][1][1][0][RTW89_IC][46] = 70,
+       [0][1][1][0][RTW89_IC][46] = 72,
+       [0][1][1][0][RTW89_KCC][46] = 60,
        [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_FCC][48] = 48,
        [0][1][1][0][RTW89_ETSI][48] = 127,
        [0][1][1][0][RTW89_MKK][48] = 127,
        [0][1][1][0][RTW89_IC][48] = 127,
+       [0][1][1][0][RTW89_KCC][48] = 127,
        [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_FCC][50] = 48,
        [0][1][1][0][RTW89_ETSI][50] = 127,
        [0][1][1][0][RTW89_MKK][50] = 127,
        [0][1][1][0][RTW89_IC][50] = 127,
+       [0][1][1][0][RTW89_KCC][50] = 127,
        [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_FCC][52] = 48,
        [0][1][1][0][RTW89_ETSI][52] = 127,
        [0][1][1][0][RTW89_MKK][52] = 127,
        [0][1][1][0][RTW89_IC][52] = 127,
+       [0][1][1][0][RTW89_KCC][52] = 127,
        [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][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] = 66,
-       [0][0][2][0][RTW89_ACMA][0] = 62,
-       [0][0][2][0][RTW89_FCC][2] = 70,
+       [0][0][2][0][RTW89_IC][0] = 60,
+       [0][0][2][0][RTW89_KCC][0] = 54,
+       [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_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] = 66,
-       [0][0][2][0][RTW89_ACMA][2] = 62,
-       [0][0][2][0][RTW89_FCC][4] = 70,
+       [0][0][2][0][RTW89_IC][2] = 60,
+       [0][0][2][0][RTW89_KCC][2] = 54,
+       [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_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] = 66,
-       [0][0][2][0][RTW89_ACMA][4] = 62,
-       [0][0][2][0][RTW89_FCC][6] = 70,
+       [0][0][2][0][RTW89_IC][4] = 60,
+       [0][0][2][0][RTW89_KCC][4] = 54,
+       [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_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] = 66,
-       [0][0][2][0][RTW89_ACMA][6] = 62,
-       [0][0][2][0][RTW89_FCC][8] = 70,
+       [0][0][2][0][RTW89_IC][6] = 60,
+       [0][0][2][0][RTW89_KCC][6] = 68,
+       [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_FCC][8] = 72,
        [0][0][2][0][RTW89_ETSI][8] = 66,
        [0][0][2][0][RTW89_MKK][8] = 58,
-       [0][0][2][0][RTW89_IC][8] = 66,
-       [0][0][2][0][RTW89_ACMA][8] = 62,
-       [0][0][2][0][RTW89_FCC][10] = 70,
+       [0][0][2][0][RTW89_IC][8] = 64,
+       [0][0][2][0][RTW89_KCC][8] = 70,
+       [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_FCC][10] = 72,
        [0][0][2][0][RTW89_ETSI][10] = 66,
        [0][0][2][0][RTW89_MKK][10] = 70,
-       [0][0][2][0][RTW89_IC][10] = 66,
-       [0][0][2][0][RTW89_ACMA][10] = 62,
-       [0][0][2][0][RTW89_FCC][12] = 70,
+       [0][0][2][0][RTW89_IC][10] = 64,
+       [0][0][2][0][RTW89_KCC][10] = 70,
+       [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_FCC][12] = 72,
        [0][0][2][0][RTW89_ETSI][12] = 66,
        [0][0][2][0][RTW89_MKK][12] = 70,
-       [0][0][2][0][RTW89_IC][12] = 66,
-       [0][0][2][0][RTW89_ACMA][12] = 62,
-       [0][0][2][0][RTW89_FCC][14] = 70,
+       [0][0][2][0][RTW89_IC][12] = 64,
+       [0][0][2][0][RTW89_KCC][12] = 66,
+       [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_FCC][14] = 68,
        [0][0][2][0][RTW89_ETSI][14] = 66,
        [0][0][2][0][RTW89_MKK][14] = 70,
-       [0][0][2][0][RTW89_IC][14] = 66,
-       [0][0][2][0][RTW89_ACMA][14] = 62,
-       [0][0][2][0][RTW89_FCC][15] = 66,
+       [0][0][2][0][RTW89_IC][14] = 64,
+       [0][0][2][0][RTW89_KCC][14] = 66,
+       [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_FCC][15] = 70,
        [0][0][2][0][RTW89_ETSI][15] = 66,
        [0][0][2][0][RTW89_MKK][15] = 70,
        [0][0][2][0][RTW89_IC][15] = 70,
-       [0][0][2][0][RTW89_ACMA][15] = 62,
-       [0][0][2][0][RTW89_FCC][17] = 70,
+       [0][0][2][0][RTW89_KCC][15] = 70,
+       [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_FCC][17] = 72,
        [0][0][2][0][RTW89_ETSI][17] = 66,
        [0][0][2][0][RTW89_MKK][17] = 70,
-       [0][0][2][0][RTW89_IC][17] = 70,
-       [0][0][2][0][RTW89_ACMA][17] = 62,
-       [0][0][2][0][RTW89_FCC][19] = 70,
+       [0][0][2][0][RTW89_IC][17] = 72,
+       [0][0][2][0][RTW89_KCC][17] = 70,
+       [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_FCC][19] = 72,
        [0][0][2][0][RTW89_ETSI][19] = 66,
        [0][0][2][0][RTW89_MKK][19] = 70,
-       [0][0][2][0][RTW89_IC][19] = 70,
-       [0][0][2][0][RTW89_ACMA][19] = 62,
-       [0][0][2][0][RTW89_FCC][21] = 70,
+       [0][0][2][0][RTW89_IC][19] = 72,
+       [0][0][2][0][RTW89_KCC][19] = 70,
+       [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_FCC][21] = 72,
        [0][0][2][0][RTW89_ETSI][21] = 66,
        [0][0][2][0][RTW89_MKK][21] = 70,
-       [0][0][2][0][RTW89_IC][21] = 70,
-       [0][0][2][0][RTW89_ACMA][21] = 62,
-       [0][0][2][0][RTW89_FCC][23] = 70,
+       [0][0][2][0][RTW89_IC][21] = 72,
+       [0][0][2][0][RTW89_KCC][21] = 70,
+       [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_FCC][23] = 72,
        [0][0][2][0][RTW89_ETSI][23] = 66,
        [0][0][2][0][RTW89_MKK][23] = 70,
-       [0][0][2][0][RTW89_IC][23] = 70,
-       [0][0][2][0][RTW89_ACMA][23] = 62,
-       [0][0][2][0][RTW89_FCC][25] = 70,
+       [0][0][2][0][RTW89_IC][23] = 72,
+       [0][0][2][0][RTW89_KCC][23] = 70,
+       [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_FCC][25] = 72,
        [0][0][2][0][RTW89_ETSI][25] = 66,
        [0][0][2][0][RTW89_MKK][25] = 70,
        [0][0][2][0][RTW89_IC][25] = 127,
+       [0][0][2][0][RTW89_KCC][25] = 70,
        [0][0][2][0][RTW89_ACMA][25] = 127,
-       [0][0][2][0][RTW89_FCC][27] = 70,
+       [0][0][2][0][RTW89_CN][25] = 127,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][27] = 127,
+       [0][0][2][0][RTW89_KCC][27] = 70,
        [0][0][2][0][RTW89_ACMA][27] = 127,
-       [0][0][2][0][RTW89_FCC][29] = 70,
+       [0][0][2][0][RTW89_CN][27] = 127,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][29] = 127,
+       [0][0][2][0][RTW89_KCC][29] = 70,
        [0][0][2][0][RTW89_ACMA][29] = 127,
-       [0][0][2][0][RTW89_FCC][31] = 70,
+       [0][0][2][0][RTW89_CN][29] = 127,
+       [0][0][2][0][RTW89_UK][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,
-       [0][0][2][0][RTW89_IC][31] = 70,
-       [0][0][2][0][RTW89_ACMA][31] = 62,
-       [0][0][2][0][RTW89_FCC][33] = 70,
+       [0][0][2][0][RTW89_IC][31] = 72,
+       [0][0][2][0][RTW89_KCC][31] = 70,
+       [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_FCC][33] = 72,
        [0][0][2][0][RTW89_ETSI][33] = 66,
        [0][0][2][0][RTW89_MKK][33] = 70,
-       [0][0][2][0][RTW89_IC][33] = 70,
-       [0][0][2][0][RTW89_ACMA][33] = 62,
-       [0][0][2][0][RTW89_FCC][35] = 62,
+       [0][0][2][0][RTW89_IC][33] = 72,
+       [0][0][2][0][RTW89_KCC][33] = 70,
+       [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_FCC][35] = 56,
        [0][0][2][0][RTW89_ETSI][35] = 66,
        [0][0][2][0][RTW89_MKK][35] = 70,
-       [0][0][2][0][RTW89_IC][35] = 70,
-       [0][0][2][0][RTW89_ACMA][35] = 62,
-       [0][0][2][0][RTW89_FCC][37] = 70,
+       [0][0][2][0][RTW89_IC][35] = 56,
+       [0][0][2][0][RTW89_KCC][35] = 70,
+       [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_FCC][37] = 72,
        [0][0][2][0][RTW89_ETSI][37] = 127,
        [0][0][2][0][RTW89_MKK][37] = 70,
-       [0][0][2][0][RTW89_IC][37] = 70,
+       [0][0][2][0][RTW89_IC][37] = 72,
+       [0][0][2][0][RTW89_KCC][37] = 70,
        [0][0][2][0][RTW89_ACMA][37] = 70,
-       [0][0][2][0][RTW89_FCC][38] = 70,
+       [0][0][2][0][RTW89_CN][37] = 127,
+       [0][0][2][0][RTW89_UK][37] = 64,
+       [0][0][2][0][RTW89_FCC][38] = 72,
        [0][0][2][0][RTW89_ETSI][38] = 30,
        [0][0][2][0][RTW89_MKK][38] = 127,
-       [0][0][2][0][RTW89_IC][38] = 70,
+       [0][0][2][0][RTW89_IC][38] = 72,
+       [0][0][2][0][RTW89_KCC][38] = 58,
        [0][0][2][0][RTW89_ACMA][38] = 70,
-       [0][0][2][0][RTW89_FCC][40] = 70,
+       [0][0][2][0][RTW89_CN][38] = 68,
+       [0][0][2][0][RTW89_UK][38] = 64,
+       [0][0][2][0][RTW89_FCC][40] = 72,
        [0][0][2][0][RTW89_ETSI][40] = 30,
        [0][0][2][0][RTW89_MKK][40] = 127,
-       [0][0][2][0][RTW89_IC][40] = 70,
+       [0][0][2][0][RTW89_IC][40] = 72,
+       [0][0][2][0][RTW89_KCC][40] = 58,
        [0][0][2][0][RTW89_ACMA][40] = 70,
-       [0][0][2][0][RTW89_FCC][42] = 70,
+       [0][0][2][0][RTW89_CN][40] = 68,
+       [0][0][2][0][RTW89_UK][40] = 64,
+       [0][0][2][0][RTW89_FCC][42] = 72,
        [0][0][2][0][RTW89_ETSI][42] = 30,
        [0][0][2][0][RTW89_MKK][42] = 127,
-       [0][0][2][0][RTW89_IC][42] = 70,
+       [0][0][2][0][RTW89_IC][42] = 72,
+       [0][0][2][0][RTW89_KCC][42] = 58,
        [0][0][2][0][RTW89_ACMA][42] = 70,
-       [0][0][2][0][RTW89_FCC][44] = 70,
+       [0][0][2][0][RTW89_CN][42] = 68,
+       [0][0][2][0][RTW89_UK][42] = 64,
+       [0][0][2][0][RTW89_FCC][44] = 72,
        [0][0][2][0][RTW89_ETSI][44] = 30,
        [0][0][2][0][RTW89_MKK][44] = 127,
-       [0][0][2][0][RTW89_IC][44] = 70,
+       [0][0][2][0][RTW89_IC][44] = 72,
+       [0][0][2][0][RTW89_KCC][44] = 58,
        [0][0][2][0][RTW89_ACMA][44] = 70,
-       [0][0][2][0][RTW89_FCC][46] = 70,
+       [0][0][2][0][RTW89_CN][44] = 68,
+       [0][0][2][0][RTW89_UK][44] = 64,
+       [0][0][2][0][RTW89_FCC][46] = 72,
        [0][0][2][0][RTW89_ETSI][46] = 30,
        [0][0][2][0][RTW89_MKK][46] = 127,
-       [0][0][2][0][RTW89_IC][46] = 70,
+       [0][0][2][0][RTW89_IC][46] = 72,
+       [0][0][2][0][RTW89_KCC][46] = 58,
        [0][0][2][0][RTW89_ACMA][46] = 70,
-       [0][0][2][0][RTW89_FCC][48] = 70,
+       [0][0][2][0][RTW89_CN][46] = 68,
+       [0][0][2][0][RTW89_UK][46] = 64,
+       [0][0][2][0][RTW89_FCC][48] = 72,
        [0][0][2][0][RTW89_ETSI][48] = 127,
        [0][0][2][0][RTW89_MKK][48] = 127,
        [0][0][2][0][RTW89_IC][48] = 127,
+       [0][0][2][0][RTW89_KCC][48] = 127,
        [0][0][2][0][RTW89_ACMA][48] = 127,
-       [0][0][2][0][RTW89_FCC][50] = 70,
+       [0][0][2][0][RTW89_CN][48] = 127,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][50] = 127,
+       [0][0][2][0][RTW89_KCC][50] = 127,
        [0][0][2][0][RTW89_ACMA][50] = 127,
-       [0][0][2][0][RTW89_FCC][52] = 70,
+       [0][0][2][0][RTW89_CN][50] = 127,
+       [0][0][2][0][RTW89_UK][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,
        [0][0][2][0][RTW89_IC][52] = 127,
+       [0][0][2][0][RTW89_KCC][52] = 127,
        [0][0][2][0][RTW89_ACMA][52] = 127,
-       [0][1][2][0][RTW89_FCC][0] = 62,
+       [0][0][2][0][RTW89_CN][52] = 127,
+       [0][0][2][0][RTW89_UK][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] = 44,
-       [0][1][2][0][RTW89_ACMA][0] = 50,
+       [0][1][2][0][RTW89_IC][0] = 36,
+       [0][1][2][0][RTW89_KCC][0] = 40,
+       [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_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] = 44,
-       [0][1][2][0][RTW89_ACMA][2] = 50,
+       [0][1][2][0][RTW89_IC][2] = 36,
+       [0][1][2][0][RTW89_KCC][2] = 40,
+       [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_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] = 44,
-       [0][1][2][0][RTW89_ACMA][4] = 50,
+       [0][1][2][0][RTW89_IC][4] = 36,
+       [0][1][2][0][RTW89_KCC][4] = 40,
+       [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_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] = 44,
-       [0][1][2][0][RTW89_ACMA][6] = 50,
+       [0][1][2][0][RTW89_IC][6] = 38,
+       [0][1][2][0][RTW89_KCC][6] = 64,
+       [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_FCC][8] = 62,
        [0][1][2][0][RTW89_ETSI][8] = 54,
        [0][1][2][0][RTW89_MKK][8] = 42,
-       [0][1][2][0][RTW89_IC][8] = 54,
-       [0][1][2][0][RTW89_ACMA][8] = 50,
+       [0][1][2][0][RTW89_IC][8] = 52,
+       [0][1][2][0][RTW89_KCC][8] = 62,
+       [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_FCC][10] = 62,
        [0][1][2][0][RTW89_ETSI][10] = 54,
        [0][1][2][0][RTW89_MKK][10] = 54,
-       [0][1][2][0][RTW89_IC][10] = 54,
-       [0][1][2][0][RTW89_ACMA][10] = 50,
+       [0][1][2][0][RTW89_IC][10] = 52,
+       [0][1][2][0][RTW89_KCC][10] = 62,
+       [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_FCC][12] = 62,
        [0][1][2][0][RTW89_ETSI][12] = 54,
        [0][1][2][0][RTW89_MKK][12] = 54,
-       [0][1][2][0][RTW89_IC][12] = 54,
-       [0][1][2][0][RTW89_ACMA][12] = 50,
+       [0][1][2][0][RTW89_IC][12] = 52,
+       [0][1][2][0][RTW89_KCC][12] = 62,
+       [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_FCC][14] = 62,
        [0][1][2][0][RTW89_ETSI][14] = 54,
        [0][1][2][0][RTW89_MKK][14] = 54,
-       [0][1][2][0][RTW89_IC][14] = 54,
-       [0][1][2][0][RTW89_ACMA][14] = 50,
+       [0][1][2][0][RTW89_IC][14] = 52,
+       [0][1][2][0][RTW89_KCC][14] = 62,
+       [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_FCC][15] = 60,
        [0][1][2][0][RTW89_ETSI][15] = 54,
        [0][1][2][0][RTW89_MKK][15] = 68,
-       [0][1][2][0][RTW89_IC][15] = 70,
-       [0][1][2][0][RTW89_ACMA][15] = 50,
+       [0][1][2][0][RTW89_IC][15] = 60,
+       [0][1][2][0][RTW89_KCC][15] = 64,
+       [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_FCC][17] = 62,
        [0][1][2][0][RTW89_ETSI][17] = 54,
        [0][1][2][0][RTW89_MKK][17] = 68,
-       [0][1][2][0][RTW89_IC][17] = 70,
-       [0][1][2][0][RTW89_ACMA][17] = 50,
+       [0][1][2][0][RTW89_IC][17] = 62,
+       [0][1][2][0][RTW89_KCC][17] = 64,
+       [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_FCC][19] = 62,
        [0][1][2][0][RTW89_ETSI][19] = 54,
        [0][1][2][0][RTW89_MKK][19] = 68,
-       [0][1][2][0][RTW89_IC][19] = 70,
-       [0][1][2][0][RTW89_ACMA][19] = 50,
+       [0][1][2][0][RTW89_IC][19] = 62,
+       [0][1][2][0][RTW89_KCC][19] = 64,
+       [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_FCC][21] = 62,
        [0][1][2][0][RTW89_ETSI][21] = 54,
        [0][1][2][0][RTW89_MKK][21] = 68,
-       [0][1][2][0][RTW89_IC][21] = 70,
-       [0][1][2][0][RTW89_ACMA][21] = 50,
+       [0][1][2][0][RTW89_IC][21] = 62,
+       [0][1][2][0][RTW89_KCC][21] = 64,
+       [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_FCC][23] = 62,
        [0][1][2][0][RTW89_ETSI][23] = 54,
        [0][1][2][0][RTW89_MKK][23] = 68,
-       [0][1][2][0][RTW89_IC][23] = 70,
-       [0][1][2][0][RTW89_ACMA][23] = 50,
+       [0][1][2][0][RTW89_IC][23] = 62,
+       [0][1][2][0][RTW89_KCC][23] = 64,
+       [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_FCC][25] = 62,
        [0][1][2][0][RTW89_ETSI][25] = 54,
        [0][1][2][0][RTW89_MKK][25] = 68,
        [0][1][2][0][RTW89_IC][25] = 127,
+       [0][1][2][0][RTW89_KCC][25] = 64,
        [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_FCC][27] = 62,
        [0][1][2][0][RTW89_ETSI][27] = 54,
        [0][1][2][0][RTW89_MKK][27] = 68,
        [0][1][2][0][RTW89_IC][27] = 127,
+       [0][1][2][0][RTW89_KCC][27] = 64,
        [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_FCC][29] = 62,
        [0][1][2][0][RTW89_ETSI][29] = 54,
        [0][1][2][0][RTW89_MKK][29] = 68,
        [0][1][2][0][RTW89_IC][29] = 127,
+       [0][1][2][0][RTW89_KCC][29] = 64,
        [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_FCC][31] = 62,
        [0][1][2][0][RTW89_ETSI][31] = 54,
        [0][1][2][0][RTW89_MKK][31] = 68,
-       [0][1][2][0][RTW89_IC][31] = 70,
-       [0][1][2][0][RTW89_ACMA][31] = 50,
+       [0][1][2][0][RTW89_IC][31] = 62,
+       [0][1][2][0][RTW89_KCC][31] = 62,
+       [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_FCC][33] = 62,
        [0][1][2][0][RTW89_ETSI][33] = 54,
        [0][1][2][0][RTW89_MKK][33] = 68,
-       [0][1][2][0][RTW89_IC][33] = 70,
-       [0][1][2][0][RTW89_ACMA][33] = 50,
-       [0][1][2][0][RTW89_FCC][35] = 58,
+       [0][1][2][0][RTW89_IC][33] = 62,
+       [0][1][2][0][RTW89_KCC][33] = 62,
+       [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_FCC][35] = 46,
        [0][1][2][0][RTW89_ETSI][35] = 54,
        [0][1][2][0][RTW89_MKK][35] = 68,
-       [0][1][2][0][RTW89_IC][35] = 68,
-       [0][1][2][0][RTW89_ACMA][35] = 50,
-       [0][1][2][0][RTW89_FCC][37] = 62,
+       [0][1][2][0][RTW89_IC][35] = 46,
+       [0][1][2][0][RTW89_KCC][35] = 62,
+       [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_FCC][37] = 64,
        [0][1][2][0][RTW89_ETSI][37] = 127,
        [0][1][2][0][RTW89_MKK][37] = 68,
-       [0][1][2][0][RTW89_IC][37] = 70,
-       [0][1][2][0][RTW89_ACMA][37] = 70,
-       [0][1][2][0][RTW89_FCC][38] = 70,
+       [0][1][2][0][RTW89_IC][37] = 64,
+       [0][1][2][0][RTW89_KCC][37] = 62,
+       [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_FCC][38] = 72,
        [0][1][2][0][RTW89_ETSI][38] = 18,
        [0][1][2][0][RTW89_MKK][38] = 127,
-       [0][1][2][0][RTW89_IC][38] = 70,
+       [0][1][2][0][RTW89_IC][38] = 72,
+       [0][1][2][0][RTW89_KCC][38] = 56,
        [0][1][2][0][RTW89_ACMA][38] = 70,
-       [0][1][2][0][RTW89_FCC][40] = 70,
+       [0][1][2][0][RTW89_CN][38] = 68,
+       [0][1][2][0][RTW89_UK][38] = 52,
+       [0][1][2][0][RTW89_FCC][40] = 72,
        [0][1][2][0][RTW89_ETSI][40] = 18,
        [0][1][2][0][RTW89_MKK][40] = 127,
-       [0][1][2][0][RTW89_IC][40] = 70,
+       [0][1][2][0][RTW89_IC][40] = 72,
+       [0][1][2][0][RTW89_KCC][40] = 56,
        [0][1][2][0][RTW89_ACMA][40] = 70,
-       [0][1][2][0][RTW89_FCC][42] = 70,
+       [0][1][2][0][RTW89_CN][40] = 68,
+       [0][1][2][0][RTW89_UK][40] = 52,
+       [0][1][2][0][RTW89_FCC][42] = 72,
        [0][1][2][0][RTW89_ETSI][42] = 18,
        [0][1][2][0][RTW89_MKK][42] = 127,
-       [0][1][2][0][RTW89_IC][42] = 70,
+       [0][1][2][0][RTW89_IC][42] = 72,
+       [0][1][2][0][RTW89_KCC][42] = 56,
        [0][1][2][0][RTW89_ACMA][42] = 70,
-       [0][1][2][0][RTW89_FCC][44] = 70,
+       [0][1][2][0][RTW89_CN][42] = 68,
+       [0][1][2][0][RTW89_UK][42] = 52,
+       [0][1][2][0][RTW89_FCC][44] = 72,
        [0][1][2][0][RTW89_ETSI][44] = 18,
        [0][1][2][0][RTW89_MKK][44] = 127,
-       [0][1][2][0][RTW89_IC][44] = 70,
+       [0][1][2][0][RTW89_IC][44] = 72,
+       [0][1][2][0][RTW89_KCC][44] = 56,
        [0][1][2][0][RTW89_ACMA][44] = 70,
-       [0][1][2][0][RTW89_FCC][46] = 70,
+       [0][1][2][0][RTW89_CN][44] = 68,
+       [0][1][2][0][RTW89_UK][44] = 52,
+       [0][1][2][0][RTW89_FCC][46] = 72,
        [0][1][2][0][RTW89_ETSI][46] = 18,
        [0][1][2][0][RTW89_MKK][46] = 127,
-       [0][1][2][0][RTW89_IC][46] = 70,
+       [0][1][2][0][RTW89_IC][46] = 72,
+       [0][1][2][0][RTW89_KCC][46] = 56,
        [0][1][2][0][RTW89_ACMA][46] = 70,
-       [0][1][2][0][RTW89_FCC][48] = 50,
+       [0][1][2][0][RTW89_CN][46] = 68,
+       [0][1][2][0][RTW89_UK][46] = 52,
+       [0][1][2][0][RTW89_FCC][48] = 48,
        [0][1][2][0][RTW89_ETSI][48] = 127,
        [0][1][2][0][RTW89_MKK][48] = 127,
        [0][1][2][0][RTW89_IC][48] = 127,
+       [0][1][2][0][RTW89_KCC][48] = 127,
        [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_FCC][50] = 50,
        [0][1][2][0][RTW89_ETSI][50] = 127,
        [0][1][2][0][RTW89_MKK][50] = 127,
        [0][1][2][0][RTW89_IC][50] = 127,
+       [0][1][2][0][RTW89_KCC][50] = 127,
        [0][1][2][0][RTW89_ACMA][50] = 127,
-       [0][1][2][0][RTW89_FCC][52] = 50,
+       [0][1][2][0][RTW89_CN][50] = 127,
+       [0][1][2][0][RTW89_UK][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,
        [0][1][2][0][RTW89_IC][52] = 127,
+       [0][1][2][0][RTW89_KCC][52] = 127,
        [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][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] = 42,
-       [0][1][2][1][RTW89_ACMA][0] = 38,
-       [0][1][2][1][RTW89_FCC][2] = 60,
+       [0][1][2][1][RTW89_IC][0] = 40,
+       [0][1][2][1][RTW89_KCC][0] = 40,
+       [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_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] = 42,
-       [0][1][2][1][RTW89_ACMA][2] = 38,
-       [0][1][2][1][RTW89_FCC][4] = 60,
+       [0][1][2][1][RTW89_IC][2] = 40,
+       [0][1][2][1][RTW89_KCC][2] = 40,
+       [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_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] = 42,
-       [0][1][2][1][RTW89_ACMA][4] = 38,
-       [0][1][2][1][RTW89_FCC][6] = 60,
+       [0][1][2][1][RTW89_IC][4] = 40,
+       [0][1][2][1][RTW89_KCC][4] = 40,
+       [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_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] = 42,
-       [0][1][2][1][RTW89_ACMA][6] = 38,
-       [0][1][2][1][RTW89_FCC][8] = 60,
+       [0][1][2][1][RTW89_IC][6] = 40,
+       [0][1][2][1][RTW89_KCC][6] = 64,
+       [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_FCC][8] = 62,
        [0][1][2][1][RTW89_ETSI][8] = 40,
        [0][1][2][1][RTW89_MKK][8] = 42,
-       [0][1][2][1][RTW89_IC][8] = 42,
-       [0][1][2][1][RTW89_ACMA][8] = 38,
-       [0][1][2][1][RTW89_FCC][10] = 60,
+       [0][1][2][1][RTW89_IC][8] = 40,
+       [0][1][2][1][RTW89_KCC][8] = 62,
+       [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_FCC][10] = 62,
        [0][1][2][1][RTW89_ETSI][10] = 40,
-       [0][1][2][1][RTW89_MKK][10] = 66,
-       [0][1][2][1][RTW89_IC][10] = 42,
-       [0][1][2][1][RTW89_ACMA][10] = 38,
-       [0][1][2][1][RTW89_FCC][12] = 60,
+       [0][1][2][1][RTW89_MKK][10] = 54,
+       [0][1][2][1][RTW89_IC][10] = 40,
+       [0][1][2][1][RTW89_KCC][10] = 62,
+       [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_FCC][12] = 62,
        [0][1][2][1][RTW89_ETSI][12] = 40,
-       [0][1][2][1][RTW89_MKK][12] = 66,
-       [0][1][2][1][RTW89_IC][12] = 42,
-       [0][1][2][1][RTW89_ACMA][12] = 38,
-       [0][1][2][1][RTW89_FCC][14] = 60,
+       [0][1][2][1][RTW89_MKK][12] = 54,
+       [0][1][2][1][RTW89_IC][12] = 40,
+       [0][1][2][1][RTW89_KCC][12] = 62,
+       [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_FCC][14] = 62,
        [0][1][2][1][RTW89_ETSI][14] = 40,
-       [0][1][2][1][RTW89_MKK][14] = 66,
-       [0][1][2][1][RTW89_IC][14] = 42,
-       [0][1][2][1][RTW89_ACMA][14] = 38,
+       [0][1][2][1][RTW89_MKK][14] = 54,
+       [0][1][2][1][RTW89_IC][14] = 40,
+       [0][1][2][1][RTW89_KCC][14] = 62,
+       [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_FCC][15] = 60,
        [0][1][2][1][RTW89_ETSI][15] = 40,
        [0][1][2][1][RTW89_MKK][15] = 68,
-       [0][1][2][1][RTW89_IC][15] = 70,
-       [0][1][2][1][RTW89_ACMA][15] = 38,
-       [0][1][2][1][RTW89_FCC][17] = 60,
+       [0][1][2][1][RTW89_IC][15] = 60,
+       [0][1][2][1][RTW89_KCC][15] = 64,
+       [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_FCC][17] = 62,
        [0][1][2][1][RTW89_ETSI][17] = 40,
        [0][1][2][1][RTW89_MKK][17] = 68,
-       [0][1][2][1][RTW89_IC][17] = 70,
-       [0][1][2][1][RTW89_ACMA][17] = 38,
-       [0][1][2][1][RTW89_FCC][19] = 60,
+       [0][1][2][1][RTW89_IC][17] = 62,
+       [0][1][2][1][RTW89_KCC][17] = 64,
+       [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_FCC][19] = 62,
        [0][1][2][1][RTW89_ETSI][19] = 40,
        [0][1][2][1][RTW89_MKK][19] = 68,
-       [0][1][2][1][RTW89_IC][19] = 70,
-       [0][1][2][1][RTW89_ACMA][19] = 38,
-       [0][1][2][1][RTW89_FCC][21] = 60,
+       [0][1][2][1][RTW89_IC][19] = 62,
+       [0][1][2][1][RTW89_KCC][19] = 64,
+       [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_FCC][21] = 62,
        [0][1][2][1][RTW89_ETSI][21] = 40,
        [0][1][2][1][RTW89_MKK][21] = 68,
-       [0][1][2][1][RTW89_IC][21] = 70,
-       [0][1][2][1][RTW89_ACMA][21] = 38,
-       [0][1][2][1][RTW89_FCC][23] = 60,
+       [0][1][2][1][RTW89_IC][21] = 62,
+       [0][1][2][1][RTW89_KCC][21] = 64,
+       [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_FCC][23] = 62,
        [0][1][2][1][RTW89_ETSI][23] = 40,
        [0][1][2][1][RTW89_MKK][23] = 68,
-       [0][1][2][1][RTW89_IC][23] = 70,
-       [0][1][2][1][RTW89_ACMA][23] = 38,
-       [0][1][2][1][RTW89_FCC][25] = 58,
+       [0][1][2][1][RTW89_IC][23] = 62,
+       [0][1][2][1][RTW89_KCC][23] = 64,
+       [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_FCC][25] = 46,
        [0][1][2][1][RTW89_ETSI][25] = 40,
        [0][1][2][1][RTW89_MKK][25] = 68,
        [0][1][2][1][RTW89_IC][25] = 127,
+       [0][1][2][1][RTW89_KCC][25] = 64,
        [0][1][2][1][RTW89_ACMA][25] = 127,
-       [0][1][2][1][RTW89_FCC][27] = 58,
+       [0][1][2][1][RTW89_CN][25] = 127,
+       [0][1][2][1][RTW89_UK][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,
        [0][1][2][1][RTW89_IC][27] = 127,
+       [0][1][2][1][RTW89_KCC][27] = 64,
        [0][1][2][1][RTW89_ACMA][27] = 127,
-       [0][1][2][1][RTW89_FCC][29] = 58,
+       [0][1][2][1][RTW89_CN][27] = 127,
+       [0][1][2][1][RTW89_UK][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,
        [0][1][2][1][RTW89_IC][29] = 127,
+       [0][1][2][1][RTW89_KCC][29] = 64,
        [0][1][2][1][RTW89_ACMA][29] = 127,
-       [0][1][2][1][RTW89_FCC][31] = 58,
+       [0][1][2][1][RTW89_CN][29] = 127,
+       [0][1][2][1][RTW89_UK][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,
-       [0][1][2][1][RTW89_IC][31] = 68,
-       [0][1][2][1][RTW89_ACMA][31] = 38,
-       [0][1][2][1][RTW89_FCC][33] = 58,
+       [0][1][2][1][RTW89_IC][31] = 46,
+       [0][1][2][1][RTW89_KCC][31] = 62,
+       [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_FCC][33] = 46,
        [0][1][2][1][RTW89_ETSI][33] = 40,
        [0][1][2][1][RTW89_MKK][33] = 68,
-       [0][1][2][1][RTW89_IC][33] = 68,
-       [0][1][2][1][RTW89_ACMA][33] = 38,
-       [0][1][2][1][RTW89_FCC][35] = 58,
+       [0][1][2][1][RTW89_IC][33] = 46,
+       [0][1][2][1][RTW89_KCC][33] = 62,
+       [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_FCC][35] = 46,
        [0][1][2][1][RTW89_ETSI][35] = 40,
        [0][1][2][1][RTW89_MKK][35] = 68,
-       [0][1][2][1][RTW89_IC][35] = 68,
-       [0][1][2][1][RTW89_ACMA][35] = 38,
-       [0][1][2][1][RTW89_FCC][37] = 60,
+       [0][1][2][1][RTW89_IC][35] = 46,
+       [0][1][2][1][RTW89_KCC][35] = 62,
+       [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_FCC][37] = 64,
        [0][1][2][1][RTW89_ETSI][37] = 127,
        [0][1][2][1][RTW89_MKK][37] = 68,
-       [0][1][2][1][RTW89_IC][37] = 70,
-       [0][1][2][1][RTW89_ACMA][37] = 70,
-       [0][1][2][1][RTW89_FCC][38] = 70,
+       [0][1][2][1][RTW89_IC][37] = 64,
+       [0][1][2][1][RTW89_KCC][37] = 62,
+       [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_FCC][38] = 72,
        [0][1][2][1][RTW89_ETSI][38] = 6,
        [0][1][2][1][RTW89_MKK][38] = 127,
-       [0][1][2][1][RTW89_IC][38] = 70,
+       [0][1][2][1][RTW89_IC][38] = 72,
+       [0][1][2][1][RTW89_KCC][38] = 56,
        [0][1][2][1][RTW89_ACMA][38] = 70,
-       [0][1][2][1][RTW89_FCC][40] = 70,
+       [0][1][2][1][RTW89_CN][38] = 60,
+       [0][1][2][1][RTW89_UK][38] = 40,
+       [0][1][2][1][RTW89_FCC][40] = 72,
        [0][1][2][1][RTW89_ETSI][40] = 6,
        [0][1][2][1][RTW89_MKK][40] = 127,
-       [0][1][2][1][RTW89_IC][40] = 70,
+       [0][1][2][1][RTW89_IC][40] = 72,
+       [0][1][2][1][RTW89_KCC][40] = 56,
        [0][1][2][1][RTW89_ACMA][40] = 70,
-       [0][1][2][1][RTW89_FCC][42] = 70,
+       [0][1][2][1][RTW89_CN][40] = 60,
+       [0][1][2][1][RTW89_UK][40] = 40,
+       [0][1][2][1][RTW89_FCC][42] = 72,
        [0][1][2][1][RTW89_ETSI][42] = 6,
        [0][1][2][1][RTW89_MKK][42] = 127,
-       [0][1][2][1][RTW89_IC][42] = 70,
+       [0][1][2][1][RTW89_IC][42] = 72,
+       [0][1][2][1][RTW89_KCC][42] = 56,
        [0][1][2][1][RTW89_ACMA][42] = 70,
-       [0][1][2][1][RTW89_FCC][44] = 70,
+       [0][1][2][1][RTW89_CN][42] = 60,
+       [0][1][2][1][RTW89_UK][42] = 40,
+       [0][1][2][1][RTW89_FCC][44] = 72,
        [0][1][2][1][RTW89_ETSI][44] = 6,
        [0][1][2][1][RTW89_MKK][44] = 127,
-       [0][1][2][1][RTW89_IC][44] = 70,
+       [0][1][2][1][RTW89_IC][44] = 72,
+       [0][1][2][1][RTW89_KCC][44] = 56,
        [0][1][2][1][RTW89_ACMA][44] = 70,
-       [0][1][2][1][RTW89_FCC][46] = 70,
+       [0][1][2][1][RTW89_CN][44] = 54,
+       [0][1][2][1][RTW89_UK][44] = 40,
+       [0][1][2][1][RTW89_FCC][46] = 72,
        [0][1][2][1][RTW89_ETSI][46] = 6,
        [0][1][2][1][RTW89_MKK][46] = 127,
-       [0][1][2][1][RTW89_IC][46] = 70,
+       [0][1][2][1][RTW89_IC][46] = 72,
+       [0][1][2][1][RTW89_KCC][46] = 56,
        [0][1][2][1][RTW89_ACMA][46] = 70,
-       [0][1][2][1][RTW89_FCC][48] = 50,
+       [0][1][2][1][RTW89_CN][46] = 54,
+       [0][1][2][1][RTW89_UK][46] = 40,
+       [0][1][2][1][RTW89_FCC][48] = 48,
        [0][1][2][1][RTW89_ETSI][48] = 127,
        [0][1][2][1][RTW89_MKK][48] = 127,
        [0][1][2][1][RTW89_IC][48] = 127,
+       [0][1][2][1][RTW89_KCC][48] = 127,
        [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_FCC][50] = 50,
        [0][1][2][1][RTW89_ETSI][50] = 127,
        [0][1][2][1][RTW89_MKK][50] = 127,
        [0][1][2][1][RTW89_IC][50] = 127,
+       [0][1][2][1][RTW89_KCC][50] = 127,
        [0][1][2][1][RTW89_ACMA][50] = 127,
-       [0][1][2][1][RTW89_FCC][52] = 50,
+       [0][1][2][1][RTW89_CN][50] = 127,
+       [0][1][2][1][RTW89_UK][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,
        [0][1][2][1][RTW89_IC][52] = 127,
+       [0][1][2][1][RTW89_KCC][52] = 127,
        [0][1][2][1][RTW89_ACMA][52] = 127,
-       [1][0][2][0][RTW89_FCC][1] = 58,
+       [0][1][2][1][RTW89_CN][52] = 127,
+       [0][1][2][1][RTW89_UK][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] = 66,
+       [1][0][2][0][RTW89_IC][1] = 62,
+       [1][0][2][0][RTW89_KCC][1] = 66,
        [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_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] = 66,
+       [1][0][2][0][RTW89_IC][5] = 64,
+       [1][0][2][0][RTW89_KCC][5] = 54,
        [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_FCC][9] = 68,
        [1][0][2][0][RTW89_ETSI][9] = 66,
        [1][0][2][0][RTW89_MKK][9] = 66,
-       [1][0][2][0][RTW89_IC][9] = 66,
+       [1][0][2][0][RTW89_IC][9] = 64,
+       [1][0][2][0][RTW89_KCC][9] = 66,
        [1][0][2][0][RTW89_ACMA][9] = 66,
-       [1][0][2][0][RTW89_FCC][13] = 58,
+       [1][0][2][0][RTW89_CN][9] = 54,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][13] = 66,
+       [1][0][2][0][RTW89_IC][13] = 60,
+       [1][0][2][0][RTW89_KCC][13] = 52,
        [1][0][2][0][RTW89_ACMA][13] = 66,
-       [1][0][2][0][RTW89_FCC][16] = 56,
+       [1][0][2][0][RTW89_CN][13] = 54,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][16] = 66,
+       [1][0][2][0][RTW89_IC][16] = 64,
+       [1][0][2][0][RTW89_KCC][16] = 56,
        [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_FCC][20] = 68,
        [1][0][2][0][RTW89_ETSI][20] = 66,
        [1][0][2][0][RTW89_MKK][20] = 66,
-       [1][0][2][0][RTW89_IC][20] = 66,
+       [1][0][2][0][RTW89_IC][20] = 68,
+       [1][0][2][0][RTW89_KCC][20] = 56,
        [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_FCC][24] = 68,
        [1][0][2][0][RTW89_ETSI][24] = 66,
        [1][0][2][0][RTW89_MKK][24] = 66,
        [1][0][2][0][RTW89_IC][24] = 127,
+       [1][0][2][0][RTW89_KCC][24] = 56,
        [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_FCC][28] = 68,
        [1][0][2][0][RTW89_ETSI][28] = 66,
        [1][0][2][0][RTW89_MKK][28] = 66,
        [1][0][2][0][RTW89_IC][28] = 127,
+       [1][0][2][0][RTW89_KCC][28] = 66,
        [1][0][2][0][RTW89_ACMA][28] = 127,
-       [1][0][2][0][RTW89_FCC][32] = 68,
+       [1][0][2][0][RTW89_CN][28] = 127,
+       [1][0][2][0][RTW89_UK][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,
-       [1][0][2][0][RTW89_IC][32] = 66,
+       [1][0][2][0][RTW89_IC][32] = 62,
+       [1][0][2][0][RTW89_KCC][32] = 66,
        [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_FCC][36] = 68,
        [1][0][2][0][RTW89_ETSI][36] = 127,
        [1][0][2][0][RTW89_MKK][36] = 66,
-       [1][0][2][0][RTW89_IC][36] = 66,
+       [1][0][2][0][RTW89_IC][36] = 68,
+       [1][0][2][0][RTW89_KCC][36] = 66,
        [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_FCC][39] = 68,
        [1][0][2][0][RTW89_ETSI][39] = 30,
        [1][0][2][0][RTW89_MKK][39] = 127,
-       [1][0][2][0][RTW89_IC][39] = 66,
+       [1][0][2][0][RTW89_IC][39] = 68,
+       [1][0][2][0][RTW89_KCC][39] = 66,
        [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_FCC][43] = 68,
        [1][0][2][0][RTW89_ETSI][43] = 30,
        [1][0][2][0][RTW89_MKK][43] = 127,
-       [1][0][2][0][RTW89_IC][43] = 66,
+       [1][0][2][0][RTW89_IC][43] = 68,
+       [1][0][2][0][RTW89_KCC][43] = 66,
        [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_FCC][47] = 68,
        [1][0][2][0][RTW89_ETSI][47] = 127,
        [1][0][2][0][RTW89_MKK][47] = 127,
        [1][0][2][0][RTW89_IC][47] = 127,
+       [1][0][2][0][RTW89_KCC][47] = 127,
        [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_FCC][51] = 68,
        [1][0][2][0][RTW89_ETSI][51] = 127,
        [1][0][2][0][RTW89_MKK][51] = 127,
        [1][0][2][0][RTW89_IC][51] = 127,
+       [1][0][2][0][RTW89_KCC][51] = 127,
        [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][1][2][0][RTW89_FCC][1] = 54,
        [1][1][2][0][RTW89_ETSI][1] = 54,
        [1][1][2][0][RTW89_MKK][1] = 48,
-       [1][1][2][0][RTW89_IC][1] = 60,
-       [1][1][2][0][RTW89_ACMA][1] = 60,
+       [1][1][2][0][RTW89_IC][1] = 48,
+       [1][1][2][0][RTW89_KCC][1] = 54,
+       [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_FCC][5] = 68,
        [1][1][2][0][RTW89_ETSI][5] = 54,
        [1][1][2][0][RTW89_MKK][5] = 52,
-       [1][1][2][0][RTW89_IC][5] = 60,
-       [1][1][2][0][RTW89_ACMA][5] = 60,
+       [1][1][2][0][RTW89_IC][5] = 48,
+       [1][1][2][0][RTW89_KCC][5] = 54,
+       [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_FCC][9] = 68,
        [1][1][2][0][RTW89_ETSI][9] = 54,
        [1][1][2][0][RTW89_MKK][9] = 52,
-       [1][1][2][0][RTW89_IC][9] = 60,
-       [1][1][2][0][RTW89_ACMA][9] = 60,
+       [1][1][2][0][RTW89_IC][9] = 52,
+       [1][1][2][0][RTW89_KCC][9] = 64,
+       [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_FCC][13] = 54,
        [1][1][2][0][RTW89_ETSI][13] = 54,
        [1][1][2][0][RTW89_MKK][13] = 52,
-       [1][1][2][0][RTW89_IC][13] = 60,
-       [1][1][2][0][RTW89_ACMA][13] = 60,
-       [1][1][2][0][RTW89_FCC][16] = 48,
+       [1][1][2][0][RTW89_IC][13] = 52,
+       [1][1][2][0][RTW89_KCC][13] = 52,
+       [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_FCC][16] = 56,
        [1][1][2][0][RTW89_ETSI][16] = 54,
        [1][1][2][0][RTW89_MKK][16] = 66,
-       [1][1][2][0][RTW89_IC][16] = 58,
-       [1][1][2][0][RTW89_ACMA][16] = 60,
+       [1][1][2][0][RTW89_IC][16] = 56,
+       [1][1][2][0][RTW89_KCC][16] = 54,
+       [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_FCC][20] = 68,
        [1][1][2][0][RTW89_ETSI][20] = 54,
        [1][1][2][0][RTW89_MKK][20] = 66,
-       [1][1][2][0][RTW89_IC][20] = 66,
-       [1][1][2][0][RTW89_ACMA][20] = 60,
+       [1][1][2][0][RTW89_IC][20] = 68,
+       [1][1][2][0][RTW89_KCC][20] = 54,
+       [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_FCC][24] = 68,
        [1][1][2][0][RTW89_ETSI][24] = 54,
        [1][1][2][0][RTW89_MKK][24] = 66,
        [1][1][2][0][RTW89_IC][24] = 127,
+       [1][1][2][0][RTW89_KCC][24] = 54,
        [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_FCC][28] = 68,
        [1][1][2][0][RTW89_ETSI][28] = 54,
        [1][1][2][0][RTW89_MKK][28] = 66,
        [1][1][2][0][RTW89_IC][28] = 127,
+       [1][1][2][0][RTW89_KCC][28] = 66,
        [1][1][2][0][RTW89_ACMA][28] = 127,
-       [1][1][2][0][RTW89_FCC][32] = 60,
+       [1][1][2][0][RTW89_CN][28] = 127,
+       [1][1][2][0][RTW89_UK][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,
-       [1][1][2][0][RTW89_IC][32] = 66,
+       [1][1][2][0][RTW89_IC][32] = 56,
+       [1][1][2][0][RTW89_KCC][32] = 66,
        [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_FCC][36] = 68,
        [1][1][2][0][RTW89_ETSI][36] = 127,
        [1][1][2][0][RTW89_MKK][36] = 66,
-       [1][1][2][0][RTW89_IC][36] = 66,
+       [1][1][2][0][RTW89_IC][36] = 68,
+       [1][1][2][0][RTW89_KCC][36] = 66,
        [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_FCC][39] = 68,
        [1][1][2][0][RTW89_ETSI][39] = 18,
        [1][1][2][0][RTW89_MKK][39] = 127,
-       [1][1][2][0][RTW89_IC][39] = 66,
+       [1][1][2][0][RTW89_IC][39] = 68,
+       [1][1][2][0][RTW89_KCC][39] = 56,
        [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_FCC][43] = 68,
        [1][1][2][0][RTW89_ETSI][43] = 18,
        [1][1][2][0][RTW89_MKK][43] = 127,
-       [1][1][2][0][RTW89_IC][43] = 66,
+       [1][1][2][0][RTW89_IC][43] = 68,
+       [1][1][2][0][RTW89_KCC][43] = 56,
        [1][1][2][0][RTW89_ACMA][43] = 66,
-       [1][1][2][0][RTW89_FCC][47] = 60,
+       [1][1][2][0][RTW89_CN][43] = 66,
+       [1][1][2][0][RTW89_UK][43] = 52,
+       [1][1][2][0][RTW89_FCC][47] = 62,
        [1][1][2][0][RTW89_ETSI][47] = 127,
        [1][1][2][0][RTW89_MKK][47] = 127,
        [1][1][2][0][RTW89_IC][47] = 127,
+       [1][1][2][0][RTW89_KCC][47] = 127,
        [1][1][2][0][RTW89_ACMA][47] = 127,
-       [1][1][2][0][RTW89_FCC][51] = 58,
+       [1][1][2][0][RTW89_CN][47] = 127,
+       [1][1][2][0][RTW89_UK][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,
        [1][1][2][0][RTW89_IC][51] = 127,
+       [1][1][2][0][RTW89_KCC][51] = 127,
        [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][1][RTW89_FCC][1] = 54,
        [1][1][2][1][RTW89_ETSI][1] = 40,
        [1][1][2][1][RTW89_MKK][1] = 48,
-       [1][1][2][1][RTW89_IC][1] = 48,
-       [1][1][2][1][RTW89_ACMA][1] = 48,
-       [1][1][2][1][RTW89_FCC][5] = 60,
+       [1][1][2][1][RTW89_IC][1] = 40,
+       [1][1][2][1][RTW89_KCC][1] = 54,
+       [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_FCC][5] = 68,
        [1][1][2][1][RTW89_ETSI][5] = 40,
        [1][1][2][1][RTW89_MKK][5] = 52,
-       [1][1][2][1][RTW89_IC][5] = 48,
-       [1][1][2][1][RTW89_ACMA][5] = 48,
-       [1][1][2][1][RTW89_FCC][9] = 60,
+       [1][1][2][1][RTW89_IC][5] = 40,
+       [1][1][2][1][RTW89_KCC][5] = 54,
+       [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_FCC][9] = 68,
        [1][1][2][1][RTW89_ETSI][9] = 40,
        [1][1][2][1][RTW89_MKK][9] = 52,
-       [1][1][2][1][RTW89_IC][9] = 48,
-       [1][1][2][1][RTW89_ACMA][9] = 48,
+       [1][1][2][1][RTW89_IC][9] = 40,
+       [1][1][2][1][RTW89_KCC][9] = 64,
+       [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_FCC][13] = 54,
        [1][1][2][1][RTW89_ETSI][13] = 40,
        [1][1][2][1][RTW89_MKK][13] = 52,
-       [1][1][2][1][RTW89_IC][13] = 48,
-       [1][1][2][1][RTW89_ACMA][13] = 48,
-       [1][1][2][1][RTW89_FCC][16] = 48,
+       [1][1][2][1][RTW89_IC][13] = 40,
+       [1][1][2][1][RTW89_KCC][13] = 52,
+       [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_FCC][16] = 56,
        [1][1][2][1][RTW89_ETSI][16] = 40,
        [1][1][2][1][RTW89_MKK][16] = 66,
-       [1][1][2][1][RTW89_IC][16] = 58,
-       [1][1][2][1][RTW89_ACMA][16] = 48,
-       [1][1][2][1][RTW89_FCC][20] = 60,
+       [1][1][2][1][RTW89_IC][16] = 56,
+       [1][1][2][1][RTW89_KCC][16] = 54,
+       [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_FCC][20] = 68,
        [1][1][2][1][RTW89_ETSI][20] = 40,
        [1][1][2][1][RTW89_MKK][20] = 66,
-       [1][1][2][1][RTW89_IC][20] = 66,
-       [1][1][2][1][RTW89_ACMA][20] = 48,
-       [1][1][2][1][RTW89_FCC][24] = 60,
+       [1][1][2][1][RTW89_IC][20] = 68,
+       [1][1][2][1][RTW89_KCC][20] = 54,
+       [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_FCC][24] = 68,
        [1][1][2][1][RTW89_ETSI][24] = 40,
        [1][1][2][1][RTW89_MKK][24] = 66,
        [1][1][2][1][RTW89_IC][24] = 127,
+       [1][1][2][1][RTW89_KCC][24] = 54,
        [1][1][2][1][RTW89_ACMA][24] = 127,
-       [1][1][2][1][RTW89_FCC][28] = 60,
+       [1][1][2][1][RTW89_CN][24] = 127,
+       [1][1][2][1][RTW89_UK][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,
        [1][1][2][1][RTW89_IC][28] = 127,
+       [1][1][2][1][RTW89_KCC][28] = 66,
        [1][1][2][1][RTW89_ACMA][28] = 127,
-       [1][1][2][1][RTW89_FCC][32] = 60,
+       [1][1][2][1][RTW89_CN][28] = 127,
+       [1][1][2][1][RTW89_UK][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,
-       [1][1][2][1][RTW89_IC][32] = 66,
-       [1][1][2][1][RTW89_ACMA][32] = 42,
-       [1][1][2][1][RTW89_FCC][36] = 60,
+       [1][1][2][1][RTW89_IC][32] = 56,
+       [1][1][2][1][RTW89_KCC][32] = 66,
+       [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_FCC][36] = 68,
        [1][1][2][1][RTW89_ETSI][36] = 127,
        [1][1][2][1][RTW89_MKK][36] = 66,
-       [1][1][2][1][RTW89_IC][36] = 66,
+       [1][1][2][1][RTW89_IC][36] = 68,
+       [1][1][2][1][RTW89_KCC][36] = 66,
        [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_FCC][39] = 68,
        [1][1][2][1][RTW89_ETSI][39] = 6,
        [1][1][2][1][RTW89_MKK][39] = 127,
-       [1][1][2][1][RTW89_IC][39] = 66,
+       [1][1][2][1][RTW89_IC][39] = 68,
+       [1][1][2][1][RTW89_KCC][39] = 56,
        [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_FCC][43] = 68,
        [1][1][2][1][RTW89_ETSI][43] = 6,
        [1][1][2][1][RTW89_MKK][43] = 127,
-       [1][1][2][1][RTW89_IC][43] = 66,
+       [1][1][2][1][RTW89_IC][43] = 68,
+       [1][1][2][1][RTW89_KCC][43] = 56,
        [1][1][2][1][RTW89_ACMA][43] = 66,
-       [1][1][2][1][RTW89_FCC][47] = 60,
+       [1][1][2][1][RTW89_CN][43] = 52,
+       [1][1][2][1][RTW89_UK][43] = 40,
+       [1][1][2][1][RTW89_FCC][47] = 62,
        [1][1][2][1][RTW89_ETSI][47] = 127,
        [1][1][2][1][RTW89_MKK][47] = 127,
        [1][1][2][1][RTW89_IC][47] = 127,
+       [1][1][2][1][RTW89_KCC][47] = 127,
        [1][1][2][1][RTW89_ACMA][47] = 127,
-       [1][1][2][1][RTW89_FCC][51] = 58,
+       [1][1][2][1][RTW89_CN][47] = 127,
+       [1][1][2][1][RTW89_UK][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,
        [1][1][2][1][RTW89_IC][51] = 127,
+       [1][1][2][1][RTW89_KCC][51] = 127,
        [1][1][2][1][RTW89_ACMA][51] = 127,
-       [2][0][2][0][RTW89_FCC][3] = 56,
+       [1][1][2][1][RTW89_CN][51] = 127,
+       [1][1][2][1][RTW89_UK][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,
-       [2][0][2][0][RTW89_IC][3] = 60,
+       [2][0][2][0][RTW89_IC][3] = 56,
+       [2][0][2][0][RTW89_KCC][3] = 60,
        [2][0][2][0][RTW89_ACMA][3] = 60,
-       [2][0][2][0][RTW89_FCC][11] = 58,
+       [2][0][2][0][RTW89_CN][3] = 54,
+       [2][0][2][0][RTW89_UK][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,
-       [2][0][2][0][RTW89_IC][11] = 60,
+       [2][0][2][0][RTW89_IC][11] = 50,
+       [2][0][2][0][RTW89_KCC][11] = 58,
        [2][0][2][0][RTW89_ACMA][11] = 60,
-       [2][0][2][0][RTW89_FCC][18] = 54,
+       [2][0][2][0][RTW89_CN][11] = 54,
+       [2][0][2][0][RTW89_UK][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,
        [2][0][2][0][RTW89_IC][18] = 60,
+       [2][0][2][0][RTW89_KCC][18] = 56,
        [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_FCC][26] = 62,
        [2][0][2][0][RTW89_ETSI][26] = 60,
        [2][0][2][0][RTW89_MKK][26] = 60,
        [2][0][2][0][RTW89_IC][26] = 127,
+       [2][0][2][0][RTW89_KCC][26] = 60,
        [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_FCC][34] = 62,
        [2][0][2][0][RTW89_ETSI][34] = 127,
        [2][0][2][0][RTW89_MKK][34] = 60,
-       [2][0][2][0][RTW89_IC][34] = 60,
+       [2][0][2][0][RTW89_IC][34] = 62,
+       [2][0][2][0][RTW89_KCC][34] = 60,
        [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_FCC][41] = 62,
        [2][0][2][0][RTW89_ETSI][41] = 30,
        [2][0][2][0][RTW89_MKK][41] = 127,
-       [2][0][2][0][RTW89_IC][41] = 60,
+       [2][0][2][0][RTW89_IC][41] = 62,
+       [2][0][2][0][RTW89_KCC][41] = 58,
        [2][0][2][0][RTW89_ACMA][41] = 60,
-       [2][0][2][0][RTW89_FCC][49] = 56,
+       [2][0][2][0][RTW89_CN][41] = 62,
+       [2][0][2][0][RTW89_UK][41] = 60,
+       [2][0][2][0][RTW89_FCC][49] = 62,
        [2][0][2][0][RTW89_ETSI][49] = 127,
        [2][0][2][0][RTW89_MKK][49] = 127,
        [2][0][2][0][RTW89_IC][49] = 127,
+       [2][0][2][0][RTW89_KCC][49] = 127,
        [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][1][2][0][RTW89_FCC][3] = 48,
        [2][1][2][0][RTW89_ETSI][3] = 54,
        [2][1][2][0][RTW89_MKK][3] = 56,
-       [2][1][2][0][RTW89_IC][3] = 52,
-       [2][1][2][0][RTW89_ACMA][3] = 52,
-       [2][1][2][0][RTW89_FCC][11] = 54,
+       [2][1][2][0][RTW89_IC][3] = 46,
+       [2][1][2][0][RTW89_KCC][3] = 56,
+       [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_FCC][11] = 38,
        [2][1][2][0][RTW89_ETSI][11] = 54,
        [2][1][2][0][RTW89_MKK][11] = 54,
-       [2][1][2][0][RTW89_IC][11] = 52,
-       [2][1][2][0][RTW89_ACMA][11] = 52,
-       [2][1][2][0][RTW89_FCC][18] = 48,
+       [2][1][2][0][RTW89_IC][11] = 38,
+       [2][1][2][0][RTW89_KCC][11] = 52,
+       [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_FCC][18] = 50,
        [2][1][2][0][RTW89_ETSI][18] = 54,
        [2][1][2][0][RTW89_MKK][18] = 60,
-       [2][1][2][0][RTW89_IC][18] = 58,
-       [2][1][2][0][RTW89_ACMA][18] = 52,
-       [2][1][2][0][RTW89_FCC][26] = 62,
+       [2][1][2][0][RTW89_IC][18] = 50,
+       [2][1][2][0][RTW89_KCC][18] = 54,
+       [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_FCC][26] = 52,
        [2][1][2][0][RTW89_ETSI][26] = 54,
        [2][1][2][0][RTW89_MKK][26] = 56,
        [2][1][2][0][RTW89_IC][26] = 127,
+       [2][1][2][0][RTW89_KCC][26] = 60,
        [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_FCC][34] = 62,
        [2][1][2][0][RTW89_ETSI][34] = 127,
        [2][1][2][0][RTW89_MKK][34] = 60,
-       [2][1][2][0][RTW89_IC][34] = 60,
+       [2][1][2][0][RTW89_IC][34] = 62,
+       [2][1][2][0][RTW89_KCC][34] = 60,
        [2][1][2][0][RTW89_ACMA][34] = 60,
-       [2][1][2][0][RTW89_FCC][41] = 62,
+       [2][1][2][0][RTW89_CN][34] = 127,
+       [2][1][2][0][RTW89_UK][34] = 52,
+       [2][1][2][0][RTW89_FCC][41] = 60,
        [2][1][2][0][RTW89_ETSI][41] = 18,
        [2][1][2][0][RTW89_MKK][41] = 127,
        [2][1][2][0][RTW89_IC][41] = 60,
-       [2][1][2][0][RTW89_ACMA][41] = 60,
-       [2][1][2][0][RTW89_FCC][49] = 50,
+       [2][1][2][0][RTW89_KCC][41] = 50,
+       [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_FCC][49] = 62,
        [2][1][2][0][RTW89_ETSI][49] = 127,
        [2][1][2][0][RTW89_MKK][49] = 127,
        [2][1][2][0][RTW89_IC][49] = 127,
+       [2][1][2][0][RTW89_KCC][49] = 127,
        [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][1][RTW89_FCC][3] = 48,
        [2][1][2][1][RTW89_ETSI][3] = 40,
        [2][1][2][1][RTW89_MKK][3] = 56,
        [2][1][2][1][RTW89_IC][3] = 40,
+       [2][1][2][1][RTW89_KCC][3] = 56,
        [2][1][2][1][RTW89_ACMA][3] = 40,
-       [2][1][2][1][RTW89_FCC][11] = 54,
+       [2][1][2][1][RTW89_CN][3] = 42,
+       [2][1][2][1][RTW89_UK][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,
-       [2][1][2][1][RTW89_IC][11] = 40,
+       [2][1][2][1][RTW89_IC][11] = 38,
+       [2][1][2][1][RTW89_KCC][11] = 52,
        [2][1][2][1][RTW89_ACMA][11] = 40,
-       [2][1][2][1][RTW89_FCC][18] = 48,
+       [2][1][2][1][RTW89_CN][11] = 42,
+       [2][1][2][1][RTW89_UK][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,
-       [2][1][2][1][RTW89_IC][18] = 58,
+       [2][1][2][1][RTW89_IC][18] = 50,
+       [2][1][2][1][RTW89_KCC][18] = 54,
        [2][1][2][1][RTW89_ACMA][18] = 40,
-       [2][1][2][1][RTW89_FCC][26] = 60,
+       [2][1][2][1][RTW89_CN][18] = 127,
+       [2][1][2][1][RTW89_UK][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,
        [2][1][2][1][RTW89_IC][26] = 127,
+       [2][1][2][1][RTW89_KCC][26] = 60,
        [2][1][2][1][RTW89_ACMA][26] = 127,
-       [2][1][2][1][RTW89_FCC][34] = 60,
+       [2][1][2][1][RTW89_CN][26] = 127,
+       [2][1][2][1][RTW89_UK][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,
-       [2][1][2][1][RTW89_IC][34] = 60,
+       [2][1][2][1][RTW89_IC][34] = 62,
+       [2][1][2][1][RTW89_KCC][34] = 60,
        [2][1][2][1][RTW89_ACMA][34] = 60,
-       [2][1][2][1][RTW89_FCC][41] = 62,
+       [2][1][2][1][RTW89_CN][34] = 127,
+       [2][1][2][1][RTW89_UK][34] = 40,
+       [2][1][2][1][RTW89_FCC][41] = 60,
        [2][1][2][1][RTW89_ETSI][41] = 6,
        [2][1][2][1][RTW89_MKK][41] = 127,
        [2][1][2][1][RTW89_IC][41] = 60,
-       [2][1][2][1][RTW89_ACMA][41] = 60,
-       [2][1][2][1][RTW89_FCC][49] = 50,
+       [2][1][2][1][RTW89_KCC][41] = 50,
+       [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_FCC][49] = 62,
        [2][1][2][1][RTW89_ETSI][49] = 127,
        [2][1][2][1][RTW89_MKK][49] = 127,
        [2][1][2][1][RTW89_IC][49] = 127,
+       [2][1][2][1][RTW89_KCC][49] = 127,
        [2][1][2][1][RTW89_ACMA][49] = 127,
-       [3][0][2][0][RTW89_FCC][7] = 38,
+       [2][1][2][1][RTW89_CN][49] = 127,
+       [2][1][2][1][RTW89_UK][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,
-       [3][0][2][0][RTW89_IC][7] = 50,
-       [3][0][2][0][RTW89_ACMA][7] = 50,
-       [3][0][2][0][RTW89_FCC][22] = 52,
+       [3][0][2][0][RTW89_IC][7] = 40,
+       [3][0][2][0][RTW89_KCC][7] = 44,
+       [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_FCC][22] = 42,
        [3][0][2][0][RTW89_ETSI][22] = 50,
        [3][0][2][0][RTW89_MKK][22] = 50,
-       [3][0][2][0][RTW89_IC][22] = 50,
-       [3][0][2][0][RTW89_ACMA][22] = 50,
-       [3][0][2][0][RTW89_FCC][45] = 127,
+       [3][0][2][0][RTW89_IC][22] = 127,
+       [3][0][2][0][RTW89_KCC][22] = 50,
+       [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_FCC][45] = 52,
        [3][0][2][0][RTW89_ETSI][45] = 127,
        [3][0][2][0][RTW89_MKK][45] = 127,
        [3][0][2][0][RTW89_IC][45] = 127,
+       [3][0][2][0][RTW89_KCC][45] = 127,
        [3][0][2][0][RTW89_ACMA][45] = 127,
-       [3][1][2][0][RTW89_FCC][7] = 26,
+       [3][0][2][0][RTW89_CN][45] = 127,
+       [3][0][2][0][RTW89_UK][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,
        [3][1][2][0][RTW89_IC][7] = 44,
-       [3][1][2][0][RTW89_ACMA][7] = 44,
-       [3][1][2][0][RTW89_FCC][22] = 42,
+       [3][1][2][0][RTW89_KCC][7] = 50,
+       [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_FCC][22] = 36,
        [3][1][2][0][RTW89_ETSI][22] = 50,
        [3][1][2][0][RTW89_MKK][22] = 48,
-       [3][1][2][0][RTW89_IC][22] = 44,
-       [3][1][2][0][RTW89_ACMA][22] = 44,
-       [3][1][2][0][RTW89_FCC][45] = 127,
+       [3][1][2][0][RTW89_IC][22] = 127,
+       [3][1][2][0][RTW89_KCC][22] = 50,
+       [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_FCC][45] = 46,
        [3][1][2][0][RTW89_ETSI][45] = 127,
        [3][1][2][0][RTW89_MKK][45] = 127,
        [3][1][2][0][RTW89_IC][45] = 127,
+       [3][1][2][0][RTW89_KCC][45] = 127,
        [3][1][2][0][RTW89_ACMA][45] = 127,
-       [3][1][2][1][RTW89_FCC][7] = 14,
+       [3][1][2][0][RTW89_CN][45] = 127,
+       [3][1][2][0][RTW89_UK][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,
-       [3][1][2][1][RTW89_IC][7] = 32,
-       [3][1][2][1][RTW89_ACMA][7] = 32,
-       [3][1][2][1][RTW89_FCC][22] = 30,
+       [3][1][2][1][RTW89_IC][7] = 44,
+       [3][1][2][1][RTW89_KCC][7] = 50,
+       [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_FCC][22] = 36,
        [3][1][2][1][RTW89_ETSI][22] = 42,
        [3][1][2][1][RTW89_MKK][22] = 48,
-       [3][1][2][1][RTW89_IC][22] = 32,
-       [3][1][2][1][RTW89_ACMA][22] = 32,
-       [3][1][2][1][RTW89_FCC][45] = 127,
+       [3][1][2][1][RTW89_IC][22] = 127,
+       [3][1][2][1][RTW89_KCC][22] = 50,
+       [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_FCC][45] = 46,
        [3][1][2][1][RTW89_ETSI][45] = 127,
        [3][1][2][1][RTW89_MKK][45] = 127,
        [3][1][2][1][RTW89_IC][45] = 127,
+       [3][1][2][1][RTW89_KCC][45] = 127,
        [3][1][2][1][RTW89_ACMA][45] = 127,
+       [3][1][2][1][RTW89_CN][45] = 127,
+       [3][1][2][1][RTW89_UK][45] = 127,
 };
 
 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] = 72,
-       [0][0][1][0][RTW89_WW][2] = 72,
-       [0][0][1][0][RTW89_WW][4] = 72,
-       [0][0][1][0][RTW89_WW][6] = 72,
-       [0][0][1][0][RTW89_WW][8] = 72,
-       [0][0][1][0][RTW89_WW][10] = 72,
-       [0][0][1][0][RTW89_WW][12] = 72,
-       [0][0][1][0][RTW89_WW][14] = 72,
-       [0][0][1][0][RTW89_WW][15] = 72,
-       [0][0][1][0][RTW89_WW][17] = 72,
-       [0][0][1][0][RTW89_WW][19] = 72,
-       [0][0][1][0][RTW89_WW][21] = 72,
-       [0][0][1][0][RTW89_WW][23] = 72,
-       [0][0][1][0][RTW89_WW][25] = 72,
-       [0][0][1][0][RTW89_WW][27] = 72,
-       [0][0][1][0][RTW89_WW][29] = 72,
-       [0][0][1][0][RTW89_WW][30] = 72,
-       [0][0][1][0][RTW89_WW][32] = 72,
-       [0][0][1][0][RTW89_WW][34] = 72,
-       [0][0][1][0][RTW89_WW][36] = 72,
-       [0][0][1][0][RTW89_WW][38] = 72,
-       [0][0][1][0][RTW89_WW][40] = 72,
-       [0][0][1][0][RTW89_WW][42] = 72,
-       [0][0][1][0][RTW89_WW][44] = 72,
-       [0][0][1][0][RTW89_WW][45] = 72,
-       [0][0][1][0][RTW89_WW][47] = 72,
-       [0][0][1][0][RTW89_WW][49] = 72,
-       [0][0][1][0][RTW89_WW][51] = 72,
-       [0][0][1][0][RTW89_WW][53] = 72,
-       [0][0][1][0][RTW89_WW][55] = 72,
-       [0][0][1][0][RTW89_WW][57] = 72,
-       [0][0][1][0][RTW89_WW][59] = 72,
-       [0][0][1][0][RTW89_WW][60] = 72,
-       [0][0][1][0][RTW89_WW][62] = 72,
-       [0][0][1][0][RTW89_WW][64] = 72,
-       [0][0][1][0][RTW89_WW][66] = 72,
-       [0][0][1][0][RTW89_WW][68] = 72,
-       [0][0][1][0][RTW89_WW][70] = 72,
-       [0][0][1][0][RTW89_WW][72] = 72,
-       [0][0][1][0][RTW89_WW][74] = 72,
-       [0][0][1][0][RTW89_WW][75] = 72,
-       [0][0][1][0][RTW89_WW][77] = 72,
-       [0][0][1][0][RTW89_WW][79] = 72,
-       [0][0][1][0][RTW89_WW][81] = 72,
-       [0][0][1][0][RTW89_WW][83] = 72,
-       [0][0][1][0][RTW89_WW][85] = 72,
-       [0][0][1][0][RTW89_WW][87] = 72,
-       [0][0][1][0][RTW89_WW][89] = 72,
-       [0][0][1][0][RTW89_WW][90] = 72,
-       [0][0][1][0][RTW89_WW][92] = 72,
-       [0][0][1][0][RTW89_WW][94] = 72,
-       [0][0][1][0][RTW89_WW][96] = 72,
-       [0][0][1][0][RTW89_WW][98] = 72,
-       [0][0][1][0][RTW89_WW][100] = 72,
-       [0][0][1][0][RTW89_WW][102] = 72,
-       [0][0][1][0][RTW89_WW][104] = 72,
-       [0][0][1][0][RTW89_WW][105] = 72,
-       [0][0][1][0][RTW89_WW][107] = 72,
-       [0][0][1][0][RTW89_WW][109] = 72,
+       [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] = 60,
-       [0][1][1][0][RTW89_WW][2] = 60,
-       [0][1][1][0][RTW89_WW][4] = 60,
-       [0][1][1][0][RTW89_WW][6] = 60,
-       [0][1][1][0][RTW89_WW][8] = 60,
-       [0][1][1][0][RTW89_WW][10] = 60,
-       [0][1][1][0][RTW89_WW][12] = 60,
-       [0][1][1][0][RTW89_WW][14] = 60,
-       [0][1][1][0][RTW89_WW][15] = 60,
-       [0][1][1][0][RTW89_WW][17] = 60,
-       [0][1][1][0][RTW89_WW][19] = 60,
-       [0][1][1][0][RTW89_WW][21] = 60,
-       [0][1][1][0][RTW89_WW][23] = 60,
-       [0][1][1][0][RTW89_WW][25] = 60,
-       [0][1][1][0][RTW89_WW][27] = 60,
-       [0][1][1][0][RTW89_WW][29] = 60,
-       [0][1][1][0][RTW89_WW][30] = 60,
-       [0][1][1][0][RTW89_WW][32] = 60,
-       [0][1][1][0][RTW89_WW][34] = 60,
-       [0][1][1][0][RTW89_WW][36] = 60,
-       [0][1][1][0][RTW89_WW][38] = 60,
-       [0][1][1][0][RTW89_WW][40] = 60,
-       [0][1][1][0][RTW89_WW][42] = 60,
-       [0][1][1][0][RTW89_WW][44] = 60,
-       [0][1][1][0][RTW89_WW][45] = 60,
-       [0][1][1][0][RTW89_WW][47] = 60,
-       [0][1][1][0][RTW89_WW][49] = 60,
-       [0][1][1][0][RTW89_WW][51] = 60,
-       [0][1][1][0][RTW89_WW][53] = 60,
-       [0][1][1][0][RTW89_WW][55] = 60,
-       [0][1][1][0][RTW89_WW][57] = 60,
-       [0][1][1][0][RTW89_WW][59] = 60,
-       [0][1][1][0][RTW89_WW][60] = 60,
-       [0][1][1][0][RTW89_WW][62] = 60,
-       [0][1][1][0][RTW89_WW][64] = 60,
-       [0][1][1][0][RTW89_WW][66] = 60,
-       [0][1][1][0][RTW89_WW][68] = 60,
-       [0][1][1][0][RTW89_WW][70] = 60,
-       [0][1][1][0][RTW89_WW][72] = 60,
-       [0][1][1][0][RTW89_WW][74] = 60,
-       [0][1][1][0][RTW89_WW][75] = 60,
-       [0][1][1][0][RTW89_WW][77] = 60,
-       [0][1][1][0][RTW89_WW][79] = 60,
-       [0][1][1][0][RTW89_WW][81] = 60,
-       [0][1][1][0][RTW89_WW][83] = 60,
-       [0][1][1][0][RTW89_WW][85] = 60,
-       [0][1][1][0][RTW89_WW][87] = 60,
-       [0][1][1][0][RTW89_WW][89] = 60,
-       [0][1][1][0][RTW89_WW][90] = 60,
-       [0][1][1][0][RTW89_WW][92] = 60,
-       [0][1][1][0][RTW89_WW][94] = 60,
-       [0][1][1][0][RTW89_WW][96] = 60,
-       [0][1][1][0][RTW89_WW][98] = 60,
-       [0][1][1][0][RTW89_WW][100] = 60,
-       [0][1][1][0][RTW89_WW][102] = 60,
-       [0][1][1][0][RTW89_WW][104] = 60,
-       [0][1][1][0][RTW89_WW][105] = 60,
-       [0][1][1][0][RTW89_WW][107] = 60,
-       [0][1][1][0][RTW89_WW][109] = 60,
+       [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] = 72,
-       [0][0][2][0][RTW89_WW][2] = 72,
-       [0][0][2][0][RTW89_WW][4] = 72,
-       [0][0][2][0][RTW89_WW][6] = 72,
-       [0][0][2][0][RTW89_WW][8] = 72,
-       [0][0][2][0][RTW89_WW][10] = 72,
-       [0][0][2][0][RTW89_WW][12] = 72,
-       [0][0][2][0][RTW89_WW][14] = 72,
-       [0][0][2][0][RTW89_WW][15] = 72,
-       [0][0][2][0][RTW89_WW][17] = 72,
-       [0][0][2][0][RTW89_WW][19] = 72,
-       [0][0][2][0][RTW89_WW][21] = 72,
-       [0][0][2][0][RTW89_WW][23] = 72,
-       [0][0][2][0][RTW89_WW][25] = 72,
-       [0][0][2][0][RTW89_WW][27] = 72,
-       [0][0][2][0][RTW89_WW][29] = 72,
-       [0][0][2][0][RTW89_WW][30] = 72,
-       [0][0][2][0][RTW89_WW][32] = 72,
-       [0][0][2][0][RTW89_WW][34] = 72,
-       [0][0][2][0][RTW89_WW][36] = 72,
-       [0][0][2][0][RTW89_WW][38] = 72,
-       [0][0][2][0][RTW89_WW][40] = 72,
-       [0][0][2][0][RTW89_WW][42] = 72,
-       [0][0][2][0][RTW89_WW][44] = 72,
-       [0][0][2][0][RTW89_WW][45] = 72,
-       [0][0][2][0][RTW89_WW][47] = 72,
-       [0][0][2][0][RTW89_WW][49] = 72,
-       [0][0][2][0][RTW89_WW][51] = 72,
-       [0][0][2][0][RTW89_WW][53] = 72,
-       [0][0][2][0][RTW89_WW][55] = 72,
-       [0][0][2][0][RTW89_WW][57] = 72,
-       [0][0][2][0][RTW89_WW][59] = 72,
-       [0][0][2][0][RTW89_WW][60] = 72,
-       [0][0][2][0][RTW89_WW][62] = 72,
-       [0][0][2][0][RTW89_WW][64] = 72,
-       [0][0][2][0][RTW89_WW][66] = 72,
-       [0][0][2][0][RTW89_WW][68] = 72,
-       [0][0][2][0][RTW89_WW][70] = 72,
-       [0][0][2][0][RTW89_WW][72] = 72,
-       [0][0][2][0][RTW89_WW][74] = 72,
-       [0][0][2][0][RTW89_WW][75] = 72,
-       [0][0][2][0][RTW89_WW][77] = 72,
-       [0][0][2][0][RTW89_WW][79] = 72,
-       [0][0][2][0][RTW89_WW][81] = 72,
-       [0][0][2][0][RTW89_WW][83] = 72,
-       [0][0][2][0][RTW89_WW][85] = 72,
-       [0][0][2][0][RTW89_WW][87] = 72,
-       [0][0][2][0][RTW89_WW][89] = 72,
-       [0][0][2][0][RTW89_WW][90] = 72,
-       [0][0][2][0][RTW89_WW][92] = 72,
-       [0][0][2][0][RTW89_WW][94] = 72,
-       [0][0][2][0][RTW89_WW][96] = 72,
-       [0][0][2][0][RTW89_WW][98] = 72,
-       [0][0][2][0][RTW89_WW][100] = 72,
-       [0][0][2][0][RTW89_WW][102] = 72,
-       [0][0][2][0][RTW89_WW][104] = 72,
-       [0][0][2][0][RTW89_WW][105] = 72,
-       [0][0][2][0][RTW89_WW][107] = 72,
-       [0][0][2][0][RTW89_WW][109] = 72,
+       [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] = 60,
-       [0][1][2][0][RTW89_WW][2] = 60,
-       [0][1][2][0][RTW89_WW][4] = 60,
-       [0][1][2][0][RTW89_WW][6] = 60,
-       [0][1][2][0][RTW89_WW][8] = 60,
-       [0][1][2][0][RTW89_WW][10] = 60,
-       [0][1][2][0][RTW89_WW][12] = 60,
-       [0][1][2][0][RTW89_WW][14] = 60,
-       [0][1][2][0][RTW89_WW][15] = 60,
-       [0][1][2][0][RTW89_WW][17] = 60,
-       [0][1][2][0][RTW89_WW][19] = 60,
-       [0][1][2][0][RTW89_WW][21] = 60,
-       [0][1][2][0][RTW89_WW][23] = 60,
-       [0][1][2][0][RTW89_WW][25] = 60,
-       [0][1][2][0][RTW89_WW][27] = 60,
-       [0][1][2][0][RTW89_WW][29] = 60,
-       [0][1][2][0][RTW89_WW][30] = 60,
-       [0][1][2][0][RTW89_WW][32] = 60,
-       [0][1][2][0][RTW89_WW][34] = 60,
-       [0][1][2][0][RTW89_WW][36] = 60,
-       [0][1][2][0][RTW89_WW][38] = 60,
-       [0][1][2][0][RTW89_WW][40] = 60,
-       [0][1][2][0][RTW89_WW][42] = 60,
-       [0][1][2][0][RTW89_WW][44] = 60,
-       [0][1][2][0][RTW89_WW][45] = 60,
-       [0][1][2][0][RTW89_WW][47] = 60,
-       [0][1][2][0][RTW89_WW][49] = 60,
-       [0][1][2][0][RTW89_WW][51] = 60,
-       [0][1][2][0][RTW89_WW][53] = 60,
-       [0][1][2][0][RTW89_WW][55] = 60,
-       [0][1][2][0][RTW89_WW][57] = 60,
-       [0][1][2][0][RTW89_WW][59] = 60,
-       [0][1][2][0][RTW89_WW][60] = 60,
-       [0][1][2][0][RTW89_WW][62] = 60,
-       [0][1][2][0][RTW89_WW][64] = 60,
-       [0][1][2][0][RTW89_WW][66] = 60,
-       [0][1][2][0][RTW89_WW][68] = 60,
-       [0][1][2][0][RTW89_WW][70] = 60,
-       [0][1][2][0][RTW89_WW][72] = 60,
-       [0][1][2][0][RTW89_WW][74] = 60,
-       [0][1][2][0][RTW89_WW][75] = 60,
-       [0][1][2][0][RTW89_WW][77] = 60,
-       [0][1][2][0][RTW89_WW][79] = 60,
-       [0][1][2][0][RTW89_WW][81] = 60,
-       [0][1][2][0][RTW89_WW][83] = 60,
-       [0][1][2][0][RTW89_WW][85] = 60,
-       [0][1][2][0][RTW89_WW][87] = 60,
-       [0][1][2][0][RTW89_WW][89] = 60,
-       [0][1][2][0][RTW89_WW][90] = 60,
-       [0][1][2][0][RTW89_WW][92] = 60,
-       [0][1][2][0][RTW89_WW][94] = 60,
-       [0][1][2][0][RTW89_WW][96] = 60,
-       [0][1][2][0][RTW89_WW][98] = 60,
-       [0][1][2][0][RTW89_WW][100] = 60,
-       [0][1][2][0][RTW89_WW][102] = 60,
-       [0][1][2][0][RTW89_WW][104] = 60,
-       [0][1][2][0][RTW89_WW][105] = 60,
-       [0][1][2][0][RTW89_WW][107] = 60,
-       [0][1][2][0][RTW89_WW][109] = 60,
+       [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] = 48,
-       [0][1][2][1][RTW89_WW][2] = 48,
-       [0][1][2][1][RTW89_WW][4] = 48,
-       [0][1][2][1][RTW89_WW][6] = 48,
-       [0][1][2][1][RTW89_WW][8] = 48,
-       [0][1][2][1][RTW89_WW][10] = 48,
-       [0][1][2][1][RTW89_WW][12] = 48,
-       [0][1][2][1][RTW89_WW][14] = 48,
-       [0][1][2][1][RTW89_WW][15] = 48,
-       [0][1][2][1][RTW89_WW][17] = 48,
-       [0][1][2][1][RTW89_WW][19] = 48,
-       [0][1][2][1][RTW89_WW][21] = 48,
-       [0][1][2][1][RTW89_WW][23] = 48,
-       [0][1][2][1][RTW89_WW][25] = 48,
-       [0][1][2][1][RTW89_WW][27] = 48,
-       [0][1][2][1][RTW89_WW][29] = 48,
-       [0][1][2][1][RTW89_WW][30] = 48,
-       [0][1][2][1][RTW89_WW][32] = 48,
-       [0][1][2][1][RTW89_WW][34] = 48,
-       [0][1][2][1][RTW89_WW][36] = 48,
-       [0][1][2][1][RTW89_WW][38] = 48,
-       [0][1][2][1][RTW89_WW][40] = 48,
-       [0][1][2][1][RTW89_WW][42] = 48,
-       [0][1][2][1][RTW89_WW][44] = 48,
-       [0][1][2][1][RTW89_WW][45] = 48,
-       [0][1][2][1][RTW89_WW][47] = 48,
-       [0][1][2][1][RTW89_WW][49] = 48,
-       [0][1][2][1][RTW89_WW][51] = 48,
-       [0][1][2][1][RTW89_WW][53] = 48,
-       [0][1][2][1][RTW89_WW][55] = 48,
-       [0][1][2][1][RTW89_WW][57] = 48,
-       [0][1][2][1][RTW89_WW][59] = 48,
-       [0][1][2][1][RTW89_WW][60] = 48,
-       [0][1][2][1][RTW89_WW][62] = 48,
-       [0][1][2][1][RTW89_WW][64] = 48,
-       [0][1][2][1][RTW89_WW][66] = 48,
-       [0][1][2][1][RTW89_WW][68] = 48,
-       [0][1][2][1][RTW89_WW][70] = 48,
-       [0][1][2][1][RTW89_WW][72] = 48,
-       [0][1][2][1][RTW89_WW][74] = 48,
-       [0][1][2][1][RTW89_WW][75] = 48,
-       [0][1][2][1][RTW89_WW][77] = 48,
-       [0][1][2][1][RTW89_WW][79] = 48,
-       [0][1][2][1][RTW89_WW][81] = 48,
-       [0][1][2][1][RTW89_WW][83] = 48,
-       [0][1][2][1][RTW89_WW][85] = 48,
-       [0][1][2][1][RTW89_WW][87] = 48,
-       [0][1][2][1][RTW89_WW][89] = 48,
-       [0][1][2][1][RTW89_WW][90] = 48,
-       [0][1][2][1][RTW89_WW][92] = 48,
-       [0][1][2][1][RTW89_WW][94] = 48,
-       [0][1][2][1][RTW89_WW][96] = 48,
-       [0][1][2][1][RTW89_WW][98] = 48,
-       [0][1][2][1][RTW89_WW][100] = 48,
-       [0][1][2][1][RTW89_WW][102] = 48,
-       [0][1][2][1][RTW89_WW][104] = 48,
-       [0][1][2][1][RTW89_WW][105] = 48,
-       [0][1][2][1][RTW89_WW][107] = 48,
-       [0][1][2][1][RTW89_WW][109] = 48,
+       [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] = 72,
-       [1][0][2][0][RTW89_WW][5] = 72,
-       [1][0][2][0][RTW89_WW][9] = 72,
-       [1][0][2][0][RTW89_WW][13] = 72,
-       [1][0][2][0][RTW89_WW][16] = 72,
-       [1][0][2][0][RTW89_WW][20] = 72,
-       [1][0][2][0][RTW89_WW][24] = 72,
-       [1][0][2][0][RTW89_WW][28] = 72,
-       [1][0][2][0][RTW89_WW][31] = 72,
-       [1][0][2][0][RTW89_WW][35] = 72,
-       [1][0][2][0][RTW89_WW][39] = 72,
-       [1][0][2][0][RTW89_WW][43] = 72,
-       [1][0][2][0][RTW89_WW][46] = 72,
-       [1][0][2][0][RTW89_WW][50] = 72,
-       [1][0][2][0][RTW89_WW][54] = 72,
-       [1][0][2][0][RTW89_WW][58] = 72,
-       [1][0][2][0][RTW89_WW][61] = 72,
-       [1][0][2][0][RTW89_WW][65] = 72,
-       [1][0][2][0][RTW89_WW][69] = 72,
-       [1][0][2][0][RTW89_WW][73] = 72,
-       [1][0][2][0][RTW89_WW][76] = 72,
-       [1][0][2][0][RTW89_WW][80] = 72,
-       [1][0][2][0][RTW89_WW][84] = 72,
-       [1][0][2][0][RTW89_WW][88] = 72,
-       [1][0][2][0][RTW89_WW][91] = 72,
-       [1][0][2][0][RTW89_WW][95] = 72,
-       [1][0][2][0][RTW89_WW][99] = 72,
-       [1][0][2][0][RTW89_WW][103] = 72,
-       [1][0][2][0][RTW89_WW][106] = 72,
+       [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] = 60,
-       [1][1][2][0][RTW89_WW][5] = 60,
-       [1][1][2][0][RTW89_WW][9] = 60,
-       [1][1][2][0][RTW89_WW][13] = 60,
-       [1][1][2][0][RTW89_WW][16] = 60,
-       [1][1][2][0][RTW89_WW][20] = 60,
-       [1][1][2][0][RTW89_WW][24] = 60,
-       [1][1][2][0][RTW89_WW][28] = 60,
-       [1][1][2][0][RTW89_WW][31] = 60,
-       [1][1][2][0][RTW89_WW][35] = 60,
-       [1][1][2][0][RTW89_WW][39] = 60,
-       [1][1][2][0][RTW89_WW][43] = 60,
-       [1][1][2][0][RTW89_WW][46] = 60,
-       [1][1][2][0][RTW89_WW][50] = 60,
-       [1][1][2][0][RTW89_WW][54] = 60,
-       [1][1][2][0][RTW89_WW][58] = 60,
-       [1][1][2][0][RTW89_WW][61] = 60,
-       [1][1][2][0][RTW89_WW][65] = 60,
-       [1][1][2][0][RTW89_WW][69] = 60,
-       [1][1][2][0][RTW89_WW][73] = 60,
-       [1][1][2][0][RTW89_WW][76] = 60,
-       [1][1][2][0][RTW89_WW][80] = 60,
-       [1][1][2][0][RTW89_WW][84] = 60,
-       [1][1][2][0][RTW89_WW][88] = 60,
-       [1][1][2][0][RTW89_WW][91] = 60,
-       [1][1][2][0][RTW89_WW][95] = 60,
-       [1][1][2][0][RTW89_WW][99] = 60,
-       [1][1][2][0][RTW89_WW][103] = 60,
-       [1][1][2][0][RTW89_WW][106] = 60,
+       [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] = 48,
-       [1][1][2][1][RTW89_WW][5] = 48,
-       [1][1][2][1][RTW89_WW][9] = 48,
-       [1][1][2][1][RTW89_WW][13] = 48,
-       [1][1][2][1][RTW89_WW][16] = 48,
-       [1][1][2][1][RTW89_WW][20] = 48,
-       [1][1][2][1][RTW89_WW][24] = 48,
-       [1][1][2][1][RTW89_WW][28] = 48,
-       [1][1][2][1][RTW89_WW][31] = 48,
-       [1][1][2][1][RTW89_WW][35] = 48,
-       [1][1][2][1][RTW89_WW][39] = 48,
-       [1][1][2][1][RTW89_WW][43] = 48,
-       [1][1][2][1][RTW89_WW][46] = 48,
-       [1][1][2][1][RTW89_WW][50] = 48,
-       [1][1][2][1][RTW89_WW][54] = 48,
-       [1][1][2][1][RTW89_WW][58] = 48,
-       [1][1][2][1][RTW89_WW][61] = 48,
-       [1][1][2][1][RTW89_WW][65] = 48,
-       [1][1][2][1][RTW89_WW][69] = 48,
-       [1][1][2][1][RTW89_WW][73] = 48,
-       [1][1][2][1][RTW89_WW][76] = 48,
-       [1][1][2][1][RTW89_WW][80] = 48,
-       [1][1][2][1][RTW89_WW][84] = 48,
-       [1][1][2][1][RTW89_WW][88] = 48,
-       [1][1][2][1][RTW89_WW][91] = 48,
-       [1][1][2][1][RTW89_WW][95] = 48,
-       [1][1][2][1][RTW89_WW][99] = 48,
-       [1][1][2][1][RTW89_WW][103] = 48,
-       [1][1][2][1][RTW89_WW][106] = 48,
+       [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] = 64,
-       [2][0][2][0][RTW89_WW][11] = 64,
-       [2][0][2][0][RTW89_WW][18] = 64,
-       [2][0][2][0][RTW89_WW][26] = 64,
-       [2][0][2][0][RTW89_WW][33] = 64,
-       [2][0][2][0][RTW89_WW][41] = 64,
-       [2][0][2][0][RTW89_WW][48] = 64,
-       [2][0][2][0][RTW89_WW][56] = 64,
-       [2][0][2][0][RTW89_WW][63] = 64,
-       [2][0][2][0][RTW89_WW][71] = 64,
-       [2][0][2][0][RTW89_WW][78] = 64,
-       [2][0][2][0][RTW89_WW][86] = 64,
-       [2][0][2][0][RTW89_WW][93] = 64,
-       [2][0][2][0][RTW89_WW][101] = 64,
+       [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] = 52,
-       [2][1][2][0][RTW89_WW][11] = 52,
-       [2][1][2][0][RTW89_WW][18] = 52,
-       [2][1][2][0][RTW89_WW][26] = 52,
-       [2][1][2][0][RTW89_WW][33] = 52,
-       [2][1][2][0][RTW89_WW][41] = 52,
-       [2][1][2][0][RTW89_WW][48] = 52,
-       [2][1][2][0][RTW89_WW][56] = 52,
-       [2][1][2][0][RTW89_WW][63] = 52,
-       [2][1][2][0][RTW89_WW][71] = 52,
-       [2][1][2][0][RTW89_WW][78] = 52,
-       [2][1][2][0][RTW89_WW][86] = 52,
-       [2][1][2][0][RTW89_WW][93] = 52,
-       [2][1][2][0][RTW89_WW][101] = 52,
+       [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] = 40,
-       [2][1][2][1][RTW89_WW][11] = 40,
-       [2][1][2][1][RTW89_WW][18] = 40,
-       [2][1][2][1][RTW89_WW][26] = 40,
-       [2][1][2][1][RTW89_WW][33] = 40,
-       [2][1][2][1][RTW89_WW][41] = 40,
-       [2][1][2][1][RTW89_WW][48] = 40,
-       [2][1][2][1][RTW89_WW][56] = 40,
-       [2][1][2][1][RTW89_WW][63] = 40,
-       [2][1][2][1][RTW89_WW][71] = 40,
-       [2][1][2][1][RTW89_WW][78] = 40,
-       [2][1][2][1][RTW89_WW][86] = 40,
-       [2][1][2][1][RTW89_WW][93] = 40,
-       [2][1][2][1][RTW89_WW][101] = 40,
+       [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] = 56,
-       [3][0][2][0][RTW89_WW][22] = 56,
-       [3][0][2][0][RTW89_WW][37] = 56,
-       [3][0][2][0][RTW89_WW][52] = 56,
-       [3][0][2][0][RTW89_WW][67] = 56,
-       [3][0][2][0][RTW89_WW][82] = 56,
-       [3][0][2][0][RTW89_WW][97] = 56,
+       [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] = 44,
-       [3][1][2][0][RTW89_WW][22] = 44,
-       [3][1][2][0][RTW89_WW][37] = 44,
-       [3][1][2][0][RTW89_WW][52] = 44,
-       [3][1][2][0][RTW89_WW][67] = 44,
-       [3][1][2][0][RTW89_WW][82] = 44,
-       [3][1][2][0][RTW89_WW][97] = 44,
+       [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] = 32,
-       [3][1][2][1][RTW89_WW][37] = 32,
-       [3][1][2][1][RTW89_WW][52] = 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] = 32,
-       [3][1][2][1][RTW89_WW][97] = 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] = 72,
-       [0][0][1][0][RTW89_FCC][2] = 72,
-       [0][0][1][0][RTW89_FCC][4] = 72,
-       [0][0][1][0][RTW89_FCC][6] = 72,
-       [0][0][1][0][RTW89_FCC][8] = 72,
-       [0][0][1][0][RTW89_FCC][10] = 72,
-       [0][0][1][0][RTW89_FCC][12] = 72,
-       [0][0][1][0][RTW89_FCC][14] = 72,
-       [0][0][1][0][RTW89_FCC][15] = 72,
-       [0][0][1][0][RTW89_FCC][17] = 72,
-       [0][0][1][0][RTW89_FCC][19] = 72,
-       [0][0][1][0][RTW89_FCC][21] = 72,
-       [0][0][1][0][RTW89_FCC][23] = 72,
-       [0][0][1][0][RTW89_FCC][25] = 72,
-       [0][0][1][0][RTW89_FCC][27] = 72,
-       [0][0][1][0][RTW89_FCC][29] = 72,
-       [0][0][1][0][RTW89_FCC][30] = 72,
-       [0][0][1][0][RTW89_FCC][32] = 72,
-       [0][0][1][0][RTW89_FCC][34] = 72,
-       [0][0][1][0][RTW89_FCC][36] = 72,
-       [0][0][1][0][RTW89_FCC][38] = 72,
-       [0][0][1][0][RTW89_FCC][40] = 72,
-       [0][0][1][0][RTW89_FCC][42] = 72,
-       [0][0][1][0][RTW89_FCC][44] = 72,
-       [0][0][1][0][RTW89_FCC][45] = 72,
-       [0][0][1][0][RTW89_FCC][47] = 72,
-       [0][0][1][0][RTW89_FCC][49] = 72,
-       [0][0][1][0][RTW89_FCC][51] = 72,
-       [0][0][1][0][RTW89_FCC][53] = 72,
-       [0][0][1][0][RTW89_FCC][55] = 72,
-       [0][0][1][0][RTW89_FCC][57] = 72,
-       [0][0][1][0][RTW89_FCC][59] = 72,
-       [0][0][1][0][RTW89_FCC][60] = 72,
-       [0][0][1][0][RTW89_FCC][62] = 72,
-       [0][0][1][0][RTW89_FCC][64] = 72,
-       [0][0][1][0][RTW89_FCC][66] = 72,
-       [0][0][1][0][RTW89_FCC][68] = 72,
-       [0][0][1][0][RTW89_FCC][70] = 72,
-       [0][0][1][0][RTW89_FCC][72] = 72,
-       [0][0][1][0][RTW89_FCC][74] = 72,
-       [0][0][1][0][RTW89_FCC][75] = 72,
-       [0][0][1][0][RTW89_FCC][77] = 72,
-       [0][0][1][0][RTW89_FCC][79] = 72,
-       [0][0][1][0][RTW89_FCC][81] = 72,
-       [0][0][1][0][RTW89_FCC][83] = 72,
-       [0][0][1][0][RTW89_FCC][85] = 72,
-       [0][0][1][0][RTW89_FCC][87] = 72,
-       [0][0][1][0][RTW89_FCC][89] = 72,
-       [0][0][1][0][RTW89_FCC][90] = 72,
-       [0][0][1][0][RTW89_FCC][92] = 72,
-       [0][0][1][0][RTW89_FCC][94] = 72,
-       [0][0][1][0][RTW89_FCC][96] = 72,
-       [0][0][1][0][RTW89_FCC][98] = 72,
-       [0][0][1][0][RTW89_FCC][100] = 72,
-       [0][0][1][0][RTW89_FCC][102] = 72,
-       [0][0][1][0][RTW89_FCC][104] = 72,
-       [0][0][1][0][RTW89_FCC][105] = 72,
-       [0][0][1][0][RTW89_FCC][107] = 72,
-       [0][0][1][0][RTW89_FCC][109] = 72,
+       [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][1][1][0][RTW89_FCC][0] = 60,
-       [0][1][1][0][RTW89_FCC][2] = 60,
-       [0][1][1][0][RTW89_FCC][4] = 60,
-       [0][1][1][0][RTW89_FCC][6] = 60,
-       [0][1][1][0][RTW89_FCC][8] = 60,
-       [0][1][1][0][RTW89_FCC][10] = 60,
-       [0][1][1][0][RTW89_FCC][12] = 60,
-       [0][1][1][0][RTW89_FCC][14] = 60,
-       [0][1][1][0][RTW89_FCC][15] = 60,
-       [0][1][1][0][RTW89_FCC][17] = 60,
-       [0][1][1][0][RTW89_FCC][19] = 60,
-       [0][1][1][0][RTW89_FCC][21] = 60,
-       [0][1][1][0][RTW89_FCC][23] = 60,
-       [0][1][1][0][RTW89_FCC][25] = 60,
-       [0][1][1][0][RTW89_FCC][27] = 60,
-       [0][1][1][0][RTW89_FCC][29] = 60,
-       [0][1][1][0][RTW89_FCC][30] = 60,
-       [0][1][1][0][RTW89_FCC][32] = 60,
-       [0][1][1][0][RTW89_FCC][34] = 60,
-       [0][1][1][0][RTW89_FCC][36] = 60,
-       [0][1][1][0][RTW89_FCC][38] = 60,
-       [0][1][1][0][RTW89_FCC][40] = 60,
-       [0][1][1][0][RTW89_FCC][42] = 60,
-       [0][1][1][0][RTW89_FCC][44] = 60,
-       [0][1][1][0][RTW89_FCC][45] = 60,
-       [0][1][1][0][RTW89_FCC][47] = 60,
-       [0][1][1][0][RTW89_FCC][49] = 60,
-       [0][1][1][0][RTW89_FCC][51] = 60,
-       [0][1][1][0][RTW89_FCC][53] = 60,
-       [0][1][1][0][RTW89_FCC][55] = 60,
-       [0][1][1][0][RTW89_FCC][57] = 60,
-       [0][1][1][0][RTW89_FCC][59] = 60,
-       [0][1][1][0][RTW89_FCC][60] = 60,
-       [0][1][1][0][RTW89_FCC][62] = 60,
-       [0][1][1][0][RTW89_FCC][64] = 60,
-       [0][1][1][0][RTW89_FCC][66] = 60,
-       [0][1][1][0][RTW89_FCC][68] = 60,
-       [0][1][1][0][RTW89_FCC][70] = 60,
-       [0][1][1][0][RTW89_FCC][72] = 60,
-       [0][1][1][0][RTW89_FCC][74] = 60,
-       [0][1][1][0][RTW89_FCC][75] = 60,
-       [0][1][1][0][RTW89_FCC][77] = 60,
-       [0][1][1][0][RTW89_FCC][79] = 60,
-       [0][1][1][0][RTW89_FCC][81] = 60,
-       [0][1][1][0][RTW89_FCC][83] = 60,
-       [0][1][1][0][RTW89_FCC][85] = 60,
-       [0][1][1][0][RTW89_FCC][87] = 60,
-       [0][1][1][0][RTW89_FCC][89] = 60,
-       [0][1][1][0][RTW89_FCC][90] = 60,
-       [0][1][1][0][RTW89_FCC][92] = 60,
-       [0][1][1][0][RTW89_FCC][94] = 60,
-       [0][1][1][0][RTW89_FCC][96] = 60,
-       [0][1][1][0][RTW89_FCC][98] = 60,
-       [0][1][1][0][RTW89_FCC][100] = 60,
-       [0][1][1][0][RTW89_FCC][102] = 60,
-       [0][1][1][0][RTW89_FCC][104] = 60,
-       [0][1][1][0][RTW89_FCC][105] = 60,
-       [0][1][1][0][RTW89_FCC][107] = 60,
-       [0][1][1][0][RTW89_FCC][109] = 60,
+       [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][0][2][0][RTW89_FCC][0] = 72,
-       [0][0][2][0][RTW89_FCC][2] = 72,
-       [0][0][2][0][RTW89_FCC][4] = 72,
-       [0][0][2][0][RTW89_FCC][6] = 72,
-       [0][0][2][0][RTW89_FCC][8] = 72,
-       [0][0][2][0][RTW89_FCC][10] = 72,
-       [0][0][2][0][RTW89_FCC][12] = 72,
-       [0][0][2][0][RTW89_FCC][14] = 72,
-       [0][0][2][0][RTW89_FCC][15] = 72,
-       [0][0][2][0][RTW89_FCC][17] = 72,
-       [0][0][2][0][RTW89_FCC][19] = 72,
-       [0][0][2][0][RTW89_FCC][21] = 72,
-       [0][0][2][0][RTW89_FCC][23] = 72,
-       [0][0][2][0][RTW89_FCC][25] = 72,
-       [0][0][2][0][RTW89_FCC][27] = 72,
-       [0][0][2][0][RTW89_FCC][29] = 72,
-       [0][0][2][0][RTW89_FCC][30] = 72,
-       [0][0][2][0][RTW89_FCC][32] = 72,
-       [0][0][2][0][RTW89_FCC][34] = 72,
-       [0][0][2][0][RTW89_FCC][36] = 72,
-       [0][0][2][0][RTW89_FCC][38] = 72,
-       [0][0][2][0][RTW89_FCC][40] = 72,
-       [0][0][2][0][RTW89_FCC][42] = 72,
-       [0][0][2][0][RTW89_FCC][44] = 72,
-       [0][0][2][0][RTW89_FCC][45] = 72,
-       [0][0][2][0][RTW89_FCC][47] = 72,
-       [0][0][2][0][RTW89_FCC][49] = 72,
-       [0][0][2][0][RTW89_FCC][51] = 72,
-       [0][0][2][0][RTW89_FCC][53] = 72,
-       [0][0][2][0][RTW89_FCC][55] = 72,
-       [0][0][2][0][RTW89_FCC][57] = 72,
-       [0][0][2][0][RTW89_FCC][59] = 72,
-       [0][0][2][0][RTW89_FCC][60] = 72,
-       [0][0][2][0][RTW89_FCC][62] = 72,
-       [0][0][2][0][RTW89_FCC][64] = 72,
-       [0][0][2][0][RTW89_FCC][66] = 72,
-       [0][0][2][0][RTW89_FCC][68] = 72,
-       [0][0][2][0][RTW89_FCC][70] = 72,
-       [0][0][2][0][RTW89_FCC][72] = 72,
-       [0][0][2][0][RTW89_FCC][74] = 72,
-       [0][0][2][0][RTW89_FCC][75] = 72,
-       [0][0][2][0][RTW89_FCC][77] = 72,
-       [0][0][2][0][RTW89_FCC][79] = 72,
-       [0][0][2][0][RTW89_FCC][81] = 72,
-       [0][0][2][0][RTW89_FCC][83] = 72,
-       [0][0][2][0][RTW89_FCC][85] = 72,
-       [0][0][2][0][RTW89_FCC][87] = 72,
-       [0][0][2][0][RTW89_FCC][89] = 72,
-       [0][0][2][0][RTW89_FCC][90] = 72,
-       [0][0][2][0][RTW89_FCC][92] = 72,
-       [0][0][2][0][RTW89_FCC][94] = 72,
-       [0][0][2][0][RTW89_FCC][96] = 72,
-       [0][0][2][0][RTW89_FCC][98] = 72,
-       [0][0][2][0][RTW89_FCC][100] = 72,
-       [0][0][2][0][RTW89_FCC][102] = 72,
-       [0][0][2][0][RTW89_FCC][104] = 72,
-       [0][0][2][0][RTW89_FCC][105] = 72,
-       [0][0][2][0][RTW89_FCC][107] = 72,
-       [0][0][2][0][RTW89_FCC][109] = 72,
+       [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][1][2][0][RTW89_FCC][0] = 60,
-       [0][1][2][0][RTW89_FCC][2] = 60,
-       [0][1][2][0][RTW89_FCC][4] = 60,
-       [0][1][2][0][RTW89_FCC][6] = 60,
-       [0][1][2][0][RTW89_FCC][8] = 60,
-       [0][1][2][0][RTW89_FCC][10] = 60,
-       [0][1][2][0][RTW89_FCC][12] = 60,
-       [0][1][2][0][RTW89_FCC][14] = 60,
-       [0][1][2][0][RTW89_FCC][15] = 60,
-       [0][1][2][0][RTW89_FCC][17] = 60,
-       [0][1][2][0][RTW89_FCC][19] = 60,
-       [0][1][2][0][RTW89_FCC][21] = 60,
-       [0][1][2][0][RTW89_FCC][23] = 60,
-       [0][1][2][0][RTW89_FCC][25] = 60,
-       [0][1][2][0][RTW89_FCC][27] = 60,
-       [0][1][2][0][RTW89_FCC][29] = 60,
-       [0][1][2][0][RTW89_FCC][30] = 60,
-       [0][1][2][0][RTW89_FCC][32] = 60,
-       [0][1][2][0][RTW89_FCC][34] = 60,
-       [0][1][2][0][RTW89_FCC][36] = 60,
-       [0][1][2][0][RTW89_FCC][38] = 60,
-       [0][1][2][0][RTW89_FCC][40] = 60,
-       [0][1][2][0][RTW89_FCC][42] = 60,
-       [0][1][2][0][RTW89_FCC][44] = 60,
-       [0][1][2][0][RTW89_FCC][45] = 60,
-       [0][1][2][0][RTW89_FCC][47] = 60,
-       [0][1][2][0][RTW89_FCC][49] = 60,
-       [0][1][2][0][RTW89_FCC][51] = 60,
-       [0][1][2][0][RTW89_FCC][53] = 60,
-       [0][1][2][0][RTW89_FCC][55] = 60,
-       [0][1][2][0][RTW89_FCC][57] = 60,
-       [0][1][2][0][RTW89_FCC][59] = 60,
-       [0][1][2][0][RTW89_FCC][60] = 60,
-       [0][1][2][0][RTW89_FCC][62] = 60,
-       [0][1][2][0][RTW89_FCC][64] = 60,
-       [0][1][2][0][RTW89_FCC][66] = 60,
-       [0][1][2][0][RTW89_FCC][68] = 60,
-       [0][1][2][0][RTW89_FCC][70] = 60,
-       [0][1][2][0][RTW89_FCC][72] = 60,
-       [0][1][2][0][RTW89_FCC][74] = 60,
-       [0][1][2][0][RTW89_FCC][75] = 60,
-       [0][1][2][0][RTW89_FCC][77] = 60,
-       [0][1][2][0][RTW89_FCC][79] = 60,
-       [0][1][2][0][RTW89_FCC][81] = 60,
-       [0][1][2][0][RTW89_FCC][83] = 60,
-       [0][1][2][0][RTW89_FCC][85] = 60,
-       [0][1][2][0][RTW89_FCC][87] = 60,
-       [0][1][2][0][RTW89_FCC][89] = 60,
-       [0][1][2][0][RTW89_FCC][90] = 60,
-       [0][1][2][0][RTW89_FCC][92] = 60,
-       [0][1][2][0][RTW89_FCC][94] = 60,
-       [0][1][2][0][RTW89_FCC][96] = 60,
-       [0][1][2][0][RTW89_FCC][98] = 60,
-       [0][1][2][0][RTW89_FCC][100] = 60,
-       [0][1][2][0][RTW89_FCC][102] = 60,
-       [0][1][2][0][RTW89_FCC][104] = 60,
-       [0][1][2][0][RTW89_FCC][105] = 60,
-       [0][1][2][0][RTW89_FCC][107] = 60,
-       [0][1][2][0][RTW89_FCC][109] = 60,
+       [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][1][RTW89_FCC][0] = 48,
-       [0][1][2][1][RTW89_FCC][2] = 48,
-       [0][1][2][1][RTW89_FCC][4] = 48,
-       [0][1][2][1][RTW89_FCC][6] = 48,
-       [0][1][2][1][RTW89_FCC][8] = 48,
-       [0][1][2][1][RTW89_FCC][10] = 48,
-       [0][1][2][1][RTW89_FCC][12] = 48,
-       [0][1][2][1][RTW89_FCC][14] = 48,
-       [0][1][2][1][RTW89_FCC][15] = 48,
-       [0][1][2][1][RTW89_FCC][17] = 48,
-       [0][1][2][1][RTW89_FCC][19] = 48,
-       [0][1][2][1][RTW89_FCC][21] = 48,
-       [0][1][2][1][RTW89_FCC][23] = 48,
-       [0][1][2][1][RTW89_FCC][25] = 48,
-       [0][1][2][1][RTW89_FCC][27] = 48,
-       [0][1][2][1][RTW89_FCC][29] = 48,
-       [0][1][2][1][RTW89_FCC][30] = 48,
-       [0][1][2][1][RTW89_FCC][32] = 48,
-       [0][1][2][1][RTW89_FCC][34] = 48,
-       [0][1][2][1][RTW89_FCC][36] = 48,
-       [0][1][2][1][RTW89_FCC][38] = 48,
-       [0][1][2][1][RTW89_FCC][40] = 48,
-       [0][1][2][1][RTW89_FCC][42] = 48,
-       [0][1][2][1][RTW89_FCC][44] = 48,
-       [0][1][2][1][RTW89_FCC][45] = 48,
-       [0][1][2][1][RTW89_FCC][47] = 48,
-       [0][1][2][1][RTW89_FCC][49] = 48,
-       [0][1][2][1][RTW89_FCC][51] = 48,
-       [0][1][2][1][RTW89_FCC][53] = 48,
-       [0][1][2][1][RTW89_FCC][55] = 48,
-       [0][1][2][1][RTW89_FCC][57] = 48,
-       [0][1][2][1][RTW89_FCC][59] = 48,
-       [0][1][2][1][RTW89_FCC][60] = 48,
-       [0][1][2][1][RTW89_FCC][62] = 48,
-       [0][1][2][1][RTW89_FCC][64] = 48,
-       [0][1][2][1][RTW89_FCC][66] = 48,
-       [0][1][2][1][RTW89_FCC][68] = 48,
-       [0][1][2][1][RTW89_FCC][70] = 48,
-       [0][1][2][1][RTW89_FCC][72] = 48,
-       [0][1][2][1][RTW89_FCC][74] = 48,
-       [0][1][2][1][RTW89_FCC][75] = 48,
-       [0][1][2][1][RTW89_FCC][77] = 48,
-       [0][1][2][1][RTW89_FCC][79] = 48,
-       [0][1][2][1][RTW89_FCC][81] = 48,
-       [0][1][2][1][RTW89_FCC][83] = 48,
-       [0][1][2][1][RTW89_FCC][85] = 48,
-       [0][1][2][1][RTW89_FCC][87] = 48,
-       [0][1][2][1][RTW89_FCC][89] = 48,
-       [0][1][2][1][RTW89_FCC][90] = 48,
-       [0][1][2][1][RTW89_FCC][92] = 48,
-       [0][1][2][1][RTW89_FCC][94] = 48,
-       [0][1][2][1][RTW89_FCC][96] = 48,
-       [0][1][2][1][RTW89_FCC][98] = 48,
-       [0][1][2][1][RTW89_FCC][100] = 48,
-       [0][1][2][1][RTW89_FCC][102] = 48,
-       [0][1][2][1][RTW89_FCC][104] = 48,
-       [0][1][2][1][RTW89_FCC][105] = 48,
-       [0][1][2][1][RTW89_FCC][107] = 48,
-       [0][1][2][1][RTW89_FCC][109] = 48,
+       [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,
-       [1][0][2][0][RTW89_FCC][1] = 72,
-       [1][0][2][0][RTW89_FCC][5] = 72,
-       [1][0][2][0][RTW89_FCC][9] = 72,
-       [1][0][2][0][RTW89_FCC][13] = 72,
-       [1][0][2][0][RTW89_FCC][16] = 72,
-       [1][0][2][0][RTW89_FCC][20] = 72,
-       [1][0][2][0][RTW89_FCC][24] = 72,
-       [1][0][2][0][RTW89_FCC][28] = 72,
-       [1][0][2][0][RTW89_FCC][31] = 72,
-       [1][0][2][0][RTW89_FCC][35] = 72,
-       [1][0][2][0][RTW89_FCC][39] = 72,
-       [1][0][2][0][RTW89_FCC][43] = 72,
-       [1][0][2][0][RTW89_FCC][46] = 72,
-       [1][0][2][0][RTW89_FCC][50] = 72,
-       [1][0][2][0][RTW89_FCC][54] = 72,
-       [1][0][2][0][RTW89_FCC][58] = 72,
-       [1][0][2][0][RTW89_FCC][61] = 72,
-       [1][0][2][0][RTW89_FCC][65] = 72,
-       [1][0][2][0][RTW89_FCC][69] = 72,
-       [1][0][2][0][RTW89_FCC][73] = 72,
-       [1][0][2][0][RTW89_FCC][76] = 72,
-       [1][0][2][0][RTW89_FCC][80] = 72,
-       [1][0][2][0][RTW89_FCC][84] = 72,
-       [1][0][2][0][RTW89_FCC][88] = 72,
-       [1][0][2][0][RTW89_FCC][91] = 72,
-       [1][0][2][0][RTW89_FCC][95] = 72,
-       [1][0][2][0][RTW89_FCC][99] = 72,
-       [1][0][2][0][RTW89_FCC][103] = 72,
-       [1][0][2][0][RTW89_FCC][106] = 72,
+       [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][1][2][0][RTW89_FCC][1] = 60,
-       [1][1][2][0][RTW89_FCC][5] = 60,
-       [1][1][2][0][RTW89_FCC][9] = 60,
-       [1][1][2][0][RTW89_FCC][13] = 60,
-       [1][1][2][0][RTW89_FCC][16] = 60,
-       [1][1][2][0][RTW89_FCC][20] = 60,
-       [1][1][2][0][RTW89_FCC][24] = 60,
-       [1][1][2][0][RTW89_FCC][28] = 60,
-       [1][1][2][0][RTW89_FCC][31] = 60,
-       [1][1][2][0][RTW89_FCC][35] = 60,
-       [1][1][2][0][RTW89_FCC][39] = 60,
-       [1][1][2][0][RTW89_FCC][43] = 60,
-       [1][1][2][0][RTW89_FCC][46] = 60,
-       [1][1][2][0][RTW89_FCC][50] = 60,
-       [1][1][2][0][RTW89_FCC][54] = 60,
-       [1][1][2][0][RTW89_FCC][58] = 60,
-       [1][1][2][0][RTW89_FCC][61] = 60,
-       [1][1][2][0][RTW89_FCC][65] = 60,
-       [1][1][2][0][RTW89_FCC][69] = 60,
-       [1][1][2][0][RTW89_FCC][73] = 60,
-       [1][1][2][0][RTW89_FCC][76] = 60,
-       [1][1][2][0][RTW89_FCC][80] = 60,
-       [1][1][2][0][RTW89_FCC][84] = 60,
-       [1][1][2][0][RTW89_FCC][88] = 60,
-       [1][1][2][0][RTW89_FCC][91] = 60,
-       [1][1][2][0][RTW89_FCC][95] = 60,
-       [1][1][2][0][RTW89_FCC][99] = 60,
-       [1][1][2][0][RTW89_FCC][103] = 60,
-       [1][1][2][0][RTW89_FCC][106] = 60,
+       [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][1][RTW89_FCC][1] = 48,
-       [1][1][2][1][RTW89_FCC][5] = 48,
-       [1][1][2][1][RTW89_FCC][9] = 48,
-       [1][1][2][1][RTW89_FCC][13] = 48,
-       [1][1][2][1][RTW89_FCC][16] = 48,
-       [1][1][2][1][RTW89_FCC][20] = 48,
-       [1][1][2][1][RTW89_FCC][24] = 48,
-       [1][1][2][1][RTW89_FCC][28] = 48,
-       [1][1][2][1][RTW89_FCC][31] = 48,
-       [1][1][2][1][RTW89_FCC][35] = 48,
-       [1][1][2][1][RTW89_FCC][39] = 48,
-       [1][1][2][1][RTW89_FCC][43] = 48,
-       [1][1][2][1][RTW89_FCC][46] = 48,
-       [1][1][2][1][RTW89_FCC][50] = 48,
-       [1][1][2][1][RTW89_FCC][54] = 48,
-       [1][1][2][1][RTW89_FCC][58] = 48,
-       [1][1][2][1][RTW89_FCC][61] = 48,
-       [1][1][2][1][RTW89_FCC][65] = 48,
-       [1][1][2][1][RTW89_FCC][69] = 48,
-       [1][1][2][1][RTW89_FCC][73] = 48,
-       [1][1][2][1][RTW89_FCC][76] = 48,
-       [1][1][2][1][RTW89_FCC][80] = 48,
-       [1][1][2][1][RTW89_FCC][84] = 48,
-       [1][1][2][1][RTW89_FCC][88] = 48,
-       [1][1][2][1][RTW89_FCC][91] = 48,
-       [1][1][2][1][RTW89_FCC][95] = 48,
-       [1][1][2][1][RTW89_FCC][99] = 48,
-       [1][1][2][1][RTW89_FCC][103] = 48,
-       [1][1][2][1][RTW89_FCC][106] = 48,
+       [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,
-       [2][0][2][0][RTW89_FCC][3] = 64,
-       [2][0][2][0][RTW89_FCC][11] = 64,
-       [2][0][2][0][RTW89_FCC][18] = 64,
-       [2][0][2][0][RTW89_FCC][26] = 64,
-       [2][0][2][0][RTW89_FCC][33] = 64,
-       [2][0][2][0][RTW89_FCC][41] = 64,
-       [2][0][2][0][RTW89_FCC][48] = 64,
-       [2][0][2][0][RTW89_FCC][56] = 64,
-       [2][0][2][0][RTW89_FCC][63] = 64,
-       [2][0][2][0][RTW89_FCC][71] = 64,
-       [2][0][2][0][RTW89_FCC][78] = 64,
-       [2][0][2][0][RTW89_FCC][86] = 64,
-       [2][0][2][0][RTW89_FCC][93] = 64,
-       [2][0][2][0][RTW89_FCC][101] = 64,
+       [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][1][2][0][RTW89_FCC][3] = 52,
-       [2][1][2][0][RTW89_FCC][11] = 52,
-       [2][1][2][0][RTW89_FCC][18] = 52,
-       [2][1][2][0][RTW89_FCC][26] = 52,
-       [2][1][2][0][RTW89_FCC][33] = 52,
-       [2][1][2][0][RTW89_FCC][41] = 52,
-       [2][1][2][0][RTW89_FCC][48] = 52,
-       [2][1][2][0][RTW89_FCC][56] = 52,
-       [2][1][2][0][RTW89_FCC][63] = 52,
-       [2][1][2][0][RTW89_FCC][71] = 52,
-       [2][1][2][0][RTW89_FCC][78] = 52,
-       [2][1][2][0][RTW89_FCC][86] = 52,
-       [2][1][2][0][RTW89_FCC][93] = 52,
-       [2][1][2][0][RTW89_FCC][101] = 52,
+       [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][1][RTW89_FCC][3] = 40,
-       [2][1][2][1][RTW89_FCC][11] = 40,
-       [2][1][2][1][RTW89_FCC][18] = 40,
-       [2][1][2][1][RTW89_FCC][26] = 40,
-       [2][1][2][1][RTW89_FCC][33] = 40,
-       [2][1][2][1][RTW89_FCC][41] = 40,
-       [2][1][2][1][RTW89_FCC][48] = 40,
-       [2][1][2][1][RTW89_FCC][56] = 40,
-       [2][1][2][1][RTW89_FCC][63] = 40,
-       [2][1][2][1][RTW89_FCC][71] = 40,
-       [2][1][2][1][RTW89_FCC][78] = 40,
-       [2][1][2][1][RTW89_FCC][86] = 40,
-       [2][1][2][1][RTW89_FCC][93] = 40,
-       [2][1][2][1][RTW89_FCC][101] = 40,
+       [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,
-       [3][0][2][0][RTW89_FCC][7] = 56,
-       [3][0][2][0][RTW89_FCC][22] = 56,
-       [3][0][2][0][RTW89_FCC][37] = 56,
-       [3][0][2][0][RTW89_FCC][52] = 56,
-       [3][0][2][0][RTW89_FCC][67] = 56,
-       [3][0][2][0][RTW89_FCC][82] = 56,
-       [3][0][2][0][RTW89_FCC][97] = 56,
+       [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][1][2][0][RTW89_FCC][7] = 44,
-       [3][1][2][0][RTW89_FCC][22] = 44,
-       [3][1][2][0][RTW89_FCC][37] = 44,
-       [3][1][2][0][RTW89_FCC][52] = 44,
-       [3][1][2][0][RTW89_FCC][67] = 44,
-       [3][1][2][0][RTW89_FCC][82] = 44,
-       [3][1][2][0][RTW89_FCC][97] = 44,
+       [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_FCC][22] = 32,
-       [3][1][2][1][RTW89_FCC][37] = 32,
-       [3][1][2][1][RTW89_FCC][52] = 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_FCC][97] = 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,
 };
 
 const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
@@ -17126,8 +33220,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
        [0][0][RTW89_WW][8] = 32,
        [0][0][RTW89_WW][9] = 32,
        [0][0][RTW89_WW][10] = 32,
-       [0][0][RTW89_WW][11] = 32,
-       [0][0][RTW89_WW][12] = 24,
+       [0][0][RTW89_WW][11] = 26,
+       [0][0][RTW89_WW][12] = -20,
        [0][0][RTW89_WW][13] = 0,
        [0][1][RTW89_WW][0] = 20,
        [0][1][RTW89_WW][1] = 22,
@@ -17141,7 +33235,7 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
        [0][1][RTW89_WW][9] = 22,
        [0][1][RTW89_WW][10] = 22,
        [0][1][RTW89_WW][11] = 22,
-       [0][1][RTW89_WW][12] = 20,
+       [0][1][RTW89_WW][12] = -30,
        [0][1][RTW89_WW][13] = 0,
        [1][0][RTW89_WW][0] = 42,
        [1][0][RTW89_WW][1] = 44,
@@ -17154,8 +33248,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
        [1][0][RTW89_WW][8] = 44,
        [1][0][RTW89_WW][9] = 44,
        [1][0][RTW89_WW][10] = 44,
-       [1][0][RTW89_WW][11] = 42,
-       [1][0][RTW89_WW][12] = 30,
+       [1][0][RTW89_WW][11] = 36,
+       [1][0][RTW89_WW][12] = 4,
        [1][0][RTW89_WW][13] = 0,
        [1][1][RTW89_WW][0] = 32,
        [1][1][RTW89_WW][1] = 32,
@@ -17169,7 +33263,7 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
        [1][1][RTW89_WW][9] = 32,
        [1][1][RTW89_WW][10] = 32,
        [1][1][RTW89_WW][11] = 30,
-       [1][1][RTW89_WW][12] = 24,
+       [1][1][RTW89_WW][12] = -6,
        [1][1][RTW89_WW][13] = 0,
        [2][0][RTW89_WW][0] = 56,
        [2][0][RTW89_WW][1] = 56,
@@ -17182,8 +33276,8 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
        [2][0][RTW89_WW][8] = 56,
        [2][0][RTW89_WW][9] = 56,
        [2][0][RTW89_WW][10] = 56,
-       [2][0][RTW89_WW][11] = 42,
-       [2][0][RTW89_WW][12] = 38,
+       [2][0][RTW89_WW][11] = 48,
+       [2][0][RTW89_WW][12] = 16,
        [2][0][RTW89_WW][13] = 0,
        [2][1][RTW89_WW][0] = 44,
        [2][1][RTW89_WW][1] = 44,
@@ -17196,2213 +33290,3353 @@ const s8 rtw89_8852c_txpwr_lmt_ru_2g[RTW89_RU_NUM][RTW89_NTX_NUM]
        [2][1][RTW89_WW][8] = 44,
        [2][1][RTW89_WW][9] = 44,
        [2][1][RTW89_WW][10] = 44,
-       [2][1][RTW89_WW][11] = 30,
-       [2][1][RTW89_WW][12] = 26,
+       [2][1][RTW89_WW][11] = 44,
+       [2][1][RTW89_WW][12] = 6,
        [2][1][RTW89_WW][13] = 0,
        [0][0][RTW89_FCC][0] = 60,
        [0][0][RTW89_ETSI][0] = 34,
        [0][0][RTW89_MKK][0] = 36,
-       [0][0][RTW89_IC][0] = 68,
-       [0][0][RTW89_ACMA][0] = 32,
+       [0][0][RTW89_IC][0] = 60,
+       [0][0][RTW89_KCC][0] = 42,
+       [0][0][RTW89_ACMA][0] = 34,
+       [0][0][RTW89_CN][0] = 32,
+       [0][0][RTW89_UK][0] = 34,
        [0][0][RTW89_FCC][1] = 60,
        [0][0][RTW89_ETSI][1] = 38,
        [0][0][RTW89_MKK][1] = 40,
-       [0][0][RTW89_IC][1] = 68,
-       [0][0][RTW89_ACMA][1] = 32,
+       [0][0][RTW89_IC][1] = 60,
+       [0][0][RTW89_KCC][1] = 42,
+       [0][0][RTW89_ACMA][1] = 38,
+       [0][0][RTW89_CN][1] = 32,
+       [0][0][RTW89_UK][1] = 38,
        [0][0][RTW89_FCC][2] = 64,
        [0][0][RTW89_ETSI][2] = 38,
        [0][0][RTW89_MKK][2] = 40,
-       [0][0][RTW89_IC][2] = 72,
-       [0][0][RTW89_ACMA][2] = 32,
+       [0][0][RTW89_IC][2] = 64,
+       [0][0][RTW89_KCC][2] = 42,
+       [0][0][RTW89_ACMA][2] = 38,
+       [0][0][RTW89_CN][2] = 32,
+       [0][0][RTW89_UK][2] = 38,
        [0][0][RTW89_FCC][3] = 68,
        [0][0][RTW89_ETSI][3] = 38,
        [0][0][RTW89_MKK][3] = 40,
-       [0][0][RTW89_IC][3] = 76,
-       [0][0][RTW89_ACMA][3] = 32,
+       [0][0][RTW89_IC][3] = 68,
+       [0][0][RTW89_KCC][3] = 42,
+       [0][0][RTW89_ACMA][3] = 38,
+       [0][0][RTW89_CN][3] = 32,
+       [0][0][RTW89_UK][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] = 76,
-       [0][0][RTW89_ACMA][4] = 32,
-       [0][0][RTW89_FCC][5] = 76,
+       [0][0][RTW89_IC][4] = 68,
+       [0][0][RTW89_KCC][4] = 42,
+       [0][0][RTW89_ACMA][4] = 38,
+       [0][0][RTW89_CN][4] = 32,
+       [0][0][RTW89_UK][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] = 84,
-       [0][0][RTW89_ACMA][5] = 32,
-       [0][0][RTW89_FCC][6] = 66,
+       [0][0][RTW89_IC][5] = 78,
+       [0][0][RTW89_KCC][5] = 42,
+       [0][0][RTW89_ACMA][5] = 38,
+       [0][0][RTW89_CN][5] = 32,
+       [0][0][RTW89_UK][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] = 74,
-       [0][0][RTW89_ACMA][6] = 32,
-       [0][0][RTW89_FCC][7] = 66,
+       [0][0][RTW89_IC][6] = 54,
+       [0][0][RTW89_KCC][6] = 42,
+       [0][0][RTW89_ACMA][6] = 38,
+       [0][0][RTW89_CN][6] = 32,
+       [0][0][RTW89_UK][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] = 74,
-       [0][0][RTW89_ACMA][7] = 32,
-       [0][0][RTW89_FCC][8] = 62,
+       [0][0][RTW89_IC][7] = 54,
+       [0][0][RTW89_KCC][7] = 42,
+       [0][0][RTW89_ACMA][7] = 38,
+       [0][0][RTW89_CN][7] = 32,
+       [0][0][RTW89_UK][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] = 70,
-       [0][0][RTW89_ACMA][8] = 32,
-       [0][0][RTW89_FCC][9] = 58,
+       [0][0][RTW89_IC][8] = 50,
+       [0][0][RTW89_KCC][8] = 42,
+       [0][0][RTW89_ACMA][8] = 38,
+       [0][0][RTW89_CN][8] = 32,
+       [0][0][RTW89_UK][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] = 66,
-       [0][0][RTW89_ACMA][9] = 32,
-       [0][0][RTW89_FCC][10] = 58,
+       [0][0][RTW89_IC][9] = 46,
+       [0][0][RTW89_KCC][9] = 40,
+       [0][0][RTW89_ACMA][9] = 38,
+       [0][0][RTW89_CN][9] = 32,
+       [0][0][RTW89_UK][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] = 66,
-       [0][0][RTW89_ACMA][10] = 32,
-       [0][0][RTW89_FCC][11] = 42,
+       [0][0][RTW89_IC][10] = 46,
+       [0][0][RTW89_KCC][10] = 40,
+       [0][0][RTW89_ACMA][10] = 38,
+       [0][0][RTW89_CN][10] = 32,
+       [0][0][RTW89_UK][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] = 56,
-       [0][0][RTW89_ACMA][11] = 32,
-       [0][0][RTW89_FCC][12] = 24,
+       [0][0][RTW89_IC][11] = 26,
+       [0][0][RTW89_KCC][11] = 40,
+       [0][0][RTW89_ACMA][11] = 38,
+       [0][0][RTW89_CN][11] = 32,
+       [0][0][RTW89_UK][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] = 32,
-       [0][0][RTW89_ACMA][12] = 32,
+       [0][0][RTW89_IC][12] = -20,
+       [0][0][RTW89_KCC][12] = 40,
+       [0][0][RTW89_ACMA][12] = 34,
+       [0][0][RTW89_CN][12] = 32,
+       [0][0][RTW89_UK][12] = 34,
        [0][0][RTW89_FCC][13] = 127,
        [0][0][RTW89_ETSI][13] = 127,
        [0][0][RTW89_MKK][13] = 127,
        [0][0][RTW89_IC][13] = 127,
+       [0][0][RTW89_KCC][13] = 127,
        [0][0][RTW89_ACMA][13] = 127,
-       [0][1][RTW89_FCC][0] = 46,
+       [0][0][RTW89_CN][13] = 127,
+       [0][0][RTW89_UK][13] = 127,
+       [0][1][RTW89_FCC][0] = 56,
        [0][1][RTW89_ETSI][0] = 22,
        [0][1][RTW89_MKK][0] = 24,
-       [0][1][RTW89_IC][0] = 62,
-       [0][1][RTW89_ACMA][0] = 20,
-       [0][1][RTW89_FCC][1] = 46,
+       [0][1][RTW89_IC][0] = 56,
+       [0][1][RTW89_KCC][0] = 30,
+       [0][1][RTW89_ACMA][0] = 22,
+       [0][1][RTW89_CN][0] = 20,
+       [0][1][RTW89_UK][0] = 22,
+       [0][1][RTW89_FCC][1] = 56,
        [0][1][RTW89_ETSI][1] = 24,
        [0][1][RTW89_MKK][1] = 30,
-       [0][1][RTW89_IC][1] = 62,
-       [0][1][RTW89_ACMA][1] = 22,
-       [0][1][RTW89_FCC][2] = 50,
+       [0][1][RTW89_IC][1] = 56,
+       [0][1][RTW89_KCC][1] = 30,
+       [0][1][RTW89_ACMA][1] = 24,
+       [0][1][RTW89_CN][1] = 22,
+       [0][1][RTW89_UK][1] = 24,
+       [0][1][RTW89_FCC][2] = 60,
        [0][1][RTW89_ETSI][2] = 24,
        [0][1][RTW89_MKK][2] = 30,
-       [0][1][RTW89_IC][2] = 66,
-       [0][1][RTW89_ACMA][2] = 22,
-       [0][1][RTW89_FCC][3] = 54,
+       [0][1][RTW89_IC][2] = 60,
+       [0][1][RTW89_KCC][2] = 30,
+       [0][1][RTW89_ACMA][2] = 24,
+       [0][1][RTW89_CN][2] = 22,
+       [0][1][RTW89_UK][2] = 24,
+       [0][1][RTW89_FCC][3] = 64,
        [0][1][RTW89_ETSI][3] = 24,
        [0][1][RTW89_MKK][3] = 30,
-       [0][1][RTW89_IC][3] = 70,
-       [0][1][RTW89_ACMA][3] = 22,
-       [0][1][RTW89_FCC][4] = 58,
+       [0][1][RTW89_IC][3] = 64,
+       [0][1][RTW89_KCC][3] = 30,
+       [0][1][RTW89_ACMA][3] = 24,
+       [0][1][RTW89_CN][3] = 22,
+       [0][1][RTW89_UK][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] = 74,
-       [0][1][RTW89_ACMA][4] = 22,
-       [0][1][RTW89_FCC][5] = 66,
+       [0][1][RTW89_IC][4] = 68,
+       [0][1][RTW89_KCC][4] = 28,
+       [0][1][RTW89_ACMA][4] = 24,
+       [0][1][RTW89_CN][4] = 22,
+       [0][1][RTW89_UK][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] = 74,
-       [0][1][RTW89_ACMA][5] = 22,
-       [0][1][RTW89_FCC][6] = 58,
+       [0][1][RTW89_IC][5] = 76,
+       [0][1][RTW89_KCC][5] = 28,
+       [0][1][RTW89_ACMA][5] = 24,
+       [0][1][RTW89_CN][5] = 22,
+       [0][1][RTW89_UK][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] = 72,
-       [0][1][RTW89_ACMA][6] = 22,
-       [0][1][RTW89_FCC][7] = 54,
+       [0][1][RTW89_IC][6] = 54,
+       [0][1][RTW89_KCC][6] = 28,
+       [0][1][RTW89_ACMA][6] = 24,
+       [0][1][RTW89_CN][6] = 22,
+       [0][1][RTW89_UK][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] = 68,
-       [0][1][RTW89_ACMA][7] = 22,
-       [0][1][RTW89_FCC][8] = 50,
+       [0][1][RTW89_IC][7] = 50,
+       [0][1][RTW89_KCC][7] = 28,
+       [0][1][RTW89_ACMA][7] = 24,
+       [0][1][RTW89_CN][7] = 22,
+       [0][1][RTW89_UK][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] = 64,
-       [0][1][RTW89_ACMA][8] = 22,
-       [0][1][RTW89_FCC][9] = 46,
+       [0][1][RTW89_IC][8] = 46,
+       [0][1][RTW89_KCC][8] = 28,
+       [0][1][RTW89_ACMA][8] = 24,
+       [0][1][RTW89_CN][8] = 22,
+       [0][1][RTW89_UK][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] = 60,
-       [0][1][RTW89_ACMA][9] = 22,
-       [0][1][RTW89_FCC][10] = 46,
+       [0][1][RTW89_IC][9] = 42,
+       [0][1][RTW89_KCC][9] = 28,
+       [0][1][RTW89_ACMA][9] = 24,
+       [0][1][RTW89_CN][9] = 22,
+       [0][1][RTW89_UK][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] = 60,
-       [0][1][RTW89_ACMA][10] = 22,
-       [0][1][RTW89_FCC][11] = 30,
+       [0][1][RTW89_IC][10] = 42,
+       [0][1][RTW89_KCC][10] = 28,
+       [0][1][RTW89_ACMA][10] = 24,
+       [0][1][RTW89_CN][10] = 22,
+       [0][1][RTW89_UK][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] = 52,
-       [0][1][RTW89_ACMA][11] = 22,
-       [0][1][RTW89_FCC][12] = 22,
+       [0][1][RTW89_IC][11] = 22,
+       [0][1][RTW89_KCC][11] = 28,
+       [0][1][RTW89_ACMA][11] = 24,
+       [0][1][RTW89_CN][11] = 22,
+       [0][1][RTW89_UK][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_IC][12] = -30,
+       [0][1][RTW89_KCC][12] = 28,
        [0][1][RTW89_ACMA][12] = 20,
+       [0][1][RTW89_CN][12] = 20,
+       [0][1][RTW89_UK][12] = 20,
        [0][1][RTW89_FCC][13] = 127,
        [0][1][RTW89_ETSI][13] = 127,
        [0][1][RTW89_MKK][13] = 127,
        [0][1][RTW89_IC][13] = 127,
+       [0][1][RTW89_KCC][13] = 127,
        [0][1][RTW89_ACMA][13] = 127,
-       [1][0][RTW89_FCC][0] = 64,
+       [0][1][RTW89_CN][13] = 127,
+       [0][1][RTW89_UK][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] = 78,
-       [1][0][RTW89_ACMA][0] = 42,
-       [1][0][RTW89_FCC][1] = 64,
+       [1][0][RTW89_IC][0] = 66,
+       [1][0][RTW89_KCC][0] = 50,
+       [1][0][RTW89_ACMA][0] = 46,
+       [1][0][RTW89_CN][0] = 42,
+       [1][0][RTW89_UK][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] = 78,
-       [1][0][RTW89_ACMA][1] = 44,
-       [1][0][RTW89_FCC][2] = 68,
+       [1][0][RTW89_IC][1] = 66,
+       [1][0][RTW89_KCC][1] = 50,
+       [1][0][RTW89_ACMA][1] = 46,
+       [1][0][RTW89_CN][1] = 44,
+       [1][0][RTW89_UK][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] = 82,
-       [1][0][RTW89_ACMA][2] = 44,
-       [1][0][RTW89_FCC][3] = 70,
+       [1][0][RTW89_IC][2] = 70,
+       [1][0][RTW89_KCC][2] = 50,
+       [1][0][RTW89_ACMA][2] = 46,
+       [1][0][RTW89_CN][2] = 44,
+       [1][0][RTW89_UK][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] = 84,
-       [1][0][RTW89_ACMA][3] = 44,
-       [1][0][RTW89_FCC][4] = 70,
+       [1][0][RTW89_IC][3] = 72,
+       [1][0][RTW89_KCC][3] = 50,
+       [1][0][RTW89_ACMA][3] = 46,
+       [1][0][RTW89_CN][3] = 44,
+       [1][0][RTW89_UK][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] = 84,
-       [1][0][RTW89_ACMA][4] = 44,
-       [1][0][RTW89_FCC][5] = 76,
+       [1][0][RTW89_IC][4] = 72,
+       [1][0][RTW89_KCC][4] = 50,
+       [1][0][RTW89_ACMA][4] = 46,
+       [1][0][RTW89_CN][4] = 44,
+       [1][0][RTW89_UK][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] = 84,
-       [1][0][RTW89_ACMA][5] = 44,
-       [1][0][RTW89_FCC][6] = 64,
+       [1][0][RTW89_IC][5] = 82,
+       [1][0][RTW89_KCC][5] = 50,
+       [1][0][RTW89_ACMA][5] = 46,
+       [1][0][RTW89_CN][5] = 44,
+       [1][0][RTW89_UK][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] = 78,
+       [1][0][RTW89_IC][6] = 58,
+       [1][0][RTW89_KCC][6] = 50,
        [1][0][RTW89_ACMA][6] = 44,
-       [1][0][RTW89_FCC][7] = 64,
+       [1][0][RTW89_CN][6] = 44,
+       [1][0][RTW89_UK][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] = 78,
-       [1][0][RTW89_ACMA][7] = 44,
-       [1][0][RTW89_FCC][8] = 64,
+       [1][0][RTW89_IC][7] = 58,
+       [1][0][RTW89_KCC][7] = 50,
+       [1][0][RTW89_ACMA][7] = 46,
+       [1][0][RTW89_CN][7] = 44,
+       [1][0][RTW89_UK][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] = 78,
-       [1][0][RTW89_ACMA][8] = 44,
-       [1][0][RTW89_FCC][9] = 60,
+       [1][0][RTW89_IC][8] = 58,
+       [1][0][RTW89_KCC][8] = 50,
+       [1][0][RTW89_ACMA][8] = 46,
+       [1][0][RTW89_CN][8] = 44,
+       [1][0][RTW89_UK][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] = 74,
-       [1][0][RTW89_ACMA][9] = 44,
-       [1][0][RTW89_FCC][10] = 60,
+       [1][0][RTW89_IC][9] = 54,
+       [1][0][RTW89_KCC][9] = 50,
+       [1][0][RTW89_ACMA][9] = 46,
+       [1][0][RTW89_CN][9] = 44,
+       [1][0][RTW89_UK][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] = 74,
-       [1][0][RTW89_ACMA][10] = 44,
-       [1][0][RTW89_FCC][11] = 42,
+       [1][0][RTW89_IC][10] = 54,
+       [1][0][RTW89_KCC][10] = 50,
+       [1][0][RTW89_ACMA][10] = 46,
+       [1][0][RTW89_CN][10] = 44,
+       [1][0][RTW89_UK][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] = 72,
-       [1][0][RTW89_ACMA][11] = 44,
-       [1][0][RTW89_FCC][12] = 30,
+       [1][0][RTW89_IC][11] = 36,
+       [1][0][RTW89_KCC][11] = 50,
+       [1][0][RTW89_ACMA][11] = 46,
+       [1][0][RTW89_CN][11] = 44,
+       [1][0][RTW89_UK][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] = 38,
-       [1][0][RTW89_ACMA][12] = 42,
+       [1][0][RTW89_IC][12] = 4,
+       [1][0][RTW89_KCC][12] = 50,
+       [1][0][RTW89_ACMA][12] = 46,
+       [1][0][RTW89_CN][12] = 42,
+       [1][0][RTW89_UK][12] = 46,
        [1][0][RTW89_FCC][13] = 127,
        [1][0][RTW89_ETSI][13] = 127,
        [1][0][RTW89_MKK][13] = 127,
        [1][0][RTW89_IC][13] = 127,
+       [1][0][RTW89_KCC][13] = 127,
        [1][0][RTW89_ACMA][13] = 127,
-       [1][1][RTW89_FCC][0] = 46,
+       [1][0][RTW89_CN][13] = 127,
+       [1][0][RTW89_UK][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] = 66,
+       [1][1][RTW89_IC][0] = 58,
+       [1][1][RTW89_KCC][0] = 38,
        [1][1][RTW89_ACMA][0] = 32,
-       [1][1][RTW89_FCC][1] = 46,
+       [1][1][RTW89_CN][0] = 32,
+       [1][1][RTW89_UK][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] = 66,
-       [1][1][RTW89_ACMA][1] = 32,
-       [1][1][RTW89_FCC][2] = 50,
+       [1][1][RTW89_IC][1] = 58,
+       [1][1][RTW89_KCC][1] = 38,
+       [1][1][RTW89_ACMA][1] = 34,
+       [1][1][RTW89_CN][1] = 32,
+       [1][1][RTW89_UK][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] = 70,
-       [1][1][RTW89_ACMA][2] = 32,
-       [1][1][RTW89_FCC][3] = 54,
+       [1][1][RTW89_IC][2] = 62,
+       [1][1][RTW89_KCC][2] = 38,
+       [1][1][RTW89_ACMA][2] = 34,
+       [1][1][RTW89_CN][2] = 32,
+       [1][1][RTW89_UK][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] = 74,
-       [1][1][RTW89_ACMA][3] = 32,
-       [1][1][RTW89_FCC][4] = 58,
+       [1][1][RTW89_IC][3] = 66,
+       [1][1][RTW89_KCC][3] = 38,
+       [1][1][RTW89_ACMA][3] = 34,
+       [1][1][RTW89_CN][3] = 32,
+       [1][1][RTW89_UK][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] = 74,
-       [1][1][RTW89_ACMA][4] = 32,
-       [1][1][RTW89_FCC][5] = 66,
+       [1][1][RTW89_IC][4] = 70,
+       [1][1][RTW89_KCC][4] = 38,
+       [1][1][RTW89_ACMA][4] = 34,
+       [1][1][RTW89_CN][4] = 32,
+       [1][1][RTW89_UK][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] = 74,
-       [1][1][RTW89_ACMA][5] = 32,
-       [1][1][RTW89_FCC][6] = 58,
+       [1][1][RTW89_IC][5] = 82,
+       [1][1][RTW89_KCC][5] = 38,
+       [1][1][RTW89_ACMA][5] = 34,
+       [1][1][RTW89_CN][5] = 32,
+       [1][1][RTW89_UK][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] = 74,
-       [1][1][RTW89_ACMA][6] = 32,
-       [1][1][RTW89_FCC][7] = 54,
+       [1][1][RTW89_IC][6] = 60,
+       [1][1][RTW89_KCC][6] = 38,
+       [1][1][RTW89_ACMA][6] = 34,
+       [1][1][RTW89_CN][6] = 32,
+       [1][1][RTW89_UK][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] = 74,
-       [1][1][RTW89_ACMA][7] = 32,
-       [1][1][RTW89_FCC][8] = 50,
+       [1][1][RTW89_IC][7] = 56,
+       [1][1][RTW89_KCC][7] = 38,
+       [1][1][RTW89_ACMA][7] = 34,
+       [1][1][RTW89_CN][7] = 32,
+       [1][1][RTW89_UK][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] = 70,
-       [1][1][RTW89_ACMA][8] = 32,
-       [1][1][RTW89_FCC][9] = 46,
+       [1][1][RTW89_IC][8] = 52,
+       [1][1][RTW89_KCC][8] = 38,
+       [1][1][RTW89_ACMA][8] = 34,
+       [1][1][RTW89_CN][8] = 32,
+       [1][1][RTW89_UK][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] = 66,
-       [1][1][RTW89_ACMA][9] = 32,
-       [1][1][RTW89_FCC][10] = 46,
+       [1][1][RTW89_IC][9] = 48,
+       [1][1][RTW89_KCC][9] = 38,
+       [1][1][RTW89_ACMA][9] = 34,
+       [1][1][RTW89_CN][9] = 32,
+       [1][1][RTW89_UK][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] = 66,
-       [1][1][RTW89_ACMA][10] = 32,
+       [1][1][RTW89_IC][10] = 48,
+       [1][1][RTW89_KCC][10] = 38,
+       [1][1][RTW89_ACMA][10] = 34,
+       [1][1][RTW89_CN][10] = 32,
+       [1][1][RTW89_UK][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] = 48,
-       [1][1][RTW89_ACMA][11] = 32,
-       [1][1][RTW89_FCC][12] = 24,
+       [1][1][RTW89_IC][11] = 30,
+       [1][1][RTW89_KCC][11] = 38,
+       [1][1][RTW89_ACMA][11] = 34,
+       [1][1][RTW89_CN][11] = 32,
+       [1][1][RTW89_UK][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] = 32,
-       [1][1][RTW89_ACMA][12] = 32,
+       [1][1][RTW89_IC][12] = -6,
+       [1][1][RTW89_KCC][12] = 38,
+       [1][1][RTW89_ACMA][12] = 34,
+       [1][1][RTW89_CN][12] = 32,
+       [1][1][RTW89_UK][12] = 34,
        [1][1][RTW89_FCC][13] = 127,
        [1][1][RTW89_ETSI][13] = 127,
        [1][1][RTW89_MKK][13] = 127,
        [1][1][RTW89_IC][13] = 127,
+       [1][1][RTW89_KCC][13] = 127,
        [1][1][RTW89_ACMA][13] = 127,
-       [2][0][RTW89_FCC][0] = 64,
+       [1][1][RTW89_CN][13] = 127,
+       [1][1][RTW89_UK][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] = 78,
-       [2][0][RTW89_ACMA][0] = 56,
-       [2][0][RTW89_FCC][1] = 64,
+       [2][0][RTW89_IC][0] = 70,
+       [2][0][RTW89_KCC][0] = 64,
+       [2][0][RTW89_ACMA][0] = 58,
+       [2][0][RTW89_CN][0] = 56,
+       [2][0][RTW89_UK][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] = 78,
-       [2][0][RTW89_ACMA][1] = 56,
-       [2][0][RTW89_FCC][2] = 66,
+       [2][0][RTW89_IC][1] = 70,
+       [2][0][RTW89_KCC][1] = 64,
+       [2][0][RTW89_ACMA][1] = 58,
+       [2][0][RTW89_CN][1] = 56,
+       [2][0][RTW89_UK][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] = 80,
-       [2][0][RTW89_ACMA][2] = 56,
-       [2][0][RTW89_FCC][3] = 66,
+       [2][0][RTW89_IC][2] = 72,
+       [2][0][RTW89_KCC][2] = 64,
+       [2][0][RTW89_ACMA][2] = 58,
+       [2][0][RTW89_CN][2] = 56,
+       [2][0][RTW89_UK][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] = 80,
-       [2][0][RTW89_ACMA][3] = 56,
-       [2][0][RTW89_FCC][4] = 66,
+       [2][0][RTW89_IC][3] = 72,
+       [2][0][RTW89_KCC][3] = 64,
+       [2][0][RTW89_ACMA][3] = 58,
+       [2][0][RTW89_CN][3] = 56,
+       [2][0][RTW89_UK][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] = 80,
-       [2][0][RTW89_ACMA][4] = 56,
-       [2][0][RTW89_FCC][5] = 76,
+       [2][0][RTW89_IC][4] = 72,
+       [2][0][RTW89_KCC][4] = 64,
+       [2][0][RTW89_ACMA][4] = 58,
+       [2][0][RTW89_CN][4] = 56,
+       [2][0][RTW89_UK][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] = 84,
-       [2][0][RTW89_ACMA][5] = 56,
-       [2][0][RTW89_FCC][6] = 62,
+       [2][0][RTW89_IC][5] = 82,
+       [2][0][RTW89_KCC][5] = 64,
+       [2][0][RTW89_ACMA][5] = 58,
+       [2][0][RTW89_CN][5] = 56,
+       [2][0][RTW89_UK][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] = 76,
+       [2][0][RTW89_IC][6] = 66,
+       [2][0][RTW89_KCC][6] = 64,
        [2][0][RTW89_ACMA][6] = 56,
-       [2][0][RTW89_FCC][7] = 62,
+       [2][0][RTW89_CN][6] = 56,
+       [2][0][RTW89_UK][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] = 76,
-       [2][0][RTW89_ACMA][7] = 56,
-       [2][0][RTW89_FCC][8] = 62,
+       [2][0][RTW89_IC][7] = 66,
+       [2][0][RTW89_KCC][7] = 64,
+       [2][0][RTW89_ACMA][7] = 58,
+       [2][0][RTW89_CN][7] = 56,
+       [2][0][RTW89_UK][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] = 76,
-       [2][0][RTW89_ACMA][8] = 56,
-       [2][0][RTW89_FCC][9] = 60,
+       [2][0][RTW89_IC][8] = 66,
+       [2][0][RTW89_KCC][8] = 64,
+       [2][0][RTW89_ACMA][8] = 58,
+       [2][0][RTW89_CN][8] = 56,
+       [2][0][RTW89_UK][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] = 74,
-       [2][0][RTW89_ACMA][9] = 56,
-       [2][0][RTW89_FCC][10] = 60,
+       [2][0][RTW89_IC][9] = 64,
+       [2][0][RTW89_KCC][9] = 64,
+       [2][0][RTW89_ACMA][9] = 58,
+       [2][0][RTW89_CN][9] = 56,
+       [2][0][RTW89_UK][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] = 74,
-       [2][0][RTW89_ACMA][10] = 56,
-       [2][0][RTW89_FCC][11] = 42,
+       [2][0][RTW89_IC][10] = 64,
+       [2][0][RTW89_KCC][10] = 64,
+       [2][0][RTW89_ACMA][10] = 58,
+       [2][0][RTW89_CN][10] = 56,
+       [2][0][RTW89_UK][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] = 66,
-       [2][0][RTW89_ACMA][11] = 56,
-       [2][0][RTW89_FCC][12] = 38,
+       [2][0][RTW89_IC][11] = 48,
+       [2][0][RTW89_KCC][11] = 64,
+       [2][0][RTW89_ACMA][11] = 58,
+       [2][0][RTW89_CN][11] = 56,
+       [2][0][RTW89_UK][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] = 56,
-       [2][0][RTW89_ACMA][12] = 56,
+       [2][0][RTW89_IC][12] = 16,
+       [2][0][RTW89_KCC][12] = 64,
+       [2][0][RTW89_ACMA][12] = 58,
+       [2][0][RTW89_CN][12] = 56,
+       [2][0][RTW89_UK][12] = 58,
        [2][0][RTW89_FCC][13] = 127,
        [2][0][RTW89_ETSI][13] = 127,
        [2][0][RTW89_MKK][13] = 127,
        [2][0][RTW89_IC][13] = 127,
+       [2][0][RTW89_KCC][13] = 127,
        [2][0][RTW89_ACMA][13] = 127,
-       [2][1][RTW89_FCC][0] = 46,
+       [2][0][RTW89_CN][13] = 127,
+       [2][0][RTW89_UK][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] = 70,
-       [2][1][RTW89_ACMA][0] = 44,
-       [2][1][RTW89_FCC][1] = 46,
+       [2][1][RTW89_IC][0] = 64,
+       [2][1][RTW89_KCC][0] = 52,
+       [2][1][RTW89_ACMA][0] = 46,
+       [2][1][RTW89_CN][0] = 44,
+       [2][1][RTW89_UK][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] = 70,
-       [2][1][RTW89_ACMA][1] = 44,
-       [2][1][RTW89_FCC][2] = 50,
+       [2][1][RTW89_IC][1] = 64,
+       [2][1][RTW89_KCC][1] = 52,
+       [2][1][RTW89_ACMA][1] = 46,
+       [2][1][RTW89_CN][1] = 44,
+       [2][1][RTW89_UK][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] = 74,
-       [2][1][RTW89_ACMA][2] = 44,
-       [2][1][RTW89_FCC][3] = 54,
+       [2][1][RTW89_IC][2] = 68,
+       [2][1][RTW89_KCC][2] = 52,
+       [2][1][RTW89_ACMA][2] = 46,
+       [2][1][RTW89_CN][2] = 44,
+       [2][1][RTW89_UK][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] = 78,
-       [2][1][RTW89_ACMA][3] = 44,
-       [2][1][RTW89_FCC][4] = 56,
+       [2][1][RTW89_IC][3] = 72,
+       [2][1][RTW89_KCC][3] = 52,
+       [2][1][RTW89_ACMA][3] = 46,
+       [2][1][RTW89_CN][3] = 44,
+       [2][1][RTW89_UK][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] = 80,
-       [2][1][RTW89_ACMA][4] = 44,
-       [2][1][RTW89_FCC][5] = 72,
+       [2][1][RTW89_IC][4] = 74,
+       [2][1][RTW89_KCC][4] = 50,
+       [2][1][RTW89_ACMA][4] = 46,
+       [2][1][RTW89_CN][4] = 44,
+       [2][1][RTW89_UK][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] = 80,
-       [2][1][RTW89_ACMA][5] = 44,
-       [2][1][RTW89_FCC][6] = 54,
+       [2][1][RTW89_IC][5] = 82,
+       [2][1][RTW89_KCC][5] = 50,
+       [2][1][RTW89_ACMA][5] = 46,
+       [2][1][RTW89_CN][5] = 44,
+       [2][1][RTW89_UK][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] = 78,
+       [2][1][RTW89_IC][6] = 72,
+       [2][1][RTW89_KCC][6] = 50,
        [2][1][RTW89_ACMA][6] = 44,
-       [2][1][RTW89_FCC][7] = 54,
+       [2][1][RTW89_CN][6] = 44,
+       [2][1][RTW89_UK][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] = 78,
-       [2][1][RTW89_ACMA][7] = 44,
-       [2][1][RTW89_FCC][8] = 50,
+       [2][1][RTW89_IC][7] = 72,
+       [2][1][RTW89_KCC][7] = 50,
+       [2][1][RTW89_ACMA][7] = 46,
+       [2][1][RTW89_CN][7] = 44,
+       [2][1][RTW89_UK][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] = 74,
-       [2][1][RTW89_ACMA][8] = 44,
-       [2][1][RTW89_FCC][9] = 46,
+       [2][1][RTW89_IC][8] = 68,
+       [2][1][RTW89_KCC][8] = 50,
+       [2][1][RTW89_ACMA][8] = 46,
+       [2][1][RTW89_CN][8] = 44,
+       [2][1][RTW89_UK][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] = 70,
-       [2][1][RTW89_ACMA][9] = 44,
-       [2][1][RTW89_FCC][10] = 46,
+       [2][1][RTW89_IC][9] = 64,
+       [2][1][RTW89_KCC][9] = 52,
+       [2][1][RTW89_ACMA][9] = 46,
+       [2][1][RTW89_CN][9] = 44,
+       [2][1][RTW89_UK][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] = 70,
-       [2][1][RTW89_ACMA][10] = 44,
-       [2][1][RTW89_FCC][11] = 30,
+       [2][1][RTW89_IC][10] = 64,
+       [2][1][RTW89_KCC][10] = 52,
+       [2][1][RTW89_ACMA][10] = 46,
+       [2][1][RTW89_CN][10] = 44,
+       [2][1][RTW89_UK][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] = 60,
-       [2][1][RTW89_ACMA][11] = 44,
-       [2][1][RTW89_FCC][12] = 26,
+       [2][1][RTW89_IC][11] = 46,
+       [2][1][RTW89_KCC][11] = 52,
+       [2][1][RTW89_ACMA][11] = 46,
+       [2][1][RTW89_CN][11] = 44,
+       [2][1][RTW89_UK][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] = 44,
-       [2][1][RTW89_ACMA][12] = 42,
+       [2][1][RTW89_IC][12] = 6,
+       [2][1][RTW89_KCC][12] = 52,
+       [2][1][RTW89_ACMA][12] = 44,
+       [2][1][RTW89_CN][12] = 42,
+       [2][1][RTW89_UK][12] = 44,
        [2][1][RTW89_FCC][13] = 127,
        [2][1][RTW89_ETSI][13] = 127,
        [2][1][RTW89_MKK][13] = 127,
        [2][1][RTW89_IC][13] = 127,
+       [2][1][RTW89_KCC][13] = 127,
        [2][1][RTW89_ACMA][13] = 127,
+       [2][1][RTW89_CN][13] = 127,
+       [2][1][RTW89_UK][13] = 127,
 };
 
 const s8 rtw89_8852c_txpwr_lmt_ru_5g[RTW89_RU_NUM][RTW89_NTX_NUM]
                                    [RTW89_REGD_NUM][RTW89_5G_CH_NUM] = {
-       [0][0][RTW89_WW][0] = 24,
-       [0][0][RTW89_WW][2] = 24,
-       [0][0][RTW89_WW][4] = 22,
-       [0][0][RTW89_WW][6] = 22,
-       [0][0][RTW89_WW][8] = 18,
-       [0][0][RTW89_WW][10] = 18,
-       [0][0][RTW89_WW][12] = 24,
-       [0][0][RTW89_WW][14] = 24,
-       [0][0][RTW89_WW][15] = 24,
-       [0][0][RTW89_WW][17] = 24,
-       [0][0][RTW89_WW][19] = 24,
-       [0][0][RTW89_WW][21] = 24,
-       [0][0][RTW89_WW][23] = 24,
+       [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][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] = 24,
-       [0][0][RTW89_WW][33] = 24,
-       [0][0][RTW89_WW][35] = 24,
-       [0][0][RTW89_WW][37] = 44,
+       [0][0][RTW89_WW][31] = 30,
+       [0][0][RTW89_WW][33] = 30,
+       [0][0][RTW89_WW][35] = 30,
+       [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][48] = 24,
-       [0][0][RTW89_WW][50] = 24,
-       [0][0][RTW89_WW][52] = 24,
-       [0][1][RTW89_WW][0] = 0,
+       [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] = 0,
-       [0][1][RTW89_WW][6] = 0,
-       [0][1][RTW89_WW][8] = 12,
-       [0][1][RTW89_WW][10] = 12,
-       [0][1][RTW89_WW][12] = 12,
-       [0][1][RTW89_WW][14] = 12,
-       [0][1][RTW89_WW][15] = 12,
-       [0][1][RTW89_WW][17] = 12,
-       [0][1][RTW89_WW][19] = 12,
-       [0][1][RTW89_WW][21] = 12,
-       [0][1][RTW89_WW][23] = 12,
+       [0][1][RTW89_WW][4] = 4,
+       [0][1][RTW89_WW][6] = 1,
+       [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] = 12,
-       [0][1][RTW89_WW][33] = 12,
-       [0][1][RTW89_WW][35] = 12,
-       [0][1][RTW89_WW][37] = 30,
+       [0][1][RTW89_WW][31] = 16,
+       [0][1][RTW89_WW][33] = 16,
+       [0][1][RTW89_WW][35] = 16,
+       [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][48] = 12,
-       [0][1][RTW89_WW][50] = 12,
-       [0][1][RTW89_WW][52] = 12,
-       [1][0][RTW89_WW][0] = 34,
-       [1][0][RTW89_WW][2] = 34,
-       [1][0][RTW89_WW][4] = 34,
-       [1][0][RTW89_WW][6] = 34,
-       [1][0][RTW89_WW][8] = 34,
-       [1][0][RTW89_WW][10] = 34,
-       [1][0][RTW89_WW][12] = 34,
-       [1][0][RTW89_WW][14] = 34,
-       [1][0][RTW89_WW][15] = 34,
-       [1][0][RTW89_WW][17] = 34,
-       [1][0][RTW89_WW][19] = 34,
-       [1][0][RTW89_WW][21] = 34,
-       [1][0][RTW89_WW][23] = 34,
+       [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][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] = 34,
-       [1][0][RTW89_WW][33] = 34,
-       [1][0][RTW89_WW][35] = 34,
-       [1][0][RTW89_WW][37] = 56,
+       [1][0][RTW89_WW][31] = 42,
+       [1][0][RTW89_WW][33] = 42,
+       [1][0][RTW89_WW][35] = 42,
+       [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][48] = 36,
-       [1][0][RTW89_WW][50] = 36,
-       [1][0][RTW89_WW][52] = 36,
-       [1][1][RTW89_WW][0] = 10,
+       [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] = 10,
-       [1][1][RTW89_WW][6] = 10,
-       [1][1][RTW89_WW][8] = 20,
-       [1][1][RTW89_WW][10] = 20,
-       [1][1][RTW89_WW][12] = 22,
-       [1][1][RTW89_WW][14] = 22,
-       [1][1][RTW89_WW][15] = 22,
-       [1][1][RTW89_WW][17] = 22,
-       [1][1][RTW89_WW][19] = 22,
-       [1][1][RTW89_WW][21] = 22,
-       [1][1][RTW89_WW][23] = 22,
+       [1][1][RTW89_WW][4] = 14,
+       [1][1][RTW89_WW][6] = 8,
+       [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] = 22,
-       [1][1][RTW89_WW][33] = 22,
-       [1][1][RTW89_WW][35] = 22,
-       [1][1][RTW89_WW][37] = 40,
+       [1][1][RTW89_WW][31] = 30,
+       [1][1][RTW89_WW][33] = 30,
+       [1][1][RTW89_WW][35] = 30,
+       [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][48] = 24,
-       [1][1][RTW89_WW][50] = 24,
-       [1][1][RTW89_WW][52] = 24,
-       [2][0][RTW89_WW][0] = 46,
-       [2][0][RTW89_WW][2] = 46,
-       [2][0][RTW89_WW][4] = 46,
-       [2][0][RTW89_WW][6] = 46,
-       [2][0][RTW89_WW][8] = 44,
-       [2][0][RTW89_WW][10] = 44,
-       [2][0][RTW89_WW][12] = 48,
-       [2][0][RTW89_WW][14] = 48,
-       [2][0][RTW89_WW][15] = 48,
-       [2][0][RTW89_WW][17] = 48,
-       [2][0][RTW89_WW][19] = 48,
-       [2][0][RTW89_WW][21] = 48,
-       [2][0][RTW89_WW][23] = 48,
+       [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][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] = 48,
-       [2][0][RTW89_WW][33] = 48,
-       [2][0][RTW89_WW][35] = 48,
-       [2][0][RTW89_WW][37] = 62,
+       [2][0][RTW89_WW][31] = 52,
+       [2][0][RTW89_WW][33] = 52,
+       [2][0][RTW89_WW][35] = 52,
+       [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][48] = 48,
-       [2][0][RTW89_WW][50] = 48,
-       [2][0][RTW89_WW][52] = 48,
-       [2][1][RTW89_WW][0] = 20,
-       [2][1][RTW89_WW][2] = 18,
-       [2][1][RTW89_WW][4] = 22,
-       [2][1][RTW89_WW][6] = 22,
-       [2][1][RTW89_WW][8] = 32,
-       [2][1][RTW89_WW][10] = 32,
-       [2][1][RTW89_WW][12] = 36,
-       [2][1][RTW89_WW][14] = 36,
-       [2][1][RTW89_WW][15] = 36,
-       [2][1][RTW89_WW][17] = 36,
-       [2][1][RTW89_WW][19] = 36,
-       [2][1][RTW89_WW][21] = 36,
-       [2][1][RTW89_WW][23] = 36,
+       [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][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] = 36,
-       [2][1][RTW89_WW][33] = 36,
-       [2][1][RTW89_WW][35] = 36,
+       [2][1][RTW89_WW][31] = 40,
+       [2][1][RTW89_WW][33] = 40,
+       [2][1][RTW89_WW][35] = 40,
        [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][48] = 36,
-       [2][1][RTW89_WW][50] = 36,
-       [2][1][RTW89_WW][52] = 36,
-       [0][0][RTW89_FCC][0] = 44,
+       [2][1][RTW89_WW][48] = 40,
+       [2][1][RTW89_WW][50] = 40,
+       [2][1][RTW89_WW][52] = 40,
+       [0][0][RTW89_FCC][0] = 50,
        [0][0][RTW89_ETSI][0] = 30,
        [0][0][RTW89_MKK][0] = 36,
-       [0][0][RTW89_IC][0] = 24,
-       [0][0][RTW89_ACMA][0] = 24,
-       [0][0][RTW89_FCC][2] = 44,
+       [0][0][RTW89_IC][0] = 32,
+       [0][0][RTW89_KCC][0] = 42,
+       [0][0][RTW89_ACMA][0] = 30,
+       [0][0][RTW89_CN][0] = 16,
+       [0][0][RTW89_UK][0] = 30,
+       [0][0][RTW89_FCC][2] = 50,
        [0][0][RTW89_ETSI][2] = 30,
        [0][0][RTW89_MKK][2] = 36,
-       [0][0][RTW89_IC][2] = 24,
-       [0][0][RTW89_ACMA][2] = 24,
-       [0][0][RTW89_FCC][4] = 44,
+       [0][0][RTW89_IC][2] = 32,
+       [0][0][RTW89_KCC][2] = 42,
+       [0][0][RTW89_ACMA][2] = 30,
+       [0][0][RTW89_CN][2] = 16,
+       [0][0][RTW89_UK][2] = 30,
+       [0][0][RTW89_FCC][4] = 50,
        [0][0][RTW89_ETSI][4] = 30,
        [0][0][RTW89_MKK][4] = 22,
-       [0][0][RTW89_IC][4] = 24,
-       [0][0][RTW89_ACMA][4] = 24,
-       [0][0][RTW89_FCC][6] = 44,
+       [0][0][RTW89_IC][4] = 32,
+       [0][0][RTW89_KCC][4] = 42,
+       [0][0][RTW89_ACMA][4] = 30,
+       [0][0][RTW89_CN][4] = 16,
+       [0][0][RTW89_UK][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] = 24,
-       [0][0][RTW89_ACMA][6] = 24,
-       [0][0][RTW89_FCC][8] = 44,
+       [0][0][RTW89_IC][6] = 32,
+       [0][0][RTW89_KCC][6] = 10,
+       [0][0][RTW89_ACMA][6] = 30,
+       [0][0][RTW89_CN][6] = 16,
+       [0][0][RTW89_UK][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_ACMA][8] = 24,
-       [0][0][RTW89_FCC][10] = 44,
+       [0][0][RTW89_KCC][8] = 44,
+       [0][0][RTW89_ACMA][8] = 28,
+       [0][0][RTW89_CN][8] = 16,
+       [0][0][RTW89_UK][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_ACMA][10] = 24,
-       [0][0][RTW89_FCC][12] = 44,
+       [0][0][RTW89_KCC][10] = 44,
+       [0][0][RTW89_ACMA][10] = 28,
+       [0][0][RTW89_CN][10] = 16,
+       [0][0][RTW89_UK][10] = 28,
+       [0][0][RTW89_FCC][12] = 52,
        [0][0][RTW89_ETSI][12] = 28,
        [0][0][RTW89_MKK][12] = 34,
        [0][0][RTW89_IC][12] = 52,
-       [0][0][RTW89_ACMA][12] = 24,
-       [0][0][RTW89_FCC][14] = 44,
+       [0][0][RTW89_KCC][12] = 40,
+       [0][0][RTW89_ACMA][12] = 28,
+       [0][0][RTW89_CN][12] = 16,
+       [0][0][RTW89_UK][12] = 28,
+       [0][0][RTW89_FCC][14] = 52,
        [0][0][RTW89_ETSI][14] = 28,
        [0][0][RTW89_MKK][14] = 34,
        [0][0][RTW89_IC][14] = 52,
-       [0][0][RTW89_ACMA][14] = 24,
-       [0][0][RTW89_FCC][15] = 44,
+       [0][0][RTW89_KCC][14] = 40,
+       [0][0][RTW89_ACMA][14] = 28,
+       [0][0][RTW89_CN][14] = 16,
+       [0][0][RTW89_UK][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_ACMA][15] = 24,
-       [0][0][RTW89_FCC][17] = 44,
+       [0][0][RTW89_KCC][15] = 42,
+       [0][0][RTW89_ACMA][15] = 30,
+       [0][0][RTW89_CN][15] = 127,
+       [0][0][RTW89_UK][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_ACMA][17] = 24,
-       [0][0][RTW89_FCC][19] = 44,
+       [0][0][RTW89_KCC][17] = 42,
+       [0][0][RTW89_ACMA][17] = 30,
+       [0][0][RTW89_CN][17] = 127,
+       [0][0][RTW89_UK][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_ACMA][19] = 24,
-       [0][0][RTW89_FCC][21] = 44,
+       [0][0][RTW89_KCC][19] = 42,
+       [0][0][RTW89_ACMA][19] = 30,
+       [0][0][RTW89_CN][19] = 127,
+       [0][0][RTW89_UK][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_ACMA][21] = 24,
-       [0][0][RTW89_FCC][23] = 44,
+       [0][0][RTW89_KCC][21] = 42,
+       [0][0][RTW89_ACMA][21] = 30,
+       [0][0][RTW89_CN][21] = 127,
+       [0][0][RTW89_UK][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_ACMA][23] = 24,
-       [0][0][RTW89_FCC][25] = 44,
+       [0][0][RTW89_KCC][23] = 42,
+       [0][0][RTW89_ACMA][23] = 30,
+       [0][0][RTW89_CN][23] = 127,
+       [0][0][RTW89_UK][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_ACMA][25] = 127,
-       [0][0][RTW89_FCC][27] = 44,
+       [0][0][RTW89_CN][25] = 127,
+       [0][0][RTW89_UK][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_ACMA][27] = 127,
-       [0][0][RTW89_FCC][29] = 44,
+       [0][0][RTW89_CN][27] = 127,
+       [0][0][RTW89_UK][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_ACMA][29] = 127,
-       [0][0][RTW89_FCC][31] = 44,
+       [0][0][RTW89_CN][29] = 127,
+       [0][0][RTW89_UK][29] = 30,
+       [0][0][RTW89_FCC][31] = 52,
        [0][0][RTW89_ETSI][31] = 30,
        [0][0][RTW89_MKK][31] = 58,
-       [0][0][RTW89_IC][31] = 52,
-       [0][0][RTW89_ACMA][31] = 24,
+       [0][0][RTW89_IC][31] = 44,
+       [0][0][RTW89_KCC][31] = 42,
+       [0][0][RTW89_ACMA][31] = 30,
+       [0][0][RTW89_CN][31] = 127,
+       [0][0][RTW89_UK][31] = 30,
        [0][0][RTW89_FCC][33] = 44,
        [0][0][RTW89_ETSI][33] = 30,
        [0][0][RTW89_MKK][33] = 58,
-       [0][0][RTW89_IC][33] = 52,
-       [0][0][RTW89_ACMA][33] = 24,
+       [0][0][RTW89_IC][33] = 44,
+       [0][0][RTW89_KCC][33] = 42,
+       [0][0][RTW89_ACMA][33] = 30,
+       [0][0][RTW89_CN][33] = 127,
+       [0][0][RTW89_UK][33] = 30,
        [0][0][RTW89_FCC][35] = 44,
        [0][0][RTW89_ETSI][35] = 30,
        [0][0][RTW89_MKK][35] = 58,
-       [0][0][RTW89_IC][35] = 52,
-       [0][0][RTW89_ACMA][35] = 24,
-       [0][0][RTW89_FCC][37] = 44,
+       [0][0][RTW89_IC][35] = 44,
+       [0][0][RTW89_KCC][35] = 42,
+       [0][0][RTW89_ACMA][35] = 30,
+       [0][0][RTW89_CN][35] = 127,
+       [0][0][RTW89_UK][35] = 30,
+       [0][0][RTW89_FCC][37] = 52,
        [0][0][RTW89_ETSI][37] = 127,
        [0][0][RTW89_MKK][37] = 58,
        [0][0][RTW89_IC][37] = 52,
+       [0][0][RTW89_KCC][37] = 42,
        [0][0][RTW89_ACMA][37] = 52,
-       [0][0][RTW89_FCC][38] = 76,
+       [0][0][RTW89_CN][37] = 127,
+       [0][0][RTW89_UK][37] = 30,
+       [0][0][RTW89_FCC][38] = 64,
        [0][0][RTW89_ETSI][38] = 28,
        [0][0][RTW89_MKK][38] = 127,
-       [0][0][RTW89_IC][38] = 84,
-       [0][0][RTW89_ACMA][38] = 84,
-       [0][0][RTW89_FCC][40] = 76,
+       [0][0][RTW89_IC][38] = 64,
+       [0][0][RTW89_KCC][38] = 42,
+       [0][0][RTW89_ACMA][38] = 64,
+       [0][0][RTW89_CN][38] = 54,
+       [0][0][RTW89_UK][38] = 30,
+       [0][0][RTW89_FCC][40] = 64,
        [0][0][RTW89_ETSI][40] = 28,
        [0][0][RTW89_MKK][40] = 127,
-       [0][0][RTW89_IC][40] = 84,
-       [0][0][RTW89_ACMA][40] = 84,
-       [0][0][RTW89_FCC][42] = 76,
+       [0][0][RTW89_IC][40] = 64,
+       [0][0][RTW89_KCC][40] = 42,
+       [0][0][RTW89_ACMA][40] = 64,
+       [0][0][RTW89_CN][40] = 54,
+       [0][0][RTW89_UK][40] = 30,
+       [0][0][RTW89_FCC][42] = 60,
        [0][0][RTW89_ETSI][42] = 28,
        [0][0][RTW89_MKK][42] = 127,
-       [0][0][RTW89_IC][42] = 84,
-       [0][0][RTW89_ACMA][42] = 84,
-       [0][0][RTW89_FCC][44] = 76,
+       [0][0][RTW89_IC][42] = 60,
+       [0][0][RTW89_KCC][42] = 42,
+       [0][0][RTW89_ACMA][42] = 60,
+       [0][0][RTW89_CN][42] = 54,
+       [0][0][RTW89_UK][42] = 30,
+       [0][0][RTW89_FCC][44] = 60,
        [0][0][RTW89_ETSI][44] = 28,
        [0][0][RTW89_MKK][44] = 127,
-       [0][0][RTW89_IC][44] = 84,
-       [0][0][RTW89_ACMA][44] = 84,
-       [0][0][RTW89_FCC][46] = 76,
+       [0][0][RTW89_IC][44] = 60,
+       [0][0][RTW89_KCC][44] = 42,
+       [0][0][RTW89_ACMA][44] = 60,
+       [0][0][RTW89_CN][44] = 54,
+       [0][0][RTW89_UK][44] = 30,
+       [0][0][RTW89_FCC][46] = 60,
        [0][0][RTW89_ETSI][46] = 28,
        [0][0][RTW89_MKK][46] = 127,
-       [0][0][RTW89_IC][46] = 84,
-       [0][0][RTW89_ACMA][46] = 84,
-       [0][0][RTW89_FCC][48] = 24,
+       [0][0][RTW89_IC][46] = 60,
+       [0][0][RTW89_KCC][46] = 42,
+       [0][0][RTW89_ACMA][46] = 60,
+       [0][0][RTW89_CN][46] = 54,
+       [0][0][RTW89_UK][46] = 30,
+       [0][0][RTW89_FCC][48] = 46,
        [0][0][RTW89_ETSI][48] = 127,
        [0][0][RTW89_MKK][48] = 127,
        [0][0][RTW89_IC][48] = 127,
+       [0][0][RTW89_KCC][48] = 127,
        [0][0][RTW89_ACMA][48] = 127,
-       [0][0][RTW89_FCC][50] = 24,
+       [0][0][RTW89_CN][48] = 127,
+       [0][0][RTW89_UK][48] = 127,
+       [0][0][RTW89_FCC][50] = 44,
        [0][0][RTW89_ETSI][50] = 127,
        [0][0][RTW89_MKK][50] = 127,
        [0][0][RTW89_IC][50] = 127,
+       [0][0][RTW89_KCC][50] = 127,
        [0][0][RTW89_ACMA][50] = 127,
-       [0][0][RTW89_FCC][52] = 24,
+       [0][0][RTW89_CN][50] = 127,
+       [0][0][RTW89_UK][50] = 127,
+       [0][0][RTW89_FCC][52] = 34,
        [0][0][RTW89_ETSI][52] = 127,
        [0][0][RTW89_MKK][52] = 127,
        [0][0][RTW89_IC][52] = 127,
+       [0][0][RTW89_KCC][52] = 127,
        [0][0][RTW89_ACMA][52] = 127,
-       [0][1][RTW89_FCC][0] = 26,
+       [0][0][RTW89_CN][52] = 127,
+       [0][0][RTW89_UK][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] = 0,
-       [0][1][RTW89_ACMA][0] = 12,
-       [0][1][RTW89_FCC][2] = 30,
+       [0][1][RTW89_IC][0] = 8,
+       [0][1][RTW89_KCC][0] = 26,
+       [0][1][RTW89_ACMA][0] = 18,
+       [0][1][RTW89_CN][0] = 4,
+       [0][1][RTW89_UK][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] = 4,
-       [0][1][RTW89_ACMA][2] = 12,
-       [0][1][RTW89_FCC][4] = 26,
+       [0][1][RTW89_IC][2] = 8,
+       [0][1][RTW89_KCC][2] = 26,
+       [0][1][RTW89_ACMA][2] = 18,
+       [0][1][RTW89_CN][2] = 4,
+       [0][1][RTW89_UK][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] = 0,
-       [0][1][RTW89_ACMA][4] = 12,
-       [0][1][RTW89_FCC][6] = 26,
+       [0][1][RTW89_IC][4] = 8,
+       [0][1][RTW89_KCC][4] = 26,
+       [0][1][RTW89_ACMA][4] = 18,
+       [0][1][RTW89_CN][4] = 4,
+       [0][1][RTW89_UK][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] = 0,
-       [0][1][RTW89_ACMA][6] = 12,
-       [0][1][RTW89_FCC][8] = 26,
+       [0][1][RTW89_IC][6] = 8,
+       [0][1][RTW89_KCC][6] = 0,
+       [0][1][RTW89_ACMA][6] = 18,
+       [0][1][RTW89_CN][6] = 4,
+       [0][1][RTW89_UK][6] = 18,
+       [0][1][RTW89_FCC][8] = 30,
        [0][1][RTW89_ETSI][8] = 16,
        [0][1][RTW89_MKK][8] = 20,
-       [0][1][RTW89_IC][8] = 34,
-       [0][1][RTW89_ACMA][8] = 12,
-       [0][1][RTW89_FCC][10] = 26,
+       [0][1][RTW89_IC][8] = 30,
+       [0][1][RTW89_KCC][8] = 28,
+       [0][1][RTW89_ACMA][8] = 16,
+       [0][1][RTW89_CN][8] = 4,
+       [0][1][RTW89_UK][8] = 16,
+       [0][1][RTW89_FCC][10] = 30,
        [0][1][RTW89_ETSI][10] = 16,
        [0][1][RTW89_MKK][10] = 20,
-       [0][1][RTW89_IC][10] = 34,
-       [0][1][RTW89_ACMA][10] = 12,
+       [0][1][RTW89_IC][10] = 30,
+       [0][1][RTW89_KCC][10] = 28,
+       [0][1][RTW89_ACMA][10] = 16,
+       [0][1][RTW89_CN][10] = 4,
+       [0][1][RTW89_UK][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] = 38,
-       [0][1][RTW89_ACMA][12] = 12,
-       [0][1][RTW89_FCC][14] = 26,
+       [0][1][RTW89_IC][12] = 30,
+       [0][1][RTW89_KCC][12] = 28,
+       [0][1][RTW89_ACMA][12] = 16,
+       [0][1][RTW89_CN][12] = 4,
+       [0][1][RTW89_UK][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] = 34,
-       [0][1][RTW89_ACMA][14] = 12,
-       [0][1][RTW89_FCC][15] = 26,
+       [0][1][RTW89_IC][14] = 30,
+       [0][1][RTW89_KCC][14] = 28,
+       [0][1][RTW89_ACMA][14] = 16,
+       [0][1][RTW89_CN][14] = 4,
+       [0][1][RTW89_UK][14] = 16,
+       [0][1][RTW89_FCC][15] = 32,
        [0][1][RTW89_ETSI][15] = 18,
        [0][1][RTW89_MKK][15] = 44,
-       [0][1][RTW89_IC][15] = 34,
-       [0][1][RTW89_ACMA][15] = 12,
-       [0][1][RTW89_FCC][17] = 26,
+       [0][1][RTW89_IC][15] = 32,
+       [0][1][RTW89_KCC][15] = 28,
+       [0][1][RTW89_ACMA][15] = 18,
+       [0][1][RTW89_CN][15] = 127,
+       [0][1][RTW89_UK][15] = 18,
+       [0][1][RTW89_FCC][17] = 32,
        [0][1][RTW89_ETSI][17] = 18,
        [0][1][RTW89_MKK][17] = 44,
-       [0][1][RTW89_IC][17] = 34,
-       [0][1][RTW89_ACMA][17] = 12,
-       [0][1][RTW89_FCC][19] = 30,
+       [0][1][RTW89_IC][17] = 32,
+       [0][1][RTW89_KCC][17] = 28,
+       [0][1][RTW89_ACMA][17] = 18,
+       [0][1][RTW89_CN][17] = 127,
+       [0][1][RTW89_UK][17] = 18,
+       [0][1][RTW89_FCC][19] = 32,
        [0][1][RTW89_ETSI][19] = 18,
        [0][1][RTW89_MKK][19] = 44,
-       [0][1][RTW89_IC][19] = 38,
-       [0][1][RTW89_ACMA][19] = 12,
-       [0][1][RTW89_FCC][21] = 30,
+       [0][1][RTW89_IC][19] = 32,
+       [0][1][RTW89_KCC][19] = 28,
+       [0][1][RTW89_ACMA][19] = 18,
+       [0][1][RTW89_CN][19] = 127,
+       [0][1][RTW89_UK][19] = 18,
+       [0][1][RTW89_FCC][21] = 32,
        [0][1][RTW89_ETSI][21] = 18,
        [0][1][RTW89_MKK][21] = 44,
-       [0][1][RTW89_IC][21] = 38,
-       [0][1][RTW89_ACMA][21] = 12,
-       [0][1][RTW89_FCC][23] = 30,
+       [0][1][RTW89_IC][21] = 32,
+       [0][1][RTW89_KCC][21] = 28,
+       [0][1][RTW89_ACMA][21] = 18,
+       [0][1][RTW89_CN][21] = 127,
+       [0][1][RTW89_UK][21] = 18,
+       [0][1][RTW89_FCC][23] = 32,
        [0][1][RTW89_ETSI][23] = 18,
        [0][1][RTW89_MKK][23] = 44,
-       [0][1][RTW89_IC][23] = 38,
-       [0][1][RTW89_ACMA][23] = 12,
-       [0][1][RTW89_FCC][25] = 30,
+       [0][1][RTW89_IC][23] = 32,
+       [0][1][RTW89_KCC][23] = 28,
+       [0][1][RTW89_ACMA][23] = 18,
+       [0][1][RTW89_CN][23] = 127,
+       [0][1][RTW89_UK][23] = 18,
+       [0][1][RTW89_FCC][25] = 32,
        [0][1][RTW89_ETSI][25] = 18,
        [0][1][RTW89_MKK][25] = 44,
        [0][1][RTW89_IC][25] = 127,
+       [0][1][RTW89_KCC][25] = 28,
        [0][1][RTW89_ACMA][25] = 127,
-       [0][1][RTW89_FCC][27] = 30,
+       [0][1][RTW89_CN][25] = 127,
+       [0][1][RTW89_UK][25] = 18,
+       [0][1][RTW89_FCC][27] = 32,
        [0][1][RTW89_ETSI][27] = 16,
        [0][1][RTW89_MKK][27] = 44,
        [0][1][RTW89_IC][27] = 127,
+       [0][1][RTW89_KCC][27] = 28,
        [0][1][RTW89_ACMA][27] = 127,
-       [0][1][RTW89_FCC][29] = 30,
+       [0][1][RTW89_CN][27] = 127,
+       [0][1][RTW89_UK][27] = 16,
+       [0][1][RTW89_FCC][29] = 32,
        [0][1][RTW89_ETSI][29] = 16,
        [0][1][RTW89_MKK][29] = 44,
        [0][1][RTW89_IC][29] = 127,
+       [0][1][RTW89_KCC][29] = 28,
        [0][1][RTW89_ACMA][29] = 127,
-       [0][1][RTW89_FCC][31] = 30,
+       [0][1][RTW89_CN][29] = 127,
+       [0][1][RTW89_UK][29] = 16,
+       [0][1][RTW89_FCC][31] = 32,
        [0][1][RTW89_ETSI][31] = 16,
        [0][1][RTW89_MKK][31] = 44,
-       [0][1][RTW89_IC][31] = 34,
-       [0][1][RTW89_ACMA][31] = 12,
-       [0][1][RTW89_FCC][33] = 26,
+       [0][1][RTW89_IC][31] = 30,
+       [0][1][RTW89_KCC][31] = 28,
+       [0][1][RTW89_ACMA][31] = 16,
+       [0][1][RTW89_CN][31] = 127,
+       [0][1][RTW89_UK][31] = 16,
+       [0][1][RTW89_FCC][33] = 30,
        [0][1][RTW89_ETSI][33] = 16,
        [0][1][RTW89_MKK][33] = 44,
-       [0][1][RTW89_IC][33] = 34,
-       [0][1][RTW89_ACMA][33] = 12,
-       [0][1][RTW89_FCC][35] = 26,
+       [0][1][RTW89_IC][33] = 30,
+       [0][1][RTW89_KCC][33] = 28,
+       [0][1][RTW89_ACMA][33] = 16,
+       [0][1][RTW89_CN][33] = 127,
+       [0][1][RTW89_UK][33] = 16,
+       [0][1][RTW89_FCC][35] = 30,
        [0][1][RTW89_ETSI][35] = 16,
        [0][1][RTW89_MKK][35] = 44,
-       [0][1][RTW89_IC][35] = 34,
-       [0][1][RTW89_ACMA][35] = 12,
-       [0][1][RTW89_FCC][37] = 30,
+       [0][1][RTW89_IC][35] = 30,
+       [0][1][RTW89_KCC][35] = 28,
+       [0][1][RTW89_ACMA][35] = 16,
+       [0][1][RTW89_CN][35] = 127,
+       [0][1][RTW89_UK][35] = 16,
+       [0][1][RTW89_FCC][37] = 34,
        [0][1][RTW89_ETSI][37] = 127,
        [0][1][RTW89_MKK][37] = 44,
-       [0][1][RTW89_IC][37] = 38,
-       [0][1][RTW89_ACMA][37] = 38,
-       [0][1][RTW89_FCC][38] = 74,
+       [0][1][RTW89_IC][37] = 34,
+       [0][1][RTW89_KCC][37] = 28,
+       [0][1][RTW89_ACMA][37] = 34,
+       [0][1][RTW89_CN][37] = 127,
+       [0][1][RTW89_UK][37] = 18,
+       [0][1][RTW89_FCC][38] = 62,
        [0][1][RTW89_ETSI][38] = 16,
        [0][1][RTW89_MKK][38] = 127,
-       [0][1][RTW89_IC][38] = 82,
-       [0][1][RTW89_ACMA][38] = 84,
-       [0][1][RTW89_FCC][40] = 74,
+       [0][1][RTW89_IC][38] = 62,
+       [0][1][RTW89_KCC][38] = 28,
+       [0][1][RTW89_ACMA][38] = 62,
+       [0][1][RTW89_CN][38] = 42,
+       [0][1][RTW89_UK][38] = 18,
+       [0][1][RTW89_FCC][40] = 62,
        [0][1][RTW89_ETSI][40] = 16,
        [0][1][RTW89_MKK][40] = 127,
-       [0][1][RTW89_IC][40] = 82,
-       [0][1][RTW89_ACMA][40] = 84,
-       [0][1][RTW89_FCC][42] = 74,
+       [0][1][RTW89_IC][40] = 62,
+       [0][1][RTW89_KCC][40] = 28,
+       [0][1][RTW89_ACMA][40] = 62,
+       [0][1][RTW89_CN][40] = 42,
+       [0][1][RTW89_UK][40] = 18,
+       [0][1][RTW89_FCC][42] = 58,
        [0][1][RTW89_ETSI][42] = 16,
        [0][1][RTW89_MKK][42] = 127,
-       [0][1][RTW89_IC][42] = 82,
-       [0][1][RTW89_ACMA][42] = 84,
-       [0][1][RTW89_FCC][44] = 74,
+       [0][1][RTW89_IC][42] = 58,
+       [0][1][RTW89_KCC][42] = 28,
+       [0][1][RTW89_ACMA][42] = 58,
+       [0][1][RTW89_CN][42] = 42,
+       [0][1][RTW89_UK][42] = 18,
+       [0][1][RTW89_FCC][44] = 56,
        [0][1][RTW89_ETSI][44] = 16,
        [0][1][RTW89_MKK][44] = 127,
-       [0][1][RTW89_IC][44] = 82,
-       [0][1][RTW89_ACMA][44] = 84,
-       [0][1][RTW89_FCC][46] = 74,
+       [0][1][RTW89_IC][44] = 56,
+       [0][1][RTW89_KCC][44] = 28,
+       [0][1][RTW89_ACMA][44] = 56,
+       [0][1][RTW89_CN][44] = 42,
+       [0][1][RTW89_UK][44] = 18,
+       [0][1][RTW89_FCC][46] = 56,
        [0][1][RTW89_ETSI][46] = 16,
        [0][1][RTW89_MKK][46] = 127,
-       [0][1][RTW89_IC][46] = 82,
-       [0][1][RTW89_ACMA][46] = 84,
-       [0][1][RTW89_FCC][48] = 12,
+       [0][1][RTW89_IC][46] = 56,
+       [0][1][RTW89_KCC][46] = 28,
+       [0][1][RTW89_ACMA][46] = 56,
+       [0][1][RTW89_CN][46] = 42,
+       [0][1][RTW89_UK][46] = 18,
+       [0][1][RTW89_FCC][48] = 20,
        [0][1][RTW89_ETSI][48] = 127,
        [0][1][RTW89_MKK][48] = 127,
        [0][1][RTW89_IC][48] = 127,
+       [0][1][RTW89_KCC][48] = 127,
        [0][1][RTW89_ACMA][48] = 127,
-       [0][1][RTW89_FCC][50] = 12,
+       [0][1][RTW89_CN][48] = 127,
+       [0][1][RTW89_UK][48] = 127,
+       [0][1][RTW89_FCC][50] = 20,
        [0][1][RTW89_ETSI][50] = 127,
        [0][1][RTW89_MKK][50] = 127,
        [0][1][RTW89_IC][50] = 127,
+       [0][1][RTW89_KCC][50] = 127,
        [0][1][RTW89_ACMA][50] = 127,
-       [0][1][RTW89_FCC][52] = 12,
+       [0][1][RTW89_CN][50] = 127,
+       [0][1][RTW89_UK][50] = 127,
+       [0][1][RTW89_FCC][52] = 8,
        [0][1][RTW89_ETSI][52] = 127,
        [0][1][RTW89_MKK][52] = 127,
        [0][1][RTW89_IC][52] = 127,
+       [0][1][RTW89_KCC][52] = 127,
        [0][1][RTW89_ACMA][52] = 127,
-       [1][0][RTW89_FCC][0] = 54,
+       [0][1][RTW89_CN][52] = 127,
+       [0][1][RTW89_UK][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] = 36,
-       [1][0][RTW89_ACMA][0] = 34,
-       [1][0][RTW89_FCC][2] = 54,
+       [1][0][RTW89_IC][0] = 42,
+       [1][0][RTW89_KCC][0] = 50,
+       [1][0][RTW89_ACMA][0] = 40,
+       [1][0][RTW89_CN][0] = 26,
+       [1][0][RTW89_UK][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] = 36,
-       [1][0][RTW89_ACMA][2] = 34,
-       [1][0][RTW89_FCC][4] = 54,
+       [1][0][RTW89_IC][2] = 42,
+       [1][0][RTW89_KCC][2] = 50,
+       [1][0][RTW89_ACMA][2] = 40,
+       [1][0][RTW89_CN][2] = 26,
+       [1][0][RTW89_UK][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] = 36,
-       [1][0][RTW89_ACMA][4] = 34,
-       [1][0][RTW89_FCC][6] = 54,
+       [1][0][RTW89_IC][4] = 42,
+       [1][0][RTW89_KCC][4] = 50,
+       [1][0][RTW89_ACMA][4] = 40,
+       [1][0][RTW89_CN][4] = 26,
+       [1][0][RTW89_UK][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] = 36,
-       [1][0][RTW89_ACMA][6] = 34,
-       [1][0][RTW89_FCC][8] = 54,
+       [1][0][RTW89_IC][6] = 42,
+       [1][0][RTW89_KCC][6] = 24,
+       [1][0][RTW89_ACMA][6] = 40,
+       [1][0][RTW89_CN][6] = 26,
+       [1][0][RTW89_UK][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_ACMA][8] = 34,
-       [1][0][RTW89_FCC][10] = 54,
+       [1][0][RTW89_KCC][8] = 52,
+       [1][0][RTW89_ACMA][8] = 40,
+       [1][0][RTW89_CN][8] = 26,
+       [1][0][RTW89_UK][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_ACMA][10] = 34,
-       [1][0][RTW89_FCC][12] = 56,
+       [1][0][RTW89_KCC][10] = 52,
+       [1][0][RTW89_ACMA][10] = 40,
+       [1][0][RTW89_CN][10] = 26,
+       [1][0][RTW89_UK][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] = 64,
-       [1][0][RTW89_ACMA][12] = 34,
-       [1][0][RTW89_FCC][14] = 54,
+       [1][0][RTW89_IC][12] = 62,
+       [1][0][RTW89_KCC][12] = 52,
+       [1][0][RTW89_ACMA][12] = 40,
+       [1][0][RTW89_CN][12] = 26,
+       [1][0][RTW89_UK][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_ACMA][14] = 34,
-       [1][0][RTW89_FCC][15] = 54,
+       [1][0][RTW89_KCC][14] = 52,
+       [1][0][RTW89_ACMA][14] = 40,
+       [1][0][RTW89_CN][14] = 26,
+       [1][0][RTW89_UK][14] = 40,
+       [1][0][RTW89_FCC][15] = 62,
        [1][0][RTW89_ETSI][15] = 40,
        [1][0][RTW89_MKK][15] = 62,
        [1][0][RTW89_IC][15] = 62,
-       [1][0][RTW89_ACMA][15] = 34,
-       [1][0][RTW89_FCC][17] = 54,
+       [1][0][RTW89_KCC][15] = 52,
+       [1][0][RTW89_ACMA][15] = 40,
+       [1][0][RTW89_CN][15] = 127,
+       [1][0][RTW89_UK][15] = 40,
+       [1][0][RTW89_FCC][17] = 62,
        [1][0][RTW89_ETSI][17] = 40,
        [1][0][RTW89_MKK][17] = 68,
        [1][0][RTW89_IC][17] = 62,
-       [1][0][RTW89_ACMA][17] = 34,
-       [1][0][RTW89_FCC][19] = 54,
+       [1][0][RTW89_KCC][17] = 52,
+       [1][0][RTW89_ACMA][17] = 40,
+       [1][0][RTW89_CN][17] = 127,
+       [1][0][RTW89_UK][17] = 40,
+       [1][0][RTW89_FCC][19] = 64,
        [1][0][RTW89_ETSI][19] = 40,
        [1][0][RTW89_MKK][19] = 68,
-       [1][0][RTW89_IC][19] = 62,
-       [1][0][RTW89_ACMA][19] = 34,
-       [1][0][RTW89_FCC][21] = 54,
+       [1][0][RTW89_IC][19] = 64,
+       [1][0][RTW89_KCC][19] = 52,
+       [1][0][RTW89_ACMA][19] = 40,
+       [1][0][RTW89_CN][19] = 127,
+       [1][0][RTW89_UK][19] = 40,
+       [1][0][RTW89_FCC][21] = 64,
        [1][0][RTW89_ETSI][21] = 40,
        [1][0][RTW89_MKK][21] = 68,
-       [1][0][RTW89_IC][21] = 62,
-       [1][0][RTW89_ACMA][21] = 34,
-       [1][0][RTW89_FCC][23] = 54,
+       [1][0][RTW89_IC][21] = 64,
+       [1][0][RTW89_KCC][21] = 52,
+       [1][0][RTW89_ACMA][21] = 40,
+       [1][0][RTW89_CN][21] = 127,
+       [1][0][RTW89_UK][21] = 40,
+       [1][0][RTW89_FCC][23] = 64,
        [1][0][RTW89_ETSI][23] = 40,
        [1][0][RTW89_MKK][23] = 68,
-       [1][0][RTW89_IC][23] = 62,
-       [1][0][RTW89_ACMA][23] = 34,
-       [1][0][RTW89_FCC][25] = 54,
+       [1][0][RTW89_IC][23] = 64,
+       [1][0][RTW89_KCC][23] = 52,
+       [1][0][RTW89_ACMA][23] = 40,
+       [1][0][RTW89_CN][23] = 127,
+       [1][0][RTW89_UK][23] = 40,
+       [1][0][RTW89_FCC][25] = 64,
        [1][0][RTW89_ETSI][25] = 40,
        [1][0][RTW89_MKK][25] = 68,
        [1][0][RTW89_IC][25] = 127,
+       [1][0][RTW89_KCC][25] = 52,
        [1][0][RTW89_ACMA][25] = 127,
-       [1][0][RTW89_FCC][27] = 54,
+       [1][0][RTW89_CN][25] = 127,
+       [1][0][RTW89_UK][25] = 40,
+       [1][0][RTW89_FCC][27] = 64,
        [1][0][RTW89_ETSI][27] = 42,
        [1][0][RTW89_MKK][27] = 68,
        [1][0][RTW89_IC][27] = 127,
+       [1][0][RTW89_KCC][27] = 52,
        [1][0][RTW89_ACMA][27] = 127,
-       [1][0][RTW89_FCC][29] = 54,
+       [1][0][RTW89_CN][27] = 127,
+       [1][0][RTW89_UK][27] = 42,
+       [1][0][RTW89_FCC][29] = 64,
        [1][0][RTW89_ETSI][29] = 42,
        [1][0][RTW89_MKK][29] = 68,
        [1][0][RTW89_IC][29] = 127,
+       [1][0][RTW89_KCC][29] = 52,
        [1][0][RTW89_ACMA][29] = 127,
-       [1][0][RTW89_FCC][31] = 54,
+       [1][0][RTW89_CN][29] = 127,
+       [1][0][RTW89_UK][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] = 62,
-       [1][0][RTW89_ACMA][31] = 34,
-       [1][0][RTW89_FCC][33] = 54,
+       [1][0][RTW89_IC][31] = 56,
+       [1][0][RTW89_KCC][31] = 52,
+       [1][0][RTW89_ACMA][31] = 42,
+       [1][0][RTW89_CN][31] = 127,
+       [1][0][RTW89_UK][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] = 62,
-       [1][0][RTW89_ACMA][33] = 34,
-       [1][0][RTW89_FCC][35] = 54,
+       [1][0][RTW89_IC][33] = 56,
+       [1][0][RTW89_KCC][33] = 52,
+       [1][0][RTW89_ACMA][33] = 42,
+       [1][0][RTW89_CN][33] = 127,
+       [1][0][RTW89_UK][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] = 62,
-       [1][0][RTW89_ACMA][35] = 34,
-       [1][0][RTW89_FCC][37] = 56,
+       [1][0][RTW89_IC][35] = 56,
+       [1][0][RTW89_KCC][35] = 52,
+       [1][0][RTW89_ACMA][35] = 42,
+       [1][0][RTW89_CN][35] = 127,
+       [1][0][RTW89_UK][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] = 64,
-       [1][0][RTW89_ACMA][37] = 64,
+       [1][0][RTW89_IC][37] = 66,
+       [1][0][RTW89_KCC][37] = 52,
+       [1][0][RTW89_ACMA][37] = 66,
+       [1][0][RTW89_CN][37] = 127,
+       [1][0][RTW89_UK][37] = 42,
        [1][0][RTW89_FCC][38] = 76,
        [1][0][RTW89_ETSI][38] = 28,
        [1][0][RTW89_MKK][38] = 127,
-       [1][0][RTW89_IC][38] = 84,
-       [1][0][RTW89_ACMA][38] = 84,
+       [1][0][RTW89_IC][38] = 76,
+       [1][0][RTW89_KCC][38] = 54,
+       [1][0][RTW89_ACMA][38] = 76,
+       [1][0][RTW89_CN][38] = 66,
+       [1][0][RTW89_UK][38] = 44,
        [1][0][RTW89_FCC][40] = 76,
        [1][0][RTW89_ETSI][40] = 28,
        [1][0][RTW89_MKK][40] = 127,
-       [1][0][RTW89_IC][40] = 84,
-       [1][0][RTW89_ACMA][40] = 84,
-       [1][0][RTW89_FCC][42] = 76,
+       [1][0][RTW89_IC][40] = 76,
+       [1][0][RTW89_KCC][40] = 54,
+       [1][0][RTW89_ACMA][40] = 76,
+       [1][0][RTW89_CN][40] = 66,
+       [1][0][RTW89_UK][40] = 44,
+       [1][0][RTW89_FCC][42] = 68,
        [1][0][RTW89_ETSI][42] = 28,
        [1][0][RTW89_MKK][42] = 127,
-       [1][0][RTW89_IC][42] = 84,
-       [1][0][RTW89_ACMA][42] = 84,
-       [1][0][RTW89_FCC][44] = 76,
+       [1][0][RTW89_IC][42] = 68,
+       [1][0][RTW89_KCC][42] = 54,
+       [1][0][RTW89_ACMA][42] = 68,
+       [1][0][RTW89_CN][42] = 66,
+       [1][0][RTW89_UK][42] = 44,
+       [1][0][RTW89_FCC][44] = 70,
        [1][0][RTW89_ETSI][44] = 28,
        [1][0][RTW89_MKK][44] = 127,
-       [1][0][RTW89_IC][44] = 84,
-       [1][0][RTW89_ACMA][44] = 84,
-       [1][0][RTW89_FCC][46] = 76,
+       [1][0][RTW89_IC][44] = 70,
+       [1][0][RTW89_KCC][44] = 54,
+       [1][0][RTW89_ACMA][44] = 70,
+       [1][0][RTW89_CN][44] = 66,
+       [1][0][RTW89_UK][44] = 42,
+       [1][0][RTW89_FCC][46] = 70,
        [1][0][RTW89_ETSI][46] = 28,
        [1][0][RTW89_MKK][46] = 127,
-       [1][0][RTW89_IC][46] = 84,
-       [1][0][RTW89_ACMA][46] = 84,
-       [1][0][RTW89_FCC][48] = 36,
+       [1][0][RTW89_IC][46] = 70,
+       [1][0][RTW89_KCC][46] = 54,
+       [1][0][RTW89_ACMA][46] = 70,
+       [1][0][RTW89_CN][46] = 66,
+       [1][0][RTW89_UK][46] = 42,
+       [1][0][RTW89_FCC][48] = 56,
        [1][0][RTW89_ETSI][48] = 127,
        [1][0][RTW89_MKK][48] = 127,
        [1][0][RTW89_IC][48] = 127,
+       [1][0][RTW89_KCC][48] = 127,
        [1][0][RTW89_ACMA][48] = 127,
-       [1][0][RTW89_FCC][50] = 36,
+       [1][0][RTW89_CN][48] = 127,
+       [1][0][RTW89_UK][48] = 127,
+       [1][0][RTW89_FCC][50] = 58,
        [1][0][RTW89_ETSI][50] = 127,
        [1][0][RTW89_MKK][50] = 127,
        [1][0][RTW89_IC][50] = 127,
+       [1][0][RTW89_KCC][50] = 127,
        [1][0][RTW89_ACMA][50] = 127,
-       [1][0][RTW89_FCC][52] = 36,
+       [1][0][RTW89_CN][50] = 127,
+       [1][0][RTW89_UK][50] = 127,
+       [1][0][RTW89_FCC][52] = 56,
        [1][0][RTW89_ETSI][52] = 127,
        [1][0][RTW89_MKK][52] = 127,
        [1][0][RTW89_IC][52] = 127,
+       [1][0][RTW89_KCC][52] = 127,
        [1][0][RTW89_ACMA][52] = 127,
-       [1][1][RTW89_FCC][0] = 34,
+       [1][0][RTW89_CN][52] = 127,
+       [1][0][RTW89_UK][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] = 10,
-       [1][1][RTW89_ACMA][0] = 22,
-       [1][1][RTW89_FCC][2] = 36,
+       [1][1][RTW89_IC][0] = 20,
+       [1][1][RTW89_KCC][0] = 34,
+       [1][1][RTW89_ACMA][0] = 30,
+       [1][1][RTW89_CN][0] = 14,
+       [1][1][RTW89_UK][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] = 14,
-       [1][1][RTW89_ACMA][2] = 22,
-       [1][1][RTW89_FCC][4] = 34,
+       [1][1][RTW89_IC][2] = 18,
+       [1][1][RTW89_KCC][2] = 34,
+       [1][1][RTW89_ACMA][2] = 30,
+       [1][1][RTW89_CN][2] = 14,
+       [1][1][RTW89_UK][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] = 10,
-       [1][1][RTW89_ACMA][4] = 22,
-       [1][1][RTW89_FCC][6] = 34,
+       [1][1][RTW89_IC][4] = 20,
+       [1][1][RTW89_KCC][4] = 34,
+       [1][1][RTW89_ACMA][4] = 30,
+       [1][1][RTW89_CN][4] = 14,
+       [1][1][RTW89_UK][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] = 10,
-       [1][1][RTW89_ACMA][6] = 22,
-       [1][1][RTW89_FCC][8] = 36,
+       [1][1][RTW89_IC][6] = 20,
+       [1][1][RTW89_KCC][6] = 8,
+       [1][1][RTW89_ACMA][6] = 30,
+       [1][1][RTW89_CN][6] = 14,
+       [1][1][RTW89_UK][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_ACMA][8] = 22,
-       [1][1][RTW89_FCC][10] = 36,
+       [1][1][RTW89_KCC][8] = 34,
+       [1][1][RTW89_ACMA][8] = 30,
+       [1][1][RTW89_CN][8] = 14,
+       [1][1][RTW89_UK][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_ACMA][10] = 22,
-       [1][1][RTW89_FCC][12] = 38,
+       [1][1][RTW89_KCC][10] = 34,
+       [1][1][RTW89_ACMA][10] = 30,
+       [1][1][RTW89_CN][10] = 14,
+       [1][1][RTW89_UK][10] = 30,
+       [1][1][RTW89_FCC][12] = 44,
        [1][1][RTW89_ETSI][12] = 30,
        [1][1][RTW89_MKK][12] = 34,
-       [1][1][RTW89_IC][12] = 46,
-       [1][1][RTW89_ACMA][12] = 22,
-       [1][1][RTW89_FCC][14] = 34,
+       [1][1][RTW89_IC][12] = 44,
+       [1][1][RTW89_KCC][12] = 38,
+       [1][1][RTW89_ACMA][12] = 30,
+       [1][1][RTW89_CN][12] = 14,
+       [1][1][RTW89_UK][12] = 30,
+       [1][1][RTW89_FCC][14] = 44,
        [1][1][RTW89_ETSI][14] = 30,
        [1][1][RTW89_MKK][14] = 34,
-       [1][1][RTW89_IC][14] = 40,
-       [1][1][RTW89_ACMA][14] = 22,
-       [1][1][RTW89_FCC][15] = 34,
+       [1][1][RTW89_IC][14] = 44,
+       [1][1][RTW89_KCC][14] = 38,
+       [1][1][RTW89_ACMA][14] = 30,
+       [1][1][RTW89_CN][14] = 14,
+       [1][1][RTW89_UK][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] = 42,
-       [1][1][RTW89_ACMA][15] = 22,
-       [1][1][RTW89_FCC][17] = 34,
+       [1][1][RTW89_IC][15] = 44,
+       [1][1][RTW89_KCC][15] = 36,
+       [1][1][RTW89_ACMA][15] = 28,
+       [1][1][RTW89_CN][15] = 127,
+       [1][1][RTW89_UK][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] = 42,
-       [1][1][RTW89_ACMA][17] = 22,
-       [1][1][RTW89_FCC][19] = 34,
+       [1][1][RTW89_IC][17] = 44,
+       [1][1][RTW89_KCC][17] = 36,
+       [1][1][RTW89_ACMA][17] = 28,
+       [1][1][RTW89_CN][17] = 127,
+       [1][1][RTW89_UK][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] = 42,
-       [1][1][RTW89_ACMA][19] = 22,
-       [1][1][RTW89_FCC][21] = 34,
+       [1][1][RTW89_IC][19] = 44,
+       [1][1][RTW89_KCC][19] = 36,
+       [1][1][RTW89_ACMA][19] = 28,
+       [1][1][RTW89_CN][19] = 127,
+       [1][1][RTW89_UK][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] = 42,
-       [1][1][RTW89_ACMA][21] = 22,
-       [1][1][RTW89_FCC][23] = 34,
+       [1][1][RTW89_IC][21] = 44,
+       [1][1][RTW89_KCC][21] = 36,
+       [1][1][RTW89_ACMA][21] = 28,
+       [1][1][RTW89_CN][21] = 127,
+       [1][1][RTW89_UK][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] = 42,
-       [1][1][RTW89_ACMA][23] = 22,
-       [1][1][RTW89_FCC][25] = 34,
+       [1][1][RTW89_IC][23] = 44,
+       [1][1][RTW89_KCC][23] = 36,
+       [1][1][RTW89_ACMA][23] = 28,
+       [1][1][RTW89_CN][23] = 127,
+       [1][1][RTW89_UK][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_ACMA][25] = 127,
-       [1][1][RTW89_FCC][27] = 34,
+       [1][1][RTW89_CN][25] = 127,
+       [1][1][RTW89_UK][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_ACMA][27] = 127,
-       [1][1][RTW89_FCC][29] = 34,
+       [1][1][RTW89_CN][27] = 127,
+       [1][1][RTW89_UK][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_ACMA][29] = 127,
-       [1][1][RTW89_FCC][31] = 34,
+       [1][1][RTW89_CN][29] = 127,
+       [1][1][RTW89_UK][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_ACMA][31] = 22,
-       [1][1][RTW89_FCC][33] = 32,
+       [1][1][RTW89_KCC][31] = 36,
+       [1][1][RTW89_ACMA][31] = 30,
+       [1][1][RTW89_CN][31] = 127,
+       [1][1][RTW89_UK][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_ACMA][33] = 22,
-       [1][1][RTW89_FCC][35] = 32,
+       [1][1][RTW89_KCC][33] = 36,
+       [1][1][RTW89_ACMA][33] = 30,
+       [1][1][RTW89_CN][33] = 127,
+       [1][1][RTW89_UK][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_ACMA][35] = 22,
-       [1][1][RTW89_FCC][37] = 40,
+       [1][1][RTW89_KCC][35] = 36,
+       [1][1][RTW89_ACMA][35] = 30,
+       [1][1][RTW89_CN][35] = 127,
+       [1][1][RTW89_UK][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] = 48,
-       [1][1][RTW89_ACMA][37] = 48,
-       [1][1][RTW89_FCC][38] = 76,
+       [1][1][RTW89_IC][37] = 46,
+       [1][1][RTW89_KCC][37] = 36,
+       [1][1][RTW89_ACMA][37] = 46,
+       [1][1][RTW89_CN][37] = 127,
+       [1][1][RTW89_UK][37] = 32,
+       [1][1][RTW89_FCC][38] = 74,
        [1][1][RTW89_ETSI][38] = 16,
        [1][1][RTW89_MKK][38] = 127,
-       [1][1][RTW89_IC][38] = 84,
-       [1][1][RTW89_ACMA][38] = 82,
-       [1][1][RTW89_FCC][40] = 76,
+       [1][1][RTW89_IC][38] = 74,
+       [1][1][RTW89_KCC][38] = 36,
+       [1][1][RTW89_ACMA][38] = 74,
+       [1][1][RTW89_CN][38] = 54,
+       [1][1][RTW89_UK][38] = 30,
+       [1][1][RTW89_FCC][40] = 74,
        [1][1][RTW89_ETSI][40] = 16,
        [1][1][RTW89_MKK][40] = 127,
-       [1][1][RTW89_IC][40] = 84,
-       [1][1][RTW89_ACMA][40] = 82,
-       [1][1][RTW89_FCC][42] = 76,
+       [1][1][RTW89_IC][40] = 74,
+       [1][1][RTW89_KCC][40] = 36,
+       [1][1][RTW89_ACMA][40] = 74,
+       [1][1][RTW89_CN][40] = 54,
+       [1][1][RTW89_UK][40] = 30,
+       [1][1][RTW89_FCC][42] = 74,
        [1][1][RTW89_ETSI][42] = 16,
        [1][1][RTW89_MKK][42] = 127,
-       [1][1][RTW89_IC][42] = 84,
-       [1][1][RTW89_ACMA][42] = 84,
-       [1][1][RTW89_FCC][44] = 76,
+       [1][1][RTW89_IC][42] = 74,
+       [1][1][RTW89_KCC][42] = 36,
+       [1][1][RTW89_ACMA][42] = 74,
+       [1][1][RTW89_CN][42] = 54,
+       [1][1][RTW89_UK][42] = 30,
+       [1][1][RTW89_FCC][44] = 74,
        [1][1][RTW89_ETSI][44] = 16,
        [1][1][RTW89_MKK][44] = 127,
-       [1][1][RTW89_IC][44] = 84,
-       [1][1][RTW89_ACMA][44] = 84,
-       [1][1][RTW89_FCC][46] = 76,
+       [1][1][RTW89_IC][44] = 74,
+       [1][1][RTW89_KCC][44] = 36,
+       [1][1][RTW89_ACMA][44] = 74,
+       [1][1][RTW89_CN][44] = 54,
+       [1][1][RTW89_UK][44] = 30,
+       [1][1][RTW89_FCC][46] = 74,
        [1][1][RTW89_ETSI][46] = 16,
        [1][1][RTW89_MKK][46] = 127,
-       [1][1][RTW89_IC][46] = 84,
-       [1][1][RTW89_ACMA][46] = 84,
-       [1][1][RTW89_FCC][48] = 24,
+       [1][1][RTW89_IC][46] = 74,
+       [1][1][RTW89_KCC][46] = 36,
+       [1][1][RTW89_ACMA][46] = 74,
+       [1][1][RTW89_CN][46] = 54,
+       [1][1][RTW89_UK][46] = 30,
+       [1][1][RTW89_FCC][48] = 34,
        [1][1][RTW89_ETSI][48] = 127,
        [1][1][RTW89_MKK][48] = 127,
        [1][1][RTW89_IC][48] = 127,
+       [1][1][RTW89_KCC][48] = 127,
        [1][1][RTW89_ACMA][48] = 127,
-       [1][1][RTW89_FCC][50] = 24,
+       [1][1][RTW89_CN][48] = 127,
+       [1][1][RTW89_UK][48] = 127,
+       [1][1][RTW89_FCC][50] = 34,
        [1][1][RTW89_ETSI][50] = 127,
        [1][1][RTW89_MKK][50] = 127,
        [1][1][RTW89_IC][50] = 127,
+       [1][1][RTW89_KCC][50] = 127,
        [1][1][RTW89_ACMA][50] = 127,
-       [1][1][RTW89_FCC][52] = 24,
+       [1][1][RTW89_CN][50] = 127,
+       [1][1][RTW89_UK][50] = 127,
+       [1][1][RTW89_FCC][52] = 30,
        [1][1][RTW89_ETSI][52] = 127,
        [1][1][RTW89_MKK][52] = 127,
        [1][1][RTW89_IC][52] = 127,
+       [1][1][RTW89_KCC][52] = 127,
        [1][1][RTW89_ACMA][52] = 127,
-       [2][0][RTW89_FCC][0] = 62,
+       [1][1][RTW89_CN][52] = 127,
+       [1][1][RTW89_UK][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] = 46,
-       [2][0][RTW89_ACMA][0] = 48,
-       [2][0][RTW89_FCC][2] = 62,
+       [2][0][RTW89_IC][0] = 52,
+       [2][0][RTW89_KCC][0] = 64,
+       [2][0][RTW89_ACMA][0] = 52,
+       [2][0][RTW89_CN][0] = 40,
+       [2][0][RTW89_UK][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] = 46,
-       [2][0][RTW89_ACMA][2] = 48,
-       [2][0][RTW89_FCC][4] = 62,
+       [2][0][RTW89_IC][2] = 50,
+       [2][0][RTW89_KCC][2] = 64,
+       [2][0][RTW89_ACMA][2] = 52,
+       [2][0][RTW89_CN][2] = 40,
+       [2][0][RTW89_UK][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] = 46,
-       [2][0][RTW89_ACMA][4] = 48,
-       [2][0][RTW89_FCC][6] = 62,
+       [2][0][RTW89_IC][4] = 50,
+       [2][0][RTW89_KCC][4] = 64,
+       [2][0][RTW89_ACMA][4] = 52,
+       [2][0][RTW89_CN][4] = 40,
+       [2][0][RTW89_UK][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] = 46,
-       [2][0][RTW89_ACMA][6] = 48,
-       [2][0][RTW89_FCC][8] = 62,
+       [2][0][RTW89_IC][6] = 50,
+       [2][0][RTW89_KCC][6] = 36,
+       [2][0][RTW89_ACMA][6] = 52,
+       [2][0][RTW89_CN][6] = 40,
+       [2][0][RTW89_UK][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] = 66,
-       [2][0][RTW89_ACMA][8] = 48,
-       [2][0][RTW89_FCC][10] = 62,
+       [2][0][RTW89_IC][8] = 64,
+       [2][0][RTW89_KCC][8] = 62,
+       [2][0][RTW89_ACMA][8] = 52,
+       [2][0][RTW89_CN][8] = 40,
+       [2][0][RTW89_UK][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] = 66,
-       [2][0][RTW89_ACMA][10] = 48,
-       [2][0][RTW89_FCC][12] = 62,
+       [2][0][RTW89_IC][10] = 64,
+       [2][0][RTW89_KCC][10] = 62,
+       [2][0][RTW89_ACMA][10] = 52,
+       [2][0][RTW89_CN][10] = 40,
+       [2][0][RTW89_UK][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] = 66,
-       [2][0][RTW89_ACMA][12] = 48,
-       [2][0][RTW89_FCC][14] = 62,
+       [2][0][RTW89_IC][12] = 64,
+       [2][0][RTW89_KCC][12] = 62,
+       [2][0][RTW89_ACMA][12] = 52,
+       [2][0][RTW89_CN][12] = 40,
+       [2][0][RTW89_UK][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] = 66,
-       [2][0][RTW89_ACMA][14] = 48,
-       [2][0][RTW89_FCC][15] = 62,
+       [2][0][RTW89_IC][14] = 64,
+       [2][0][RTW89_KCC][14] = 62,
+       [2][0][RTW89_ACMA][14] = 52,
+       [2][0][RTW89_CN][14] = 40,
+       [2][0][RTW89_UK][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] = 70,
-       [2][0][RTW89_ACMA][15] = 48,
-       [2][0][RTW89_FCC][17] = 62,
+       [2][0][RTW89_IC][15] = 68,
+       [2][0][RTW89_KCC][15] = 62,
+       [2][0][RTW89_ACMA][15] = 52,
+       [2][0][RTW89_CN][15] = 127,
+       [2][0][RTW89_UK][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] = 70,
-       [2][0][RTW89_ACMA][17] = 48,
-       [2][0][RTW89_FCC][19] = 62,
+       [2][0][RTW89_IC][17] = 68,
+       [2][0][RTW89_KCC][17] = 62,
+       [2][0][RTW89_ACMA][17] = 52,
+       [2][0][RTW89_CN][17] = 127,
+       [2][0][RTW89_UK][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_ACMA][19] = 48,
-       [2][0][RTW89_FCC][21] = 62,
+       [2][0][RTW89_KCC][19] = 62,
+       [2][0][RTW89_ACMA][19] = 52,
+       [2][0][RTW89_CN][19] = 127,
+       [2][0][RTW89_UK][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_ACMA][21] = 48,
-       [2][0][RTW89_FCC][23] = 62,
+       [2][0][RTW89_KCC][21] = 62,
+       [2][0][RTW89_ACMA][21] = 52,
+       [2][0][RTW89_CN][21] = 127,
+       [2][0][RTW89_UK][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_ACMA][23] = 48,
-       [2][0][RTW89_FCC][25] = 62,
+       [2][0][RTW89_KCC][23] = 62,
+       [2][0][RTW89_ACMA][23] = 52,
+       [2][0][RTW89_CN][23] = 127,
+       [2][0][RTW89_UK][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_ACMA][25] = 127,
-       [2][0][RTW89_FCC][27] = 62,
+       [2][0][RTW89_CN][25] = 127,
+       [2][0][RTW89_UK][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_ACMA][27] = 127,
-       [2][0][RTW89_FCC][29] = 62,
+       [2][0][RTW89_CN][27] = 127,
+       [2][0][RTW89_UK][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_ACMA][29] = 127,
-       [2][0][RTW89_FCC][31] = 62,
+       [2][0][RTW89_CN][29] = 127,
+       [2][0][RTW89_UK][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] = 72,
-       [2][0][RTW89_ACMA][31] = 48,
-       [2][0][RTW89_FCC][33] = 64,
+       [2][0][RTW89_IC][31] = 62,
+       [2][0][RTW89_KCC][31] = 62,
+       [2][0][RTW89_ACMA][31] = 52,
+       [2][0][RTW89_CN][31] = 127,
+       [2][0][RTW89_UK][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] = 72,
-       [2][0][RTW89_ACMA][33] = 48,
-       [2][0][RTW89_FCC][35] = 64,
+       [2][0][RTW89_IC][33] = 62,
+       [2][0][RTW89_KCC][33] = 62,
+       [2][0][RTW89_ACMA][33] = 52,
+       [2][0][RTW89_CN][33] = 127,
+       [2][0][RTW89_UK][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] = 72,
-       [2][0][RTW89_ACMA][35] = 48,
-       [2][0][RTW89_FCC][37] = 62,
+       [2][0][RTW89_IC][35] = 62,
+       [2][0][RTW89_KCC][35] = 62,
+       [2][0][RTW89_ACMA][35] = 52,
+       [2][0][RTW89_CN][35] = 127,
+       [2][0][RTW89_UK][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_ACMA][37] = 76,
-       [2][0][RTW89_FCC][38] = 76,
+       [2][0][RTW89_KCC][37] = 62,
+       [2][0][RTW89_ACMA][37] = 70,
+       [2][0][RTW89_CN][37] = 127,
+       [2][0][RTW89_UK][37] = 52,
+       [2][0][RTW89_FCC][38] = 82,
        [2][0][RTW89_ETSI][38] = 28,
        [2][0][RTW89_MKK][38] = 127,
-       [2][0][RTW89_IC][38] = 84,
-       [2][0][RTW89_ACMA][38] = 84,
-       [2][0][RTW89_FCC][40] = 76,
+       [2][0][RTW89_IC][38] = 82,
+       [2][0][RTW89_KCC][38] = 64,
+       [2][0][RTW89_ACMA][38] = 82,
+       [2][0][RTW89_CN][38] = 68,
+       [2][0][RTW89_UK][38] = 54,
+       [2][0][RTW89_FCC][40] = 82,
        [2][0][RTW89_ETSI][40] = 28,
        [2][0][RTW89_MKK][40] = 127,
-       [2][0][RTW89_IC][40] = 84,
-       [2][0][RTW89_ACMA][40] = 84,
+       [2][0][RTW89_IC][40] = 82,
+       [2][0][RTW89_KCC][40] = 64,
+       [2][0][RTW89_ACMA][40] = 82,
+       [2][0][RTW89_CN][40] = 68,
+       [2][0][RTW89_UK][40] = 54,
        [2][0][RTW89_FCC][42] = 76,
        [2][0][RTW89_ETSI][42] = 28,
        [2][0][RTW89_MKK][42] = 127,
-       [2][0][RTW89_IC][42] = 84,
-       [2][0][RTW89_ACMA][42] = 84,
-       [2][0][RTW89_FCC][44] = 76,
+       [2][0][RTW89_IC][42] = 76,
+       [2][0][RTW89_KCC][42] = 64,
+       [2][0][RTW89_ACMA][42] = 76,
+       [2][0][RTW89_CN][42] = 68,
+       [2][0][RTW89_UK][42] = 54,
+       [2][0][RTW89_FCC][44] = 80,
        [2][0][RTW89_ETSI][44] = 28,
        [2][0][RTW89_MKK][44] = 127,
-       [2][0][RTW89_IC][44] = 84,
-       [2][0][RTW89_ACMA][44] = 84,
-       [2][0][RTW89_FCC][46] = 76,
+       [2][0][RTW89_IC][44] = 80,
+       [2][0][RTW89_KCC][44] = 64,
+       [2][0][RTW89_ACMA][44] = 80,
+       [2][0][RTW89_CN][44] = 68,
+       [2][0][RTW89_UK][44] = 54,
+       [2][0][RTW89_FCC][46] = 80,
        [2][0][RTW89_ETSI][46] = 28,
        [2][0][RTW89_MKK][46] = 127,
-       [2][0][RTW89_IC][46] = 84,
-       [2][0][RTW89_ACMA][46] = 84,
-       [2][0][RTW89_FCC][48] = 48,
+       [2][0][RTW89_IC][46] = 80,
+       [2][0][RTW89_KCC][46] = 64,
+       [2][0][RTW89_ACMA][46] = 80,
+       [2][0][RTW89_CN][46] = 68,
+       [2][0][RTW89_UK][46] = 54,
+       [2][0][RTW89_FCC][48] = 64,
        [2][0][RTW89_ETSI][48] = 127,
        [2][0][RTW89_MKK][48] = 127,
        [2][0][RTW89_IC][48] = 127,
+       [2][0][RTW89_KCC][48] = 127,
        [2][0][RTW89_ACMA][48] = 127,
-       [2][0][RTW89_FCC][50] = 48,
+       [2][0][RTW89_CN][48] = 127,
+       [2][0][RTW89_UK][48] = 127,
+       [2][0][RTW89_FCC][50] = 64,
        [2][0][RTW89_ETSI][50] = 127,
        [2][0][RTW89_MKK][50] = 127,
        [2][0][RTW89_IC][50] = 127,
+       [2][0][RTW89_KCC][50] = 127,
        [2][0][RTW89_ACMA][50] = 127,
-       [2][0][RTW89_FCC][52] = 48,
+       [2][0][RTW89_CN][50] = 127,
+       [2][0][RTW89_UK][50] = 127,
+       [2][0][RTW89_FCC][52] = 64,
        [2][0][RTW89_ETSI][52] = 127,
        [2][0][RTW89_MKK][52] = 127,
        [2][0][RTW89_IC][52] = 127,
+       [2][0][RTW89_KCC][52] = 127,
        [2][0][RTW89_ACMA][52] = 127,
-       [2][1][RTW89_FCC][0] = 42,
+       [2][0][RTW89_CN][52] = 127,
+       [2][0][RTW89_UK][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] = 20,
-       [2][1][RTW89_ACMA][0] = 36,
-       [2][1][RTW89_FCC][2] = 42,
+       [2][1][RTW89_IC][0] = 26,
+       [2][1][RTW89_KCC][0] = 44,
+       [2][1][RTW89_ACMA][0] = 40,
+       [2][1][RTW89_CN][0] = 28,
+       [2][1][RTW89_UK][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] = 18,
-       [2][1][RTW89_ACMA][2] = 36,
-       [2][1][RTW89_FCC][4] = 42,
+       [2][1][RTW89_IC][2] = 26,
+       [2][1][RTW89_KCC][2] = 44,
+       [2][1][RTW89_ACMA][2] = 40,
+       [2][1][RTW89_CN][2] = 28,
+       [2][1][RTW89_UK][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] = 22,
-       [2][1][RTW89_ACMA][4] = 36,
-       [2][1][RTW89_FCC][6] = 42,
+       [2][1][RTW89_IC][4] = 26,
+       [2][1][RTW89_KCC][4] = 44,
+       [2][1][RTW89_ACMA][4] = 40,
+       [2][1][RTW89_CN][4] = 28,
+       [2][1][RTW89_UK][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] = 22,
-       [2][1][RTW89_ACMA][6] = 36,
-       [2][1][RTW89_FCC][8] = 42,
+       [2][1][RTW89_IC][6] = 26,
+       [2][1][RTW89_KCC][6] = 20,
+       [2][1][RTW89_ACMA][6] = 40,
+       [2][1][RTW89_CN][6] = 28,
+       [2][1][RTW89_UK][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_ACMA][8] = 36,
-       [2][1][RTW89_FCC][10] = 42,
+       [2][1][RTW89_KCC][8] = 46,
+       [2][1][RTW89_ACMA][8] = 40,
+       [2][1][RTW89_CN][8] = 28,
+       [2][1][RTW89_UK][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_ACMA][10] = 36,
-       [2][1][RTW89_FCC][12] = 44,
+       [2][1][RTW89_KCC][10] = 46,
+       [2][1][RTW89_ACMA][10] = 40,
+       [2][1][RTW89_CN][10] = 28,
+       [2][1][RTW89_UK][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] = 52,
-       [2][1][RTW89_ACMA][12] = 36,
-       [2][1][RTW89_FCC][14] = 44,
+       [2][1][RTW89_IC][12] = 48,
+       [2][1][RTW89_KCC][12] = 46,
+       [2][1][RTW89_ACMA][12] = 40,
+       [2][1][RTW89_CN][12] = 28,
+       [2][1][RTW89_UK][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] = 52,
-       [2][1][RTW89_ACMA][14] = 36,
-       [2][1][RTW89_FCC][15] = 42,
+       [2][1][RTW89_IC][14] = 48,
+       [2][1][RTW89_KCC][14] = 46,
+       [2][1][RTW89_ACMA][14] = 40,
+       [2][1][RTW89_CN][14] = 28,
+       [2][1][RTW89_UK][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_ACMA][15] = 36,
-       [2][1][RTW89_FCC][17] = 42,
+       [2][1][RTW89_KCC][15] = 46,
+       [2][1][RTW89_ACMA][15] = 40,
+       [2][1][RTW89_CN][15] = 127,
+       [2][1][RTW89_UK][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_ACMA][17] = 36,
-       [2][1][RTW89_FCC][19] = 42,
+       [2][1][RTW89_KCC][17] = 46,
+       [2][1][RTW89_ACMA][17] = 40,
+       [2][1][RTW89_CN][17] = 127,
+       [2][1][RTW89_UK][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_ACMA][19] = 36,
-       [2][1][RTW89_FCC][21] = 42,
+       [2][1][RTW89_KCC][19] = 46,
+       [2][1][RTW89_ACMA][19] = 40,
+       [2][1][RTW89_CN][19] = 127,
+       [2][1][RTW89_UK][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_ACMA][21] = 36,
-       [2][1][RTW89_FCC][23] = 42,
+       [2][1][RTW89_KCC][21] = 46,
+       [2][1][RTW89_ACMA][21] = 40,
+       [2][1][RTW89_CN][21] = 127,
+       [2][1][RTW89_UK][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_ACMA][23] = 36,
-       [2][1][RTW89_FCC][25] = 42,
+       [2][1][RTW89_KCC][23] = 46,
+       [2][1][RTW89_ACMA][23] = 40,
+       [2][1][RTW89_CN][23] = 127,
+       [2][1][RTW89_UK][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_ACMA][25] = 127,
-       [2][1][RTW89_FCC][27] = 42,
+       [2][1][RTW89_CN][25] = 127,
+       [2][1][RTW89_UK][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_ACMA][27] = 127,
-       [2][1][RTW89_FCC][29] = 42,
+       [2][1][RTW89_CN][27] = 127,
+       [2][1][RTW89_UK][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_ACMA][29] = 127,
-       [2][1][RTW89_FCC][31] = 42,
+       [2][1][RTW89_CN][29] = 127,
+       [2][1][RTW89_UK][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] = 50,
-       [2][1][RTW89_ACMA][31] = 36,
-       [2][1][RTW89_FCC][33] = 42,
+       [2][1][RTW89_IC][31] = 48,
+       [2][1][RTW89_KCC][31] = 46,
+       [2][1][RTW89_ACMA][31] = 40,
+       [2][1][RTW89_CN][31] = 127,
+       [2][1][RTW89_UK][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] = 50,
-       [2][1][RTW89_ACMA][33] = 36,
-       [2][1][RTW89_FCC][35] = 42,
+       [2][1][RTW89_IC][33] = 48,
+       [2][1][RTW89_KCC][33] = 46,
+       [2][1][RTW89_ACMA][33] = 40,
+       [2][1][RTW89_CN][33] = 127,
+       [2][1][RTW89_UK][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] = 50,
-       [2][1][RTW89_ACMA][35] = 36,
-       [2][1][RTW89_FCC][37] = 42,
+       [2][1][RTW89_IC][35] = 48,
+       [2][1][RTW89_KCC][35] = 46,
+       [2][1][RTW89_ACMA][35] = 40,
+       [2][1][RTW89_CN][35] = 127,
+       [2][1][RTW89_UK][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] = 50,
-       [2][1][RTW89_ACMA][37] = 60,
-       [2][1][RTW89_FCC][38] = 76,
+       [2][1][RTW89_IC][37] = 52,
+       [2][1][RTW89_KCC][37] = 46,
+       [2][1][RTW89_ACMA][37] = 52,
+       [2][1][RTW89_CN][37] = 127,
+       [2][1][RTW89_UK][37] = 42,
+       [2][1][RTW89_FCC][38] = 78,
        [2][1][RTW89_ETSI][38] = 16,
        [2][1][RTW89_MKK][38] = 127,
-       [2][1][RTW89_IC][38] = 84,
-       [2][1][RTW89_ACMA][38] = 84,
-       [2][1][RTW89_FCC][40] = 76,
+       [2][1][RTW89_IC][38] = 78,
+       [2][1][RTW89_KCC][38] = 46,
+       [2][1][RTW89_ACMA][38] = 78,
+       [2][1][RTW89_CN][38] = 56,
+       [2][1][RTW89_UK][38] = 42,
+       [2][1][RTW89_FCC][40] = 78,
        [2][1][RTW89_ETSI][40] = 16,
        [2][1][RTW89_MKK][40] = 127,
-       [2][1][RTW89_IC][40] = 84,
-       [2][1][RTW89_ACMA][40] = 84,
-       [2][1][RTW89_FCC][42] = 76,
+       [2][1][RTW89_IC][40] = 78,
+       [2][1][RTW89_KCC][40] = 46,
+       [2][1][RTW89_ACMA][40] = 78,
+       [2][1][RTW89_CN][40] = 56,
+       [2][1][RTW89_UK][40] = 42,
+       [2][1][RTW89_FCC][42] = 78,
        [2][1][RTW89_ETSI][42] = 16,
        [2][1][RTW89_MKK][42] = 127,
-       [2][1][RTW89_IC][42] = 84,
-       [2][1][RTW89_ACMA][42] = 84,
-       [2][1][RTW89_FCC][44] = 76,
+       [2][1][RTW89_IC][42] = 78,
+       [2][1][RTW89_KCC][42] = 46,
+       [2][1][RTW89_ACMA][42] = 78,
+       [2][1][RTW89_CN][42] = 56,
+       [2][1][RTW89_UK][42] = 42,
+       [2][1][RTW89_FCC][44] = 74,
        [2][1][RTW89_ETSI][44] = 16,
        [2][1][RTW89_MKK][44] = 127,
-       [2][1][RTW89_IC][44] = 84,
-       [2][1][RTW89_ACMA][44] = 84,
-       [2][1][RTW89_FCC][46] = 76,
+       [2][1][RTW89_IC][44] = 74,
+       [2][1][RTW89_KCC][44] = 46,
+       [2][1][RTW89_ACMA][44] = 74,
+       [2][1][RTW89_CN][44] = 56,
+       [2][1][RTW89_UK][44] = 42,
+       [2][1][RTW89_FCC][46] = 74,
        [2][1][RTW89_ETSI][46] = 16,
        [2][1][RTW89_MKK][46] = 127,
-       [2][1][RTW89_IC][46] = 84,
-       [2][1][RTW89_ACMA][46] = 84,
-       [2][1][RTW89_FCC][48] = 36,
+       [2][1][RTW89_IC][46] = 74,
+       [2][1][RTW89_KCC][46] = 46,
+       [2][1][RTW89_ACMA][46] = 74,
+       [2][1][RTW89_CN][46] = 56,
+       [2][1][RTW89_UK][46] = 42,
+       [2][1][RTW89_FCC][48] = 40,
        [2][1][RTW89_ETSI][48] = 127,
        [2][1][RTW89_MKK][48] = 127,
        [2][1][RTW89_IC][48] = 127,
+       [2][1][RTW89_KCC][48] = 127,
        [2][1][RTW89_ACMA][48] = 127,
-       [2][1][RTW89_FCC][50] = 36,
+       [2][1][RTW89_CN][48] = 127,
+       [2][1][RTW89_UK][48] = 127,
+       [2][1][RTW89_FCC][50] = 40,
        [2][1][RTW89_ETSI][50] = 127,
        [2][1][RTW89_MKK][50] = 127,
        [2][1][RTW89_IC][50] = 127,
+       [2][1][RTW89_KCC][50] = 127,
        [2][1][RTW89_ACMA][50] = 127,
-       [2][1][RTW89_FCC][52] = 36,
+       [2][1][RTW89_CN][50] = 127,
+       [2][1][RTW89_UK][50] = 127,
+       [2][1][RTW89_FCC][52] = 40,
        [2][1][RTW89_ETSI][52] = 127,
        [2][1][RTW89_MKK][52] = 127,
        [2][1][RTW89_IC][52] = 127,
+       [2][1][RTW89_KCC][52] = 127,
        [2][1][RTW89_ACMA][52] = 127,
+       [2][1][RTW89_CN][52] = 127,
+       [2][1][RTW89_UK][52] = 127,
 };
 
 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] = 76,
-       [0][0][RTW89_WW][2] = 76,
-       [0][0][RTW89_WW][4] = 76,
-       [0][0][RTW89_WW][6] = 76,
-       [0][0][RTW89_WW][8] = 76,
-       [0][0][RTW89_WW][10] = 76,
-       [0][0][RTW89_WW][12] = 76,
-       [0][0][RTW89_WW][14] = 76,
-       [0][0][RTW89_WW][15] = 76,
-       [0][0][RTW89_WW][17] = 76,
-       [0][0][RTW89_WW][19] = 76,
-       [0][0][RTW89_WW][21] = 76,
-       [0][0][RTW89_WW][23] = 76,
-       [0][0][RTW89_WW][25] = 76,
-       [0][0][RTW89_WW][27] = 76,
-       [0][0][RTW89_WW][29] = 76,
-       [0][0][RTW89_WW][30] = 76,
-       [0][0][RTW89_WW][32] = 76,
-       [0][0][RTW89_WW][34] = 76,
-       [0][0][RTW89_WW][36] = 76,
-       [0][0][RTW89_WW][38] = 76,
-       [0][0][RTW89_WW][40] = 76,
-       [0][0][RTW89_WW][42] = 76,
-       [0][0][RTW89_WW][44] = 76,
-       [0][0][RTW89_WW][45] = 76,
-       [0][0][RTW89_WW][47] = 76,
-       [0][0][RTW89_WW][49] = 76,
-       [0][0][RTW89_WW][51] = 76,
-       [0][0][RTW89_WW][53] = 76,
-       [0][0][RTW89_WW][55] = 76,
-       [0][0][RTW89_WW][57] = 76,
-       [0][0][RTW89_WW][59] = 76,
-       [0][0][RTW89_WW][60] = 76,
-       [0][0][RTW89_WW][62] = 76,
-       [0][0][RTW89_WW][64] = 76,
-       [0][0][RTW89_WW][66] = 76,
-       [0][0][RTW89_WW][68] = 76,
-       [0][0][RTW89_WW][70] = 76,
-       [0][0][RTW89_WW][72] = 76,
-       [0][0][RTW89_WW][74] = 76,
-       [0][0][RTW89_WW][75] = 76,
-       [0][0][RTW89_WW][77] = 76,
-       [0][0][RTW89_WW][79] = 76,
-       [0][0][RTW89_WW][81] = 76,
-       [0][0][RTW89_WW][83] = 76,
-       [0][0][RTW89_WW][85] = 76,
-       [0][0][RTW89_WW][87] = 76,
-       [0][0][RTW89_WW][89] = 76,
-       [0][0][RTW89_WW][90] = 76,
-       [0][0][RTW89_WW][92] = 76,
-       [0][0][RTW89_WW][94] = 76,
-       [0][0][RTW89_WW][96] = 76,
-       [0][0][RTW89_WW][98] = 76,
-       [0][0][RTW89_WW][100] = 76,
-       [0][0][RTW89_WW][102] = 76,
-       [0][0][RTW89_WW][104] = 76,
-       [0][0][RTW89_WW][105] = 76,
-       [0][0][RTW89_WW][107] = 76,
-       [0][0][RTW89_WW][109] = 76,
+       [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] = 76,
-       [0][1][RTW89_WW][2] = 76,
-       [0][1][RTW89_WW][4] = 76,
-       [0][1][RTW89_WW][6] = 76,
-       [0][1][RTW89_WW][8] = 76,
-       [0][1][RTW89_WW][10] = 76,
-       [0][1][RTW89_WW][12] = 76,
-       [0][1][RTW89_WW][14] = 76,
-       [0][1][RTW89_WW][15] = 76,
-       [0][1][RTW89_WW][17] = 76,
-       [0][1][RTW89_WW][19] = 76,
-       [0][1][RTW89_WW][21] = 76,
-       [0][1][RTW89_WW][23] = 76,
-       [0][1][RTW89_WW][25] = 76,
-       [0][1][RTW89_WW][27] = 76,
-       [0][1][RTW89_WW][29] = 76,
-       [0][1][RTW89_WW][30] = 76,
-       [0][1][RTW89_WW][32] = 76,
-       [0][1][RTW89_WW][34] = 76,
-       [0][1][RTW89_WW][36] = 76,
-       [0][1][RTW89_WW][38] = 76,
-       [0][1][RTW89_WW][40] = 76,
-       [0][1][RTW89_WW][42] = 76,
-       [0][1][RTW89_WW][44] = 76,
-       [0][1][RTW89_WW][45] = 76,
-       [0][1][RTW89_WW][47] = 76,
-       [0][1][RTW89_WW][49] = 76,
-       [0][1][RTW89_WW][51] = 76,
-       [0][1][RTW89_WW][53] = 76,
-       [0][1][RTW89_WW][55] = 76,
-       [0][1][RTW89_WW][57] = 76,
-       [0][1][RTW89_WW][59] = 76,
-       [0][1][RTW89_WW][60] = 76,
-       [0][1][RTW89_WW][62] = 76,
-       [0][1][RTW89_WW][64] = 76,
-       [0][1][RTW89_WW][66] = 76,
-       [0][1][RTW89_WW][68] = 76,
-       [0][1][RTW89_WW][70] = 76,
-       [0][1][RTW89_WW][72] = 76,
-       [0][1][RTW89_WW][74] = 76,
-       [0][1][RTW89_WW][75] = 76,
-       [0][1][RTW89_WW][77] = 76,
-       [0][1][RTW89_WW][79] = 76,
-       [0][1][RTW89_WW][81] = 76,
-       [0][1][RTW89_WW][83] = 76,
-       [0][1][RTW89_WW][85] = 76,
-       [0][1][RTW89_WW][87] = 76,
-       [0][1][RTW89_WW][89] = 76,
-       [0][1][RTW89_WW][90] = 76,
-       [0][1][RTW89_WW][92] = 76,
-       [0][1][RTW89_WW][94] = 76,
-       [0][1][RTW89_WW][96] = 76,
-       [0][1][RTW89_WW][98] = 76,
-       [0][1][RTW89_WW][100] = 76,
-       [0][1][RTW89_WW][102] = 76,
-       [0][1][RTW89_WW][104] = 76,
-       [0][1][RTW89_WW][105] = 76,
-       [0][1][RTW89_WW][107] = 76,
-       [0][1][RTW89_WW][109] = 76,
+       [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] = 76,
-       [1][0][RTW89_WW][2] = 76,
-       [1][0][RTW89_WW][4] = 76,
-       [1][0][RTW89_WW][6] = 76,
-       [1][0][RTW89_WW][8] = 76,
-       [1][0][RTW89_WW][10] = 76,
-       [1][0][RTW89_WW][12] = 76,
-       [1][0][RTW89_WW][14] = 76,
-       [1][0][RTW89_WW][15] = 76,
-       [1][0][RTW89_WW][17] = 76,
-       [1][0][RTW89_WW][19] = 76,
-       [1][0][RTW89_WW][21] = 76,
-       [1][0][RTW89_WW][23] = 76,
-       [1][0][RTW89_WW][25] = 76,
-       [1][0][RTW89_WW][27] = 76,
-       [1][0][RTW89_WW][29] = 76,
-       [1][0][RTW89_WW][30] = 76,
-       [1][0][RTW89_WW][32] = 76,
-       [1][0][RTW89_WW][34] = 76,
-       [1][0][RTW89_WW][36] = 76,
-       [1][0][RTW89_WW][38] = 76,
-       [1][0][RTW89_WW][40] = 76,
-       [1][0][RTW89_WW][42] = 76,
-       [1][0][RTW89_WW][44] = 76,
-       [1][0][RTW89_WW][45] = 76,
-       [1][0][RTW89_WW][47] = 76,
-       [1][0][RTW89_WW][49] = 76,
-       [1][0][RTW89_WW][51] = 76,
-       [1][0][RTW89_WW][53] = 76,
-       [1][0][RTW89_WW][55] = 76,
-       [1][0][RTW89_WW][57] = 76,
-       [1][0][RTW89_WW][59] = 76,
-       [1][0][RTW89_WW][60] = 76,
-       [1][0][RTW89_WW][62] = 76,
-       [1][0][RTW89_WW][64] = 76,
-       [1][0][RTW89_WW][66] = 76,
-       [1][0][RTW89_WW][68] = 76,
-       [1][0][RTW89_WW][70] = 76,
-       [1][0][RTW89_WW][72] = 76,
-       [1][0][RTW89_WW][74] = 76,
-       [1][0][RTW89_WW][75] = 76,
-       [1][0][RTW89_WW][77] = 76,
-       [1][0][RTW89_WW][79] = 76,
-       [1][0][RTW89_WW][81] = 76,
-       [1][0][RTW89_WW][83] = 76,
-       [1][0][RTW89_WW][85] = 76,
-       [1][0][RTW89_WW][87] = 76,
-       [1][0][RTW89_WW][89] = 76,
-       [1][0][RTW89_WW][90] = 76,
-       [1][0][RTW89_WW][92] = 76,
-       [1][0][RTW89_WW][94] = 76,
-       [1][0][RTW89_WW][96] = 76,
-       [1][0][RTW89_WW][98] = 76,
-       [1][0][RTW89_WW][100] = 76,
-       [1][0][RTW89_WW][102] = 76,
-       [1][0][RTW89_WW][104] = 76,
-       [1][0][RTW89_WW][105] = 76,
-       [1][0][RTW89_WW][107] = 76,
-       [1][0][RTW89_WW][109] = 76,
+       [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] = 76,
-       [1][1][RTW89_WW][2] = 76,
-       [1][1][RTW89_WW][4] = 76,
-       [1][1][RTW89_WW][6] = 76,
-       [1][1][RTW89_WW][8] = 76,
-       [1][1][RTW89_WW][10] = 76,
-       [1][1][RTW89_WW][12] = 76,
-       [1][1][RTW89_WW][14] = 76,
-       [1][1][RTW89_WW][15] = 76,
-       [1][1][RTW89_WW][17] = 76,
-       [1][1][RTW89_WW][19] = 76,
-       [1][1][RTW89_WW][21] = 76,
-       [1][1][RTW89_WW][23] = 76,
-       [1][1][RTW89_WW][25] = 76,
-       [1][1][RTW89_WW][27] = 76,
-       [1][1][RTW89_WW][29] = 76,
-       [1][1][RTW89_WW][30] = 76,
-       [1][1][RTW89_WW][32] = 76,
-       [1][1][RTW89_WW][34] = 76,
-       [1][1][RTW89_WW][36] = 76,
-       [1][1][RTW89_WW][38] = 76,
-       [1][1][RTW89_WW][40] = 76,
-       [1][1][RTW89_WW][42] = 76,
-       [1][1][RTW89_WW][44] = 76,
-       [1][1][RTW89_WW][45] = 76,
-       [1][1][RTW89_WW][47] = 76,
-       [1][1][RTW89_WW][49] = 76,
-       [1][1][RTW89_WW][51] = 76,
-       [1][1][RTW89_WW][53] = 76,
-       [1][1][RTW89_WW][55] = 76,
-       [1][1][RTW89_WW][57] = 76,
-       [1][1][RTW89_WW][59] = 76,
-       [1][1][RTW89_WW][60] = 76,
-       [1][1][RTW89_WW][62] = 76,
-       [1][1][RTW89_WW][64] = 76,
-       [1][1][RTW89_WW][66] = 76,
-       [1][1][RTW89_WW][68] = 76,
-       [1][1][RTW89_WW][70] = 76,
-       [1][1][RTW89_WW][72] = 76,
-       [1][1][RTW89_WW][74] = 76,
-       [1][1][RTW89_WW][75] = 76,
-       [1][1][RTW89_WW][77] = 76,
-       [1][1][RTW89_WW][79] = 76,
-       [1][1][RTW89_WW][81] = 76,
-       [1][1][RTW89_WW][83] = 76,
-       [1][1][RTW89_WW][85] = 76,
-       [1][1][RTW89_WW][87] = 76,
-       [1][1][RTW89_WW][89] = 76,
-       [1][1][RTW89_WW][90] = 76,
-       [1][1][RTW89_WW][92] = 76,
-       [1][1][RTW89_WW][94] = 76,
-       [1][1][RTW89_WW][96] = 76,
-       [1][1][RTW89_WW][98] = 76,
-       [1][1][RTW89_WW][100] = 76,
-       [1][1][RTW89_WW][102] = 76,
-       [1][1][RTW89_WW][104] = 76,
-       [1][1][RTW89_WW][105] = 76,
-       [1][1][RTW89_WW][107] = 76,
-       [1][1][RTW89_WW][109] = 76,
+       [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] = 76,
-       [2][0][RTW89_WW][2] = 76,
-       [2][0][RTW89_WW][4] = 76,
-       [2][0][RTW89_WW][6] = 76,
-       [2][0][RTW89_WW][8] = 76,
-       [2][0][RTW89_WW][10] = 76,
-       [2][0][RTW89_WW][12] = 76,
-       [2][0][RTW89_WW][14] = 76,
-       [2][0][RTW89_WW][15] = 76,
-       [2][0][RTW89_WW][17] = 76,
-       [2][0][RTW89_WW][19] = 76,
-       [2][0][RTW89_WW][21] = 76,
-       [2][0][RTW89_WW][23] = 76,
-       [2][0][RTW89_WW][25] = 76,
-       [2][0][RTW89_WW][27] = 76,
-       [2][0][RTW89_WW][29] = 76,
-       [2][0][RTW89_WW][30] = 76,
-       [2][0][RTW89_WW][32] = 76,
-       [2][0][RTW89_WW][34] = 76,
-       [2][0][RTW89_WW][36] = 76,
-       [2][0][RTW89_WW][38] = 76,
-       [2][0][RTW89_WW][40] = 76,
-       [2][0][RTW89_WW][42] = 76,
-       [2][0][RTW89_WW][44] = 76,
-       [2][0][RTW89_WW][45] = 76,
-       [2][0][RTW89_WW][47] = 76,
-       [2][0][RTW89_WW][49] = 76,
-       [2][0][RTW89_WW][51] = 76,
-       [2][0][RTW89_WW][53] = 76,
-       [2][0][RTW89_WW][55] = 76,
-       [2][0][RTW89_WW][57] = 76,
-       [2][0][RTW89_WW][59] = 76,
-       [2][0][RTW89_WW][60] = 76,
-       [2][0][RTW89_WW][62] = 76,
-       [2][0][RTW89_WW][64] = 76,
-       [2][0][RTW89_WW][66] = 76,
-       [2][0][RTW89_WW][68] = 76,
-       [2][0][RTW89_WW][70] = 76,
-       [2][0][RTW89_WW][72] = 76,
-       [2][0][RTW89_WW][74] = 76,
-       [2][0][RTW89_WW][75] = 76,
-       [2][0][RTW89_WW][77] = 76,
-       [2][0][RTW89_WW][79] = 76,
-       [2][0][RTW89_WW][81] = 76,
-       [2][0][RTW89_WW][83] = 76,
-       [2][0][RTW89_WW][85] = 76,
-       [2][0][RTW89_WW][87] = 76,
-       [2][0][RTW89_WW][89] = 76,
-       [2][0][RTW89_WW][90] = 76,
-       [2][0][RTW89_WW][92] = 76,
-       [2][0][RTW89_WW][94] = 76,
-       [2][0][RTW89_WW][96] = 76,
-       [2][0][RTW89_WW][98] = 76,
-       [2][0][RTW89_WW][100] = 76,
-       [2][0][RTW89_WW][102] = 76,
-       [2][0][RTW89_WW][104] = 76,
-       [2][0][RTW89_WW][105] = 76,
-       [2][0][RTW89_WW][107] = 76,
-       [2][0][RTW89_WW][109] = 76,
+       [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] = 76,
-       [2][1][RTW89_WW][2] = 76,
-       [2][1][RTW89_WW][4] = 76,
-       [2][1][RTW89_WW][6] = 76,
-       [2][1][RTW89_WW][8] = 76,
-       [2][1][RTW89_WW][10] = 76,
-       [2][1][RTW89_WW][12] = 76,
-       [2][1][RTW89_WW][14] = 76,
-       [2][1][RTW89_WW][15] = 76,
-       [2][1][RTW89_WW][17] = 76,
-       [2][1][RTW89_WW][19] = 76,
-       [2][1][RTW89_WW][21] = 76,
-       [2][1][RTW89_WW][23] = 76,
-       [2][1][RTW89_WW][25] = 76,
-       [2][1][RTW89_WW][27] = 76,
-       [2][1][RTW89_WW][29] = 76,
-       [2][1][RTW89_WW][30] = 76,
-       [2][1][RTW89_WW][32] = 76,
-       [2][1][RTW89_WW][34] = 76,
-       [2][1][RTW89_WW][36] = 76,
-       [2][1][RTW89_WW][38] = 76,
-       [2][1][RTW89_WW][40] = 76,
-       [2][1][RTW89_WW][42] = 76,
-       [2][1][RTW89_WW][44] = 76,
-       [2][1][RTW89_WW][45] = 76,
-       [2][1][RTW89_WW][47] = 76,
-       [2][1][RTW89_WW][49] = 76,
-       [2][1][RTW89_WW][51] = 76,
-       [2][1][RTW89_WW][53] = 76,
-       [2][1][RTW89_WW][55] = 76,
-       [2][1][RTW89_WW][57] = 76,
-       [2][1][RTW89_WW][59] = 76,
-       [2][1][RTW89_WW][60] = 76,
-       [2][1][RTW89_WW][62] = 76,
-       [2][1][RTW89_WW][64] = 76,
-       [2][1][RTW89_WW][66] = 76,
-       [2][1][RTW89_WW][68] = 76,
-       [2][1][RTW89_WW][70] = 76,
-       [2][1][RTW89_WW][72] = 76,
-       [2][1][RTW89_WW][74] = 76,
-       [2][1][RTW89_WW][75] = 76,
-       [2][1][RTW89_WW][77] = 76,
-       [2][1][RTW89_WW][79] = 76,
-       [2][1][RTW89_WW][81] = 76,
-       [2][1][RTW89_WW][83] = 76,
-       [2][1][RTW89_WW][85] = 76,
-       [2][1][RTW89_WW][87] = 76,
-       [2][1][RTW89_WW][89] = 76,
-       [2][1][RTW89_WW][90] = 76,
-       [2][1][RTW89_WW][92] = 76,
-       [2][1][RTW89_WW][94] = 76,
-       [2][1][RTW89_WW][96] = 76,
-       [2][1][RTW89_WW][98] = 76,
-       [2][1][RTW89_WW][100] = 76,
-       [2][1][RTW89_WW][102] = 76,
-       [2][1][RTW89_WW][104] = 76,
-       [2][1][RTW89_WW][105] = 76,
-       [2][1][RTW89_WW][107] = 76,
-       [2][1][RTW89_WW][109] = 76,
+       [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] = 76,
-       [0][0][RTW89_FCC][2] = 76,
-       [0][0][RTW89_FCC][4] = 76,
-       [0][0][RTW89_FCC][6] = 76,
-       [0][0][RTW89_FCC][8] = 76,
-       [0][0][RTW89_FCC][10] = 76,
-       [0][0][RTW89_FCC][12] = 76,
-       [0][0][RTW89_FCC][14] = 76,
-       [0][0][RTW89_FCC][15] = 76,
-       [0][0][RTW89_FCC][17] = 76,
-       [0][0][RTW89_FCC][19] = 76,
-       [0][0][RTW89_FCC][21] = 76,
-       [0][0][RTW89_FCC][23] = 76,
-       [0][0][RTW89_FCC][25] = 76,
-       [0][0][RTW89_FCC][27] = 76,
-       [0][0][RTW89_FCC][29] = 76,
-       [0][0][RTW89_FCC][30] = 76,
-       [0][0][RTW89_FCC][32] = 76,
-       [0][0][RTW89_FCC][34] = 76,
-       [0][0][RTW89_FCC][36] = 76,
-       [0][0][RTW89_FCC][38] = 76,
-       [0][0][RTW89_FCC][40] = 76,
-       [0][0][RTW89_FCC][42] = 76,
-       [0][0][RTW89_FCC][44] = 76,
-       [0][0][RTW89_FCC][45] = 76,
-       [0][0][RTW89_FCC][47] = 76,
-       [0][0][RTW89_FCC][49] = 76,
-       [0][0][RTW89_FCC][51] = 76,
-       [0][0][RTW89_FCC][53] = 76,
-       [0][0][RTW89_FCC][55] = 76,
-       [0][0][RTW89_FCC][57] = 76,
-       [0][0][RTW89_FCC][59] = 76,
-       [0][0][RTW89_FCC][60] = 76,
-       [0][0][RTW89_FCC][62] = 76,
-       [0][0][RTW89_FCC][64] = 76,
-       [0][0][RTW89_FCC][66] = 76,
-       [0][0][RTW89_FCC][68] = 76,
-       [0][0][RTW89_FCC][70] = 76,
-       [0][0][RTW89_FCC][72] = 76,
-       [0][0][RTW89_FCC][74] = 76,
-       [0][0][RTW89_FCC][75] = 76,
-       [0][0][RTW89_FCC][77] = 76,
-       [0][0][RTW89_FCC][79] = 76,
-       [0][0][RTW89_FCC][81] = 76,
-       [0][0][RTW89_FCC][83] = 76,
-       [0][0][RTW89_FCC][85] = 76,
-       [0][0][RTW89_FCC][87] = 76,
-       [0][0][RTW89_FCC][89] = 76,
-       [0][0][RTW89_FCC][90] = 76,
-       [0][0][RTW89_FCC][92] = 76,
-       [0][0][RTW89_FCC][94] = 76,
-       [0][0][RTW89_FCC][96] = 76,
-       [0][0][RTW89_FCC][98] = 76,
-       [0][0][RTW89_FCC][100] = 76,
-       [0][0][RTW89_FCC][102] = 76,
-       [0][0][RTW89_FCC][104] = 76,
-       [0][0][RTW89_FCC][105] = 76,
-       [0][0][RTW89_FCC][107] = 76,
-       [0][0][RTW89_FCC][109] = 76,
+       [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][1][RTW89_FCC][0] = 76,
-       [0][1][RTW89_FCC][2] = 76,
-       [0][1][RTW89_FCC][4] = 76,
-       [0][1][RTW89_FCC][6] = 76,
-       [0][1][RTW89_FCC][8] = 76,
-       [0][1][RTW89_FCC][10] = 76,
-       [0][1][RTW89_FCC][12] = 76,
-       [0][1][RTW89_FCC][14] = 76,
-       [0][1][RTW89_FCC][15] = 76,
-       [0][1][RTW89_FCC][17] = 76,
-       [0][1][RTW89_FCC][19] = 76,
-       [0][1][RTW89_FCC][21] = 76,
-       [0][1][RTW89_FCC][23] = 76,
-       [0][1][RTW89_FCC][25] = 76,
-       [0][1][RTW89_FCC][27] = 76,
-       [0][1][RTW89_FCC][29] = 76,
-       [0][1][RTW89_FCC][30] = 76,
-       [0][1][RTW89_FCC][32] = 76,
-       [0][1][RTW89_FCC][34] = 76,
-       [0][1][RTW89_FCC][36] = 76,
-       [0][1][RTW89_FCC][38] = 76,
-       [0][1][RTW89_FCC][40] = 76,
-       [0][1][RTW89_FCC][42] = 76,
-       [0][1][RTW89_FCC][44] = 76,
-       [0][1][RTW89_FCC][45] = 76,
-       [0][1][RTW89_FCC][47] = 76,
-       [0][1][RTW89_FCC][49] = 76,
-       [0][1][RTW89_FCC][51] = 76,
-       [0][1][RTW89_FCC][53] = 76,
-       [0][1][RTW89_FCC][55] = 76,
-       [0][1][RTW89_FCC][57] = 76,
-       [0][1][RTW89_FCC][59] = 76,
-       [0][1][RTW89_FCC][60] = 76,
-       [0][1][RTW89_FCC][62] = 76,
-       [0][1][RTW89_FCC][64] = 76,
-       [0][1][RTW89_FCC][66] = 76,
-       [0][1][RTW89_FCC][68] = 76,
-       [0][1][RTW89_FCC][70] = 76,
-       [0][1][RTW89_FCC][72] = 76,
-       [0][1][RTW89_FCC][74] = 76,
-       [0][1][RTW89_FCC][75] = 76,
-       [0][1][RTW89_FCC][77] = 76,
-       [0][1][RTW89_FCC][79] = 76,
-       [0][1][RTW89_FCC][81] = 76,
-       [0][1][RTW89_FCC][83] = 76,
-       [0][1][RTW89_FCC][85] = 76,
-       [0][1][RTW89_FCC][87] = 76,
-       [0][1][RTW89_FCC][89] = 76,
-       [0][1][RTW89_FCC][90] = 76,
-       [0][1][RTW89_FCC][92] = 76,
-       [0][1][RTW89_FCC][94] = 76,
-       [0][1][RTW89_FCC][96] = 76,
-       [0][1][RTW89_FCC][98] = 76,
-       [0][1][RTW89_FCC][100] = 76,
-       [0][1][RTW89_FCC][102] = 76,
-       [0][1][RTW89_FCC][104] = 76,
-       [0][1][RTW89_FCC][105] = 76,
-       [0][1][RTW89_FCC][107] = 76,
-       [0][1][RTW89_FCC][109] = 76,
+       [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,
-       [1][0][RTW89_FCC][0] = 76,
-       [1][0][RTW89_FCC][2] = 76,
-       [1][0][RTW89_FCC][4] = 76,
-       [1][0][RTW89_FCC][6] = 76,
-       [1][0][RTW89_FCC][8] = 76,
-       [1][0][RTW89_FCC][10] = 76,
-       [1][0][RTW89_FCC][12] = 76,
-       [1][0][RTW89_FCC][14] = 76,
-       [1][0][RTW89_FCC][15] = 76,
-       [1][0][RTW89_FCC][17] = 76,
-       [1][0][RTW89_FCC][19] = 76,
-       [1][0][RTW89_FCC][21] = 76,
-       [1][0][RTW89_FCC][23] = 76,
-       [1][0][RTW89_FCC][25] = 76,
-       [1][0][RTW89_FCC][27] = 76,
-       [1][0][RTW89_FCC][29] = 76,
-       [1][0][RTW89_FCC][30] = 76,
-       [1][0][RTW89_FCC][32] = 76,
-       [1][0][RTW89_FCC][34] = 76,
-       [1][0][RTW89_FCC][36] = 76,
-       [1][0][RTW89_FCC][38] = 76,
-       [1][0][RTW89_FCC][40] = 76,
-       [1][0][RTW89_FCC][42] = 76,
-       [1][0][RTW89_FCC][44] = 76,
-       [1][0][RTW89_FCC][45] = 76,
-       [1][0][RTW89_FCC][47] = 76,
-       [1][0][RTW89_FCC][49] = 76,
-       [1][0][RTW89_FCC][51] = 76,
-       [1][0][RTW89_FCC][53] = 76,
-       [1][0][RTW89_FCC][55] = 76,
-       [1][0][RTW89_FCC][57] = 76,
-       [1][0][RTW89_FCC][59] = 76,
-       [1][0][RTW89_FCC][60] = 76,
-       [1][0][RTW89_FCC][62] = 76,
-       [1][0][RTW89_FCC][64] = 76,
-       [1][0][RTW89_FCC][66] = 76,
-       [1][0][RTW89_FCC][68] = 76,
-       [1][0][RTW89_FCC][70] = 76,
-       [1][0][RTW89_FCC][72] = 76,
-       [1][0][RTW89_FCC][74] = 76,
-       [1][0][RTW89_FCC][75] = 76,
-       [1][0][RTW89_FCC][77] = 76,
-       [1][0][RTW89_FCC][79] = 76,
-       [1][0][RTW89_FCC][81] = 76,
-       [1][0][RTW89_FCC][83] = 76,
-       [1][0][RTW89_FCC][85] = 76,
-       [1][0][RTW89_FCC][87] = 76,
-       [1][0][RTW89_FCC][89] = 76,
-       [1][0][RTW89_FCC][90] = 76,
-       [1][0][RTW89_FCC][92] = 76,
-       [1][0][RTW89_FCC][94] = 76,
-       [1][0][RTW89_FCC][96] = 76,
-       [1][0][RTW89_FCC][98] = 76,
-       [1][0][RTW89_FCC][100] = 76,
-       [1][0][RTW89_FCC][102] = 76,
-       [1][0][RTW89_FCC][104] = 76,
-       [1][0][RTW89_FCC][105] = 76,
-       [1][0][RTW89_FCC][107] = 76,
-       [1][0][RTW89_FCC][109] = 76,
+       [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][1][RTW89_FCC][0] = 76,
-       [1][1][RTW89_FCC][2] = 76,
-       [1][1][RTW89_FCC][4] = 76,
-       [1][1][RTW89_FCC][6] = 76,
-       [1][1][RTW89_FCC][8] = 76,
-       [1][1][RTW89_FCC][10] = 76,
-       [1][1][RTW89_FCC][12] = 76,
-       [1][1][RTW89_FCC][14] = 76,
-       [1][1][RTW89_FCC][15] = 76,
-       [1][1][RTW89_FCC][17] = 76,
-       [1][1][RTW89_FCC][19] = 76,
-       [1][1][RTW89_FCC][21] = 76,
-       [1][1][RTW89_FCC][23] = 76,
-       [1][1][RTW89_FCC][25] = 76,
-       [1][1][RTW89_FCC][27] = 76,
-       [1][1][RTW89_FCC][29] = 76,
-       [1][1][RTW89_FCC][30] = 76,
-       [1][1][RTW89_FCC][32] = 76,
-       [1][1][RTW89_FCC][34] = 76,
-       [1][1][RTW89_FCC][36] = 76,
-       [1][1][RTW89_FCC][38] = 76,
-       [1][1][RTW89_FCC][40] = 76,
-       [1][1][RTW89_FCC][42] = 76,
-       [1][1][RTW89_FCC][44] = 76,
-       [1][1][RTW89_FCC][45] = 76,
-       [1][1][RTW89_FCC][47] = 76,
-       [1][1][RTW89_FCC][49] = 76,
-       [1][1][RTW89_FCC][51] = 76,
-       [1][1][RTW89_FCC][53] = 76,
-       [1][1][RTW89_FCC][55] = 76,
-       [1][1][RTW89_FCC][57] = 76,
-       [1][1][RTW89_FCC][59] = 76,
-       [1][1][RTW89_FCC][60] = 76,
-       [1][1][RTW89_FCC][62] = 76,
-       [1][1][RTW89_FCC][64] = 76,
-       [1][1][RTW89_FCC][66] = 76,
-       [1][1][RTW89_FCC][68] = 76,
-       [1][1][RTW89_FCC][70] = 76,
-       [1][1][RTW89_FCC][72] = 76,
-       [1][1][RTW89_FCC][74] = 76,
-       [1][1][RTW89_FCC][75] = 76,
-       [1][1][RTW89_FCC][77] = 76,
-       [1][1][RTW89_FCC][79] = 76,
-       [1][1][RTW89_FCC][81] = 76,
-       [1][1][RTW89_FCC][83] = 76,
-       [1][1][RTW89_FCC][85] = 76,
-       [1][1][RTW89_FCC][87] = 76,
-       [1][1][RTW89_FCC][89] = 76,
-       [1][1][RTW89_FCC][90] = 76,
-       [1][1][RTW89_FCC][92] = 76,
-       [1][1][RTW89_FCC][94] = 76,
-       [1][1][RTW89_FCC][96] = 76,
-       [1][1][RTW89_FCC][98] = 76,
-       [1][1][RTW89_FCC][100] = 76,
-       [1][1][RTW89_FCC][102] = 76,
-       [1][1][RTW89_FCC][104] = 76,
-       [1][1][RTW89_FCC][105] = 76,
-       [1][1][RTW89_FCC][107] = 76,
-       [1][1][RTW89_FCC][109] = 76,
+       [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,
-       [2][0][RTW89_FCC][0] = 76,
-       [2][0][RTW89_FCC][2] = 76,
-       [2][0][RTW89_FCC][4] = 76,
-       [2][0][RTW89_FCC][6] = 76,
-       [2][0][RTW89_FCC][8] = 76,
-       [2][0][RTW89_FCC][10] = 76,
-       [2][0][RTW89_FCC][12] = 76,
-       [2][0][RTW89_FCC][14] = 76,
-       [2][0][RTW89_FCC][15] = 76,
-       [2][0][RTW89_FCC][17] = 76,
-       [2][0][RTW89_FCC][19] = 76,
-       [2][0][RTW89_FCC][21] = 76,
-       [2][0][RTW89_FCC][23] = 76,
-       [2][0][RTW89_FCC][25] = 76,
-       [2][0][RTW89_FCC][27] = 76,
-       [2][0][RTW89_FCC][29] = 76,
-       [2][0][RTW89_FCC][30] = 76,
-       [2][0][RTW89_FCC][32] = 76,
-       [2][0][RTW89_FCC][34] = 76,
-       [2][0][RTW89_FCC][36] = 76,
-       [2][0][RTW89_FCC][38] = 76,
-       [2][0][RTW89_FCC][40] = 76,
-       [2][0][RTW89_FCC][42] = 76,
-       [2][0][RTW89_FCC][44] = 76,
-       [2][0][RTW89_FCC][45] = 76,
-       [2][0][RTW89_FCC][47] = 76,
-       [2][0][RTW89_FCC][49] = 76,
-       [2][0][RTW89_FCC][51] = 76,
-       [2][0][RTW89_FCC][53] = 76,
-       [2][0][RTW89_FCC][55] = 76,
-       [2][0][RTW89_FCC][57] = 76,
-       [2][0][RTW89_FCC][59] = 76,
-       [2][0][RTW89_FCC][60] = 76,
-       [2][0][RTW89_FCC][62] = 76,
-       [2][0][RTW89_FCC][64] = 76,
-       [2][0][RTW89_FCC][66] = 76,
-       [2][0][RTW89_FCC][68] = 76,
-       [2][0][RTW89_FCC][70] = 76,
-       [2][0][RTW89_FCC][72] = 76,
-       [2][0][RTW89_FCC][74] = 76,
-       [2][0][RTW89_FCC][75] = 76,
-       [2][0][RTW89_FCC][77] = 76,
-       [2][0][RTW89_FCC][79] = 76,
-       [2][0][RTW89_FCC][81] = 76,
-       [2][0][RTW89_FCC][83] = 76,
-       [2][0][RTW89_FCC][85] = 76,
-       [2][0][RTW89_FCC][87] = 76,
-       [2][0][RTW89_FCC][89] = 76,
-       [2][0][RTW89_FCC][90] = 76,
-       [2][0][RTW89_FCC][92] = 76,
-       [2][0][RTW89_FCC][94] = 76,
-       [2][0][RTW89_FCC][96] = 76,
-       [2][0][RTW89_FCC][98] = 76,
-       [2][0][RTW89_FCC][100] = 76,
-       [2][0][RTW89_FCC][102] = 76,
-       [2][0][RTW89_FCC][104] = 76,
-       [2][0][RTW89_FCC][105] = 76,
-       [2][0][RTW89_FCC][107] = 76,
-       [2][0][RTW89_FCC][109] = 76,
+       [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][1][RTW89_FCC][0] = 76,
-       [2][1][RTW89_FCC][2] = 76,
-       [2][1][RTW89_FCC][4] = 76,
-       [2][1][RTW89_FCC][6] = 76,
-       [2][1][RTW89_FCC][8] = 76,
-       [2][1][RTW89_FCC][10] = 76,
-       [2][1][RTW89_FCC][12] = 76,
-       [2][1][RTW89_FCC][14] = 76,
-       [2][1][RTW89_FCC][15] = 76,
-       [2][1][RTW89_FCC][17] = 76,
-       [2][1][RTW89_FCC][19] = 76,
-       [2][1][RTW89_FCC][21] = 76,
-       [2][1][RTW89_FCC][23] = 76,
-       [2][1][RTW89_FCC][25] = 76,
-       [2][1][RTW89_FCC][27] = 76,
-       [2][1][RTW89_FCC][29] = 76,
-       [2][1][RTW89_FCC][30] = 76,
-       [2][1][RTW89_FCC][32] = 76,
-       [2][1][RTW89_FCC][34] = 76,
-       [2][1][RTW89_FCC][36] = 76,
-       [2][1][RTW89_FCC][38] = 76,
-       [2][1][RTW89_FCC][40] = 76,
-       [2][1][RTW89_FCC][42] = 76,
-       [2][1][RTW89_FCC][44] = 76,
-       [2][1][RTW89_FCC][45] = 76,
-       [2][1][RTW89_FCC][47] = 76,
-       [2][1][RTW89_FCC][49] = 76,
-       [2][1][RTW89_FCC][51] = 76,
-       [2][1][RTW89_FCC][53] = 76,
-       [2][1][RTW89_FCC][55] = 76,
-       [2][1][RTW89_FCC][57] = 76,
-       [2][1][RTW89_FCC][59] = 76,
-       [2][1][RTW89_FCC][60] = 76,
-       [2][1][RTW89_FCC][62] = 76,
-       [2][1][RTW89_FCC][64] = 76,
-       [2][1][RTW89_FCC][66] = 76,
-       [2][1][RTW89_FCC][68] = 76,
-       [2][1][RTW89_FCC][70] = 76,
-       [2][1][RTW89_FCC][72] = 76,
-       [2][1][RTW89_FCC][74] = 76,
-       [2][1][RTW89_FCC][75] = 76,
-       [2][1][RTW89_FCC][77] = 76,
-       [2][1][RTW89_FCC][79] = 76,
-       [2][1][RTW89_FCC][81] = 76,
-       [2][1][RTW89_FCC][83] = 76,
-       [2][1][RTW89_FCC][85] = 76,
-       [2][1][RTW89_FCC][87] = 76,
-       [2][1][RTW89_FCC][89] = 76,
-       [2][1][RTW89_FCC][90] = 76,
-       [2][1][RTW89_FCC][92] = 76,
-       [2][1][RTW89_FCC][94] = 76,
-       [2][1][RTW89_FCC][96] = 76,
-       [2][1][RTW89_FCC][98] = 76,
-       [2][1][RTW89_FCC][100] = 76,
-       [2][1][RTW89_FCC][102] = 76,
-       [2][1][RTW89_FCC][104] = 76,
-       [2][1][RTW89_FCC][105] = 76,
-       [2][1][RTW89_FCC][107] = 76,
-       [2][1][RTW89_FCC][109] = 76,
+       [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,
 };
 
 const struct rtw89_phy_table rtw89_8852c_phy_bb_table = {
index eb2d3ec..dfccae8 100644 (file)
@@ -81,9 +81,9 @@ static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
 static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev, s32 *cfg)
 {
        struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
-       struct rtw89_hal *hal = &rtwdev->hal;
-       enum rtw89_band band = hal->current_band_type;
-       u32 center_freq = hal->current_freq;
+       const struct rtw89_chan *chan = rtw89_chan_get(rtwdev, RTW89_SUB_ENTITY_0);
+       enum rtw89_band band = chan->band_type;
+       u32 center_freq = chan->freq;
        const struct rtw89_sar_span *span = NULL;
        enum rtw89_sar_subband subband_l, subband_h;
        int idx;
@@ -228,7 +228,7 @@ static int rtw89_apply_sar_common(struct rtw89_dev *rtwdev,
        }
 
        rtw89_sar_set_src(rtwdev, RTW89_SAR_SOURCE_COMMON, cfg_common, sar);
-       rtw89_chip_set_txpwr(rtwdev);
+       rtw89_core_set_chip_txpwr(rtwdev);
 
 exit:
        mutex_unlock(&rtwdev->mutex);
index 726223f..ee0ae28 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/devcoredump.h>
 
 #include "cam.h"
+#include "chan.h"
 #include "debug.h"
 #include "fw.h"
 #include "mac.h"
@@ -152,7 +153,10 @@ static void ser_state_run(struct rtw89_ser *ser, u8 evt)
        rtw89_debug(rtwdev, RTW89_DBG_SER, "ser: %s receive %s\n",
                    ser_st_name(ser), ser_ev_name(ser, evt));
 
+       mutex_lock(&rtwdev->mutex);
        rtw89_leave_lps(rtwdev);
+       mutex_unlock(&rtwdev->mutex);
+
        ser->st_tbl[ser->state].st_func(ser, evt);
 }
 
@@ -298,7 +302,7 @@ static void ser_reset_vif(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
        rtwvif->trigger = false;
 }
 
-static void ser_sta_deinit_addr_cam_iter(void *data, struct ieee80211_sta *sta)
+static void ser_sta_deinit_cam_iter(void *data, struct ieee80211_sta *sta)
 {
        struct rtw89_vif *rtwvif = (struct rtw89_vif *)data;
        struct rtw89_dev *rtwdev = rtwvif->rtwdev;
@@ -308,15 +312,19 @@ static void ser_sta_deinit_addr_cam_iter(void *data, struct ieee80211_sta *sta)
                rtw89_cam_deinit_addr_cam(rtwdev, &rtwsta->addr_cam);
        if (sta->tdls)
                rtw89_cam_deinit_bssid_cam(rtwdev, &rtwsta->bssid_cam);
+
+       INIT_LIST_HEAD(&rtwsta->ba_cam_list);
 }
 
 static void ser_deinit_cam(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
 {
        ieee80211_iterate_stations_atomic(rtwdev->hw,
-                                         ser_sta_deinit_addr_cam_iter,
+                                         ser_sta_deinit_cam_iter,
                                          rtwvif);
 
        rtw89_cam_deinit(rtwdev, rtwvif);
+
+       bitmap_zero(rtwdev->cam_info.ba_cam_map, RTW89_MAX_BA_CAM_NUM);
 }
 
 static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)
@@ -601,6 +609,7 @@ bottom:
 
        ser_reset_mac_binding(rtwdev);
        rtw89_core_stop(rtwdev);
+       rtw89_entity_init(rtwdev);
        INIT_LIST_HEAD(&rtwdev->rtwvifs_list);
 }
 
index 0552429..3259332 100644 (file)
@@ -489,14 +489,16 @@ static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev);
 
 static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr,
-                        struct key_params *params);
+                        int link_id,  u8 key_index, bool pairwise,
+                        const u8 *mac_addr, struct key_params *params);
 
 static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr);
+                        int link_id, u8 key_index, bool pairwise,
+                        const u8 *mac_addr);
 
 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-                                u8 key_index, bool unicast, bool multicast);
+                                int link_id, u8 key_index, bool unicast,
+                                bool multicast);
 
 static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
                             const u8 *mac, struct station_info *sinfo);
@@ -2377,8 +2379,8 @@ static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 }
 
 static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr,
-                        struct key_params *params)
+                        int link_id,  u8 key_index, bool pairwise,
+                        const u8 *mac_addr, struct key_params *params)
 {
        struct rndis_wlan_private *priv = wiphy_priv(wiphy);
        struct usbnet *usbdev = priv->usbdev;
@@ -2413,7 +2415,8 @@ static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev,
 }
 
 static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
-                        u8 key_index, bool pairwise, const u8 *mac_addr)
+                        int link_id, u8 key_index, bool pairwise,
+                        const u8 *mac_addr)
 {
        struct rndis_wlan_private *priv = wiphy_priv(wiphy);
        struct usbnet *usbdev = priv->usbdev;
@@ -2424,7 +2427,8 @@ static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev,
 }
 
 static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
-                                u8 key_index, bool unicast, bool multicast)
+                                int link_id, u8 key_index, bool unicast,
+                                bool multicast)
 {
        struct rndis_wlan_private *priv = wiphy_priv(wiphy);
        struct usbnet *usbdev = priv->usbdev;
index e015bfb..84d82dd 100644 (file)
@@ -181,7 +181,7 @@ int wfx_send_pds(struct wfx_dev *wdev, u8 *buf, size_t len)
        while (len > 0) {
                chunk_type = get_unaligned_le16(buf + 0);
                chunk_len = get_unaligned_le16(buf + 2);
-               if (chunk_len > len) {
+               if (chunk_len < 4 || chunk_len > len) {
                        dev_err(wdev->dev, "PDS:%d: corrupted file\n", chunk_num);
                        return -EINVAL;
                }
index dad38fc..1b532e0 100644 (file)
@@ -1441,7 +1441,7 @@ static void wl3501_detach(struct pcmcia_device *link)
 static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info,
                           union iwreq_data *wrqu, char *extra)
 {
-       strlcpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name));
+       strscpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name));
        return 0;
 }
 
@@ -1652,7 +1652,7 @@ static int wl3501_set_nick(struct net_device *dev, struct iw_request_info *info,
 
        if (wrqu->data.length > sizeof(this->nick))
                return -E2BIG;
-       strlcpy(this->nick, extra, wrqu->data.length);
+       strscpy(this->nick, extra, wrqu->data.length);
        return 0;
 }
 
@@ -1661,7 +1661,7 @@ static int wl3501_get_nick(struct net_device *dev, struct iw_request_info *info,
 {
        struct wl3501_card *this = netdev_priv(dev);
 
-       strlcpy(extra, this->nick, 32);
+       strscpy(extra, this->nick, 32);
        wrqu->data.length = strlen(extra);
        return 0;
 }
@@ -1965,7 +1965,7 @@ static int wl3501_config(struct pcmcia_device *link)
        this->firmware_date[0]  = '\0';
        this->rssi              = 255;
        this->chan              = iw_default_channel(this->reg_domain);
-       strlcpy(this->nick, "Planet WL3501", sizeof(this->nick));
+       strscpy(this->nick, "Planet WL3501", sizeof(this->nick));
        spin_lock_init(&this->lock);
        init_waitqueue_head(&this->wait);
        netif_start_queue(dev);
index 7fa960b..42da760 100644 (file)
@@ -578,6 +578,7 @@ int of_device_compatible_match(struct device_node *device,
 
        return score;
 }
+EXPORT_SYMBOL_GPL(of_device_compatible_match);
 
 /**
  * of_machine_is_compatible - Test root of device tree for a given compatible value
index e86a879..d1a50fa 100644 (file)
@@ -401,6 +401,9 @@ static int serdes_set_mode(struct phy *phy, enum phy_mode mode, int submode)
            submode == PHY_INTERFACE_MODE_2500BASEX)
                submode = PHY_INTERFACE_MODE_SGMII;
 
+       if (submode == PHY_INTERFACE_MODE_QUSGMII)
+               submode = PHY_INTERFACE_MODE_QSGMII;
+
        for (i = 0; i < ARRAY_SIZE(lan966x_serdes_muxes); i++) {
                if (macro->idx != lan966x_serdes_muxes[i].idx ||
                    mode != lan966x_serdes_muxes[i].mode ||
index a3e117a..f6c37a9 100644 (file)
@@ -7153,22 +7153,18 @@ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
        switch (instance->adapter_type) {
        case MFI_SERIES:
                if (megasas_alloc_mfi_ctrl_mem(instance))
-                       goto fail;
+                       return -ENOMEM;
                break;
        case AERO_SERIES:
        case VENTURA_SERIES:
        case THUNDERBOLT_SERIES:
        case INVADER_SERIES:
                if (megasas_alloc_fusion_context(instance))
-                       goto fail;
+                       return -ENOMEM;
                break;
        }
 
        return 0;
- fail:
-       kfree(instance->reply_map);
-       instance->reply_map = NULL;
-       return -ENOMEM;
 }
 
 /*
index e48d426..09c5fe3 100644 (file)
@@ -5310,7 +5310,6 @@ megasas_alloc_fusion_context(struct megasas_instance *instance)
                if (!fusion->log_to_span) {
                        dev_err(&instance->pdev->dev, "Failed from %s %d\n",
                                __func__, __LINE__);
-                       kfree(instance->ctrl_context);
                        return -ENOMEM;
                }
        }
index 2b2f682..62666df 100644 (file)
@@ -6935,14 +6935,8 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha)
 
        if (ha->flags.msix_enabled) {
                if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
-                       if (IS_QLA2071(ha)) {
-                               /* 4 ports Baker: Enable Interrupt Handshake */
-                               icb->msix_atio = 0;
-                               icb->firmware_options_2 |= cpu_to_le32(BIT_26);
-                       } else {
-                               icb->msix_atio = cpu_to_le16(msix->entry);
-                               icb->firmware_options_2 &= cpu_to_le32(~BIT_26);
-                       }
+                       icb->msix_atio = cpu_to_le16(msix->entry);
+                       icb->firmware_options_2 &= cpu_to_le32(~BIT_26);
                        ql_dbg(ql_dbg_init, vha, 0xf072,
                            "Registering ICB vector 0x%x for atio que.\n",
                            msix->entry);
index 4dbd29a..ef08029 100644 (file)
@@ -111,7 +111,7 @@ scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
        }
 }
 
-static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
+static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs)
 {
        struct request *rq = scsi_cmd_to_rq(cmd);
 
@@ -121,7 +121,12 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
        } else {
                WARN_ON_ONCE(true);
        }
-       blk_mq_requeue_request(rq, true);
+
+       if (msecs) {
+               blk_mq_requeue_request(rq, false);
+               blk_mq_delay_kick_requeue_list(rq->q, msecs);
+       } else
+               blk_mq_requeue_request(rq, true);
 }
 
 /**
@@ -651,14 +656,6 @@ static unsigned int scsi_rq_err_bytes(const struct request *rq)
        return bytes;
 }
 
-/* Helper for scsi_io_completion() when "reprep" action required. */
-static void scsi_io_completion_reprep(struct scsi_cmnd *cmd,
-                                     struct request_queue *q)
-{
-       /* A new command will be prepared and issued. */
-       scsi_mq_requeue_cmd(cmd);
-}
-
 static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
 {
        struct request *req = scsi_cmd_to_rq(cmd);
@@ -676,14 +673,21 @@ static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
        return false;
 }
 
+/*
+ * When ALUA transition state is returned, reprep the cmd to
+ * use the ALUA handler's transition timeout. Delay the reprep
+ * 1 sec to avoid aggressive retries of the target in that
+ * state.
+ */
+#define ALUA_TRANSITION_REPREP_DELAY   1000
+
 /* Helper for scsi_io_completion() when special action required. */
 static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
 {
-       struct request_queue *q = cmd->device->request_queue;
        struct request *req = scsi_cmd_to_rq(cmd);
        int level = 0;
-       enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
-             ACTION_DELAYED_RETRY} action;
+       enum {ACTION_FAIL, ACTION_REPREP, ACTION_DELAYED_REPREP,
+             ACTION_RETRY, ACTION_DELAYED_RETRY} action;
        struct scsi_sense_hdr sshdr;
        bool sense_valid;
        bool sense_current = true;      /* false implies "deferred sense" */
@@ -772,8 +776,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
                                        action = ACTION_DELAYED_RETRY;
                                        break;
                                case 0x0a: /* ALUA state transition */
-                                       blk_stat = BLK_STS_TRANSPORT;
-                                       fallthrough;
+                                       action = ACTION_DELAYED_REPREP;
+                                       break;
                                default:
                                        action = ACTION_FAIL;
                                        break;
@@ -832,7 +836,10 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
                        return;
                fallthrough;
        case ACTION_REPREP:
-               scsi_io_completion_reprep(cmd, q);
+               scsi_mq_requeue_cmd(cmd, 0);
+               break;
+       case ACTION_DELAYED_REPREP:
+               scsi_mq_requeue_cmd(cmd, ALUA_TRANSITION_REPREP_DELAY);
                break;
        case ACTION_RETRY:
                /* Retry the same command immediately */
@@ -926,7 +933,7 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result,
  * command block will be released and the queue function will be goosed. If we
  * are not done then we have to figure out what to do next:
  *
- *   a) We can call scsi_io_completion_reprep().  The request will be
+ *   a) We can call scsi_mq_requeue_cmd().  The request will be
  *     unprepared and put back on the queue.  Then a new command will
  *     be created for it.  This should be used if we made forward
  *     progress, or if we want to switch from READ(10) to READ(6) for
@@ -942,7 +949,6 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result,
 void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 {
        int result = cmd->result;
-       struct request_queue *q = cmd->device->request_queue;
        struct request *req = scsi_cmd_to_rq(cmd);
        blk_status_t blk_stat = BLK_STS_OK;
 
@@ -979,7 +985,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
         * request just queue the command up again.
         */
        if (likely(result == 0))
-               scsi_io_completion_reprep(cmd, q);
+               scsi_mq_requeue_cmd(cmd, 0);
        else
                scsi_io_completion_action(cmd, result);
 }
@@ -1542,7 +1548,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
        scsi_init_command(sdev, cmd);
 
        cmd->eh_eflags = 0;
-       cmd->allowed = 0;
        cmd->prot_type = 0;
        cmd->prot_flags = 0;
        cmd->submitter = 0;
@@ -1593,6 +1598,8 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
                        return ret;
        }
 
+       /* Usually overridden by the ULP */
+       cmd->allowed = 0;
        memset(cmd->cmnd, 0, sizeof(cmd->cmnd));
        return scsi_cmd_to_driver(cmd)->init_command(cmd);
 }
index 8f79fa6..eb76ba0 100644 (file)
@@ -103,7 +103,6 @@ static void sd_config_discard(struct scsi_disk *, unsigned int);
 static void sd_config_write_same(struct scsi_disk *);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
-static void sd_start_done_work(struct work_struct *work);
 static int  sd_probe(struct device *);
 static int  sd_remove(struct device *);
 static void sd_shutdown(struct device *);
@@ -3471,7 +3470,6 @@ static int sd_probe(struct device *dev)
        sdkp->max_retries = SD_MAX_RETRIES;
        atomic_set(&sdkp->openers, 0);
        atomic_set(&sdkp->device->ioerr_cnt, 0);
-       INIT_WORK(&sdkp->start_done_work, sd_start_done_work);
 
        if (!sdp->request_queue->rq_timeout) {
                if (sdp->type != TYPE_MOD)
@@ -3594,69 +3592,12 @@ static void scsi_disk_release(struct device *dev)
        kfree(sdkp);
 }
 
-/* Process sense data after a START command finished. */
-static void sd_start_done_work(struct work_struct *work)
-{
-       struct scsi_disk *sdkp = container_of(work, typeof(*sdkp),
-                                             start_done_work);
-       struct scsi_sense_hdr sshdr;
-       int res = sdkp->start_result;
-
-       if (res == 0)
-               return;
-
-       sd_print_result(sdkp, "Start/Stop Unit failed", res);
-
-       if (res < 0)
-               return;
-
-       if (scsi_normalize_sense(sdkp->start_sense_buffer,
-                                sdkp->start_sense_len, &sshdr))
-               sd_print_sense_hdr(sdkp, &sshdr);
-}
-
-/* A START command finished. May be called from interrupt context. */
-static void sd_start_done(struct request *req, blk_status_t status)
-{
-       const struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req);
-       struct scsi_disk *sdkp = scsi_disk(req->q->disk);
-
-       sdkp->start_result = scmd->result;
-       WARN_ON_ONCE(scmd->sense_len > SCSI_SENSE_BUFFERSIZE);
-       sdkp->start_sense_len = scmd->sense_len;
-       memcpy(sdkp->start_sense_buffer, scmd->sense_buffer,
-              ARRAY_SIZE(sdkp->start_sense_buffer));
-       WARN_ON_ONCE(!schedule_work(&sdkp->start_done_work));
-}
-
-/* Submit a START command asynchronously. */
-static int sd_submit_start(struct scsi_disk *sdkp, u8 cmd[], u8 cmd_len)
-{
-       struct scsi_device *sdev = sdkp->device;
-       struct request_queue *q = sdev->request_queue;
-       struct request *req;
-       struct scsi_cmnd *scmd;
-
-       req = scsi_alloc_request(q, REQ_OP_DRV_IN, BLK_MQ_REQ_PM);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       scmd = blk_mq_rq_to_pdu(req);
-       scmd->cmd_len = cmd_len;
-       memcpy(scmd->cmnd, cmd, cmd_len);
-       scmd->allowed = sdkp->max_retries;
-       req->timeout = SD_TIMEOUT;
-       req->rq_flags |= RQF_PM | RQF_QUIET;
-       req->end_io = sd_start_done;
-       blk_execute_rq_nowait(req, /*at_head=*/true);
-
-       return 0;
-}
-
 static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
 {
        unsigned char cmd[6] = { START_STOP };  /* START_VALID */
+       struct scsi_sense_hdr sshdr;
        struct scsi_device *sdp = sdkp->device;
+       int res;
 
        if (start)
                cmd[4] |= 1;    /* START */
@@ -3667,10 +3608,23 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
-       /* Wait until processing of sense data has finished. */
-       flush_work(&sdkp->start_done_work);
+       res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
+                       SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
+       if (res) {
+               sd_print_result(sdkp, "Start/Stop Unit failed", res);
+               if (res > 0 && scsi_sense_valid(&sshdr)) {
+                       sd_print_sense_hdr(sdkp, &sshdr);
+                       /* 0x3a is medium not present */
+                       if (sshdr.asc == 0x3a)
+                               res = 0;
+               }
+       }
 
-       return sd_submit_start(sdkp, cmd, sizeof(cmd));
+       /* SCSI error codes must not go to the generic layer */
+       if (res)
+               return -EIO;
+
+       return 0;
 }
 
 /*
@@ -3697,8 +3651,6 @@ static void sd_shutdown(struct device *dev)
                sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
                sd_start_stop_device(sdkp, 0);
        }
-
-       flush_work(&sdkp->start_done_work);
 }
 
 static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
index b891877..5eea762 100644 (file)
@@ -150,11 +150,6 @@ struct scsi_disk {
        unsigned        urswrz : 1;
        unsigned        security : 1;
        unsigned        ignore_medium_access_errors : 1;
-
-       int             start_result;
-       u32             start_sense_len;
-       u8              start_sense_buffer[SCSI_SENSE_BUFFERSIZE];
-       struct work_struct start_done_work;
 };
 #define to_scsi_disk(obj) container_of(obj, struct scsi_disk, disk_dev)
 
index fe000da..8ced292 100644 (file)
@@ -2012,7 +2012,7 @@ static int storvsc_probe(struct hv_device *device,
         */
        host_dev->handle_error_wq =
                        alloc_ordered_workqueue("storvsc_error_wq_%d",
-                                               WQ_MEM_RECLAIM,
+                                               0,
                                                host->host_no);
        if (!host_dev->handle_error_wq) {
                ret = -ENOMEM;
index cb6d287..2d09be6 100644 (file)
@@ -850,8 +850,8 @@ exit:
 }
 
 static int cfg80211_rtw_add_key(struct wiphy *wiphy, struct net_device *ndev,
-                               u8 key_index, bool pairwise, const u8 *mac_addr,
-                               struct key_params *params)
+                               int link_id, u8 key_index, bool pairwise,
+                               const u8 *mac_addr, struct key_params *params)
 {
        char *alg_name;
        u32 param_len;
@@ -932,8 +932,8 @@ addkey_end:
 }
 
 static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
-                               u8 key_index, bool pairwise, const u8 *mac_addr,
-                               void *cookie,
+                               int link_id, u8 key_index, bool pairwise,
+                               const u8 *mac_addr, void *cookie,
                                void (*callback)(void *cookie,
                                                 struct key_params*))
 {
@@ -941,7 +941,8 @@ static int cfg80211_rtw_get_key(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
-                               u8 key_index, bool pairwise, const u8 *mac_addr)
+                               int link_id, u8 key_index, bool pairwise,
+                               const u8 *mac_addr)
 {
        struct adapter *padapter = rtw_netdev_priv(ndev);
        struct security_priv *psecuritypriv = &padapter->securitypriv;
@@ -955,7 +956,7 @@ static int cfg80211_rtw_del_key(struct wiphy *wiphy, struct net_device *ndev,
 }
 
 static int cfg80211_rtw_set_default_key(struct wiphy *wiphy,
-       struct net_device *ndev, u8 key_index
+       struct net_device *ndev, int link_id, u8 key_index
        , bool unicast, bool multicast
        )
 {
index b7b56d8..471bb31 100644 (file)
@@ -143,8 +143,8 @@ exit:
 }
 
 static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
-                         u8 key_index, bool pairwise, const u8 *mac_addr,
-                         struct key_params *params)
+                         int link_id, u8 key_index, bool pairwise,
+                         const u8 *mac_addr, struct key_params *params)
 {
        struct wlandevice *wlandev = dev->ml_priv;
        u32 did;
@@ -172,7 +172,7 @@ static int prism2_add_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
-                         u8 key_index, bool pairwise,
+                         int link_id, u8 key_index, bool pairwise,
                          const u8 *mac_addr, void *cookie,
                          void (*callback)(void *cookie, struct key_params*))
 {
@@ -202,7 +202,8 @@ static int prism2_get_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
-                         u8 key_index, bool pairwise, const u8 *mac_addr)
+                         int link_id, u8 key_index, bool pairwise,
+                         const u8 *mac_addr)
 {
        struct wlandevice *wlandev = dev->ml_priv;
        u32 did;
@@ -227,7 +228,8 @@ static int prism2_del_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int prism2_set_default_key(struct wiphy *wiphy, struct net_device *dev,
-                                 u8 key_index, bool unicast, bool multicast)
+                                 int link_id, u8 key_index, bool unicast,
+                                 bool multicast)
 {
        struct wlandevice *wlandev = dev->ml_priv;
 
index 3deaeec..2940559 100644 (file)
@@ -486,6 +486,7 @@ static struct genl_family tcmu_genl_family __ro_after_init = {
        .netnsok = true,
        .small_ops = tcmu_genl_ops,
        .n_small_ops = ARRAY_SIZE(tcmu_genl_ops),
+       .resv_start_op = TCMU_CMD_SET_FEATURES + 1,
 };
 
 #define tcmu_cmd_set_dbi_cur(cmd, index) ((cmd)->dbi_cur = (index))
index 80d4e06..365489b 100644 (file)
@@ -527,7 +527,7 @@ static void int3400_setup_gddv(struct int3400_thermal_priv *priv)
        priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer,
                                   obj->package.elements[0].buffer.length,
                                   GFP_KERNEL);
-       if (!priv->data_vault)
+       if (ZERO_OR_NULL_PTR(priv->data_vault))
                goto out_free;
 
        bin_attr_data_vault.private = priv->data_vault;
@@ -597,7 +597,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
                        goto free_imok;
        }
 
-       if (priv->data_vault) {
+       if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
                result = sysfs_create_group(&pdev->dev.kobj,
                                            &data_attribute_group);
                if (result)
@@ -615,7 +615,8 @@ static int int3400_thermal_probe(struct platform_device *pdev)
 free_sysfs:
        cleanup_odvp(priv);
        if (priv->data_vault) {
-               sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
+               if (!ZERO_OR_NULL_PTR(priv->data_vault))
+                       sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
                kfree(priv->data_vault);
        }
 free_uuid:
@@ -647,7 +648,7 @@ static int int3400_thermal_remove(struct platform_device *pdev)
        if (!priv->rel_misc_dev_res)
                acpi_thermal_rel_misc_device_remove(priv->adev->handle);
 
-       if (priv->data_vault)
+       if (!ZERO_OR_NULL_PTR(priv->data_vault))
                sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
        sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
        sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group);
index 6a5d0ae..50d50ce 100644 (file)
@@ -1329,6 +1329,7 @@ free_tz:
        kfree(tz);
        return ERR_PTR(result);
 }
+EXPORT_SYMBOL_GPL(thermal_zone_device_register_with_trips);
 
 struct thermal_zone_device *thermal_zone_device_register(const char *type, int ntrips, int mask,
                                                         void *devdata, struct thermal_zone_device_ops *ops,
index 050d243..e2d78a9 100644 (file)
@@ -693,6 +693,7 @@ static struct genl_family thermal_gnl_family __ro_after_init = {
        .policy         = thermal_genl_policy,
        .small_ops      = thermal_genl_ops,
        .n_small_ops    = ARRAY_SIZE(thermal_genl_ops),
+       .resv_start_op  = THERMAL_GENL_CMD_CDEV_GET + 1,
        .mcgrps         = thermal_genl_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(thermal_genl_mcgrps),
 };
index cb8c9c4..b5cd967 100644 (file)
 #define RING_TYPE(ring) ((ring)->is_tx ? "TX ring" : "RX ring")
 
 #define RING_FIRST_USABLE_HOPID        1
-
+/*
+ * Used with QUIRK_E2E to specify an unused HopID the Rx credits are
+ * transferred.
+ */
+#define RING_E2E_RESERVED_HOPID        RING_FIRST_USABLE_HOPID
 /*
  * Minimal number of vectors when we use MSI-X. Two for control channel
  * Rx/Tx and the rest four are for cross domain DMA paths.
@@ -38,7 +42,9 @@
 
 #define NHI_MAILBOX_TIMEOUT    500 /* ms */
 
+/* Host interface quirks */
 #define QUIRK_AUTO_CLEAR_INT   BIT(0)
+#define QUIRK_E2E              BIT(1)
 
 static int ring_interrupt_index(struct tb_ring *ring)
 {
@@ -458,8 +464,18 @@ static void ring_release_msix(struct tb_ring *ring)
 
 static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring)
 {
+       unsigned int start_hop = RING_FIRST_USABLE_HOPID;
        int ret = 0;
 
+       if (nhi->quirks & QUIRK_E2E) {
+               start_hop = RING_FIRST_USABLE_HOPID + 1;
+               if (ring->flags & RING_FLAG_E2E && !ring->is_tx) {
+                       dev_dbg(&nhi->pdev->dev, "quirking E2E TX HopID %u -> %u\n",
+                               ring->e2e_tx_hop, RING_E2E_RESERVED_HOPID);
+                       ring->e2e_tx_hop = RING_E2E_RESERVED_HOPID;
+               }
+       }
+
        spin_lock_irq(&nhi->lock);
 
        if (ring->hop < 0) {
@@ -469,7 +485,7 @@ static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring)
                 * Automatically allocate HopID from the non-reserved
                 * range 1 .. hop_count - 1.
                 */
-               for (i = RING_FIRST_USABLE_HOPID; i < nhi->hop_count; i++) {
+               for (i = start_hop; i < nhi->hop_count; i++) {
                        if (ring->is_tx) {
                                if (!nhi->tx_rings[i]) {
                                        ring->hop = i;
@@ -484,6 +500,11 @@ static int nhi_alloc_hop(struct tb_nhi *nhi, struct tb_ring *ring)
                }
        }
 
+       if (ring->hop > 0 && ring->hop < start_hop) {
+               dev_warn(&nhi->pdev->dev, "invalid hop: %d\n", ring->hop);
+               ret = -EINVAL;
+               goto err_unlock;
+       }
        if (ring->hop < 0 || ring->hop >= nhi->hop_count) {
                dev_warn(&nhi->pdev->dev, "invalid hop: %d\n", ring->hop);
                ret = -EINVAL;
@@ -1097,12 +1118,26 @@ static void nhi_shutdown(struct tb_nhi *nhi)
 
 static void nhi_check_quirks(struct tb_nhi *nhi)
 {
-       /*
-        * Intel hardware supports auto clear of the interrupt status
-        * reqister right after interrupt is being issued.
-        */
-       if (nhi->pdev->vendor == PCI_VENDOR_ID_INTEL)
+       if (nhi->pdev->vendor == PCI_VENDOR_ID_INTEL) {
+               /*
+                * Intel hardware supports auto clear of the interrupt
+                * status register right after interrupt is being
+                * issued.
+                */
                nhi->quirks |= QUIRK_AUTO_CLEAR_INT;
+
+               switch (nhi->pdev->device) {
+               case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI:
+               case PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI:
+                       /*
+                        * Falcon Ridge controller needs the end-to-end
+                        * flow control workaround to avoid losing Rx
+                        * packets when RING_FLAG_E2E is set.
+                        */
+                       nhi->quirks |= QUIRK_E2E;
+                       break;
+               }
+       }
 }
 
 static int nhi_check_iommu_pdev(struct pci_dev *pdev, void *data)
index 9853f6c..9a27707 100644 (file)
@@ -174,10 +174,10 @@ static void tb_discover_tunnels(struct tb *tb)
        }
 }
 
-static int tb_port_configure_xdomain(struct tb_port *port)
+static int tb_port_configure_xdomain(struct tb_port *port, struct tb_xdomain *xd)
 {
        if (tb_switch_is_usb4(port->sw))
-               return usb4_port_configure_xdomain(port);
+               return usb4_port_configure_xdomain(port, xd);
        return tb_lc_configure_xdomain(port);
 }
 
@@ -212,7 +212,7 @@ static void tb_scan_xdomain(struct tb_port *port)
                              NULL);
        if (xd) {
                tb_port_at(route, sw)->xdomain = xd;
-               tb_port_configure_xdomain(port);
+               tb_port_configure_xdomain(port, xd);
                tb_xdomain_add(xd);
        }
 }
@@ -1516,7 +1516,7 @@ static void tb_restore_children(struct tb_switch *sw)
 
                        tb_restore_children(port->remote->sw);
                } else if (port->xdomain) {
-                       tb_port_configure_xdomain(port);
+                       tb_port_configure_xdomain(port, port->xdomain);
                }
        }
 }
index 5db76de..0f067c0 100644 (file)
@@ -1176,7 +1176,7 @@ void usb4_switch_remove_ports(struct tb_switch *sw);
 int usb4_port_unlock(struct tb_port *port);
 int usb4_port_configure(struct tb_port *port);
 void usb4_port_unconfigure(struct tb_port *port);
-int usb4_port_configure_xdomain(struct tb_port *port);
+int usb4_port_configure_xdomain(struct tb_port *port, struct tb_xdomain *xd);
 void usb4_port_unconfigure_xdomain(struct tb_port *port);
 int usb4_port_router_offline(struct tb_port *port);
 int usb4_port_router_online(struct tb_port *port);
index 3a2e712..a386228 100644 (file)
@@ -1115,12 +1115,14 @@ static int usb4_set_xdomain_configured(struct tb_port *port, bool configured)
 /**
  * usb4_port_configure_xdomain() - Configure port for XDomain
  * @port: USB4 port connected to another host
+ * @xd: XDomain that is connected to the port
  *
- * Marks the USB4 port as being connected to another host. Returns %0 in
- * success and negative errno in failure.
+ * Marks the USB4 port as being connected to another host and updates
+ * the link type. Returns %0 in success and negative errno in failure.
  */
-int usb4_port_configure_xdomain(struct tb_port *port)
+int usb4_port_configure_xdomain(struct tb_port *port, struct tb_xdomain *xd)
 {
+       xd->link_usb4 = link_is_usb4(port);
        return usb4_set_xdomain_configured(port, true);
 }
 
index 6b02945..1a30c0a 100644 (file)
@@ -53,6 +53,8 @@ static ssize_t link_show(struct device *dev, struct device_attribute *attr,
                link = port->sw->link_usb4 ? "usb4" : "tbt";
        else if (tb_port_has_remote(port))
                link = port->remote->sw->link_usb4 ? "usb4" : "tbt";
+       else if (port->xdomain)
+               link = port->xdomain->link_usb4 ? "usb4" : "tbt";
        else
                link = "none";
 
index 6bc679d..a202d7d 100644 (file)
@@ -8741,6 +8741,8 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
        struct scsi_device *sdp;
        unsigned long flags;
        int ret, retries;
+       unsigned long deadline;
+       int32_t remaining;
 
        spin_lock_irqsave(hba->host->host_lock, flags);
        sdp = hba->ufs_device_wlun;
@@ -8773,9 +8775,14 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
         * callbacks hence set the RQF_PM flag so that it doesn't resume the
         * already suspended childs.
         */
+       deadline = jiffies + 10 * HZ;
        for (retries = 3; retries > 0; --retries) {
+               ret = -ETIMEDOUT;
+               remaining = deadline - jiffies;
+               if (remaining <= 0)
+                       break;
                ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
-                               START_STOP_TIMEOUT, 0, 0, RQF_PM, NULL);
+                                  remaining / HZ, 0, 0, RQF_PM, NULL);
                if (!scsi_status_is_check_condition(ret) ||
                                !scsi_sense_valid(&sshdr) ||
                                sshdr.sense_key != UNIT_ATTENTION)
index eced975..c3628a8 100644 (file)
@@ -1711,7 +1711,7 @@ static struct exynos_ufs_uic_attr fsd_uic_attr = {
        .pa_dbg_option_suite            = 0x2E820183,
 };
 
-struct exynos_ufs_drv_data fsd_ufs_drvs = {
+static const struct exynos_ufs_drv_data fsd_ufs_drvs = {
        .uic_attr               = &fsd_uic_attr,
        .quirks                 = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
                                  UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR |
index c06c027..7badf57 100644 (file)
@@ -1183,6 +1183,7 @@ static struct genl_family vdpa_nl_family __ro_after_init = {
        .module = THIS_MODULE,
        .ops = vdpa_nl_ops,
        .n_ops = ARRAY_SIZE(vdpa_nl_ops),
+       .resv_start_op = VDPA_CMD_DEV_VSTATS_GET + 1,
 };
 
 static int vdpa_init(void)
index bd4dc97..db568f6 100644 (file)
@@ -290,7 +290,7 @@ static char default_sti_path[21] __read_mostly;
 static int __init sti_setup(char *str)
 {
        if (str)
-               strlcpy (default_sti_path, str, sizeof (default_sti_path));
+               strscpy(default_sti_path, str, sizeof(default_sti_path));
        
        return 1;
 }
index a3e6fae..14eb718 100644 (file)
@@ -3891,7 +3891,7 @@ static int __init atyfb_setup(char *options)
                         && (!strncmp(this_opt, "Mach64:", 7))) {
                        static unsigned char m64_num;
                        static char mach64_str[80];
-                       strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
+                       strscpy(mach64_str, this_opt + 7, sizeof(mach64_str));
                        if (!store_video_par(mach64_str, m64_num)) {
                                m64_num++;
                                mach64_count = m64_num;
index 6851f47..a14a8d7 100644 (file)
@@ -1980,7 +1980,7 @@ static int radeon_set_fbinfo(struct radeonfb_info *rinfo)
        info->screen_base = rinfo->fb_base;
        info->screen_size = rinfo->mapped_vram;
        /* Fill fix common fields */
-       strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
+       strscpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
         info->fix.smem_start = rinfo->fb_base_phys;
         info->fix.smem_len = rinfo->video_ram;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
@@ -2094,34 +2094,34 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
        u32 tmp;
 
        /* framebuffer size */
-        if ((rinfo->family == CHIP_FAMILY_RS100) ||
+       if ((rinfo->family == CHIP_FAMILY_RS100) ||
             (rinfo->family == CHIP_FAMILY_RS200) ||
             (rinfo->family == CHIP_FAMILY_RS300) ||
             (rinfo->family == CHIP_FAMILY_RC410) ||
             (rinfo->family == CHIP_FAMILY_RS400) ||
            (rinfo->family == CHIP_FAMILY_RS480) ) {
-          u32 tom = INREG(NB_TOM);
-          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
-
-               radeon_fifo_wait(6);
-          OUTREG(MC_FB_LOCATION, tom);
-          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
-
-          /* This is supposed to fix the crtc2 noise problem. */
-          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
-
-          if ((rinfo->family == CHIP_FAMILY_RS100) ||
-              (rinfo->family == CHIP_FAMILY_RS200)) {
-             /* This is to workaround the asic bug for RMX, some versions
-                of BIOS doesn't have this register initialized correctly.
-             */
-             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
-                     ~CRTC_H_CUTOFF_ACTIVE_EN);
-          }
-        } else {
-          tmp = INREG(CNFG_MEMSIZE);
+               u32 tom = INREG(NB_TOM);
+
+               tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+               radeon_fifo_wait(6);
+               OUTREG(MC_FB_LOCATION, tom);
+               OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+               OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+               OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
+
+               /* This is supposed to fix the crtc2 noise problem. */
+               OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+               if ((rinfo->family == CHIP_FAMILY_RS100) ||
+                   (rinfo->family == CHIP_FAMILY_RS200)) {
+                       /* This is to workaround the asic bug for RMX, some versions
+                        * of BIOS doesn't have this register initialized correctly.
+                        */
+                       OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
+                               ~CRTC_H_CUTOFF_ACTIVE_EN);
+               }
+       } else {
+               tmp = INREG(CNFG_MEMSIZE);
         }
 
        /* mem size is bits [28:0], mask off the rest */
index e7702fe..6403ae0 100644 (file)
@@ -182,7 +182,7 @@ static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 
 static void bw2_init_fix(struct fb_info *info, int linebytes)
 {
-       strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
+       strscpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_MONO01;
index 393894a..2b00a9d 100644 (file)
@@ -430,6 +430,7 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
  err_release_fb:
        framebuffer_release(p);
  err_disable:
+       pci_disable_device(dp);
  err_out:
        return rc;
 }
index a41a758..2a9fa06 100644 (file)
@@ -1999,7 +1999,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
        }
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
+       strscpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
                sizeof(info->fix.id));
 
        /* monochrome: only 1 memory plane */
index 771ce1f..a1061c2 100644 (file)
@@ -326,7 +326,7 @@ static int clps711x_fb_probe(struct platform_device *pdev)
        info->var.vmode = FB_VMODE_NONINTERLACED;
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.accel = FB_ACCEL_NONE;
-       strlcpy(info->fix.id, CLPS711X_FB_NAME, sizeof(info->fix.id));
+       strscpy(info->fix.id, CLPS711X_FB_NAME, sizeof(info->fix.id));
        fb_videomode_to_var(&info->var, &cfb->mode);
 
        ret = fb_alloc_cmap(&info->cmap, BIT(CLPS711X_FB_BPP_MAX), 0);
index cf9ac4d..098b62f 100644 (file)
@@ -412,7 +412,7 @@ static int __init fb_console_setup(char *this_opt)
 
        while ((options = strsep(&this_opt, ",")) != NULL) {
                if (!strncmp(options, "font:", 5)) {
-                       strlcpy(fontname, options + 5, sizeof(fontname));
+                       strscpy(fontname, options + 5, sizeof(fontname));
                        continue;
                }
                
@@ -2401,15 +2401,21 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
        struct fbcon_display *p = &fb_display[vc->vc_num];
-       int resize;
+       int resize, ret, old_userfont, old_width, old_height, old_charcount;
        char *old_data = NULL;
 
        resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
        if (p->userfont)
                old_data = vc->vc_font.data;
        vc->vc_font.data = (void *)(p->fontdata = data);
+       old_userfont = p->userfont;
        if ((p->userfont = userfont))
                REFCOUNT(data)++;
+
+       old_width = vc->vc_font.width;
+       old_height = vc->vc_font.height;
+       old_charcount = vc->vc_font.charcount;
+
        vc->vc_font.width = w;
        vc->vc_font.height = h;
        vc->vc_font.charcount = charcount;
@@ -2425,7 +2431,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
                rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
                cols /= w;
                rows /= h;
-               vc_resize(vc, cols, rows);
+               ret = vc_resize(vc, cols, rows);
+               if (ret)
+                       goto err_out;
        } else if (con_is_visible(vc)
                   && vc->vc_mode == KD_TEXT) {
                fbcon_clear_margins(vc, 0);
@@ -2435,6 +2443,21 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
        if (old_data && (--REFCOUNT(old_data) == 0))
                kfree(old_data - FONT_EXTRA_WORDS * sizeof(int));
        return 0;
+
+err_out:
+       p->fontdata = old_data;
+       vc->vc_font.data = (void *)old_data;
+
+       if (userfont) {
+               p->userfont = old_userfont;
+               REFCOUNT(data)--;
+       }
+
+       vc->vc_font.width = old_width;
+       vc->vc_font.height = old_height;
+       vc->vc_font.charcount = old_charcount;
+
+       return ret;
 }
 
 /*
index c2a60b1..4d7f638 100644 (file)
@@ -84,6 +84,10 @@ void framebuffer_release(struct fb_info *info)
        if (WARN_ON(refcount_read(&info->count)))
                return;
 
+#if IS_ENABLED(CONFIG_FB_BACKLIGHT)
+       mutex_destroy(&info->bl_curve_mutex);
+#endif
+
        kfree(info->apertures);
        kfree(info);
 }
index d45355b..8f041f9 100644 (file)
@@ -1134,7 +1134,7 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx)
                info->fb_size         = int_cfb_info->fb.fix.smem_len;
                info->info            = int_cfb_info;
 
-               strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
+               strscpy(info->dev_name, int_cfb_info->fb.fix.id,
                        sizeof(info->dev_name));
        }
 
@@ -1229,7 +1229,7 @@ static int cyber2000fb_ddc_getsda(void *data)
 
 static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
 {
-       strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
+       strscpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
                sizeof(cfb->ddc_adapter.name));
        cfb->ddc_adapter.owner          = THIS_MODULE;
        cfb->ddc_adapter.class          = I2C_CLASS_DDC;
@@ -1304,7 +1304,7 @@ static int cyber2000fb_i2c_getscl(void *data)
 
 static int cyber2000fb_i2c_register(struct cfb_info *cfb)
 {
-       strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
+       strscpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
                sizeof(cfb->i2c_adapter.name));
        cfb->i2c_adapter.owner = THIS_MODULE;
        cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
@@ -1500,7 +1500,7 @@ static int cyber2000fb_setup(char *options)
                if (strncmp(opt, "font:", 5) == 0) {
                        static char default_font_storage[40];
 
-                       strlcpy(default_font_storage, opt + 5,
+                       strscpy(default_font_storage, opt + 5,
                                sizeof(default_font_storage));
                        default_font = default_font_storage;
                        continue;
index b3d580e..7cba396 100644 (file)
@@ -883,7 +883,7 @@ static void ffb_init_fix(struct fb_info *info)
        } else
                ffb_type_name = "Elite 3D";
 
-       strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
+       strscpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_TRUECOLOR;
index 5d34d89..e41204e 100644 (file)
@@ -410,13 +410,13 @@ static void __init gx1fb_setup(char *options)
                        continue;
 
                if (!strncmp(this_opt, "mode:", 5))
-                       strlcpy(mode_option, this_opt + 5, sizeof(mode_option));
+                       strscpy(mode_option, this_opt + 5, sizeof(mode_option));
                else if (!strncmp(this_opt, "crt:", 4))
                        crt_option = !!simple_strtoul(this_opt + 4, NULL, 0);
                else if (!strncmp(this_opt, "panel:", 6))
-                       strlcpy(panel_option, this_opt + 6, sizeof(panel_option));
+                       strscpy(panel_option, this_opt + 6, sizeof(panel_option));
                else
-                       strlcpy(mode_option, this_opt, sizeof(mode_option));
+                       strscpy(mode_option, this_opt, sizeof(mode_option));
        }
 }
 #endif
index e5475ae..94588b8 100644 (file)
@@ -650,7 +650,7 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        cardtype = ent->driver_data;
        par->refclk_ps = cardinfo[cardtype].refclk_ps;
        info->fix = gxt4500_fix;
-       strlcpy(info->fix.id, cardinfo[cardtype].cardname,
+       strscpy(info->fix.id, cardinfo[cardtype].cardname,
                sizeof(info->fix.id));
        info->pseudo_palette = par->pseudo_palette;
 
index 7f09a0d..bd30d83 100644 (file)
@@ -159,7 +159,7 @@ static int i740fb_setup_ddc_bus(struct fb_info *info)
 {
        struct i740fb_par *par = info->par;
 
-       strlcpy(par->ddc_adapter.name, info->fix.id,
+       strscpy(par->ddc_adapter.name, info->fix.id,
                sizeof(par->ddc_adapter.name));
        par->ddc_adapter.owner          = THIS_MODULE;
        par->ddc_adapter.class          = I2C_CLASS_DDC;
index d97d745..94f3bc6 100644 (file)
@@ -681,7 +681,7 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
 
        fbi->devtype = pdev->id_entry->driver_data;
 
-       strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
+       strscpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
 
        info->fix.type                  = FB_TYPE_PACKED_PIXELS;
        info->fix.type_aux              = 0;
index 236521b..68bba26 100644 (file)
@@ -2383,9 +2383,9 @@ static int __init matroxfb_setup(char *options) {
                else if (!strncmp(this_opt, "mem:", 4))
                        mem = simple_strtoul(this_opt+4, NULL, 0);
                else if (!strncmp(this_opt, "mode:", 5))
-                       strlcpy(videomode, this_opt+5, sizeof(videomode));
+                       strscpy(videomode, this_opt + 5, sizeof(videomode));
                else if (!strncmp(this_opt, "outputs:", 8))
-                       strlcpy(outputs, this_opt+8, sizeof(outputs));
+                       strscpy(outputs, this_opt + 8, sizeof(outputs));
                else if (!strncmp(this_opt, "dfp:", 4)) {
                        dfp_type = simple_strtoul(this_opt+4, NULL, 0);
                        dfp = 1;
@@ -2455,7 +2455,7 @@ static int __init matroxfb_setup(char *options) {
                        else if (!strcmp(this_opt, "dfp"))
                                dfp = value;
                        else {
-                               strlcpy(videomode, this_opt, sizeof(videomode));
+                               strscpy(videomode, this_opt, sizeof(videomode));
                        }
                }
        }
index dfb4ddc..17cda57 100644 (file)
@@ -1642,15 +1642,13 @@ static int omapfb_do_probe(struct platform_device *pdev,
                goto cleanup;
        }
        fbdev->int_irq = platform_get_irq(pdev, 0);
-       if (!fbdev->int_irq) {
-               dev_err(&pdev->dev, "unable to get irq\n");
+       if (fbdev->int_irq < 0) {
                r = ENXIO;
                goto cleanup;
        }
 
        fbdev->ext_irq = platform_get_irq(pdev, 1);
-       if (!fbdev->ext_irq) {
-               dev_err(&pdev->dev, "unable to get irq\n");
+       if (fbdev->ext_irq < 0) {
                r = ENXIO;
                goto cleanup;
        }
index afa688e..5ccddcf 100644 (file)
@@ -1331,7 +1331,7 @@ static void clear_fb_info(struct fb_info *fbi)
 {
        memset(&fbi->var, 0, sizeof(fbi->var));
        memset(&fbi->fix, 0, sizeof(fbi->fix));
-       strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
+       strscpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
 }
 
 static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
index d3be2c6..8fd79de 100644 (file)
@@ -617,6 +617,11 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                return -EINVAL;
        }
 
+       if (!var->pixclock) {
+               DPRINTK("pixclock is zero\n");
+               return -EINVAL;
+       }
+
        if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
                DPRINTK("pixclock too high (%ldKHz)\n",
                        PICOS2KHZ(var->pixclock));
index e943300..d5d0bbd 100644 (file)
@@ -640,7 +640,7 @@ static int pxa168fb_probe(struct platform_device *pdev)
        info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
                      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
        info->node = -1;
-       strlcpy(info->fix.id, mi->id, 16);
+       strscpy(info->fix.id, mi->id, 16);
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.type_aux = 0;
        info->fix.xpanstep = 0;
index 66cfc3e..696ac54 100644 (file)
@@ -2042,7 +2042,7 @@ static int __init pxafb_setup_options(void)
                return -ENODEV;
 
        if (options)
-               strlcpy(g_options, options, sizeof(g_options));
+               strscpy(g_options, options, sizeof(g_options));
 
        return 0;
 }
index 5069f6f..67b63a7 100644 (file)
@@ -248,7 +248,7 @@ static int s3fb_setup_ddc_bus(struct fb_info *info)
 {
        struct s3fb_info *par = info->par;
 
-       strlcpy(par->ddc_adapter.name, info->fix.id,
+       strscpy(par->ddc_adapter.name, info->fix.id,
                sizeof(par->ddc_adapter.name));
        par->ddc_adapter.owner          = THIS_MODULE;
        par->ddc_adapter.class          = I2C_CLASS_DDC;
index cf2a90e..e770b4a 100644 (file)
@@ -355,7 +355,7 @@ static int simplefb_regulators_get(struct simplefb_par *par,
                if (!p || p == prop->name)
                        continue;
 
-               strlcpy(name, prop->name,
+               strscpy(name, prop->name,
                        strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1);
                regulator = devm_regulator_get_optional(&pdev->dev, name);
                if (IS_ERR(regulator)) {
index f28fd69..c9e7742 100644 (file)
@@ -649,37 +649,37 @@ sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
        u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-               if(!(sisbios_mode[myindex].chipset & MD_SIS300))
+       if (ivideo->sisvga_engine == SIS_300_VGA) {
+               if (!(sisbios_mode[myindex].chipset & MD_SIS300))
                        return -1 ;
        }
 #endif
 #ifdef CONFIG_FB_SIS_315
-       if(ivideo->sisvga_engine == SIS_315_VGA) {
-               if(!(sisbios_mode[myindex].chipset & MD_SIS315))
+       if (ivideo->sisvga_engine == SIS_315_VGA) {
+               if (!(sisbios_mode[myindex].chipset & MD_SIS315))
                        return -1;
        }
 #endif
 
        myres = sisbios_mode[myindex].yres;
 
-       switch(vbflags & VB_DISPTYPE_DISP2) {
+       switch (vbflags & VB_DISPTYPE_DISP2) {
 
        case CRT2_LCD:
                xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 
-               if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
-                  (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
-                       if(sisbios_mode[myindex].xres > xres)
+               if ((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
+                   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
+                       if (sisbios_mode[myindex].xres > xres)
                                return -1;
-                       if(myres > yres)
+                       if (myres > yres)
                                return -1;
                }
 
-               if(ivideo->sisfb_fstn) {
-                       if(sisbios_mode[myindex].xres == 320) {
-                               if(myres == 240) {
-                                       switch(sisbios_mode[myindex].mode_no[1]) {
+               if (ivideo->sisfb_fstn) {
+                       if (sisbios_mode[myindex].xres == 320) {
+                               if (myres == 240) {
+                                       switch (sisbios_mode[myindex].mode_no[1]) {
                                                case 0x50: myindex = MODE_FSTN_8;  break;
                                                case 0x56: myindex = MODE_FSTN_16; break;
                                                case 0x53: return -1;
@@ -688,7 +688,7 @@ sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
                        }
                }
 
-               if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+               if (SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
                                sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
                                ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
                        return -1;
@@ -696,14 +696,14 @@ sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
                break;
 
        case CRT2_TV:
-               if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+               if (SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
                                sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
                        return -1;
                }
                break;
 
        case CRT2_VGA:
-               if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+               if (SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
                                sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
                        return -1;
                }
@@ -1872,7 +1872,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
-       strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
+       strscpy(fix->id, ivideo->myid, sizeof(fix->id));
 
        mutex_lock(&info->mm_lock);
        fix->smem_start  = ivideo->video_base + ivideo->video_offset;
@@ -2204,82 +2204,88 @@ static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
 
 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    bool mustwait = false;
-    u8  sr1F, cr17;
+       bool mustwait = false;
+       u8  sr1F, cr17;
 #ifdef CONFIG_FB_SIS_315
-    u8  cr63=0;
+       u8  cr63 = 0;
 #endif
-    u16 temp = 0xffff;
-    int i;
+       u16 temp = 0xffff;
+       int i;
+
+       sr1F = SiS_GetReg(SISSR, 0x1F);
+       SiS_SetRegOR(SISSR, 0x1F, 0x04);
+       SiS_SetRegAND(SISSR, 0x1F, 0x3F);
 
-    sr1F = SiS_GetReg(SISSR, 0x1F);
-    SiS_SetRegOR(SISSR, 0x1F, 0x04);
-    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
-    if(sr1F & 0xc0) mustwait = true;
+       if (sr1F & 0xc0)
+               mustwait = true;
 
 #ifdef CONFIG_FB_SIS_315
-    if(ivideo->sisvga_engine == SIS_315_VGA) {
-       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
-       cr63 &= 0x40;
-       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
-    }
+       if (ivideo->sisvga_engine == SIS_315_VGA) {
+               cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
+               cr63 &= 0x40;
+               SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
+       }
 #endif
 
-    cr17 = SiS_GetReg(SISCR, 0x17);
-    cr17 &= 0x80;
-    if(!cr17) {
-       SiS_SetRegOR(SISCR, 0x17, 0x80);
-       mustwait = true;
-       SiS_SetReg(SISSR, 0x00, 0x01);
-       SiS_SetReg(SISSR, 0x00, 0x03);
-    }
+       cr17 = SiS_GetReg(SISCR, 0x17);
+       cr17 &= 0x80;
 
-    if(mustwait) {
-       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
-    }
+       if (!cr17) {
+               SiS_SetRegOR(SISCR, 0x17, 0x80);
+               mustwait = true;
+               SiS_SetReg(SISSR, 0x00, 0x01);
+               SiS_SetReg(SISSR, 0x00, 0x03);
+       }
 
+       if (mustwait) {
+               for (i = 0; i < 10; i++)
+                       sisfbwaitretracecrt1(ivideo);
+       }
 #ifdef CONFIG_FB_SIS_315
-    if(ivideo->chip >= SIS_330) {
-       SiS_SetRegAND(SISCR, 0x32, ~0x20);
-       if(ivideo->chip >= SIS_340) {
-          SiS_SetReg(SISCR, 0x57, 0x4a);
-       } else {
-          SiS_SetReg(SISCR, 0x57, 0x5f);
-       }
-       SiS_SetRegOR(SISCR, 0x53, 0x02);
-       while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
-       while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
-       if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
-       SiS_SetRegAND(SISCR, 0x53, 0xfd);
-       SiS_SetRegAND(SISCR, 0x57, 0x00);
-    }
+       if (ivideo->chip >= SIS_330) {
+               SiS_SetRegAND(SISCR, 0x32, ~0x20);
+               if (ivideo->chip >= SIS_340)
+                       SiS_SetReg(SISCR, 0x57, 0x4a);
+               else
+                       SiS_SetReg(SISCR, 0x57, 0x5f);
+
+               SiS_SetRegOR(SISCR, 0x53, 0x02);
+               while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)
+                       break;
+               while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01))
+                       break;
+               if ((SiS_GetRegByte(SISMISCW)) & 0x10)
+                       temp = 1;
+
+               SiS_SetRegAND(SISCR, 0x53, 0xfd);
+               SiS_SetRegAND(SISCR, 0x57, 0x00);
+       }
 #endif
 
-    if(temp == 0xffff) {
-       i = 3;
-       do {
-         temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
-               ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
-       } while(((temp == 0) || (temp == 0xffff)) && i--);
+       if (temp == 0xffff) {
+               i = 3;
 
-       if((temp == 0) || (temp == 0xffff)) {
-          if(sisfb_test_DDC1(ivideo)) temp = 1;
-       }
-    }
+               do {
+                       temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+                       ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
+               } while (((temp == 0) || (temp == 0xffff)) && i--);
 
-    if((temp) && (temp != 0xffff)) {
-       SiS_SetRegOR(SISCR, 0x32, 0x20);
-    }
+               if ((temp == 0) || (temp == 0xffff)) {
+                       if (sisfb_test_DDC1(ivideo))
+                               temp = 1;
+               }
+       }
+
+       if ((temp) && (temp != 0xffff))
+               SiS_SetRegOR(SISCR, 0x32, 0x20);
 
 #ifdef CONFIG_FB_SIS_315
-    if(ivideo->sisvga_engine == SIS_315_VGA) {
-       SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
-    }
+       if (ivideo->sisvga_engine == SIS_315_VGA)
+               SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
 #endif
 
-    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
-
-    SiS_SetReg(SISSR, 0x1F, sr1F);
+       SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
+       SiS_SetReg(SISSR, 0x1F, sr1F);
 }
 
 /* Determine and detect attached devices on SiS30x */
@@ -2293,25 +2299,25 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
        ivideo->SiS_Pr.PanelSelfDetected = false;
 
        /* LCD detection only for TMDS bridges */
-       if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
+       if (!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
                return;
-       if(ivideo->vbflags2 & VB2_30xBDH)
+       if (ivideo->vbflags2 & VB2_30xBDH)
                return;
 
        /* If LCD already set up by BIOS, skip it */
        reg = SiS_GetReg(SISCR, 0x32);
-       if(reg & 0x08)
+       if (reg & 0x08)
                return;
 
        realcrtno = 1;
-       if(ivideo->SiS_Pr.DDCPortMixup)
+       if (ivideo->SiS_Pr.DDCPortMixup)
                realcrtno = 0;
 
        /* Check DDC capabilities */
        temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
                                realcrtno, 0, &buffer[0], ivideo->vbflags2);
 
-       if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
+       if ((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
                return;
 
        /* Read DDC data */
@@ -2320,17 +2326,17 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
                temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
                                ivideo->sisvga_engine, realcrtno, 1,
                                &buffer[0], ivideo->vbflags2);
-       } while((temp) && i--);
+       } while ((temp) && i--);
 
-       if(temp)
+       if (temp)
                return;
 
        /* No digital device */
-       if(!(buffer[0x14] & 0x80))
+       if (!(buffer[0x14] & 0x80))
                return;
 
        /* First detailed timing preferred timing? */
-       if(!(buffer[0x18] & 0x02))
+       if (!(buffer[0x18] & 0x02))
                return;
 
        xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
@@ -2338,26 +2344,26 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
 
        switch(xres) {
                case 1024:
-                       if(yres == 768)
+                       if (yres == 768)
                                paneltype = 0x02;
                        break;
                case 1280:
-                       if(yres == 1024)
+                       if (yres == 1024)
                                paneltype = 0x03;
                        break;
                case 1600:
-                       if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
+                       if ((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
                                paneltype = 0x0b;
                        break;
        }
 
-       if(!paneltype)
+       if (!paneltype)
                return;
 
-       if(buffer[0x23])
+       if (buffer[0x23])
                cr37 |= 0x10;
 
-       if((buffer[0x47] & 0x18) == 0x18)
+       if ((buffer[0x47] & 0x18) == 0x18)
                cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
        else
                cr37 |= 0xc0;
@@ -2372,31 +2378,34 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
 
 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
-    int temp, mytest, result, i, j;
-
-    for(j = 0; j < 10; j++) {
-       result = 0;
-       for(i = 0; i < 3; i++) {
-          mytest = test;
-          SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
-          temp = (type >> 8) | (mytest & 0x00ff);
-         SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
-          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
-          mytest >>= 8;
-          mytest &= 0x7f;
-          temp = SiS_GetReg(SISPART4, 0x03);
-          temp ^= 0x0e;
-          temp &= mytest;
-          if(temp == mytest) result++;
+       int temp, mytest, result, i, j;
+
+       for (j = 0; j < 10; j++) {
+               result = 0;
+               for (i = 0; i < 3; i++) {
+                       mytest = test;
+                       SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
+                       temp = (type >> 8) | (mytest & 0x00ff);
+                       SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
+                       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
+                       mytest >>= 8;
+                       mytest &= 0x7f;
+                       temp = SiS_GetReg(SISPART4, 0x03);
+                       temp ^= 0x0e;
+                       temp &= mytest;
+                       if (temp == mytest)
+                               result++;
 #if 1
-         SiS_SetReg(SISPART4, 0x11, 0x00);
-         SiS_SetRegAND(SISPART4, 0x10, 0xe0);
-         SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
+                       SiS_SetReg(SISPART4, 0x11, 0x00);
+                       SiS_SetRegAND(SISPART4, 0x10, 0xe0);
+                       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
 #endif
-       }
-       if((result == 0) || (result >= 2)) break;
-    }
-    return result;
+               }
+
+               if ((result == 0) || (result >= 2))
+                       break;
+       }
+       return result;
 }
 
 static void SiS_Sense30x(struct sis_video_info *ivideo)
@@ -4262,18 +4271,17 @@ static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
        unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
        unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
 
-        for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
-
+       for (k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
                RankCapacity = buswidth * SiS_DRAMType[k][3];
 
-               if(RankCapacity != PseudoRankCapacity)
+               if (RankCapacity != PseudoRankCapacity)
                        continue;
 
-               if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
+               if ((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
                        continue;
 
                BankNumHigh = RankCapacity * 16 * iteration - 1;
-               if(iteration == 3) {             /* Rank No */
+               if (iteration == 3) {             /* Rank No */
                        BankNumMid  = RankCapacity * 16 - 1;
                } else {
                        BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
@@ -4287,18 +4295,22 @@ static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
                SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
                SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
                sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
-               if(buswidth == 4)      sr14 |= 0x80;
-               else if(buswidth == 2) sr14 |= 0x40;
+
+               if (buswidth == 4)
+                       sr14 |= 0x80;
+               else if (buswidth == 2)
+                       sr14 |= 0x40;
+
                SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
                SiS_SetReg(SISSR, 0x14, sr14);
 
                BankNumHigh <<= 16;
                BankNumMid <<= 16;
 
-               if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
-                  (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
-                  (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
-                  (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
+               if ((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
+                   (BankNumMid  + PhysicalAdrHigh >= mapsize) ||
+                   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
+                   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
                        continue;
 
                /* Write data */
@@ -4312,7 +4324,7 @@ static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
                                (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
 
                /* Read data */
-               if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
+               if (readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
                        return 1;
        }
 
@@ -5867,7 +5879,7 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        ivideo->cardnumber++;
        }
 
-       strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
+       strscpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
 
        ivideo->warncount = 0;
        ivideo->chip_id = pdev->device;
@@ -6150,24 +6162,20 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-               if(ivideo->sisvga_engine == SIS_315_VGA) {
+               if (ivideo->sisvga_engine == SIS_315_VGA) {
                        int result = 1;
-               /*      if((ivideo->chip == SIS_315H)   ||
-                          (ivideo->chip == SIS_315)    ||
-                          (ivideo->chip == SIS_315PRO) ||
-                          (ivideo->chip == SIS_330)) {
-                               sisfb_post_sis315330(pdev);
-                       } else */ if(ivideo->chip == XGI_20) {
+
+                       if (ivideo->chip == XGI_20) {
                                result = sisfb_post_xgi(pdev);
                                ivideo->sisfb_can_post = 1;
-                       } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
+                       } else if ((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
                                result = sisfb_post_xgi(pdev);
                                ivideo->sisfb_can_post = 1;
                        } else {
                                printk(KERN_INFO "sisfb: Card is not "
                                        "POSTed and sisfb can't do this either.\n");
                        }
-                       if(!result) {
+                       if (!result) {
                                printk(KERN_ERR "sisfb: Failed to POST card\n");
                                ret = -ENODEV;
                                goto error_3;
index 6a52eba..fce6cfb 100644 (file)
@@ -1719,7 +1719,7 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
                enable = 0;
        }
 
-       strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id));
+       strscpy(fb->fix.id, fbname, sizeof(fb->fix.id));
 
        memcpy(&par->ops,
               (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
index 5c76565..52e4ed9 100644 (file)
@@ -450,7 +450,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
        if (ret < 0)
                return ret;
 
-       /* Set Set Area Color Mode ON/OFF & Low Power Display Mode */
+       /* Set Area Color Mode ON/OFF & Low Power Display Mode */
        if (par->area_color_enable || par->low_power) {
                u32 mode;
 
index 27d4b0a..cd4d640 100644 (file)
@@ -1382,7 +1382,7 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto fail;
        }
        sst_get_memsize(info, &fix->smem_len);
-       strlcpy(fix->id, spec->name, sizeof(fix->id));
+       strscpy(fix->id, spec->name, sizeof(fix->id));
 
        printk(KERN_INFO "%s (revision %d) with %s dac\n",
                fix->id, par->revision, par->dac_sw.name);
index 15b0795..490bd9a 100644 (file)
@@ -80,7 +80,7 @@ static int gfb_set_fbinfo(struct gfb_info *gp)
        info->pseudo_palette = gp->pseudo_palette;
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, "gfb", sizeof(info->fix.id));
+       strscpy(info->fix.id, "gfb", sizeof(info->fix.id));
         info->fix.smem_start = gp->fb_base_phys;
         info->fix.smem_len = gp->fb_size;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
index 1d3bacd..1279b02 100644 (file)
@@ -84,7 +84,7 @@ static int s3d_set_fbinfo(struct s3d_info *sp)
        info->pseudo_palette = sp->pseudo_palette;
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, "s3d", sizeof(info->fix.id));
+       strscpy(info->fix.id, "s3d", sizeof(info->fix.id));
         info->fix.smem_start = sp->fb_base_phys;
         info->fix.smem_len = sp->fb_size;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
index 9daf17b..f7b4636 100644 (file)
@@ -207,7 +207,7 @@ static int e3d_set_fbinfo(struct e3d_info *ep)
        info->pseudo_palette = ep->pseudo_palette;
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, "e3d", sizeof(info->fix.id));
+       strscpy(info->fix.id, "e3d", sizeof(info->fix.id));
         info->fix.smem_start = ep->fb_base_phys;
         info->fix.smem_len = ep->fb_size;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
index 1638a40..01d87f5 100644 (file)
@@ -333,7 +333,7 @@ tcx_init_fix(struct fb_info *info, int linebytes)
        else
                tcx_name = "TCX24";
 
-       strlcpy(info->fix.id, tcx_name, sizeof(info->fix.id));
+       strscpy(info->fix.id, tcx_name, sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
index 67e37a6..8a8122f 100644 (file)
@@ -1264,7 +1264,7 @@ static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
 {
        int rc;
 
-       strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+       strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
        chan->adapter.owner             = THIS_MODULE;
        chan->adapter.class             = I2C_CLASS_DDC;
        chan->adapter.algo_data         = &chan->algo;
@@ -1293,7 +1293,7 @@ static int tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, const char *name,
 {
        int rc;
 
-       strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+       strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
        chan->adapter.owner             = THIS_MODULE;
        chan->adapter.algo_data         = &chan->algo;
        chan->adapter.dev.parent        = dev;
index ae0cf55..1fff5fd 100644 (file)
@@ -1344,7 +1344,7 @@ tgafb_init_fix(struct fb_info *info)
                memory_size = 16777216;
        }
 
-       strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
+       strscpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.type_aux = 0;
index 319131b..cda0954 100644 (file)
@@ -270,7 +270,7 @@ static int tridentfb_setup_ddc_bus(struct fb_info *info)
 {
        struct tridentfb_par *par = info->par;
 
-       strlcpy(par->ddc_adapter.name, info->fix.id,
+       strscpy(par->ddc_adapter.name, info->fix.id,
                sizeof(par->ddc_adapter.name));
        par->ddc_adapter.owner          = THIS_MODULE;
        par->ddc_adapter.class          = I2C_CLASS_DDC;
index 3369734..e88e8f6 100644 (file)
@@ -581,27 +581,30 @@ static int lock_pages(
        struct privcmd_dm_op_buf kbufs[], unsigned int num,
        struct page *pages[], unsigned int nr_pages, unsigned int *pinned)
 {
-       unsigned int i;
+       unsigned int i, off = 0;
 
-       for (i = 0; i < num; i++) {
+       for (i = 0; i < num; ) {
                unsigned int requested;
                int page_count;
 
                requested = DIV_ROUND_UP(
                        offset_in_page(kbufs[i].uptr) + kbufs[i].size,
-                       PAGE_SIZE);
+                       PAGE_SIZE) - off;
                if (requested > nr_pages)
                        return -ENOSPC;
 
                page_count = pin_user_pages_fast(
-                       (unsigned long) kbufs[i].uptr,
+                       (unsigned long)kbufs[i].uptr + off * PAGE_SIZE,
                        requested, FOLL_WRITE, pages);
-               if (page_count < 0)
-                       return page_count;
+               if (page_count <= 0)
+                       return page_count ? : -EFAULT;
 
                *pinned += page_count;
                nr_pages -= page_count;
                pages += page_count;
+
+               off = (requested == page_count) ? 0 : off + page_count;
+               i += !off;
        }
 
        return 0;
@@ -677,10 +680,8 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
        }
 
        rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &pinned);
-       if (rc < 0) {
-               nr_pages = pinned;
+       if (rc < 0)
                goto out;
-       }
 
        for (i = 0; i < kdata.num; i++) {
                set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);
@@ -692,7 +693,7 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
        xen_preemptible_hcall_end();
 
 out:
-       unlock_pages(pages, nr_pages);
+       unlock_pages(pages, pinned);
        kfree(xbufs);
        kfree(pages);
        kfree(kbufs);
index 7a0c93a..d3dcda3 100644 (file)
@@ -1121,7 +1121,7 @@ static void scsiback_do_1lun_hotplug(struct vscsibk_info *info, int op,
                                "%s: writing %s", __func__, state);
                return;
        }
-       strlcpy(phy, val, VSCSI_NAMELEN);
+       strscpy(phy, val, VSCSI_NAMELEN);
        kfree(val);
 
        /* virtual SCSI device */
index 07b010a..f44d5a6 100644 (file)
@@ -40,7 +40,7 @@ static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
                return -EINVAL;
        }
 
-       strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE);
+       strscpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE);
        if (!strchr(bus_id, '/')) {
                pr_warn("bus_id %s no slash\n", bus_id);
                return -EINVAL;
index 993aca2..e0375ba 100644 (file)
@@ -440,39 +440,26 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
        btrfs_put_caching_control(caching_ctl);
 }
 
-int btrfs_wait_block_group_cache_done(struct btrfs_block_group *cache)
+static int btrfs_caching_ctl_wait_done(struct btrfs_block_group *cache,
+                                      struct btrfs_caching_control *caching_ctl)
+{
+       wait_event(caching_ctl->wait, btrfs_block_group_done(cache));
+       return cache->cached == BTRFS_CACHE_ERROR ? -EIO : 0;
+}
+
+static int btrfs_wait_block_group_cache_done(struct btrfs_block_group *cache)
 {
        struct btrfs_caching_control *caching_ctl;
-       int ret = 0;
+       int ret;
 
        caching_ctl = btrfs_get_caching_control(cache);
        if (!caching_ctl)
                return (cache->cached == BTRFS_CACHE_ERROR) ? -EIO : 0;
-
-       wait_event(caching_ctl->wait, btrfs_block_group_done(cache));
-       if (cache->cached == BTRFS_CACHE_ERROR)
-               ret = -EIO;
+       ret = btrfs_caching_ctl_wait_done(cache, caching_ctl);
        btrfs_put_caching_control(caching_ctl);
        return ret;
 }
 
-static bool space_cache_v1_done(struct btrfs_block_group *cache)
-{
-       bool ret;
-
-       spin_lock(&cache->lock);
-       ret = cache->cached != BTRFS_CACHE_FAST;
-       spin_unlock(&cache->lock);
-
-       return ret;
-}
-
-void btrfs_wait_space_cache_v1_finished(struct btrfs_block_group *cache,
-                               struct btrfs_caching_control *caching_ctl)
-{
-       wait_event(caching_ctl->wait, space_cache_v1_done(cache));
-}
-
 #ifdef CONFIG_BTRFS_DEBUG
 static void fragment_free_space(struct btrfs_block_group *block_group)
 {
@@ -750,9 +737,8 @@ done:
        btrfs_put_block_group(block_group);
 }
 
-int btrfs_cache_block_group(struct btrfs_block_group *cache, int load_cache_only)
+int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait)
 {
-       DEFINE_WAIT(wait);
        struct btrfs_fs_info *fs_info = cache->fs_info;
        struct btrfs_caching_control *caching_ctl = NULL;
        int ret = 0;
@@ -785,10 +771,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, int load_cache_only
        }
        WARN_ON(cache->caching_ctl);
        cache->caching_ctl = caching_ctl;
-       if (btrfs_test_opt(fs_info, SPACE_CACHE))
-               cache->cached = BTRFS_CACHE_FAST;
-       else
-               cache->cached = BTRFS_CACHE_STARTED;
+       cache->cached = BTRFS_CACHE_STARTED;
        cache->has_caching_ctl = 1;
        spin_unlock(&cache->lock);
 
@@ -801,8 +784,8 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, int load_cache_only
 
        btrfs_queue_work(fs_info->caching_workers, &caching_ctl->work);
 out:
-       if (load_cache_only && caching_ctl)
-               btrfs_wait_space_cache_v1_finished(cache, caching_ctl);
+       if (wait && caching_ctl)
+               ret = btrfs_caching_ctl_wait_done(cache, caching_ctl);
        if (caching_ctl)
                btrfs_put_caching_control(caching_ctl);
 
@@ -3312,7 +3295,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                 * space back to the block group, otherwise we will leak space.
                 */
                if (!alloc && !btrfs_block_group_done(cache))
-                       btrfs_cache_block_group(cache, 1);
+                       btrfs_cache_block_group(cache, true);
 
                byte_in_group = bytenr - cache->start;
                WARN_ON(byte_in_group > cache->length);
index 35e0e86..6b3cdc4 100644 (file)
@@ -263,9 +263,7 @@ void btrfs_dec_nocow_writers(struct btrfs_block_group *bg);
 void btrfs_wait_nocow_writers(struct btrfs_block_group *bg);
 void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
                                           u64 num_bytes);
-int btrfs_wait_block_group_cache_done(struct btrfs_block_group *cache);
-int btrfs_cache_block_group(struct btrfs_block_group *cache,
-                           int load_cache_only);
+int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait);
 void btrfs_put_caching_control(struct btrfs_caching_control *ctl);
 struct btrfs_caching_control *btrfs_get_caching_control(
                struct btrfs_block_group *cache);
index 4edb4bf..9ef162d 100644 (file)
@@ -505,7 +505,6 @@ struct btrfs_free_cluster {
 enum btrfs_caching_type {
        BTRFS_CACHE_NO,
        BTRFS_CACHE_STARTED,
-       BTRFS_CACHE_FAST,
        BTRFS_CACHE_FINISHED,
        BTRFS_CACHE_ERROR,
 };
index f43196a..41cddd3 100644 (file)
@@ -165,7 +165,7 @@ no_valid_dev_replace_entry_found:
                 */
                if (btrfs_find_device(fs_info->fs_devices, &args)) {
                        btrfs_err(fs_info,
-                       "replace devid present without an active replace item");
+"replace without active item, run 'device scan --forget' on the target device");
                        ret = -EUCLEAN;
                } else {
                        dev_replace->srcdev = NULL;
@@ -1129,8 +1129,7 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
                up_write(&dev_replace->rwsem);
 
                /* Scrub for replace must not be running in suspended state */
-               ret = btrfs_scrub_cancel(fs_info);
-               ASSERT(ret != -ENOTCONN);
+               btrfs_scrub_cancel(fs_info);
 
                trans = btrfs_start_transaction(root, 0);
                if (IS_ERR(trans)) {
index ab944d1..6914cd8 100644 (file)
@@ -2551,17 +2551,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
                return -EINVAL;
 
        /*
-        * pull in the free space cache (if any) so that our pin
-        * removes the free space from the cache.  We have load_only set
-        * to one because the slow code to read in the free extents does check
-        * the pinned extents.
+        * Fully cache the free space first so that our pin removes the free space
+        * from the cache.
         */
-       btrfs_cache_block_group(cache, 1);
-       /*
-        * Make sure we wait until the cache is completely built in case it is
-        * missing or is invalid and therefore needs to be rebuilt.
-        */
-       ret = btrfs_wait_block_group_cache_done(cache);
+       ret = btrfs_cache_block_group(cache, true);
        if (ret)
                goto out;
 
@@ -2584,12 +2577,7 @@ static int __exclude_logged_extent(struct btrfs_fs_info *fs_info,
        if (!block_group)
                return -EINVAL;
 
-       btrfs_cache_block_group(block_group, 1);
-       /*
-        * Make sure we wait until the cache is completely built in case it is
-        * missing or is invalid and therefore needs to be rebuilt.
-        */
-       ret = btrfs_wait_block_group_cache_done(block_group);
+       ret = btrfs_cache_block_group(block_group, true);
        if (ret)
                goto out;
 
@@ -4399,7 +4387,7 @@ have_block_group:
                ffe_ctl->cached = btrfs_block_group_done(block_group);
                if (unlikely(!ffe_ctl->cached)) {
                        ffe_ctl->have_caching_bg = true;
-                       ret = btrfs_cache_block_group(block_group, 0);
+                       ret = btrfs_cache_block_group(block_group, false);
 
                        /*
                         * If we get ENOMEM here or something else we want to
@@ -6169,13 +6157,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
 
                if (end - start >= range->minlen) {
                        if (!btrfs_block_group_done(cache)) {
-                               ret = btrfs_cache_block_group(cache, 0);
-                               if (ret) {
-                                       bg_failed++;
-                                       bg_ret = ret;
-                                       continue;
-                               }
-                               ret = btrfs_wait_block_group_cache_done(cache);
+                               ret = btrfs_cache_block_group(cache, true);
                                if (ret) {
                                        bg_failed++;
                                        bg_ret = ret;
index eed81a7..cf4f19e 100644 (file)
@@ -3233,7 +3233,7 @@ static int btrfs_bio_add_page(struct btrfs_bio_ctrl *bio_ctrl,
        u32 bio_size = bio->bi_iter.bi_size;
        u32 real_size;
        const sector_t sector = disk_bytenr >> SECTOR_SHIFT;
-       bool contig;
+       bool contig = false;
        int ret;
 
        ASSERT(bio);
@@ -3242,10 +3242,35 @@ static int btrfs_bio_add_page(struct btrfs_bio_ctrl *bio_ctrl,
        if (bio_ctrl->compress_type != compress_type)
                return 0;
 
-       if (bio_ctrl->compress_type != BTRFS_COMPRESS_NONE)
+
+       if (bio->bi_iter.bi_size == 0) {
+               /* We can always add a page into an empty bio. */
+               contig = true;
+       } else if (bio_ctrl->compress_type == BTRFS_COMPRESS_NONE) {
+               struct bio_vec *bvec = bio_last_bvec_all(bio);
+
+               /*
+                * The contig check requires the following conditions to be met:
+                * 1) The pages are belonging to the same inode
+                *    This is implied by the call chain.
+                *
+                * 2) The range has adjacent logical bytenr
+                *
+                * 3) The range has adjacent file offset
+                *    This is required for the usage of btrfs_bio->file_offset.
+                */
+               if (bio_end_sector(bio) == sector &&
+                   page_offset(bvec->bv_page) + bvec->bv_offset +
+                   bvec->bv_len == page_offset(page) + pg_offset)
+                       contig = true;
+       } else {
+               /*
+                * For compression, all IO should have its logical bytenr
+                * set to the starting bytenr of the compressed extent.
+                */
                contig = bio->bi_iter.bi_sector == sector;
-       else
-               contig = bio_end_sector(bio) == sector;
+       }
+
        if (!contig)
                return 0;
 
index 66c8221..5a3f6e0 100644 (file)
@@ -2482,6 +2482,7 @@ static int fill_holes(struct btrfs_trans_handle *trans,
                btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
                goto out;
        }
@@ -2498,6 +2499,7 @@ static int fill_holes(struct btrfs_trans_handle *trans,
                btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
                goto out;
        }
index f0c97d2..ad25089 100644 (file)
@@ -7693,6 +7693,20 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
        const u64 data_alloc_len = length;
        bool unlock_extents = false;
 
+       /*
+        * We could potentially fault if we have a buffer > PAGE_SIZE, and if
+        * we're NOWAIT we may submit a bio for a partial range and return
+        * EIOCBQUEUED, which would result in an errant short read.
+        *
+        * The best way to handle this would be to allow for partial completions
+        * of iocb's, so we could submit the partial bio, return and fault in
+        * the rest of the pages, and then submit the io for the rest of the
+        * range.  However we don't have that currently, so simply return
+        * -EAGAIN at this point so that the normal path is used.
+        */
+       if (!write && (flags & IOMAP_NOWAIT) && length > PAGE_SIZE)
+               return -EAGAIN;
+
        /*
         * Cap the size of reads to that usually seen in buffered I/O as we need
         * to allocate a contiguous array for the checksums.
index a64b26b..d647cb2 100644 (file)
@@ -349,9 +349,10 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
        key.offset = ref_id;
 again:
        ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
-       if (ret < 0)
+       if (ret < 0) {
+               err = ret;
                goto out;
-       if (ret == 0) {
+       } else if (ret == 0) {
                leaf = path->nodes[0];
                ref = btrfs_item_ptr(leaf, path->slots[0],
                                     struct btrfs_root_ref);
index 2729015..064ab2a 100644 (file)
@@ -2345,8 +2345,11 @@ int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
 
        ret = btrfs_get_bdev_and_sb(path, FMODE_READ, fs_info->bdev_holder, 0,
                                    &bdev, &disk_super);
-       if (ret)
+       if (ret) {
+               btrfs_put_dev_args_from_path(args);
                return ret;
+       }
+
        args->devid = btrfs_stack_device_id(&disk_super->dev_item);
        memcpy(args->uuid, disk_super->dev_item.uuid, BTRFS_UUID_SIZE);
        if (btrfs_fs_incompat(fs_info, METADATA_UUID))
index 7421abc..5bb8d8c 100644 (file)
@@ -371,6 +371,9 @@ static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
                                   const char *name, const void *buffer,
                                   size_t size, int flags)
 {
+       if (btrfs_root_readonly(BTRFS_I(inode)->root))
+               return -EROFS;
+
        name = xattr_full_name(handler, name);
        return btrfs_setxattr_trans(inode, name, buffer, size, flags);
 }
index 6cba2c6..2ad58c4 100644 (file)
@@ -111,6 +111,7 @@ struct cachefiles_cache {
        char                            *tag;           /* cache binding tag */
        refcount_t                      unbind_pincount;/* refcount to do daemon unbind */
        struct xarray                   reqs;           /* xarray of pending on-demand requests */
+       unsigned long                   req_id_next;
        struct xarray                   ondemand_ids;   /* xarray for ondemand_id allocation */
        u32                             ondemand_id_next;
 };
index 1fee702..0254ed3 100644 (file)
@@ -158,9 +158,13 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
 
        /* fail OPEN request if daemon reports an error */
        if (size < 0) {
-               if (!IS_ERR_VALUE(size))
-                       size = -EINVAL;
-               req->error = size;
+               if (!IS_ERR_VALUE(size)) {
+                       req->error = -EINVAL;
+                       ret = -EINVAL;
+               } else {
+                       req->error = size;
+                       ret = 0;
+               }
                goto out;
        }
 
@@ -238,14 +242,19 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
        unsigned long id = 0;
        size_t n;
        int ret = 0;
-       XA_STATE(xas, &cache->reqs, 0);
+       XA_STATE(xas, &cache->reqs, cache->req_id_next);
 
        /*
-        * Search for a request that has not ever been processed, to prevent
-        * requests from being processed repeatedly.
+        * Cyclically search for a request that has not ever been processed,
+        * to prevent requests from being processed repeatedly, and make
+        * request distribution fair.
         */
        xa_lock(&cache->reqs);
        req = xas_find_marked(&xas, UINT_MAX, CACHEFILES_REQ_NEW);
+       if (!req && cache->req_id_next > 0) {
+               xas_set(&xas, 0);
+               req = xas_find_marked(&xas, cache->req_id_next - 1, CACHEFILES_REQ_NEW);
+       }
        if (!req) {
                xa_unlock(&cache->reqs);
                return 0;
@@ -260,6 +269,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
        }
 
        xas_clear_mark(&xas, CACHEFILES_REQ_NEW);
+       cache->req_id_next = xas.xa_index + 1;
        xa_unlock(&cache->reqs);
 
        id = xas.xa_index;
index 8f7835c..46f5718 100644 (file)
@@ -32,10 +32,9 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
        int rc;
        struct kvec *iov = rqst->rq_iov;
        int n_vec = rqst->rq_nvec;
-       int is_smb2 = server->vals->header_preamble_size == 0;
 
        /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
-       if (is_smb2) {
+       if (!is_smb1(server)) {
                if (iov[0].iov_len <= 4)
                        return -EIO;
                i = 0;
index f15d7b0..ae7f571 100644 (file)
@@ -557,6 +557,8 @@ struct smb_version_values {
 
 #define HEADER_SIZE(server) (server->vals->header_size)
 #define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
+#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
+#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server))
 
 /**
  * CIFS superblock mount flags (mnt_cifs_flags) to consider when
@@ -750,6 +752,11 @@ struct TCP_Server_Info {
 #endif
 };
 
+static inline bool is_smb1(struct TCP_Server_Info *server)
+{
+       return HEADER_PREAMBLE_SIZE(server) != 0;
+}
+
 static inline void cifs_server_lock(struct TCP_Server_Info *server)
 {
        unsigned int nofs_flag = memalloc_nofs_save();
index 3da5da9..a0a06b6 100644 (file)
@@ -871,7 +871,7 @@ smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
        /*
         * SMB1 does not use credits.
         */
-       if (server->vals->header_preamble_size)
+       if (is_smb1(server))
                return 0;
 
        return le16_to_cpu(shdr->CreditRequest);
@@ -1050,7 +1050,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* make sure this will fit in a large buffer */
        if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
-               server->vals->header_preamble_size) {
+           HEADER_PREAMBLE_SIZE(server)) {
                cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
                cifs_reconnect(server, true);
                return -ECONNABORTED;
@@ -1065,8 +1065,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* now read the rest */
        length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
-                                      pdu_length - HEADER_SIZE(server) + 1
-                                      + server->vals->header_preamble_size);
+                                      pdu_length - MID_HEADER_SIZE(server));
 
        if (length < 0)
                return length;
@@ -1122,7 +1121,7 @@ smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
        /*
         * SMB1 does not use credits.
         */
-       if (server->vals->header_preamble_size)
+       if (is_smb1(server))
                return;
 
        if (shdr->CreditRequest) {
@@ -1180,10 +1179,10 @@ cifs_demultiplex_thread(void *p)
                if (length < 0)
                        continue;
 
-               if (server->vals->header_preamble_size == 0)
-                       server->total_read = 0;
-               else
+               if (is_smb1(server))
                        server->total_read = length;
+               else
+                       server->total_read = 0;
 
                /*
                 * The right amount was read from socket - 4 bytes,
@@ -1198,8 +1197,7 @@ next_pdu:
                server->pdu_size = pdu_length;
 
                /* make sure we have enough to get to the MID */
-               if (server->pdu_size < HEADER_SIZE(server) - 1 -
-                   server->vals->header_preamble_size) {
+               if (server->pdu_size < MID_HEADER_SIZE(server)) {
                        cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
                                 server->pdu_size);
                        cifs_reconnect(server, true);
@@ -1208,9 +1206,8 @@ next_pdu:
 
                /* read down to the MID */
                length = cifs_read_from_socket(server,
-                            buf + server->vals->header_preamble_size,
-                            HEADER_SIZE(server) - 1
-                            - server->vals->header_preamble_size);
+                            buf + HEADER_PREAMBLE_SIZE(server),
+                            MID_HEADER_SIZE(server));
                if (length < 0)
                        continue;
                server->total_read += length;
index 291cb60..147d940 100644 (file)
@@ -51,6 +51,7 @@ struct genl_family cifs_genl_family = {
        .policy         = cifs_genl_policy,
        .ops            = cifs_genl_ops,
        .n_ops          = ARRAY_SIZE(cifs_genl_ops),
+       .resv_start_op  = CIFS_GENL_CMD_SWN_NOTIFY + 1,
        .mcgrps         = cifs_genl_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(cifs_genl_mcgrps),
 };
index 96f3b05..4810bd6 100644 (file)
@@ -3307,26 +3307,43 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
        return pntsd;
 }
 
+static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon,
+                            loff_t offset, loff_t len, unsigned int xid)
+{
+       struct cifsFileInfo *cfile = file->private_data;
+       struct file_zero_data_information fsctl_buf;
+
+       cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
+
+       fsctl_buf.FileOffset = cpu_to_le64(offset);
+       fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
+
+       return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+                         cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
+                         (char *)&fsctl_buf,
+                         sizeof(struct file_zero_data_information),
+                         0, NULL, NULL);
+}
+
 static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
                            loff_t offset, loff_t len, bool keep_size)
 {
        struct cifs_ses *ses = tcon->ses;
-       struct inode *inode;
-       struct cifsInodeInfo *cifsi;
+       struct inode *inode = file_inode(file);
+       struct cifsInodeInfo *cifsi = CIFS_I(inode);
        struct cifsFileInfo *cfile = file->private_data;
-       struct file_zero_data_information fsctl_buf;
        long rc;
        unsigned int xid;
        __le64 eof;
 
        xid = get_xid();
 
-       inode = d_inode(cfile->dentry);
-       cifsi = CIFS_I(inode);
-
        trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
                              ses->Suid, offset, len);
 
+       inode_lock(inode);
+       filemap_invalidate_lock(inode->i_mapping);
+
        /*
         * We zero the range through ioctl, so we need remove the page caches
         * first, otherwise the data may be inconsistent with the server.
@@ -3334,26 +3351,12 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
        truncate_pagecache_range(inode, offset, offset + len - 1);
 
        /* if file not oplocked can't be sure whether asking to extend size */
-       if (!CIFS_CACHE_READ(cifsi))
-               if (keep_size == false) {
-                       rc = -EOPNOTSUPP;
-                       trace_smb3_zero_err(xid, cfile->fid.persistent_fid,
-                               tcon->tid, ses->Suid, offset, len, rc);
-                       free_xid(xid);
-                       return rc;
-               }
-
-       cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
-
-       fsctl_buf.FileOffset = cpu_to_le64(offset);
-       fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
+       rc = -EOPNOTSUPP;
+       if (keep_size == false && !CIFS_CACHE_READ(cifsi))
+               goto zero_range_exit;
 
-       rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
-                       cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
-                       (char *)&fsctl_buf,
-                       sizeof(struct file_zero_data_information),
-                       0, NULL, NULL);
-       if (rc)
+       rc = smb3_zero_data(file, tcon, offset, len, xid);
+       if (rc < 0)
                goto zero_range_exit;
 
        /*
@@ -3366,6 +3369,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
        }
 
  zero_range_exit:
+       filemap_invalidate_unlock(inode->i_mapping);
+       inode_unlock(inode);
        free_xid(xid);
        if (rc)
                trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid,
@@ -3379,7 +3384,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
                            loff_t offset, loff_t len)
 {
-       struct inode *inode;
+       struct inode *inode = file_inode(file);
        struct cifsFileInfo *cfile = file->private_data;
        struct file_zero_data_information fsctl_buf;
        long rc;
@@ -3388,14 +3393,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
 
        xid = get_xid();
 
-       inode = d_inode(cfile->dentry);
-
+       inode_lock(inode);
        /* Need to make file sparse, if not already, before freeing range. */
        /* Consider adding equivalent for compressed since it could also work */
        if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) {
                rc = -EOPNOTSUPP;
-               free_xid(xid);
-               return rc;
+               goto out;
        }
 
        filemap_invalidate_lock(inode->i_mapping);
@@ -3415,8 +3418,10 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
                        (char *)&fsctl_buf,
                        sizeof(struct file_zero_data_information),
                        CIFSMaxBufSize, NULL, NULL);
-       free_xid(xid);
        filemap_invalidate_unlock(inode->i_mapping);
+out:
+       inode_unlock(inode);
+       free_xid(xid);
        return rc;
 }
 
index 91cfc5b..128e44e 100644 (file)
@@ -2572,19 +2572,15 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
 
        path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
 
-       /*
-        * make room for one path separator between the treename and
-        * path
-        */
-       *out_len = treename_len + 1 + path_len;
+       /* make room for one path separator only if @path isn't empty */
+       *out_len = treename_len + (path[0] ? 1 : 0) + path_len;
 
        /*
-        * final path needs to be null-terminated UTF16 with a
-        * size aligned to 8
+        * final path needs to be 8-byte aligned as specified in
+        * MS-SMB2 2.2.13 SMB2 CREATE Request.
         */
-
-       *out_size = roundup((*out_len+1)*2, 8);
-       *out_path = kzalloc(*out_size, GFP_KERNEL);
+       *out_size = roundup(*out_len * sizeof(__le16), 8);
+       *out_path = kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL);
        if (!*out_path)
                return -ENOMEM;
 
index de7aece..c2fe035 100644 (file)
@@ -261,8 +261,8 @@ smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
        int nvec;
        unsigned long buflen = 0;
 
-       if (server->vals->header_preamble_size == 0 &&
-           rqst->rq_nvec >= 2 && rqst->rq_iov[0].iov_len == 4) {
+       if (!is_smb1(server) && rqst->rq_nvec >= 2 &&
+           rqst->rq_iov[0].iov_len == 4) {
                iov = &rqst->rq_iov[1];
                nvec = rqst->rq_nvec - 1;
        } else {
@@ -346,7 +346,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
        sigprocmask(SIG_BLOCK, &mask, &oldmask);
 
        /* Generate a rfc1002 marker for SMB2+ */
-       if (server->vals->header_preamble_size == 0) {
+       if (!is_smb1(server)) {
                struct kvec hiov = {
                        .iov_base = &rfc1002_marker,
                        .iov_len  = 4
@@ -1238,7 +1238,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                buf = (char *)midQ[i]->resp_buf;
                resp_iov[i].iov_base = buf;
                resp_iov[i].iov_len = midQ[i]->resp_buf_size +
-                       server->vals->header_preamble_size;
+                       HEADER_PREAMBLE_SIZE(server);
 
                if (midQ[i]->large_buf)
                        resp_buf_type[i] = CIFS_LARGE_BUFFER;
@@ -1643,7 +1643,7 @@ int
 cifs_discard_remaining_data(struct TCP_Server_Info *server)
 {
        unsigned int rfclen = server->pdu_size;
-       int remaining = rfclen + server->vals->header_preamble_size -
+       int remaining = rfclen + HEADER_PREAMBLE_SIZE(server) -
                server->total_read;
 
        while (remaining > 0) {
@@ -1689,8 +1689,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        unsigned int data_offset, data_len;
        struct cifs_readdata *rdata = mid->callback_data;
        char *buf = server->smallbuf;
-       unsigned int buflen = server->pdu_size +
-               server->vals->header_preamble_size;
+       unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
        bool use_rdma_mr = false;
 
        cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
@@ -1724,10 +1723,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* set up first two iov for signature check and to get credits */
        rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = server->vals->header_preamble_size;
-       rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
+       rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server);
+       rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server);
        rdata->iov[1].iov_len =
-               server->total_read - server->vals->header_preamble_size;
+               server->total_read - HEADER_PREAMBLE_SIZE(server);
        cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
        cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
@@ -1752,7 +1751,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        }
 
        data_offset = server->ops->read_data_offset(buf) +
-               server->vals->header_preamble_size;
+               HEADER_PREAMBLE_SIZE(server);
        if (data_offset < server->total_read) {
                /*
                 * win2k8 sometimes sends an offset of 0 when the read
index 67f68d4..4de4b86 100644 (file)
@@ -75,6 +75,7 @@ static struct genl_family family __ro_after_init = {
        .version        = DLM_GENL_VERSION,
        .small_ops      = dlm_nl_ops,
        .n_small_ops    = ARRAY_SIZE(dlm_nl_ops),
+       .resv_start_op  = DLM_CMD_HELLO + 1,
        .module         = THIS_MODULE,
 };
 
index 0522136..08a1993 100644 (file)
@@ -134,10 +134,10 @@ static bool inode_io_list_move_locked(struct inode *inode,
 
 static void wb_wakeup(struct bdi_writeback *wb)
 {
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (test_bit(WB_registered, &wb->state))
                mod_delayed_work(bdi_wq, &wb->dwork, 0);
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 }
 
 static void finish_writeback_work(struct bdi_writeback *wb,
@@ -164,7 +164,7 @@ static void wb_queue_work(struct bdi_writeback *wb,
        if (work->done)
                atomic_inc(&work->done->cnt);
 
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
 
        if (test_bit(WB_registered, &wb->state)) {
                list_add_tail(&work->list, &wb->work_list);
@@ -172,7 +172,7 @@ static void wb_queue_work(struct bdi_writeback *wb,
        } else
                finish_writeback_work(wb, work);
 
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 }
 
 /**
@@ -2082,13 +2082,13 @@ static struct wb_writeback_work *get_next_work_item(struct bdi_writeback *wb)
 {
        struct wb_writeback_work *work = NULL;
 
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (!list_empty(&wb->work_list)) {
                work = list_entry(wb->work_list.next,
                                  struct wb_writeback_work, list);
                list_del_init(&work->list);
        }
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
        return work;
 }
 
index 7cb0eeb..c9aca21 100644 (file)
@@ -197,6 +197,7 @@ static struct genl_family ksmbd_genl_family = {
        .module         = THIS_MODULE,
        .ops            = ksmbd_genl_ops,
        .n_ops          = ARRAY_SIZE(ksmbd_genl_ops),
+       .resv_start_op  = KSMBD_EVENT_SPNEGO_AUTHEN_RESPONSE + 1,
 };
 
 static void ksmbd_nl_init_fixup(void)
index 801e60b..c28bc98 100644 (file)
@@ -3403,10 +3403,12 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
        ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres);
        ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres);
 
-       ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
-       osb->cconn = NULL;
+       if (osb->cconn) {
+               ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
+               osb->cconn = NULL;
 
-       ocfs2_dlm_shutdown_debug(osb);
+               ocfs2_dlm_shutdown_debug(osb);
+       }
 }
 
 static int ocfs2_drop_lock(struct ocfs2_super *osb,
index 013a727..e2cc9ee 100644 (file)
@@ -1914,8 +1914,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
            !ocfs2_is_hard_readonly(osb))
                hangup_needed = 1;
 
-       if (osb->cconn)
-               ocfs2_dlm_shutdown(osb, hangup_needed);
+       ocfs2_dlm_shutdown(osb, hangup_needed);
 
        ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats);
        debugfs_remove_recursive(osb->osb_debug_root);
index 98e64fe..e565109 100644 (file)
@@ -593,7 +593,7 @@ static void squashfs_readahead(struct readahead_control *ractl)
 
                res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
 
-               kfree(actor);
+               squashfs_page_actor_free(actor);
 
                if (res == expected) {
                        int bytes;
index be4b12d..f1ccad5 100644 (file)
@@ -74,7 +74,7 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
        /* Decompress directly into the page cache buffers */
        res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
 
-       kfree(actor);
+       squashfs_page_actor_free(actor);
 
        if (res < 0)
                goto mark_errored;
index b23b780..54b93bf 100644 (file)
@@ -52,6 +52,7 @@ struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
        actor->buffer = buffer;
        actor->pages = pages;
        actor->next_page = 0;
+       actor->tmp_buffer = NULL;
        actor->squashfs_first_page = cache_first_page;
        actor->squashfs_next_page = cache_next_page;
        actor->squashfs_finish_page = cache_finish_page;
@@ -68,20 +69,9 @@ static void *handle_next_page(struct squashfs_page_actor *actor)
 
        if ((actor->next_page == actor->pages) ||
                        (actor->next_index != actor->page[actor->next_page]->index)) {
-               if (actor->alloc_buffer) {
-                       void *tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
-
-                       if (tmp_buffer) {
-                               actor->tmp_buffer = tmp_buffer;
-                               actor->next_index++;
-                               actor->returned_pages++;
-                               return tmp_buffer;
-                       }
-               }
-
                actor->next_index++;
                actor->returned_pages++;
-               return ERR_PTR(-ENOMEM);
+               return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
        }
 
        actor->next_index++;
@@ -96,11 +86,10 @@ static void *direct_first_page(struct squashfs_page_actor *actor)
 
 static void *direct_next_page(struct squashfs_page_actor *actor)
 {
-       if (actor->pageaddr)
+       if (actor->pageaddr) {
                kunmap_local(actor->pageaddr);
-
-       kfree(actor->tmp_buffer);
-       actor->pageaddr = actor->tmp_buffer = NULL;
+               actor->pageaddr = NULL;
+       }
 
        return handle_next_page(actor);
 }
@@ -109,8 +98,6 @@ static void direct_finish_page(struct squashfs_page_actor *actor)
 {
        if (actor->pageaddr)
                kunmap_local(actor->pageaddr);
-
-       kfree(actor->tmp_buffer);
 }
 
 struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
@@ -121,6 +108,16 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
        if (actor == NULL)
                return NULL;
 
+       if (msblk->decompressor->alloc_buffer) {
+               actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+               if (actor->tmp_buffer == NULL) {
+                       kfree(actor);
+                       return NULL;
+               }
+       } else
+               actor->tmp_buffer = NULL;
+
        actor->length = length ? : pages * PAGE_SIZE;
        actor->page = page;
        actor->pages = pages;
@@ -128,7 +125,6 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
        actor->returned_pages = 0;
        actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
        actor->pageaddr = NULL;
-       actor->tmp_buffer = NULL;
        actor->alloc_buffer = msblk->decompressor->alloc_buffer;
        actor->squashfs_first_page = direct_first_page;
        actor->squashfs_next_page = direct_next_page;
index 24841d2..95ffbb5 100644 (file)
@@ -29,6 +29,11 @@ extern struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
 extern struct squashfs_page_actor *squashfs_page_actor_init_special(
                                struct squashfs_sb_info *msblk,
                                struct page **page, int pages, int length);
+static inline void squashfs_page_actor_free(struct squashfs_page_actor *actor)
+{
+       kfree(actor->tmp_buffer);
+       kfree(actor);
+}
 static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
 {
        return actor->squashfs_first_page(actor);
index 3d5ebd2..564a8c6 100644 (file)
@@ -4,6 +4,7 @@
 #define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
 
 #include <linux/bits.h>
+#include <asm/barrier.h>
 
 #ifndef _LINUX_BITOPS_H
 #error only <linux/bitops.h> can be included directly
@@ -127,6 +128,18 @@ generic_test_bit(unsigned long nr, const volatile unsigned long *addr)
        return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
 }
 
+/**
+ * generic_test_bit_acquire - Determine, with acquire semantics, whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static __always_inline bool
+generic_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       return 1UL & (smp_load_acquire(p) >> (nr & (BITS_PER_LONG-1)));
+}
+
 /*
  * const_*() definitions provide good compile-time optimizations when
  * the passed arguments can be resolved at compile time.
@@ -137,6 +150,7 @@ generic_test_bit(unsigned long nr, const volatile unsigned long *addr)
 #define const___test_and_set_bit       generic___test_and_set_bit
 #define const___test_and_clear_bit     generic___test_and_clear_bit
 #define const___test_and_change_bit    generic___test_and_change_bit
+#define const_test_bit_acquire         generic_test_bit_acquire
 
 /**
  * const_test_bit - Determine whether a bit is set
index 988a3bb..2b238b1 100644 (file)
@@ -142,4 +142,16 @@ _test_bit(unsigned long nr, const volatile unsigned long *addr)
        return arch_test_bit(nr, addr);
 }
 
+/**
+ * _test_bit_acquire - Determine, with acquire semantics, whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static __always_inline bool
+_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long));
+       return arch_test_bit_acquire(nr, addr);
+}
+
 #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */
index 5c37ced..71f8d54 100644 (file)
@@ -13,6 +13,7 @@
 #define arch___test_and_change_bit generic___test_and_change_bit
 
 #define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 #include <asm-generic/bitops/non-instrumented-non-atomic.h>
 
index bdb9b1f..0ddc78d 100644 (file)
@@ -12,5 +12,6 @@
 #define ___test_and_change_bit arch___test_and_change_bit
 
 #define _test_bit              arch_test_bit
+#define _test_bit_acquire      arch_test_bit_acquire
 
 #endif /* __ASM_GENERIC_BITOPS_NON_INSTRUMENTED_NON_ATOMIC_H */
index d0f7bdd..db13bb6 100644 (file)
@@ -97,7 +97,7 @@ static inline bool memory_contains(void *begin, void *end, void *virt,
 /**
  * memory_intersects - checks if the region occupied by an object intersects
  *                     with another memory region
- * @begin: virtual address of the beginning of the memory regien
+ * @begin: virtual address of the beginning of the memory region
  * @end: virtual address of the end of the memory region
  * @virt: virtual address of the memory object
  * @size: size of the memory object
@@ -110,7 +110,10 @@ static inline bool memory_intersects(void *begin, void *end, void *virt,
 {
        void *vend = virt + size;
 
-       return (virt >= begin && virt < end) || (vend >= begin && vend < end);
+       if (virt < end && vend > begin)
+               return true;
+
+       return false;
 }
 
 /**
index cf9bf65..3b89c64 100644 (file)
@@ -59,6 +59,7 @@ extern unsigned long __sw_hweight64(__u64 w);
 #define __test_and_clear_bit(nr, addr) bitop(___test_and_clear_bit, nr, addr)
 #define __test_and_change_bit(nr, addr)        bitop(___test_and_change_bit, nr, addr)
 #define test_bit(nr, addr)             bitop(_test_bit, nr, addr)
+#define test_bit_acquire(nr, addr)     bitop(_test_bit_acquire, nr, addr)
 
 /*
  * Include this here because some architectures need generic_ffs/fls in
index 20c26ae..a627a02 100644 (file)
@@ -2349,6 +2349,7 @@ extern const struct bpf_func_proto bpf_get_numa_node_id_proto;
 extern const struct bpf_func_proto bpf_tail_call_proto;
 extern const struct bpf_func_proto bpf_ktime_get_ns_proto;
 extern const struct bpf_func_proto bpf_ktime_get_boot_ns_proto;
+extern const struct bpf_func_proto bpf_ktime_get_tai_ns_proto;
 extern const struct bpf_func_proto bpf_get_current_pid_tgid_proto;
 extern const struct bpf_func_proto bpf_get_current_uid_gid_proto;
 extern const struct bpf_func_proto bpf_get_current_comm_proto;
index 6ff567e..9e77165 100644 (file)
 #define MII_BRCM_FET_SHDW_MC_FAME      0x4000  /* Force Auto MDIX enable */
 
 #define MII_BRCM_FET_SHDW_AUXMODE4     0x1a    /* Auxiliary mode 4 */
+#define MII_BRCM_FET_SHDW_AM4_STANDBY  0x0008  /* Standby enable */
 #define MII_BRCM_FET_SHDW_AM4_LED_MASK 0x0003
 #define MII_BRCM_FET_SHDW_AM4_LED_MODE1 0x0001
 
index cdb376d..ad93c2d 100644 (file)
@@ -49,6 +49,8 @@
  * for this case.
  */
 #define KF_TRUSTED_ARGS (1 << 4) /* kfunc only takes trusted pointer arguments */
+#define KF_SLEEPABLE    (1 << 5) /* kfunc may sleep */
+#define KF_DESTRUCTIVE  (1 << 6) /* kfunc performs destructive actions */
 
 struct btf;
 struct btf_member;
index def8b8d..089c9ad 100644 (file)
@@ -156,7 +156,7 @@ static __always_inline int buffer_uptodate(const struct buffer_head *bh)
         * make it consistent with folio_test_uptodate
         * pairs with smp_mb__before_atomic in set_buffer_uptodate
         */
-       return (smp_load_acquire(&bh->b_state) & (1UL << BH_Uptodate)) != 0;
+       return test_bit_acquire(BH_Uptodate, &bh->b_state);
 }
 
 #define bh_offset(bh)          ((unsigned long)(bh)->b_data & ~PAGE_MASK)
index 01ce94b..7713d7b 100644 (file)
@@ -239,6 +239,12 @@ static inline void *offset_to_ptr(const int *off)
 /* &a[0] degrades to a pointer: a different type from an array */
 #define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
 
+/*
+ * Whether 'type' is a signed type or an unsigned type. Supports scalar types,
+ * bool and also pointer types.
+ */
+#define is_signed_type(type) (((type)(-1)) < (__force type)1)
+
 /*
  * This is needed in functions which generate the stack canary, see
  * arch/x86/kernel/smpboot.c::start_secondary() for an example.
index 445e805..fc93c94 100644 (file)
  */
 #define __weak                          __attribute__((__weak__))
 
+/*
+ * Used by functions that use '__builtin_return_address'. These function
+ * don't want to be splited or made inline, which can make
+ * the '__builtin_return_address' get unexpected address.
+ */
+#define __fix_address noinline __noclone
+
 #endif /* __LINUX_COMPILER_ATTRIBUTES_H */
index 92b10e6..a541f0c 100644 (file)
@@ -428,6 +428,28 @@ static inline bool ether_addr_equal_masked(const u8 *addr1, const u8 *addr2,
        return true;
 }
 
+static inline bool ether_addr_is_ipv4_mcast(const u8 *addr)
+{
+       u8 base[ETH_ALEN] = { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x00 };
+       u8 mask[ETH_ALEN] = { 0xff, 0xff, 0xff, 0x80, 0x00, 0x00 };
+
+       return ether_addr_equal_masked(addr, base, mask);
+}
+
+static inline bool ether_addr_is_ipv6_mcast(const u8 *addr)
+{
+       u8 base[ETH_ALEN] = { 0x33, 0x33, 0x00, 0x00, 0x00, 0x00 };
+       u8 mask[ETH_ALEN] = { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
+
+       return ether_addr_equal_masked(addr, base, mask);
+}
+
+static inline bool ether_addr_is_ip_mcast(const u8 *addr)
+{
+       return ether_addr_is_ipv4_mcast(addr) ||
+               ether_addr_is_ipv6_mcast(addr);
+}
+
 /**
  * ether_addr_to_u64 - Convert an Ethernet address into a u64 value.
  * @addr: Pointer to a six-byte array containing the Ethernet address
index 720874e..36e5dd8 100644 (file)
@@ -258,7 +258,7 @@ struct fscache_cookie *fscache_acquire_cookie(struct fscache_volume *volume,
 
 /**
  * fscache_use_cookie - Request usage of cookie attached to an object
- * @object: Object description
+ * @cookie: The cookie representing the cache object
  * @will_modify: If cache is expected to be modified locally
  *
  * Request usage of the cookie attached to an object.  The caller should tell
@@ -274,7 +274,7 @@ static inline void fscache_use_cookie(struct fscache_cookie *cookie,
 
 /**
  * fscache_unuse_cookie - Cease usage of cookie attached to an object
- * @object: Object description
+ * @cookie: The cookie representing the cache object
  * @aux_data: Updated auxiliary data (or NULL)
  * @object_size: Revised size of the object (or NULL)
  *
index 939b1a8..4a4b387 100644 (file)
@@ -294,6 +294,7 @@ static struct genl_family ZZZ_genl_family __ro_after_init = {
        .ops = ZZZ_genl_ops,
        .n_ops = ARRAY_SIZE(ZZZ_genl_ops),
        .mcgrps = ZZZ_genl_mcgrps,
+       .resv_start_op = 42, /* drbd is currently the only user */
        .n_mcgrps = ARRAY_SIZE(ZZZ_genl_mcgrps),
        .module = THIS_MODULE,
 };
index b6e6d5b..7969093 100644 (file)
@@ -2888,7 +2888,8 @@ ieee80211_he_spr_size(const u8 *he_spr_ie)
 /* Calculate 802.11be EHT capabilities IE Tx/Rx EHT MCS NSS Support Field size */
 static inline u8
 ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap,
-                          const struct ieee80211_eht_cap_elem_fixed *eht_cap)
+                          const struct ieee80211_eht_cap_elem_fixed *eht_cap,
+                          bool from_ap)
 {
        u8 count = 0;
 
@@ -2909,7 +2910,10 @@ ieee80211_eht_mcs_nss_size(const struct ieee80211_he_cap_elem *he_cap,
        if (eht_cap->phy_cap_info[0] & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
                count += 3;
 
-       return count ? count : 4;
+       if (count)
+               return count;
+
+       return from_ap ? 3 : 4;
 }
 
 /* 802.11be EHT PPE Thresholds */
@@ -2945,7 +2949,8 @@ ieee80211_eht_ppe_size(u16 ppe_thres_hdr, const u8 *phy_cap_info)
 }
 
 static inline bool
-ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len)
+ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len,
+                          bool from_ap)
 {
        const struct ieee80211_eht_cap_elem_fixed *elem = (const void *)data;
        u8 needed = sizeof(struct ieee80211_eht_cap_elem_fixed);
@@ -2954,7 +2959,8 @@ ieee80211_eht_capa_size_ok(const u8 *he_capa, const u8 *data, u8 len)
                return false;
 
        needed += ieee80211_eht_mcs_nss_size((const void *)he_capa,
-                                            (const void *)data);
+                                            (const void *)data,
+                                            from_ap);
        if (len < needed)
                return false;
 
index 8064481..60fff13 100644 (file)
@@ -407,4 +407,5 @@ LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
 #ifdef CONFIG_IO_URING
 LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
 LSM_HOOK(int, 0, uring_sqpoll, void)
+LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd)
 #endif /* CONFIG_IO_URING */
index 84a0d7e..3aa6030 100644 (file)
  *      Check whether the current task is allowed to spawn a io_uring polling
  *      thread (IORING_SETUP_SQPOLL).
  *
+ * @uring_cmd:
+ *      Check whether the file_operations uring_cmd is allowed to run.
+ *
  */
 union security_list_options {
        #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
index 4d31ce5..6257867 100644 (file)
@@ -987,19 +987,30 @@ static inline void mod_memcg_page_state(struct page *page,
 
 static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
 {
-       return READ_ONCE(memcg->vmstats.state[idx]);
+       long x = READ_ONCE(memcg->vmstats.state[idx]);
+#ifdef CONFIG_SMP
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
 }
 
 static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
                                              enum node_stat_item idx)
 {
        struct mem_cgroup_per_node *pn;
+       long x;
 
        if (mem_cgroup_disabled())
                return node_page_state(lruvec_pgdat(lruvec), idx);
 
        pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
-       return READ_ONCE(pn->lruvec_stats.state[idx]);
+       x = READ_ONCE(pn->lruvec_stats.state[idx]);
+#ifdef CONFIG_SMP
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
 }
 
 static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
index 982f260..21f8b27 100644 (file)
@@ -1544,9 +1544,16 @@ static inline bool is_longterm_pinnable_page(struct page *page)
        if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE)
                return false;
 #endif
-       return !(is_device_coherent_page(page) ||
-                is_zone_movable_page(page) ||
-                is_zero_pfn(page_to_pfn(page)));
+       /* The zero page may always be pinned */
+       if (is_zero_pfn(page_to_pfn(page)))
+               return true;
+
+       /* Coherent device memory must always allow eviction. */
+       if (is_device_coherent_page(page))
+               return false;
+
+       /* Otherwise, non-movable zone pages can be pinned. */
+       return !is_zone_movable_page(page);
 }
 #else
 static inline bool is_longterm_pinnable_page(struct page *page)
index 05d6f3f..f0068c1 100644 (file)
@@ -546,8 +546,8 @@ static inline bool napi_if_scheduled_mark_missed(struct napi_struct *n)
 {
        unsigned long val, new;
 
+       val = READ_ONCE(n->state);
        do {
-               val = READ_ONCE(n->state);
                if (val & NAPIF_STATE_DISABLE)
                        return true;
 
@@ -555,7 +555,7 @@ static inline bool napi_if_scheduled_mark_missed(struct napi_struct *n)
                        return false;
 
                new = val | NAPIF_STATE_MISSED;
-       } while (cmpxchg(&n->state, val, new) != val);
+       } while (!try_cmpxchg(&n->state, &val, new));
 
        return true;
 }
@@ -1851,7 +1851,6 @@ enum netdev_ml_priv_type {
  *     @tipc_ptr:      TIPC specific data
  *     @atalk_ptr:     AppleTalk link
  *     @ip_ptr:        IPv4 specific data
- *     @dn_ptr:        DECnet specific data
  *     @ip6_ptr:       IPv6 specific data
  *     @ax25_ptr:      AX.25 specific data
  *     @ieee80211_ptr: IEEE 802.11 specific data, assign before registering
@@ -2147,9 +2146,6 @@ struct net_device {
 #if IS_ENABLED(CONFIG_ATALK)
        void                    *atalk_ptr;
 #endif
-#if IS_ENABLED(CONFIG_DECNET)
-       struct dn_dev __rcu     *dn_ptr;
-#endif
 #if IS_ENABLED(CONFIG_AX25)
        void                    *ax25_ptr;
 #endif
@@ -2573,8 +2569,6 @@ netif_napi_add_tx_weight(struct net_device *dev,
        netif_napi_add_weight(dev, napi, poll, weight);
 }
 
-#define netif_tx_napi_add netif_napi_add_tx_weight
-
 /**
  * netif_napi_add_tx() - initialize a NAPI context to be used for Tx only
  * @dev:  network device
@@ -3357,6 +3351,16 @@ static inline void netdev_txq_bql_complete_prefetchw(struct netdev_queue *dev_qu
 #endif
 }
 
+/**
+ *     netdev_tx_sent_queue - report the number of bytes queued to a given tx queue
+ *     @dev_queue: network device queue
+ *     @bytes: number of bytes queued to the device queue
+ *
+ *     Report the number of bytes queued for sending/completion to the network
+ *     device hardware queue. @bytes should be a good approximation and should
+ *     exactly match netdev_completed_queue() @bytes.
+ *     This is typically called once per packet, from ndo_start_xmit().
+ */
 static inline void netdev_tx_sent_queue(struct netdev_queue *dev_queue,
                                        unsigned int bytes)
 {
@@ -3402,13 +3406,14 @@ static inline bool __netdev_tx_sent_queue(struct netdev_queue *dev_queue,
 }
 
 /**
- *     netdev_sent_queue - report the number of bytes queued to hardware
- *     @dev: network device
- *     @bytes: number of bytes queued to the hardware device queue
+ *     netdev_sent_queue - report the number of bytes queued to hardware
+ *     @dev: network device
+ *     @bytes: number of bytes queued to the hardware device queue
  *
- *     Report the number of bytes queued for sending/completion to the network
- *     device hardware queue. @bytes should be a good approximation and should
- *     exactly match netdev_completed_queue() @bytes
+ *     Report the number of bytes queued for sending/completion to the network
+ *     device hardware queue#0. @bytes should be a good approximation and should
+ *     exactly match netdev_completed_queue() @bytes.
+ *     This is typically called once per packet, from ndo_start_xmit().
  */
 static inline void netdev_sent_queue(struct net_device *dev, unsigned int bytes)
 {
@@ -3423,6 +3428,15 @@ static inline bool __netdev_sent_queue(struct net_device *dev,
                                      xmit_more);
 }
 
+/**
+ *     netdev_tx_completed_queue - report number of packets/bytes at TX completion.
+ *     @dev_queue: network device queue
+ *     @pkts: number of packets (currently ignored)
+ *     @bytes: number of bytes dequeued from the device queue
+ *
+ *     Must be called at most once per TX completion round (and not per
+ *     individual packet), so that BQL can adjust its limits appropriately.
+ */
 static inline void netdev_tx_completed_queue(struct netdev_queue *dev_queue,
                                             unsigned int pkts, unsigned int bytes)
 {
index c2c6f33..d8817d3 100644 (file)
@@ -243,11 +243,6 @@ static inline int nf_hook(u_int8_t pf, unsigned int hook, struct net *net,
                hook_head = rcu_dereference(net->nf.hooks_bridge[hook]);
 #endif
                break;
-#if IS_ENABLED(CONFIG_DECNET)
-       case NFPROTO_DECNET:
-               hook_head = rcu_dereference(net->nf.hooks_decnet[hook]);
-               break;
-#endif
        default:
                WARN_ON_ONCE(1);
                break;
index 8dddfb1..a5f7bef 100644 (file)
@@ -7,14 +7,6 @@
 /* in/out/forward only */
 #define NF_ARP_NUMHOOKS 3
 
-/* max hook is NF_DN_ROUTE (6), also see uapi/linux/netfilter_decnet.h */
-#define NF_DN_NUMHOOKS 7
-
-#if IS_ENABLED(CONFIG_DECNET)
-/* Largest hook number + 1, see uapi/linux/netfilter_decnet.h */
-#define NF_MAX_HOOKS   NF_DN_NUMHOOKS
-#else
 #define NF_MAX_HOOKS   NF_INET_NUMHOOKS
-#endif
 
 #endif
index bda1c38..d51e041 100644 (file)
@@ -71,6 +71,8 @@ netlink_kernel_create(struct net *net, int unit, struct netlink_kernel_cfg *cfg)
  *     %NL_SET_ERR_MSG
  * @bad_attr: attribute with error
  * @policy: policy for a bad attribute
+ * @miss_type: attribute type which was missing
+ * @miss_nest: nest missing an attribute (%NULL if missing top level attr)
  * @cookie: cookie data to return to userspace (for success)
  * @cookie_len: actual cookie data length
  */
@@ -78,6 +80,8 @@ struct netlink_ext_ack {
        const char *_msg;
        const struct nlattr *bad_attr;
        const struct nla_policy *policy;
+       const struct nlattr *miss_nest;
+       u16 miss_type;
        u8 cookie[NETLINK_MAX_COOKIE_LEN];
        u8 cookie_len;
 };
@@ -126,6 +130,26 @@ struct netlink_ext_ack {
 #define NL_SET_ERR_MSG_ATTR(extack, attr, msg)         \
        NL_SET_ERR_MSG_ATTR_POL(extack, attr, NULL, msg)
 
+#define NL_SET_ERR_ATTR_MISS(extack, nest, type)  do { \
+       struct netlink_ext_ack *__extack = (extack);    \
+                                                       \
+       if (__extack) {                                 \
+               __extack->miss_nest = (nest);           \
+               __extack->miss_type = (type);           \
+       }                                               \
+} while (0)
+
+#define NL_REQ_ATTR_CHECK(extack, nest, tb, type) ({           \
+       struct nlattr **__tb = (tb);                            \
+       u32 __attr = (type);                                    \
+       int __retval;                                           \
+                                                               \
+       __retval = !__tb[__attr];                               \
+       if (__retval)                                           \
+               NL_SET_ERR_ATTR_MISS((extack), (nest), __attr); \
+       __retval;                                               \
+})
+
 static inline void nl_set_extack_cookie_u64(struct netlink_ext_ack *extack,
                                            u64 cookie)
 {
index f1221d1..0eb3b19 100644 (file)
@@ -30,7 +30,6 @@
  * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
  * credit to Christian Biere.
  */
-#define is_signed_type(type)       (((type)(-1)) < (type)1)
 #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
 #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
 #define type_min(T) ((T)((T)-type_max(T)-(T)1))
index 87638c5..7c49ab9 100644 (file)
@@ -115,6 +115,7 @@ extern const int phy_10gbit_features_array[1];
  * @PHY_INTERFACE_MODE_25GBASER: 25G BaseR
  * @PHY_INTERFACE_MODE_USXGMII:  Universal Serial 10GE MII
  * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN
+ * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII
  * @PHY_INTERFACE_MODE_MAX: Book keeping
  *
  * Describes the interface between the MAC and PHY.
@@ -152,6 +153,7 @@ typedef enum {
        PHY_INTERFACE_MODE_USXGMII,
        /* 10GBASE-KR - with Clause 73 AN */
        PHY_INTERFACE_MODE_10GKR,
+       PHY_INTERFACE_MODE_QUSGMII,
        PHY_INTERFACE_MODE_MAX,
 } phy_interface_t;
 
@@ -267,6 +269,8 @@ static inline const char *phy_modes(phy_interface_t interface)
                return "10gbase-kr";
        case PHY_INTERFACE_MODE_100BASEX:
                return "100base-x";
+       case PHY_INTERFACE_MODE_QUSGMII:
+               return "qusgmii";
        default:
                return "unknown";
        }
@@ -964,6 +968,8 @@ struct phy_fixup {
 const char *phy_speed_to_str(int speed);
 const char *phy_duplex_to_str(unsigned int duplex);
 
+int phy_interface_num_ports(phy_interface_t interface);
+
 /* A structure for mapping a particular speed and duplex
  * combination to a particular SUPPORTED and ADVERTISED value
  */
index bf80adc..b89b4b8 100644 (file)
@@ -41,12 +41,15 @@ struct anon_vma {
        atomic_t refcount;
 
        /*
-        * Count of child anon_vmas and VMAs which points to this anon_vma.
+        * Count of child anon_vmas. Equals to the count of all anon_vmas that
+        * have ->parent pointing to this one, including itself.
         *
         * This counter is used for making decision about reusing anon_vma
         * instead of forking new one. See comments in function anon_vma_clone.
         */
-       unsigned degree;
+       unsigned long num_children;
+       /* Count of VMAs whose ->anon_vma pointer points to this object. */
+       unsigned long num_active_vmas;
 
        struct anon_vma *parent;        /* Parent of this anon_vma */
 
index 1bc362c..7bd0c49 100644 (file)
@@ -2060,6 +2060,7 @@ static inline int security_perf_event_write(struct perf_event *event)
 #ifdef CONFIG_SECURITY
 extern int security_uring_override_creds(const struct cred *new);
 extern int security_uring_sqpoll(void);
+extern int security_uring_cmd(struct io_uring_cmd *ioucmd);
 #else
 static inline int security_uring_override_creds(const struct cred *new)
 {
@@ -2069,6 +2070,10 @@ static inline int security_uring_sqpoll(void)
 {
        return 0;
 }
+static inline int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       return 0;
+}
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_IO_URING */
 
index ca8afa3..b51d07a 100644 (file)
@@ -1195,7 +1195,8 @@ static inline bool skb_unref(struct sk_buff *skb)
        return true;
 }
 
-void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason);
+void __fix_address
+kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason);
 
 /**
  *     kfree_skb - free an sk_buff with 'NOT_SPECIFIED' reason
index 8df475d..fb2e886 100644 (file)
@@ -257,7 +257,6 @@ struct plat_stmmacenet_data {
        u8 vlan_fail_q;
        unsigned int eee_usecs_rate;
        struct pci_dev *pdev;
-       bool has_crossts;
        int int_snapshot_num;
        int ext_snapshot_num;
        bool int_snapshot_en;
index 9f442d7..90cd08a 100644 (file)
@@ -187,6 +187,7 @@ void tb_unregister_property_dir(const char *key, struct tb_property_dir *dir);
  * @device_name: Name of the device (or %NULL if not known)
  * @link_speed: Speed of the link in Gb/s
  * @link_width: Width of the link (1 or 2)
+ * @link_usb4: Downstream link is USB4
  * @is_unplugged: The XDomain is unplugged
  * @needs_uuid: If the XDomain does not have @remote_uuid it will be
  *             queried first
@@ -234,6 +235,7 @@ struct tb_xdomain {
        const char *device_name;
        unsigned int link_speed;
        unsigned int link_width;
+       bool link_usb4;
        bool is_unplugged;
        bool needs_uuid;
        struct ida service_ids;
index b18759a..8401dec 100644 (file)
@@ -814,8 +814,6 @@ extern int trace_add_event_call(struct trace_event_call *call);
 extern int trace_remove_event_call(struct trace_event_call *call);
 extern int trace_event_get_offsets(struct trace_event_call *call);
 
-#define is_signed_type(type)   (((type)(-1)) < (type)1)
-
 int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
 int trace_set_clr_event(const char *system, const char *event, int set);
 int trace_array_set_clr_event(struct trace_array *tr, const char *system,
index 7dec36a..7725b75 100644 (file)
@@ -71,7 +71,7 @@ static inline int
 wait_on_bit(unsigned long *word, int bit, unsigned mode)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
                                       bit_wait,
@@ -96,7 +96,7 @@ static inline int
 wait_on_bit_io(unsigned long *word, int bit, unsigned mode)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
                                       bit_wait_io,
@@ -123,7 +123,7 @@ wait_on_bit_timeout(unsigned long *word, int bit, unsigned mode,
                    unsigned long timeout)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit_timeout(word, bit,
                                               bit_wait_timeout,
@@ -151,7 +151,7 @@ wait_on_bit_action(unsigned long *word, int bit, wait_bit_action_f *action,
                   unsigned mode)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit, action, mode);
 }
index 1c53c4c..568a87c 100644 (file)
@@ -78,6 +78,7 @@ struct vsock_sock {
 s64 vsock_stream_has_data(struct vsock_sock *vsk);
 s64 vsock_stream_has_space(struct vsock_sock *vsk);
 struct sock *vsock_create_connected(struct sock *parent);
+void vsock_data_ready(struct sock *sk);
 
 /**** TRANSPORT ****/
 
@@ -135,6 +136,7 @@ struct vsock_transport {
        u64 (*stream_rcvhiwat)(struct vsock_sock *);
        bool (*stream_is_active)(struct vsock_sock *);
        bool (*stream_allow)(u32 cid, u32 port);
+       int (*set_rcvlowat)(struct vsock_sock *vsk, int val);
 
        /* SEQ_PACKET. */
        ssize_t (*seqpacket_dequeue)(struct vsock_sock *vsk, struct msghdr *msg,
index 908d583..e09ff87 100644 (file)
@@ -2316,6 +2316,7 @@ struct ocb_setup {
  * @cwmax: Maximum contention window [a value of the form 2^n-1 in the range
  *     1..32767]
  * @aifs: Arbitration interframe space [0..255]
+ * @link_id: link_id or -1 for non-MLD
  */
 struct ieee80211_txq_params {
        enum nl80211_ac ac;
@@ -2323,6 +2324,7 @@ struct ieee80211_txq_params {
        u16 cwmin;
        u16 cwmax;
        u8 aifs;
+       int link_id;
 };
 
 /**
@@ -3929,22 +3931,33 @@ struct mgmt_frame_regs {
  * @del_intf_link: Remove an MLO link from the given interface.
  *
  * @add_key: add a key with the given parameters. @mac_addr will be %NULL
- *     when adding a group key.
+ *     when adding a group key. @link_id will be -1 for non-MLO connection.
+ *     For MLO connection, @link_id will be >= 0 for group key and -1 for
+ *     pairwise key, @mac_addr will be peer's MLD address for MLO pairwise key.
  *
  * @get_key: get information about the key with the given parameters.
  *     @mac_addr will be %NULL when requesting information for a group
  *     key. All pointers given to the @callback function need not be valid
  *     after it returns. This function should return an error if it is
  *     not possible to retrieve the key, -ENOENT if it doesn't exist.
+ *     @link_id will be -1 for non-MLO connection. For MLO connection,
+ *     @link_id will be >= 0 for group key and -1 for pairwise key, @mac_addr
+ *     will be peer's MLD address for MLO pairwise key.
  *
  * @del_key: remove a key given the @mac_addr (%NULL for a group key)
- *     and @key_index, return -ENOENT if the key doesn't exist.
+ *     and @key_index, return -ENOENT if the key doesn't exist. @link_id will
+ *     be -1 for non-MLO connection. For MLO connection, @link_id will be >= 0
+ *     for group key and -1 for pairwise key, @mac_addr will be peer's MLD
+ *     address for MLO pairwise key.
  *
- * @set_default_key: set the default key on an interface
+ * @set_default_key: set the default key on an interface. @link_id will be >= 0
+ *     for MLO connection and -1 for non-MLO connection.
  *
- * @set_default_mgmt_key: set the default management frame key on an interface
+ * @set_default_mgmt_key: set the default management frame key on an interface.
+ *     @link_id will be >= 0 for MLO connection and -1 for non-MLO connection.
  *
- * @set_default_beacon_key: set the default Beacon frame key on an interface
+ * @set_default_beacon_key: set the default Beacon frame key on an interface.
+ *     @link_id will be >= 0 for MLO connection and -1 for non-MLO connection.
  *
  * @set_rekey_data: give the data necessary for GTK rekeying to the driver
  *
@@ -4293,22 +4306,24 @@ struct cfg80211_ops {
                                 unsigned int link_id);
 
        int     (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
-                          u8 key_index, bool pairwise, const u8 *mac_addr,
-                          struct key_params *params);
+                          int link_id, u8 key_index, bool pairwise,
+                          const u8 *mac_addr, struct key_params *params);
        int     (*get_key)(struct wiphy *wiphy, struct net_device *netdev,
-                          u8 key_index, bool pairwise, const u8 *mac_addr,
-                          void *cookie,
+                          int link_id, u8 key_index, bool pairwise,
+                          const u8 *mac_addr, void *cookie,
                           void (*callback)(void *cookie, struct key_params*));
        int     (*del_key)(struct wiphy *wiphy, struct net_device *netdev,
-                          u8 key_index, bool pairwise, const u8 *mac_addr);
+                          int link_id, u8 key_index, bool pairwise,
+                          const u8 *mac_addr);
        int     (*set_default_key)(struct wiphy *wiphy,
-                                  struct net_device *netdev,
+                                  struct net_device *netdev, int link_id,
                                   u8 key_index, bool unicast, bool multicast);
        int     (*set_default_mgmt_key)(struct wiphy *wiphy,
-                                       struct net_device *netdev,
+                                       struct net_device *netdev, int link_id,
                                        u8 key_index);
        int     (*set_default_beacon_key)(struct wiphy *wiphy,
                                          struct net_device *netdev,
+                                         int link_id,
                                          u8 key_index);
 
        int     (*start_ap)(struct wiphy *wiphy, struct net_device *dev,
@@ -8266,6 +8281,7 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
  * cfg80211_ch_switch_started_notify - notify channel switch start
  * @dev: the device on which the channel switch started
  * @chandef: the future channel definition
+ * @link_id: the link ID for MLO, must be 0 for non-MLO
  * @count: the number of TBTTs until the channel switch happens
  * @quiet: whether or not immediate quiet was requested by the AP
  *
@@ -8275,7 +8291,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
  */
 void cfg80211_ch_switch_started_notify(struct net_device *dev,
                                       struct cfg80211_chan_def *chandef,
-                                      u8 count, bool quiet);
+                                      unsigned int link_id, u8 count,
+                                      bool quiet);
 
 /**
  * ieee80211_operating_class_to_band - convert operating class to band
index 119ed1f..264aa98 100644 (file)
@@ -118,7 +118,6 @@ struct devlink_rate {
 
 struct devlink_port {
        struct list_head list;
-       struct list_head param_list;
        struct list_head region_list;
        struct devlink *devlink;
        unsigned int index;
@@ -624,8 +623,7 @@ struct devlink_flash_update_params {
        u32 overwrite_mask;
 };
 
-#define DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT         BIT(0)
-#define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK    BIT(1)
+#define DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK    BIT(0)
 
 struct devlink_region;
 struct devlink_info_req;
@@ -1714,15 +1712,31 @@ int devlink_info_driver_name_put(struct devlink_info_req *req,
                                 const char *name);
 int devlink_info_board_serial_number_put(struct devlink_info_req *req,
                                         const char *bsn);
+
+enum devlink_info_version_type {
+       DEVLINK_INFO_VERSION_TYPE_NONE,
+       DEVLINK_INFO_VERSION_TYPE_COMPONENT, /* May be used as flash update
+                                             * component by name.
+                                             */
+};
+
 int devlink_info_version_fixed_put(struct devlink_info_req *req,
                                   const char *version_name,
                                   const char *version_value);
 int devlink_info_version_stored_put(struct devlink_info_req *req,
                                    const char *version_name,
                                    const char *version_value);
+int devlink_info_version_stored_put_ext(struct devlink_info_req *req,
+                                       const char *version_name,
+                                       const char *version_value,
+                                       enum devlink_info_version_type version_type);
 int devlink_info_version_running_put(struct devlink_info_req *req,
                                     const char *version_name,
                                     const char *version_value);
+int devlink_info_version_running_put_ext(struct devlink_info_req *req,
+                                        const char *version_name,
+                                        const char *version_value,
+                                        enum devlink_info_version_type version_type);
 
 int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg);
 int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg);
diff --git a/include/net/dn.h b/include/net/dn.h
deleted file mode 100644 (file)
index ba9655b..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _NET_DN_H
-#define _NET_DN_H
-
-#include <linux/dn.h>
-#include <net/sock.h>
-#include <net/flow.h>
-#include <asm/byteorder.h>
-#include <asm/unaligned.h>
-
-struct dn_scp                                   /* Session Control Port */
-{
-        unsigned char           state;
-#define DN_O     1                      /* Open                 */
-#define DN_CR    2                      /* Connect Receive      */
-#define DN_DR    3                      /* Disconnect Reject    */
-#define DN_DRC   4                      /* Discon. Rej. Complete*/
-#define DN_CC    5                      /* Connect Confirm      */
-#define DN_CI    6                      /* Connect Initiate     */
-#define DN_NR    7                      /* No resources         */
-#define DN_NC    8                      /* No communication     */
-#define DN_CD    9                      /* Connect Delivery     */
-#define DN_RJ    10                     /* Rejected             */
-#define DN_RUN   11                     /* Running              */
-#define DN_DI    12                     /* Disconnect Initiate  */
-#define DN_DIC   13                     /* Disconnect Complete  */
-#define DN_DN    14                     /* Disconnect Notificat */
-#define DN_CL    15                     /* Closed               */
-#define DN_CN    16                     /* Closed Notification  */
-
-        __le16          addrloc;
-        __le16          addrrem;
-        __u16          numdat;
-        __u16          numoth;
-        __u16          numoth_rcv;
-        __u16          numdat_rcv;
-        __u16          ackxmt_dat;
-        __u16          ackxmt_oth;
-        __u16          ackrcv_dat;
-        __u16          ackrcv_oth;
-        __u8           flowrem_sw;
-       __u8           flowloc_sw;
-#define DN_SEND         2
-#define DN_DONTSEND     1
-#define DN_NOCHANGE     0
-       __u16           flowrem_dat;
-       __u16           flowrem_oth;
-       __u16           flowloc_dat;
-       __u16           flowloc_oth;
-       __u8            services_rem;
-       __u8            services_loc;
-       __u8            info_rem;
-       __u8            info_loc;
-
-       __u16           segsize_rem;
-       __u16           segsize_loc;
-
-       __u8            nonagle;
-       __u8            multi_ireq;
-       __u8            accept_mode;
-       unsigned long           seg_total; /* Running total of current segment */
-
-       struct optdata_dn     conndata_in;
-       struct optdata_dn     conndata_out;
-       struct optdata_dn     discdata_in;
-       struct optdata_dn     discdata_out;
-        struct accessdata_dn  accessdata;
-
-        struct sockaddr_dn addr; /* Local address  */
-       struct sockaddr_dn peer; /* Remote address */
-
-       /*
-        * In this case the RTT estimation is not specified in the
-        * docs, nor is any back off algorithm. Here we follow well
-        * known tcp algorithms with a few small variations.
-        *
-        * snd_window: Max number of packets we send before we wait for
-        *             an ack to come back. This will become part of a
-        *             more complicated scheme when we support flow
-        *             control.
-        *
-        * nsp_srtt:   Round-Trip-Time (x8) in jiffies. This is a rolling
-        *             average.
-        * nsp_rttvar: Round-Trip-Time-Varience (x4) in jiffies. This is the
-        *             varience of the smoothed average (but calculated in
-        *             a simpler way than for normal statistical varience
-        *             calculations).
-        *
-        * nsp_rxtshift: Backoff counter. Value is zero normally, each time
-        *               a packet is lost is increases by one until an ack
-        *               is received. Its used to index an array of backoff
-        *               multipliers.
-        */
-#define NSP_MIN_WINDOW 1
-#define NSP_MAX_WINDOW (0x07fe)
-       unsigned long max_window;
-       unsigned long snd_window;
-#define NSP_INITIAL_SRTT (HZ)
-       unsigned long nsp_srtt;
-#define NSP_INITIAL_RTTVAR (HZ*3)
-       unsigned long nsp_rttvar;
-#define NSP_MAXRXTSHIFT 12
-       unsigned long nsp_rxtshift;
-
-       /*
-        * Output queues, one for data, one for otherdata/linkservice
-        */
-       struct sk_buff_head data_xmit_queue;
-       struct sk_buff_head other_xmit_queue;
-
-       /*
-        * Input queue for other data
-        */
-       struct sk_buff_head other_receive_queue;
-       int other_report;
-
-       /*
-        * Stuff to do with the slow timer
-        */
-       unsigned long stamp;          /* time of last transmit */
-       unsigned long persist;
-       int (*persist_fxn)(struct sock *sk);
-       unsigned long keepalive;
-       void (*keepalive_fxn)(struct sock *sk);
-
-};
-
-static inline struct dn_scp *DN_SK(struct sock *sk)
-{
-       return (struct dn_scp *)(sk + 1);
-}
-
-/*
- * src,dst : Source and Destination DECnet addresses
- * hops : Number of hops through the network
- * dst_port, src_port : NSP port numbers
- * services, info : Useful data extracted from conninit messages
- * rt_flags : Routing flags byte
- * nsp_flags : NSP layer flags byte
- * segsize : Size of segment
- * segnum : Number, for data, otherdata and linkservice
- * xmit_count : Number of times we've transmitted this skb
- * stamp : Time stamp of most recent transmission, used in RTT calculations
- * iif: Input interface number
- *
- * As a general policy, this structure keeps all addresses in network
- * byte order, and all else in host byte order. Thus dst, src, dst_port
- * and src_port are in network order. All else is in host order.
- * 
- */
-#define DN_SKB_CB(skb) ((struct dn_skb_cb *)(skb)->cb)
-struct dn_skb_cb {
-       __le16 dst;
-       __le16 src;
-       __u16 hops;
-       __le16 dst_port;
-       __le16 src_port;
-       __u8 services;
-       __u8 info;
-       __u8 rt_flags;
-       __u8 nsp_flags;
-       __u16 segsize;
-       __u16 segnum;
-       __u16 xmit_count;
-       unsigned long stamp;
-       int iif;
-};
-
-static inline __le16 dn_eth2dn(const unsigned char *ethaddr)
-{
-       return get_unaligned((__le16 *)(ethaddr + 4));
-}
-
-static inline __le16 dn_saddr2dn(struct sockaddr_dn *saddr)
-{
-       return *(__le16 *)saddr->sdn_nodeaddr;
-}
-
-static inline void dn_dn2eth(unsigned char *ethaddr, __le16 addr)
-{
-       __u16 a = le16_to_cpu(addr);
-       ethaddr[0] = 0xAA;
-       ethaddr[1] = 0x00;
-       ethaddr[2] = 0x04;
-       ethaddr[3] = 0x00;
-       ethaddr[4] = (__u8)(a & 0xff);
-       ethaddr[5] = (__u8)(a >> 8);
-}
-
-static inline void dn_sk_ports_copy(struct flowidn *fld, struct dn_scp *scp)
-{
-       fld->fld_sport = scp->addrloc;
-       fld->fld_dport = scp->addrrem;
-}
-
-unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu);
-void dn_register_sysctl(void);
-void dn_unregister_sysctl(void);
-
-#define DN_MENUVER_ACC 0x01
-#define DN_MENUVER_USR 0x02
-#define DN_MENUVER_PRX 0x04
-#define DN_MENUVER_UIC 0x08
-
-struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr);
-struct sock *dn_find_by_skb(struct sk_buff *skb);
-#define DN_ASCBUF_LEN 9
-char *dn_addr2asc(__u16, char *);
-int dn_destroy_timer(struct sock *sk);
-
-int dn_sockaddr2username(struct sockaddr_dn *addr, unsigned char *buf,
-                        unsigned char type);
-int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *addr,
-                        unsigned char *type);
-
-void dn_start_slow_timer(struct sock *sk);
-void dn_stop_slow_timer(struct sock *sk);
-
-extern __le16 decnet_address;
-extern int decnet_debug_level;
-extern int decnet_time_wait;
-extern int decnet_dn_count;
-extern int decnet_di_count;
-extern int decnet_dr_count;
-extern int decnet_no_fc_max_cwnd;
-
-extern long sysctl_decnet_mem[3];
-extern int sysctl_decnet_wmem[3];
-extern int sysctl_decnet_rmem[3];
-
-#endif /* _NET_DN_H */
diff --git a/include/net/dn_dev.h b/include/net/dn_dev.h
deleted file mode 100644 (file)
index bec303e..0000000
+++ /dev/null
@@ -1,200 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _NET_DN_DEV_H
-#define _NET_DN_DEV_H
-
-#include <linux/netdevice.h>
-
-struct dn_dev;
-
-struct dn_ifaddr {
-       struct dn_ifaddr __rcu *ifa_next;
-       struct dn_dev    *ifa_dev;
-       __le16            ifa_local;
-       __le16            ifa_address;
-       __u32             ifa_flags;
-       __u8              ifa_scope;
-       char              ifa_label[IFNAMSIZ];
-       struct rcu_head   rcu;
-};
-
-#define DN_DEV_S_RU  0 /* Run - working normally   */
-#define DN_DEV_S_CR  1 /* Circuit Rejected         */
-#define DN_DEV_S_DS  2 /* Data Link Start          */
-#define DN_DEV_S_RI  3 /* Routing Layer Initialize */
-#define DN_DEV_S_RV  4 /* Routing Layer Verify     */
-#define DN_DEV_S_RC  5 /* Routing Layer Complete   */
-#define DN_DEV_S_OF  6 /* Off                      */
-#define DN_DEV_S_HA  7 /* Halt                     */
-
-
-/*
- * The dn_dev_parms structure contains the set of parameters
- * for each device (hence inclusion in the dn_dev structure)
- * and an array is used to store the default types of supported
- * device (in dn_dev.c).
- *
- * The type field matches the ARPHRD_ constants and is used in
- * searching the list for supported devices when new devices
- * come up.
- *
- * The mode field is used to find out if a device is broadcast,
- * multipoint, or pointopoint. Please note that DECnet thinks
- * different ways about devices to the rest of the kernel
- * so the normal IFF_xxx flags are invalid here. For devices
- * which can be any combination of the previously mentioned
- * attributes, you can set this on a per device basis by
- * installing an up() routine.
- *
- * The device state field, defines the initial state in which the
- * device will come up. In the dn_dev structure, it is the actual
- * state.
- *
- * Things have changed here. I've killed timer1 since it's a user space
- * issue for a user space routing deamon to sort out. The kernel does
- * not need to be bothered with it.
- *
- * Timers:
- * t2 - Rate limit timer, min time between routing and hello messages
- * t3 - Hello timer, send hello messages when it expires
- *
- * Callbacks:
- * up() - Called to initialize device, return value can veto use of
- *        device with DECnet.
- * down() - Called to turn device off when it goes down
- * timer3() - Called once for each ifaddr when timer 3 goes off
- * 
- * sysctl - Hook for sysctl things
- *
- */
-struct dn_dev_parms {
-       int type;                 /* ARPHRD_xxx                         */
-       int mode;                 /* Broadcast, Unicast, Mulitpoint     */
-#define DN_DEV_BCAST  1
-#define DN_DEV_UCAST  2
-#define DN_DEV_MPOINT 4
-       int state;                /* Initial state                      */
-       int forwarding;           /* 0=EndNode, 1=L1Router, 2=L2Router  */
-       unsigned long t2;         /* Default value of t2                */
-       unsigned long t3;         /* Default value of t3                */
-       int priority;             /* Priority to be a router            */
-       char *name;               /* Name for sysctl                    */
-       int  (*up)(struct net_device *);
-       void (*down)(struct net_device *);
-       void (*timer3)(struct net_device *, struct dn_ifaddr *ifa);
-       void *sysctl;
-};
-
-
-struct dn_dev {
-       struct dn_ifaddr __rcu *ifa_list;
-       struct net_device *dev;
-       struct dn_dev_parms parms;
-       char use_long;
-       struct timer_list timer;
-       unsigned long t3;
-       struct neigh_parms *neigh_parms;
-       __u8 addr[ETH_ALEN];
-       struct neighbour *router; /* Default router on circuit */
-       struct neighbour *peer;   /* Peer on pointopoint links */
-       unsigned long uptime;     /* Time device went up in jiffies */
-};
-
-struct dn_short_packet {
-       __u8    msgflg;
-       __le16 dstnode;
-       __le16 srcnode;
-       __u8   forward;
-} __packed;
-
-struct dn_long_packet {
-       __u8   msgflg;
-       __u8   d_area;
-       __u8   d_subarea;
-       __u8   d_id[6];
-       __u8   s_area;
-       __u8   s_subarea;
-       __u8   s_id[6];
-       __u8   nl2;
-       __u8   visit_ct;
-       __u8   s_class;
-       __u8   pt;
-} __packed;
-
-/*------------------------- DRP - Routing messages ---------------------*/
-
-struct endnode_hello_message {
-       __u8   msgflg;
-       __u8   tiver[3];
-       __u8   id[6];
-       __u8   iinfo;
-       __le16 blksize;
-       __u8   area;
-       __u8   seed[8];
-       __u8   neighbor[6];
-       __le16 timer;
-       __u8   mpd;
-       __u8   datalen;
-       __u8   data[2];
-} __packed;
-
-struct rtnode_hello_message {
-       __u8   msgflg;
-       __u8   tiver[3];
-       __u8   id[6];
-       __u8   iinfo;
-       __le16  blksize;
-       __u8   priority;
-       __u8   area;
-       __le16  timer;
-       __u8   mpd;
-} __packed;
-
-
-void dn_dev_init(void);
-void dn_dev_cleanup(void);
-
-int dn_dev_ioctl(unsigned int cmd, void __user *arg);
-
-void dn_dev_devices_off(void);
-void dn_dev_devices_on(void);
-
-void dn_dev_init_pkt(struct sk_buff *skb);
-void dn_dev_veri_pkt(struct sk_buff *skb);
-void dn_dev_hello(struct sk_buff *skb);
-
-void dn_dev_up(struct net_device *);
-void dn_dev_down(struct net_device *);
-
-int dn_dev_set_default(struct net_device *dev, int force);
-struct net_device *dn_dev_get_default(void);
-int dn_dev_bind_default(__le16 *addr);
-
-int register_dnaddr_notifier(struct notifier_block *nb);
-int unregister_dnaddr_notifier(struct notifier_block *nb);
-
-static inline int dn_dev_islocal(struct net_device *dev, __le16 addr)
-{
-       struct dn_dev *dn_db;
-       struct dn_ifaddr *ifa;
-       int res = 0;
-
-       rcu_read_lock();
-       dn_db = rcu_dereference(dev->dn_ptr);
-       if (dn_db == NULL) {
-               printk(KERN_DEBUG "dn_dev_islocal: Called for non DECnet device\n");
-               goto out;
-       }
-
-       for (ifa = rcu_dereference(dn_db->ifa_list);
-            ifa != NULL;
-            ifa = rcu_dereference(ifa->ifa_next))
-               if ((addr ^ ifa->ifa_local) == 0) {
-                       res = 1;
-                       break;
-               }
-out:
-       rcu_read_unlock();
-       return res;
-}
-
-#endif /* _NET_DN_DEV_H */
diff --git a/include/net/dn_fib.h b/include/net/dn_fib.h
deleted file mode 100644 (file)
index 1929a3c..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _NET_DN_FIB_H
-#define _NET_DN_FIB_H
-
-#include <linux/netlink.h>
-#include <linux/refcount.h>
-#include <linux/rtnetlink.h>
-#include <net/fib_rules.h>
-
-extern const struct nla_policy rtm_dn_policy[];
-
-struct dn_fib_res {
-       struct fib_rule *r;
-       struct dn_fib_info *fi;
-       unsigned char prefixlen;
-       unsigned char nh_sel;
-       unsigned char type;
-       unsigned char scope;
-};
-
-struct dn_fib_nh {
-       struct net_device       *nh_dev;
-       unsigned int            nh_flags;
-       unsigned char           nh_scope;
-       int                     nh_weight;
-       int                     nh_power;
-       int                     nh_oif;
-       __le16                  nh_gw;
-};
-
-struct dn_fib_info {
-       struct dn_fib_info      *fib_next;
-       struct dn_fib_info      *fib_prev;
-       refcount_t              fib_treeref;
-       refcount_t              fib_clntref;
-       int                     fib_dead;
-       unsigned int            fib_flags;
-       int                     fib_protocol;
-       __le16                  fib_prefsrc;
-       __u32                   fib_priority;
-       __u32                   fib_metrics[RTAX_MAX];
-       int                     fib_nhs;
-       int                     fib_power;
-       struct dn_fib_nh        fib_nh[0];
-#define dn_fib_dev             fib_nh[0].nh_dev
-};
-
-
-#define DN_FIB_RES_RESET(res)  ((res).nh_sel = 0)
-#define DN_FIB_RES_NH(res)     ((res).fi->fib_nh[(res).nh_sel])
-
-#define DN_FIB_RES_PREFSRC(res)        ((res).fi->fib_prefsrc ? : __dn_fib_res_prefsrc(&res))
-#define DN_FIB_RES_GW(res)     (DN_FIB_RES_NH(res).nh_gw)
-#define DN_FIB_RES_DEV(res)    (DN_FIB_RES_NH(res).nh_dev)
-#define DN_FIB_RES_OIF(res)    (DN_FIB_RES_NH(res).nh_oif)
-
-typedef struct {
-       __le16  datum;
-} dn_fib_key_t;
-
-typedef struct {
-       __le16  datum;
-} dn_fib_hash_t;
-
-typedef struct {
-       __u16   datum;
-} dn_fib_idx_t;
-
-struct dn_fib_node {
-       struct dn_fib_node *fn_next;
-       struct dn_fib_info *fn_info;
-#define DN_FIB_INFO(f) ((f)->fn_info)
-       dn_fib_key_t    fn_key;
-       u8              fn_type;
-       u8              fn_scope;
-       u8              fn_state;
-};
-
-
-struct dn_fib_table {
-       struct hlist_node hlist;
-       u32 n;
-
-       int (*insert)(struct dn_fib_table *t, struct rtmsg *r, 
-                       struct nlattr *attrs[], struct nlmsghdr *n,
-                       struct netlink_skb_parms *req);
-       int (*delete)(struct dn_fib_table *t, struct rtmsg *r,
-                       struct nlattr *attrs[], struct nlmsghdr *n,
-                       struct netlink_skb_parms *req);
-       int (*lookup)(struct dn_fib_table *t, const struct flowidn *fld,
-                       struct dn_fib_res *res);
-       int (*flush)(struct dn_fib_table *t);
-       int (*dump)(struct dn_fib_table *t, struct sk_buff *skb, struct netlink_callback *cb);
-
-       unsigned char data[];
-};
-
-#ifdef CONFIG_DECNET_ROUTER
-/*
- * dn_fib.c
- */
-void dn_fib_init(void);
-void dn_fib_cleanup(void);
-
-int dn_fib_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg);
-struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r,
-                                      struct nlattr *attrs[],
-                                      const struct nlmsghdr *nlh, int *errp);
-int dn_fib_semantic_match(int type, struct dn_fib_info *fi,
-                         const struct flowidn *fld, struct dn_fib_res *res);
-void dn_fib_release_info(struct dn_fib_info *fi);
-void dn_fib_flush(void);
-void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res);
-
-/*
- * dn_tables.c
- */
-struct dn_fib_table *dn_fib_get_table(u32 n, int creat);
-struct dn_fib_table *dn_fib_empty_table(void);
-void dn_fib_table_init(void);
-void dn_fib_table_cleanup(void);
-
-/*
- * dn_rules.c
- */
-void dn_fib_rules_init(void);
-void dn_fib_rules_cleanup(void);
-unsigned int dnet_addr_type(__le16 addr);
-int dn_fib_lookup(struct flowidn *fld, struct dn_fib_res *res);
-
-int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb);
-
-void dn_fib_free_info(struct dn_fib_info *fi);
-
-static inline void dn_fib_info_put(struct dn_fib_info *fi)
-{
-       if (refcount_dec_and_test(&fi->fib_clntref))
-               dn_fib_free_info(fi);
-}
-
-static inline void dn_fib_res_put(struct dn_fib_res *res)
-{
-       if (res->fi)
-               dn_fib_info_put(res->fi);
-       if (res->r)
-               fib_rule_put(res->r);
-}
-
-#else /* Endnode */
-
-#define dn_fib_init()  do { } while(0)
-#define dn_fib_cleanup() do { } while(0)
-
-#define dn_fib_lookup(fl, res) (-ESRCH)
-#define dn_fib_info_put(fi) do { } while(0)
-#define dn_fib_select_multipath(fl, res) do { } while(0)
-#define dn_fib_rules_policy(saddr,res,flags) (0)
-#define dn_fib_res_put(res) do { } while(0)
-
-#endif /* CONFIG_DECNET_ROUTER */
-
-static inline __le16 dnet_make_mask(int n)
-{
-       if (n)
-               return cpu_to_le16(~((1 << (16 - n)) - 1));
-       return cpu_to_le16(0);
-}
-
-#endif /* _NET_DN_FIB_H */
diff --git a/include/net/dn_neigh.h b/include/net/dn_neigh.h
deleted file mode 100644 (file)
index 1f7df98..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _NET_DN_NEIGH_H
-#define _NET_DN_NEIGH_H
-
-#include <net/neighbour.h>
-
-/*
- * The position of the first two fields of
- * this structure are critical - SJW
- */
-struct dn_neigh {
-        struct neighbour n;
-       __le16 addr;
-        unsigned long flags;
-#define DN_NDFLAG_R1    0x0001 /* Router L1      */
-#define DN_NDFLAG_R2    0x0002 /* Router L2      */
-#define DN_NDFLAG_P3    0x0004 /* Phase III Node */
-        unsigned long blksize;
-       __u8 priority;
-};
-
-void dn_neigh_init(void);
-void dn_neigh_cleanup(void);
-int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb);
-int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb);
-void dn_neigh_pointopoint_hello(struct sk_buff *skb);
-int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n);
-int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb);
-
-extern struct neigh_table dn_neigh_table;
-
-#endif /* _NET_DN_NEIGH_H */
diff --git a/include/net/dn_nsp.h b/include/net/dn_nsp.h
deleted file mode 100644 (file)
index a4a18fe..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _NET_DN_NSP_H
-#define _NET_DN_NSP_H
-/******************************************************************************
-    (c) 1995-1998 E.M. Serrat          emserrat@geocities.com
-    
-*******************************************************************************/
-/* dn_nsp.c functions prototyping */
-#include <linux/atomic.h>
-#include <linux/types.h>
-#include <net/sock.h>
-
-struct sk_buff;
-struct sk_buff_head;
-
-void dn_nsp_send_data_ack(struct sock *sk);
-void dn_nsp_send_oth_ack(struct sock *sk);
-void dn_send_conn_ack(struct sock *sk);
-void dn_send_conn_conf(struct sock *sk, gfp_t gfp);
-void dn_nsp_send_disc(struct sock *sk, unsigned char type,
-                     unsigned short reason, gfp_t gfp);
-void dn_nsp_return_disc(struct sk_buff *skb, unsigned char type,
-                       unsigned short reason);
-void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval);
-void dn_nsp_send_conninit(struct sock *sk, unsigned char flags);
-
-void dn_nsp_output(struct sock *sk);
-int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb,
-                           struct sk_buff_head *q, unsigned short acknum);
-void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb, gfp_t gfp,
-                      int oob);
-unsigned long dn_nsp_persist(struct sock *sk);
-int dn_nsp_xmit_timeout(struct sock *sk);
-
-int dn_nsp_rx(struct sk_buff *);
-int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb);
-
-struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
-struct sk_buff *dn_alloc_send_skb(struct sock *sk, size_t *size, int noblock,
-                                 long timeo, int *err);
-
-#define NSP_REASON_OK 0                /* No error */
-#define NSP_REASON_NR 1                /* No resources */
-#define NSP_REASON_UN 2                /* Unrecognised node name */
-#define NSP_REASON_SD 3                /* Node shutting down */
-#define NSP_REASON_ID 4                /* Invalid destination end user */
-#define NSP_REASON_ER 5                /* End user lacks resources */
-#define NSP_REASON_OB 6                /* Object too busy */
-#define NSP_REASON_US 7                /* Unspecified error */
-#define NSP_REASON_TP 8                /* Third-Party abort */
-#define NSP_REASON_EA 9                /* End user has aborted the link */
-#define NSP_REASON_IF 10       /* Invalid node name format */
-#define NSP_REASON_LS 11       /* Local node shutdown */
-#define NSP_REASON_LL 32       /* Node lacks logical-link resources */
-#define NSP_REASON_LE 33       /* End user lacks logical-link resources */
-#define NSP_REASON_UR 34       /* Unacceptable RQSTRID or PASSWORD field */
-#define NSP_REASON_UA 36       /* Unacceptable ACCOUNT field */
-#define NSP_REASON_TM 38       /* End user timed out logical link */
-#define NSP_REASON_NU 39       /* Node unreachable */
-#define NSP_REASON_NL 41       /* No-link message */
-#define NSP_REASON_DC 42       /* Disconnect confirm */
-#define NSP_REASON_IO 43       /* Image data field overflow */
-
-#define NSP_DISCINIT 0x38
-#define NSP_DISCCONF 0x48
-
-/*------------------------- NSP - messages ------------------------------*/
-/* Data Messages */
-/*---------------*/
-
-/* Data Messages    (data segment/interrupt/link service)               */
-
-struct nsp_data_seg_msg {
-       __u8   msgflg;
-       __le16 dstaddr;
-       __le16 srcaddr;
-} __packed;
-
-struct nsp_data_opt_msg {
-       __le16 acknum;
-       __le16 segnum;
-       __le16 lsflgs;
-} __packed;
-
-struct nsp_data_opt_msg1 {
-       __le16 acknum;
-       __le16 segnum;
-} __packed;
-
-
-/* Acknowledgment Message (data/other data)                             */
-struct nsp_data_ack_msg {
-       __u8   msgflg;
-       __le16 dstaddr;
-       __le16 srcaddr;
-       __le16 acknum;
-} __packed;
-
-/* Connect Acknowledgment Message */
-struct  nsp_conn_ack_msg {
-       __u8 msgflg;
-       __le16 dstaddr;
-} __packed;
-
-
-/* Connect Initiate/Retransmit Initiate/Connect Confirm */
-struct  nsp_conn_init_msg {
-       __u8   msgflg;
-#define NSP_CI      0x18            /* Connect Initiate     */
-#define NSP_RCI     0x68            /* Retrans. Conn Init   */
-       __le16 dstaddr;
-       __le16 srcaddr;
-       __u8   services;
-#define NSP_FC_NONE   0x00            /* Flow Control None    */
-#define NSP_FC_SRC    0x04            /* Seg Req. Count       */
-#define NSP_FC_SCMC   0x08            /* Sess. Control Mess   */
-#define NSP_FC_MASK   0x0c            /* FC type mask         */
-       __u8   info;
-       __le16 segsize;
-} __packed;
-
-/* Disconnect Initiate/Disconnect Confirm */
-struct  nsp_disconn_init_msg {
-       __u8   msgflg;
-       __le16 dstaddr;
-       __le16 srcaddr;
-       __le16 reason;
-} __packed;
-
-
-
-struct  srcobj_fmt {
-       __u8   format;
-       __u8   task;
-       __le16 grpcode;
-       __le16 usrcode;
-       __u8   dlen;
-} __packed;
-
-/*
- * A collection of functions for manipulating the sequence
- * numbers used in NSP. Similar in operation to the functions
- * of the same name in TCP.
- */
-static __inline__ int dn_before(__u16 seq1, __u16 seq2)
-{
-        seq1 &= 0x0fff;
-        seq2 &= 0x0fff;
-
-        return (int)((seq1 - seq2) & 0x0fff) > 2048;
-}
-
-
-static __inline__ int dn_after(__u16 seq1, __u16 seq2)
-{
-        seq1 &= 0x0fff;
-        seq2 &= 0x0fff;
-
-        return (int)((seq2 - seq1) & 0x0fff) > 2048;
-}
-
-static __inline__ int dn_equal(__u16 seq1, __u16 seq2)
-{
-        return ((seq1 ^ seq2) & 0x0fff) == 0;
-}
-
-static __inline__ int dn_before_or_equal(__u16 seq1, __u16 seq2)
-{
-       return (dn_before(seq1, seq2) || dn_equal(seq1, seq2));
-}
-
-static __inline__ void seq_add(__u16 *seq, __u16 off)
-{
-        (*seq) += off;
-        (*seq) &= 0x0fff;
-}
-
-static __inline__ int seq_next(__u16 seq1, __u16 seq2)
-{
-       return dn_equal(seq1 + 1, seq2);
-}
-
-/*
- * Can we delay the ack ?
- */
-static __inline__ int sendack(__u16 seq)
-{
-        return (int)((seq & 0x1000) ? 0 : 1);
-}
-
-/*
- * Is socket congested ?
- */
-static __inline__ int dn_congested(struct sock *sk)
-{
-        return atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1);
-}
-
-#define DN_MAX_NSP_DATA_HEADER (11)
-
-#endif /* _NET_DN_NSP_H */
diff --git a/include/net/dn_route.h b/include/net/dn_route.h
deleted file mode 100644 (file)
index 88c0300..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-#ifndef _NET_DN_ROUTE_H
-#define _NET_DN_ROUTE_H
-
-/******************************************************************************
-    (c) 1995-1998 E.M. Serrat          emserrat@geocities.com
-    
-*******************************************************************************/
-
-#include <linux/types.h>
-#include <net/dst.h>
-
-struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri);
-int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *,
-                        struct sock *sk, int flags);
-int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb);
-void dn_rt_cache_flush(int delay);
-int dn_route_rcv(struct sk_buff *skb, struct net_device *dev,
-                struct packet_type *pt, struct net_device *orig_dev);
-
-/* Masks for flags field */
-#define DN_RT_F_PID 0x07 /* Mask for packet type                      */
-#define DN_RT_F_PF  0x80 /* Padding Follows                           */
-#define DN_RT_F_VER 0x40 /* Version =0 discard packet if ==1          */
-#define DN_RT_F_IE  0x20 /* Intra Ethernet, Reserved in short pkt     */
-#define DN_RT_F_RTS 0x10 /* Packet is being returned to sender        */
-#define DN_RT_F_RQR 0x08 /* Return packet to sender upon non-delivery */
-
-/* Mask for types of routing packets */
-#define DN_RT_PKT_MSK   0x06
-/* Types of routing packets */
-#define DN_RT_PKT_SHORT 0x02 /* Short routing packet */
-#define DN_RT_PKT_LONG  0x06 /* Long routing packet  */
-
-/* Mask for control/routing selection */
-#define DN_RT_PKT_CNTL  0x01 /* Set to 1 if a control packet  */
-/* Types of control packets */
-#define DN_RT_CNTL_MSK  0x0f /* Mask for control packets      */
-#define DN_RT_PKT_INIT  0x01 /* Initialisation packet         */
-#define DN_RT_PKT_VERI  0x03 /* Verification Message          */
-#define DN_RT_PKT_HELO  0x05 /* Hello and Test Message        */
-#define DN_RT_PKT_L1RT  0x07 /* Level 1 Routing Message       */
-#define DN_RT_PKT_L2RT  0x09 /* Level 2 Routing Message       */
-#define DN_RT_PKT_ERTH  0x0b /* Ethernet Router Hello         */
-#define DN_RT_PKT_EEDH  0x0d /* Ethernet EndNode Hello        */
-
-/* Values for info field in hello message */
-#define DN_RT_INFO_TYPE 0x03 /* Type mask                     */
-#define DN_RT_INFO_L1RT 0x02 /* L1 Router                     */
-#define DN_RT_INFO_L2RT 0x01 /* L2 Router                     */
-#define DN_RT_INFO_ENDN 0x03 /* EndNode                       */
-#define DN_RT_INFO_VERI 0x04 /* Verification Reqd.            */
-#define DN_RT_INFO_RJCT 0x08 /* Reject Flag, Reserved         */
-#define DN_RT_INFO_VFLD 0x10 /* Verification Failed, Reserved */
-#define DN_RT_INFO_NOML 0x20 /* No Multicast traffic accepted */
-#define DN_RT_INFO_BLKR 0x40 /* Blocking Requested            */
-
-/*
- * The fl structure is what we used to look up the route.
- * The rt_saddr & rt_daddr entries are the same as key.saddr & key.daddr
- * except for local input routes, where the rt_saddr = fl.fld_dst and
- * rt_daddr = fl.fld_src to allow the route to be used for returning
- * packets to the originating host.
- */
-struct dn_route {
-       struct dst_entry dst;
-       struct dn_route __rcu *dn_next;
-
-       struct neighbour *n;
-
-       struct flowidn fld;
-
-       __le16 rt_saddr;
-       __le16 rt_daddr;
-       __le16 rt_gateway;
-       __le16 rt_local_src;    /* Source used for forwarding packets */
-       __le16 rt_src_map;
-       __le16 rt_dst_map;
-
-       unsigned int rt_flags;
-       unsigned int rt_type;
-};
-
-static inline bool dn_is_input_route(struct dn_route *rt)
-{
-       return rt->fld.flowidn_iif != 0;
-}
-
-static inline bool dn_is_output_route(struct dn_route *rt)
-{
-       return rt->fld.flowidn_iif == 0;
-}
-
-void dn_route_init(void);
-void dn_route_cleanup(void);
-
-#include <net/sock.h>
-#include <linux/if_arp.h>
-
-static inline void dn_rt_send(struct sk_buff *skb)
-{
-       dev_queue_xmit(skb);
-}
-
-static inline void dn_rt_finish_output(struct sk_buff *skb, char *dst, char *src)
-{
-       struct net_device *dev = skb->dev;
-
-       if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
-               dst = NULL;
-
-       if (dev_hard_header(skb, dev, ETH_P_DNA_RT, dst, src, skb->len) >= 0)
-               dn_rt_send(skb);
-       else
-               kfree_skb(skb);
-}
-
-#endif /* _NET_DN_ROUTE_H */
index b902b31..f2ce128 100644 (file)
@@ -559,6 +559,10 @@ static inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
        list_for_each_entry((_dp), &(_dst)->ports, list) \
                if (dsa_port_is_user((_dp)))
 
+#define dsa_tree_for_each_cpu_port(_dp, _dst) \
+       list_for_each_entry((_dp), &(_dst)->ports, list) \
+               if (dsa_port_is_cpu((_dp)))
+
 #define dsa_switch_for_each_port(_dp, _ds) \
        list_for_each_entry((_dp), &(_ds)->dst->ports, list) \
                if ((_dp)->ds == (_ds))
index 56a50e1..8f78017 100644 (file)
@@ -39,6 +39,8 @@ struct genl_info;
  *     undo operations done by pre_doit, for example release locks
  * @mcgrps: multicast groups used by this family
  * @n_mcgrps: number of multicast groups
+ * @resv_start_op: first operation for which reserved fields of the header
+ *     can be validated, new families should leave this field at zero
  * @mcgrp_offset: starting number of multicast group IDs in this family
  *     (private)
  * @ops: the operations supported by this family
@@ -58,6 +60,7 @@ struct genl_family {
        u8                      n_ops;
        u8                      n_small_ops;
        u8                      n_mcgrps;
+       u8                      resv_start_op;
        const struct nla_policy *policy;
        int                     (*pre_doit)(const struct genl_ops *ops,
                                            struct sk_buff *skb,
@@ -107,6 +110,13 @@ static inline void genl_info_net_set(struct genl_info *info, struct net *net)
 
 #define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG((info)->extack, msg)
 
+/* Report that a root attribute is missing */
+#define GENL_REQ_ATTR_CHECK(info, attr) ({                             \
+       struct genl_info *__info = (info);                              \
+                                                                       \
+       NL_REQ_ATTR_CHECK(__info->extack, NULL, __info->attrs, (attr)); \
+})
+
 enum genl_validate_flags {
        GENL_DONT_VALIDATE_STRICT               = BIT(0),
        GENL_DONT_VALIDATE_DUMP                 = BIT(1),
index 24003de..a4fab70 100644 (file)
@@ -160,6 +160,17 @@ static inline void *skb_gro_header_slow(struct sk_buff *skb, unsigned int hlen,
        return skb->data + offset;
 }
 
+static inline void *skb_gro_header(struct sk_buff *skb,
+                                       unsigned int hlen, unsigned int offset)
+{
+       void *ptr;
+
+       ptr = skb_gro_header_fast(skb, offset);
+       if (skb_gro_header_hard(skb, hlen))
+               ptr = skb_gro_header_slow(skb, hlen, offset);
+       return ptr;
+}
+
 static inline void *skb_gro_network_header(struct sk_buff *skb)
 {
        return (NAPI_GRO_CB(skb)->frag0 ?: skb->data) +
@@ -301,12 +312,9 @@ static inline void *skb_gro_remcsum_process(struct sk_buff *skb, void *ptr,
                return ptr;
        }
 
-       ptr = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, off + plen)) {
-               ptr = skb_gro_header_slow(skb, off + plen, off);
-               if (!ptr)
-                       return NULL;
-       }
+       ptr = skb_gro_header(skb, off + plen, off);
+       if (!ptr)
+               return NULL;
 
        delta = remcsum_adjust(ptr + hdrlen, NAPI_GRO_CB(skb)->csum,
                               start, offset);
@@ -329,12 +337,9 @@ static inline void skb_gro_remcsum_cleanup(struct sk_buff *skb,
        if (!grc->delta)
                return;
 
-       ptr = skb_gro_header_fast(skb, grc->offset);
-       if (skb_gro_header_hard(skb, grc->offset + sizeof(u16))) {
-               ptr = skb_gro_header_slow(skb, plen, grc->offset);
-               if (!ptr)
-                       return;
-       }
+       ptr = skb_gro_header(skb, plen, grc->offset);
+       if (!ptr)
+               return;
 
        remcsum_unadjust((__sum16 *)ptr, grc->delta);
 }
@@ -405,9 +410,7 @@ static inline struct udphdr *udp_gro_udphdr(struct sk_buff *skb)
 
        off  = skb_gro_offset(skb);
        hlen = off + sizeof(*uh);
-       uh   = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, hlen))
-               uh = skb_gro_header_slow(skb, hlen, off);
+       uh   = skb_gro_header(skb, hlen, off);
 
        return uh;
 }
index ee88f0f..c2b15f7 100644 (file)
@@ -25,6 +25,7 @@
 #undef INET_CSK_CLEAR_TIMERS
 
 struct inet_bind_bucket;
+struct inet_bind2_bucket;
 struct tcp_congestion_ops;
 
 /*
@@ -57,6 +58,7 @@ struct inet_connection_sock_af_ops {
  *
  * @icsk_accept_queue:    FIFO of established children
  * @icsk_bind_hash:       Bind node
+ * @icsk_bind2_hash:      Bind node in the bhash2 table
  * @icsk_timeout:         Timeout
  * @icsk_retransmit_timer: Resend (no ack)
  * @icsk_rto:             Retransmit timeout
@@ -83,6 +85,7 @@ struct inet_connection_sock {
        struct inet_sock          icsk_inet;
        struct request_sock_queue icsk_accept_queue;
        struct inet_bind_bucket   *icsk_bind_hash;
+       struct inet_bind2_bucket  *icsk_bind2_hash;
        unsigned long             icsk_timeout;
        struct timer_list         icsk_retransmit_timer;
        struct timer_list         icsk_delack_timer;
index e9cf215..44a419b 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <net/inet_connection_sock.h>
 #include <net/inet_sock.h>
+#include <net/ip.h>
 #include <net/sock.h>
 #include <net/route.h>
 #include <net/tcp_states.h>
@@ -90,7 +91,28 @@ struct inet_bind_bucket {
        struct hlist_head       owners;
 };
 
-static inline struct net *ib_net(struct inet_bind_bucket *ib)
+struct inet_bind2_bucket {
+       possible_net_t          ib_net;
+       int                     l3mdev;
+       unsigned short          port;
+       union {
+#if IS_ENABLED(CONFIG_IPV6)
+               struct in6_addr         v6_rcv_saddr;
+#endif
+               __be32                  rcv_saddr;
+       };
+       /* Node in the bhash2 inet_bind_hashbucket chain */
+       struct hlist_node       node;
+       /* List of sockets hashed to this bucket */
+       struct hlist_head       owners;
+};
+
+static inline struct net *ib_net(const struct inet_bind_bucket *ib)
+{
+       return read_pnet(&ib->ib_net);
+}
+
+static inline struct net *ib2_net(const struct inet_bind2_bucket *ib)
 {
        return read_pnet(&ib->ib_net);
 }
@@ -133,7 +155,14 @@ struct inet_hashinfo {
         * TCP hash as well as the others for fast bind/connect.
         */
        struct kmem_cache               *bind_bucket_cachep;
+       /* This bind table is hashed by local port */
        struct inet_bind_hashbucket     *bhash;
+       struct kmem_cache               *bind2_bucket_cachep;
+       /* This bind table is hashed by local port and sk->sk_rcv_saddr (ipv4)
+        * or sk->sk_v6_rcv_saddr (ipv6). This 2nd bind table is used
+        * primarily for expediting bind conflict resolution.
+        */
+       struct inet_bind_hashbucket     *bhash2;
        unsigned int                    bhash_size;
 
        /* The 2nd listener table hashed by local port and address */
@@ -182,14 +211,61 @@ inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
 void inet_bind_bucket_destroy(struct kmem_cache *cachep,
                              struct inet_bind_bucket *tb);
 
+bool inet_bind_bucket_match(const struct inet_bind_bucket *tb,
+                           const struct net *net, unsigned short port,
+                           int l3mdev);
+
+struct inet_bind2_bucket *
+inet_bind2_bucket_create(struct kmem_cache *cachep, struct net *net,
+                        struct inet_bind_hashbucket *head,
+                        unsigned short port, int l3mdev,
+                        const struct sock *sk);
+
+void inet_bind2_bucket_destroy(struct kmem_cache *cachep,
+                              struct inet_bind2_bucket *tb);
+
+struct inet_bind2_bucket *
+inet_bind2_bucket_find(const struct inet_bind_hashbucket *head,
+                      const struct net *net,
+                      unsigned short port, int l3mdev,
+                      const struct sock *sk);
+
+bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb,
+                                     const struct net *net, unsigned short port,
+                                     int l3mdev, const struct sock *sk);
+
 static inline u32 inet_bhashfn(const struct net *net, const __u16 lport,
                               const u32 bhash_size)
 {
        return (lport + net_hash_mix(net)) & (bhash_size - 1);
 }
 
+static inline struct inet_bind_hashbucket *
+inet_bhashfn_portaddr(const struct inet_hashinfo *hinfo, const struct sock *sk,
+                     const struct net *net, unsigned short port)
+{
+       u32 hash;
+
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               hash = ipv6_portaddr_hash(net, &sk->sk_v6_rcv_saddr, port);
+       else
+#endif
+               hash = ipv4_portaddr_hash(net, sk->sk_rcv_saddr, port);
+       return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)];
+}
+
+struct inet_bind_hashbucket *
+inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port);
+
+/* This should be called whenever a socket's sk_rcv_saddr (ipv4) or
+ * sk_v6_rcv_saddr (ipv6) changes after it has been binded. The socket's
+ * rcv_saddr field should already have been updated when this is called.
+ */
+int inet_bhash2_update_saddr(struct inet_bind_hashbucket *prev_saddr, struct sock *sk);
+
 void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
-                   const unsigned short snum);
+                   struct inet_bind2_bucket *tb2, unsigned short port);
 
 /* Caller must disable local BH processing. */
 int __inet_inherit_port(const struct sock *sk, struct sock *child);
index 63fac94..ced80e2 100644 (file)
@@ -246,7 +246,8 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
                                       __be32 daddr, __be32 saddr,
                                       __be32 key, __u8 tos,
                                       struct net *net, int oif,
-                                      __u32 mark, __u32 tun_inner_hash)
+                                      __u32 mark, __u32 tun_inner_hash,
+                                      __u8 flow_flags)
 {
        memset(fl4, 0, sizeof(*fl4));
 
@@ -263,6 +264,7 @@ static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
        fl4->fl4_gre_key = key;
        fl4->flowi4_mark = mark;
        fl4->flowi4_multipath_hash = tun_inner_hash;
+       fl4->flowi4_flags = flow_flags;
 }
 
 int ip_tunnel_init(struct net_device *dev);
index f198af6..ffd0ebb 100644 (file)
@@ -1480,6 +1480,10 @@ enum mac80211_rx_encoding {
  *     each A-MPDU but the same for each subframe within one A-MPDU
  * @ampdu_delimiter_crc: A-MPDU delimiter CRC
  * @zero_length_psdu_type: radiotap type of the 0-length PSDU
+ * @link_valid: if the link which is identified by @link_id is valid. This flag
+ *     is set only when connection is MLO.
+ * @link_id: id of the link used to receive the packet. This is used along with
+ *     @link_valid.
  */
 struct ieee80211_rx_status {
        u64 mactime;
@@ -1504,6 +1508,7 @@ struct ieee80211_rx_status {
        s8 chain_signal[IEEE80211_MAX_CHAINS];
        u8 ampdu_delimiter_crc;
        u8 zero_length_psdu_type;
+       u8 link_valid:1, link_id:4;
 };
 
 static inline u32
@@ -1975,6 +1980,7 @@ enum ieee80211_key_flags {
  *     - Temporal Authenticator Rx MIC Key (64 bits)
  * @icv_len: The ICV length for this key type
  * @iv_len: The IV length for this key type
+ * @link_id: the link ID for MLO, or -1 for non-MLO or pairwise keys
  */
 struct ieee80211_key_conf {
        atomic64_t tx_pn;
@@ -1984,6 +1990,7 @@ struct ieee80211_key_conf {
        u8 hw_key_idx;
        s8 keyidx;
        u16 flags;
+       s8 link_id;
        u8 keylen;
        u8 key[];
 };
@@ -2128,6 +2135,7 @@ struct ieee80211_sta_txpwr {
  * @addr: MAC address of the Link STA. For non-MLO STA this is same as the addr
  *     in ieee80211_sta. For MLO Link STA this addr can be same or different
  *     from addr in ieee80211_sta (representing MLD STA addr)
+ * @link_id: the link ID for this link STA (0 for deflink)
  * @supp_rates: Bitmap of supported rates
  * @ht_cap: HT capabilities of this STA; restricted to our own capabilities
  * @vht_cap: VHT capabilities of this STA; restricted to our own capabilities
@@ -2144,6 +2152,7 @@ struct ieee80211_sta_txpwr {
  */
 struct ieee80211_link_sta {
        u8 addr[ETH_ALEN];
+       u8 link_id;
 
        u32 supp_rates[NUM_NL80211_BANDS];
        struct ieee80211_sta_ht_cap ht_cap;
index d6fa6b9..73780aa 100644 (file)
@@ -14,7 +14,6 @@
 #define MACSEC_DEFAULT_PN_LEN 4
 #define MACSEC_XPN_PN_LEN 8
 
-#define MACSEC_SALT_LEN 12
 #define MACSEC_NUM_AN 4 /* 2 bits for the association number */
 
 typedef u64 __bitwise sci_t;
index 3cd3a6e..b2b9de7 100644 (file)
@@ -86,10 +86,6 @@ extern spinlock_t nf_conntrack_expect_lock;
 
 /* ctnetlink code shared by both ctnetlink and nf_conntrack_bpf */
 
-#if (IS_BUILTIN(CONFIG_NF_CONNTRACK) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) || \
-    (IS_MODULE(CONFIG_NF_CONNTRACK) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES) || \
-    IS_ENABLED(CONFIG_NF_CT_NETLINK))
-
 static inline void __nf_ct_set_timeout(struct nf_conn *ct, u64 timeout)
 {
        if (timeout > INT_MAX)
@@ -101,6 +97,4 @@ int __nf_ct_change_timeout(struct nf_conn *ct, u64 cta_timeout);
 void __nf_ct_change_status(struct nf_conn *ct, unsigned long on, unsigned long off);
 int nf_ct_change_status_common(struct nf_conn *ct, unsigned int status);
 
-#endif
-
 #endif /* _NF_CONNTRACK_CORE_H */
index 7a2a9d3..e658d18 100644 (file)
@@ -741,6 +741,7 @@ static inline int __nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
  * @hdrlen: length of family specific header
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
  * @extack: extended ACK report struct
  *
  * See nla_parse()
@@ -760,6 +761,7 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
  * @hdrlen: length of family specific header
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
  * @extack: extended ACK report struct
  *
  * See nla_parse_deprecated()
@@ -779,6 +781,7 @@ static inline int nlmsg_parse_deprecated(const struct nlmsghdr *nlh, int hdrlen,
  * @hdrlen: length of family specific header
  * @tb: destination array with maxtype+1 elements
  * @maxtype: maximum attribute type to be expected
+ * @policy: validation policy
  * @extack: extended ACK report struct
  *
  * See nla_parse_deprecated_strict()
@@ -814,7 +817,6 @@ static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh,
  * @len: length of attribute stream
  * @maxtype: maximum attribute type to be expected
  * @policy: validation policy
- * @validate: validation strictness
  * @extack: extended ACK report struct
  *
  * Validates all attributes in the specified attribute stream against the
index c7320ef..6320a76 100644 (file)
@@ -179,6 +179,8 @@ struct netns_ipv4 {
        unsigned int sysctl_tcp_fastopen_blackhole_timeout;
        atomic_t tfo_active_disable_times;
        unsigned long tfo_active_disable_stamp;
+       u32 tcp_challenge_timestamp;
+       u32 tcp_challenge_count;
 
        int sysctl_udp_wmem_min;
        int sysctl_udp_rmem_min;
index b593f95..02bbdc5 100644 (file)
@@ -24,9 +24,6 @@ struct netns_nf {
 #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
        struct nf_hook_entries __rcu *hooks_bridge[NF_INET_NUMHOOKS];
 #endif
-#if IS_ENABLED(CONFIG_DECNET)
-       struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS];
-#endif
 #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
        unsigned int defrag_ipv4_users;
 #endif
index 145acb8..f5850b5 100644 (file)
@@ -58,9 +58,6 @@ enum nl802154_commands {
 
        NL802154_CMD_SET_WPAN_PHY_NETNS,
 
-       /* add new commands above here */
-
-#ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL
        NL802154_CMD_SET_SEC_PARAMS,
        NL802154_CMD_GET_SEC_KEY,               /* can dump */
        NL802154_CMD_NEW_SEC_KEY,
@@ -74,7 +71,8 @@ enum nl802154_commands {
        NL802154_CMD_GET_SEC_LEVEL,             /* can dump */
        NL802154_CMD_NEW_SEC_LEVEL,
        NL802154_CMD_DEL_SEC_LEVEL,
-#endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */
+
+       /* add new commands above here */
 
        /* used to define NL802154_CMD_MAX below */
        __NL802154_CMD_AFTER_LAST,
index 3372a1f..29f6563 100644 (file)
@@ -100,7 +100,7 @@ struct Qdisc *fifo_create_dflt(struct Qdisc *sch, struct Qdisc_ops *ops,
                               struct netlink_ext_ack *extack);
 
 int register_qdisc(struct Qdisc_ops *qops);
-int unregister_qdisc(struct Qdisc_ops *qops);
+void unregister_qdisc(struct Qdisc_ops *qops);
 void qdisc_get_default(char *id, size_t len);
 int qdisc_set_default(const char *id);
 
index be11dbd..454ac2b 100644 (file)
@@ -122,7 +122,6 @@ struct red_stats {
        u32             forced_drop;    /* Forced drops, qavg > max_thresh */
        u32             forced_mark;    /* Forced marks, qavg > max_thresh */
        u32             pdrop;          /* Drops due to queue limits */
-       u32             other;          /* Drops due to drop() calls */
 };
 
 struct red_parms {
index ec693fe..7dc8340 100644 (file)
@@ -940,13 +940,6 @@ static inline void qdisc_purge_queue(struct Qdisc *sch)
        qdisc_tree_reduce_backlog(sch, qlen, backlog);
 }
 
-static inline void qdisc_skb_head_init(struct qdisc_skb_head *qh)
-{
-       qh->head = NULL;
-       qh->tail = NULL;
-       qh->qlen = 0;
-}
-
 static inline void __qdisc_enqueue_tail(struct sk_buff *skb,
                                        struct qdisc_skb_head *qh)
 {
@@ -1137,7 +1130,6 @@ static inline void __qdisc_reset_queue(struct qdisc_skb_head *qh)
 static inline void qdisc_reset_queue(struct Qdisc *sch)
 {
        __qdisc_reset_queue(&sch->q);
-       sch->qstats.backlog = 0;
 }
 
 static inline struct Qdisc *qdisc_replace(struct Qdisc *sch, struct Qdisc *new,
index d08cfe1..ca46998 100644 (file)
@@ -348,6 +348,7 @@ struct sk_filter;
   *    @sk_txtime_report_errors: set report errors mode for SO_TXTIME
   *    @sk_txtime_unused: unused txtime flags
   *    @ns_tracker: tracker for netns reference
+  *    @sk_bind2_node: bind node in the bhash2 table
   */
 struct sock {
        /*
@@ -537,6 +538,7 @@ struct sock {
 #endif
        struct rcu_head         sk_rcu;
        netns_tracker           ns_tracker;
+       struct hlist_node       sk_bind2_node;
 };
 
 enum sk_pacing {
@@ -870,6 +872,16 @@ static inline void sk_add_bind_node(struct sock *sk,
        hlist_add_head(&sk->sk_bind_node, list);
 }
 
+static inline void __sk_del_bind2_node(struct sock *sk)
+{
+       __hlist_del(&sk->sk_bind2_node);
+}
+
+static inline void sk_add_bind2_node(struct sock *sk, struct hlist_head *list)
+{
+       hlist_add_head(&sk->sk_bind2_node, list);
+}
+
 #define sk_for_each(__sk, list) \
        hlist_for_each_entry(__sk, list, sk_node)
 #define sk_for_each_rcu(__sk, list) \
@@ -887,6 +899,8 @@ static inline void sk_add_bind_node(struct sock *sk,
        hlist_for_each_entry_safe(__sk, tmp, list, sk_node)
 #define sk_for_each_bound(__sk, list) \
        hlist_for_each_entry(__sk, list, sk_bind_node)
+#define sk_for_each_bound_bhash2(__sk, list) \
+       hlist_for_each_entry(__sk, list, sk_bind2_node)
 
 /**
  * sk_for_each_entry_offset_rcu - iterate over a list at a given struct offset
index 2edea90..2a7e18e 100644 (file)
@@ -1024,6 +1024,8 @@ void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);
 void ocelot_deinit_port(struct ocelot *ocelot, int port);
 
+void ocelot_port_setup_dsa_8021q_cpu(struct ocelot *ocelot, int cpu);
+void ocelot_port_teardown_dsa_8021q_cpu(struct ocelot *ocelot, int cpu);
 void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port, int cpu);
 void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port);
 u32 ocelot_port_assigned_dsa_8021q_cpu_mask(struct ocelot *ocelot, int port);
index 7bf9ba1..1d6085e 100644 (file)
@@ -79,7 +79,7 @@ struct bpf_insn {
 /* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */
 struct bpf_lpm_trie_key {
        __u32   prefixlen;      /* up to 32 for AF_INET, 128 for AF_INET6 */
-       __u8    data[]; /* Arbitrary size */
+       __u8    data[0];        /* Arbitrary size */
 };
 
 struct bpf_cgroup_storage_key {
@@ -2573,10 +2573,12 @@ union bpf_attr {
  *             There are two supported modes at this time:
  *
  *             * **BPF_ADJ_ROOM_MAC**: Adjust room at the mac layer
- *               (room space is added or removed below the layer 2 header).
+ *               (room space is added or removed between the layer 2 and
+ *               layer 3 headers).
  *
  *             * **BPF_ADJ_ROOM_NET**: Adjust room at the network layer
- *               (room space is added or removed below the layer 3 header).
+ *               (room space is added or removed between the layer 3 and
+ *               layer 4 headers).
  *
  *             The following flags are supported at this time:
  *
@@ -3008,8 +3010,18 @@ union bpf_attr {
  *             **BPF_F_USER_STACK**
  *                     Collect a user space stack instead of a kernel stack.
  *             **BPF_F_USER_BUILD_ID**
- *                     Collect buildid+offset instead of ips for user stack,
- *                     only valid if **BPF_F_USER_STACK** is also specified.
+ *                     Collect (build_id, file_offset) instead of ips for user
+ *                     stack, only valid if **BPF_F_USER_STACK** is also
+ *                     specified.
+ *
+ *                     *file_offset* is an offset relative to the beginning
+ *                     of the executable or shared object file backing the vma
+ *                     which the *ip* falls in. It is *not* an offset relative
+ *                     to that object's base address. Accordingly, it must be
+ *                     adjusted by adding (sh_addr - sh_offset), where
+ *                     sh_{addr,offset} correspond to the executable section
+ *                     containing *file_offset* in the object, for comparisons
+ *                     to symbols' st_value to be valid.
  *
  *             **bpf_get_stack**\ () can collect up to
  *             **PERF_MAX_STACK_DEPTH** both kernel and user frames, subject
@@ -5331,6 +5343,18 @@ union bpf_attr {
  *             **-EACCES** if the SYN cookie is not valid.
  *
  *             **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin.
+ *
+ * u64 bpf_ktime_get_tai_ns(void)
+ *     Description
+ *             A nonsettable system-wide clock derived from wall-clock time but
+ *             ignoring leap seconds.  This clock does not experience
+ *             discontinuities and backwards jumps caused by NTP inserting leap
+ *             seconds as CLOCK_REALTIME does.
+ *
+ *             See: **clock_gettime**\ (**CLOCK_TAI**)
+ *     Return
+ *             Current *ktime*.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
@@ -5541,6 +5565,7 @@ union bpf_attr {
        FN(tcp_raw_gen_syncookie_ipv6), \
        FN(tcp_raw_check_syncookie_ipv4),       \
        FN(tcp_raw_check_syncookie_ipv6),       \
+       FN(ktime_get_tai_ns),           \
        /* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
diff --git a/include/uapi/linux/dn.h b/include/uapi/linux/dn.h
deleted file mode 100644 (file)
index 36ca71b..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef _LINUX_DN_H
-#define _LINUX_DN_H
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-#include <linux/if_ether.h>
-
-/*
-
-       DECnet Data Structures and Constants
-
-*/
-
-/* 
- * DNPROTO_NSP can't be the same as SOL_SOCKET, 
- * so increment each by one (compared to ULTRIX)
- */
-#define DNPROTO_NSP     2                       /* NSP protocol number       */
-#define DNPROTO_ROU     3                       /* Routing protocol number   */
-#define DNPROTO_NML     4                       /* Net mgt protocol number   */
-#define DNPROTO_EVL     5                       /* Evl protocol number (usr) */
-#define DNPROTO_EVR     6                       /* Evl protocol number (evl) */
-#define DNPROTO_NSPT    7                       /* NSP trace protocol number */
-
-
-#define DN_ADDL                2
-#define DN_MAXADDL     2 /* ULTRIX headers have 20 here, but pathworks has 2 */
-#define DN_MAXOPTL     16
-#define DN_MAXOBJL     16
-#define DN_MAXACCL     40
-#define DN_MAXALIASL   128
-#define DN_MAXNODEL    256
-#define DNBUFSIZE      65023
-
-/* 
- * SET/GET Socket options  - must match the DSO_ numbers below
- */
-#define SO_CONDATA      1
-#define SO_CONACCESS    2
-#define SO_PROXYUSR     3
-#define SO_LINKINFO     7
-
-#define DSO_CONDATA     1        /* Set/Get connect data                */
-#define DSO_DISDATA     10       /* Set/Get disconnect data             */
-#define DSO_CONACCESS   2        /* Set/Get connect access data         */
-#define DSO_ACCEPTMODE  4        /* Set/Get accept mode                 */
-#define DSO_CONACCEPT   5        /* Accept deferred connection          */
-#define DSO_CONREJECT   6        /* Reject deferred connection          */
-#define DSO_LINKINFO    7        /* Set/Get link information            */
-#define DSO_STREAM      8        /* Set socket type to stream           */
-#define DSO_SEQPACKET   9        /* Set socket type to sequenced packet */
-#define DSO_MAXWINDOW   11       /* Maximum window size allowed         */
-#define DSO_NODELAY    12       /* Turn off nagle                      */
-#define DSO_CORK        13       /* Wait for more data!                 */
-#define DSO_SERVICES   14       /* NSP Services field                  */
-#define DSO_INFO       15       /* NSP Info field                      */
-#define DSO_MAX         15       /* Maximum option number               */
-
-
-/* LINK States */
-#define LL_INACTIVE    0
-#define LL_CONNECTING  1
-#define LL_RUNNING     2
-#define LL_DISCONNECTING 3
-
-#define ACC_IMMED 0
-#define ACC_DEFER 1
-
-#define SDF_WILD        1                  /* Wild card object          */
-#define SDF_PROXY       2                  /* Addr eligible for proxy   */
-#define SDF_UICPROXY    4                  /* Use uic-based proxy       */
-
-/* Structures */
-
-
-struct dn_naddr {
-       __le16          a_len;
-       __u8 a_addr[DN_MAXADDL]; /* Two bytes little endian */
-};
-
-struct sockaddr_dn {
-       __u16           sdn_family;
-       __u8            sdn_flags;
-       __u8            sdn_objnum;
-       __le16          sdn_objnamel;
-       __u8            sdn_objname[DN_MAXOBJL];
-       struct   dn_naddr       sdn_add;
-};
-#define sdn_nodeaddrl   sdn_add.a_len   /* Node address length  */
-#define sdn_nodeaddr    sdn_add.a_addr  /* Node address         */
-
-
-
-/*
- * DECnet set/get DSO_CONDATA, DSO_DISDATA (optional data) structure
- */
-struct optdata_dn {
-        __le16  opt_status;     /* Extended status return */
-#define opt_sts opt_status
-        __le16  opt_optl;       /* Length of user data    */
-        __u8   opt_data[16];   /* User data              */
-};
-
-struct accessdata_dn {
-       __u8            acc_accl;
-       __u8            acc_acc[DN_MAXACCL];
-       __u8            acc_passl;
-       __u8            acc_pass[DN_MAXACCL];
-       __u8            acc_userl;
-       __u8            acc_user[DN_MAXACCL];
-};
-
-/*
- * DECnet logical link information structure
- */
-struct linkinfo_dn {
-        __u16  idn_segsize;    /* Segment size for link */
-        __u8   idn_linkstate;  /* Logical link state    */
-};
-
-/*
- * Ethernet address format (for DECnet)
- */
-union etheraddress {
-        __u8 dne_addr[ETH_ALEN];      /* Full ethernet address */
-  struct {
-                __u8 dne_hiord[4];    /* DECnet HIORD prefix   */
-                __u8 dne_nodeaddr[2]; /* DECnet node address   */
-  } dne_remote;
-};
-
-
-/*
- * DECnet physical socket address format
- */
-struct dn_addr {
-        __le16 dna_family;      /* AF_DECnet               */
-        union etheraddress dna_netaddr; /* DECnet ethernet address */
-};
-
-#define DECNET_IOCTL_BASE 0x89 /* PROTOPRIVATE range */
-
-#define SIOCSNETADDR  _IOW(DECNET_IOCTL_BASE, 0xe0, struct dn_naddr)
-#define SIOCGNETADDR  _IOR(DECNET_IOCTL_BASE, 0xe1, struct dn_naddr)
-#define OSIOCSNETADDR _IOW(DECNET_IOCTL_BASE, 0xe0, int)
-#define OSIOCGNETADDR _IOR(DECNET_IOCTL_BASE, 0xe1, int)
-
-#endif /* _LINUX_DN_H */
index 3af2aa0..d5b6d1f 100644 (file)
@@ -22,6 +22,8 @@
 
 #define MACSEC_KEYID_LEN 16
 
+#define MACSEC_SALT_LEN 12
+
 /* cipher IDs as per IEEE802.1AE-2018 (Table 14-1) */
 #define MACSEC_CIPHER_ID_GCM_AES_128 0x0080C20001000001ULL
 #define MACSEC_CIPHER_ID_GCM_AES_256 0x0080C20001000002ULL
index 1416822..578daa6 100644 (file)
@@ -188,21 +188,13 @@ struct ip_mreq_source {
 };
 
 struct ip_msfilter {
+       __be32          imsf_multiaddr;
+       __be32          imsf_interface;
+       __u32           imsf_fmode;
+       __u32           imsf_numsrc;
        union {
-               struct {
-                       __be32          imsf_multiaddr_aux;
-                       __be32          imsf_interface_aux;
-                       __u32           imsf_fmode_aux;
-                       __u32           imsf_numsrc_aux;
-                       __be32          imsf_slist[1];
-               };
-               struct {
-                       __be32          imsf_multiaddr;
-                       __be32          imsf_interface;
-                       __u32           imsf_fmode;
-                       __u32           imsf_numsrc;
-                       __be32          imsf_slist_flex[];
-               };
+               __be32          imsf_slist[1];
+               __DECLARE_FLEX_ARRAY(__be32, imsf_slist_flex);
        };
 };
 
index 1463cfe..9e0b5c8 100644 (file)
 #include <linux/types.h>
 #include <linux/time_types.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * IO submission data structure (Submission Queue Entry)
  */
@@ -661,4 +665,8 @@ struct io_uring_recvmsg_out {
        __u32 flags;
 };
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/include/uapi/linux/netfilter_decnet.h b/include/uapi/linux/netfilter_decnet.h
deleted file mode 100644 (file)
index 3c77f54..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef __LINUX_DECNET_NETFILTER_H
-#define __LINUX_DECNET_NETFILTER_H
-
-/* DECnet-specific defines for netfilter. 
- * This file (C) Steve Whitehouse 1999 derived from the
- * ipv4 netfilter header file which is
- * (C)1998 Rusty Russell -- This code is GPL.
- */
-
-#include <linux/netfilter.h>
-
-/* only for userspace compatibility */
-#ifndef __KERNEL__
-
-#include <limits.h> /* for INT_MIN, INT_MAX */
-
-/* kernel define is in netfilter_defs.h */
-#define NF_DN_NUMHOOKS         7
-#endif /* ! __KERNEL__ */
-
-/* DECnet Hooks */
-/* After promisc drops, checksum checks. */
-#define NF_DN_PRE_ROUTING      0
-/* If the packet is destined for this box. */
-#define NF_DN_LOCAL_IN         1
-/* If the packet is destined for another interface. */
-#define NF_DN_FORWARD          2
-/* Packets coming from a local process. */
-#define NF_DN_LOCAL_OUT                3
-/* Packets about to hit the wire. */
-#define NF_DN_POST_ROUTING     4
-/* Input Hello Packets */
-#define NF_DN_HELLO            5
-/* Input Routing Packets */
-#define NF_DN_ROUTE            6
-
-enum nf_dn_hook_priorities {
-       NF_DN_PRI_FIRST = INT_MIN,
-       NF_DN_PRI_CONNTRACK = -200,
-       NF_DN_PRI_MANGLE = -150,
-       NF_DN_PRI_NAT_DST = -100,
-       NF_DN_PRI_FILTER = 0,
-       NF_DN_PRI_NAT_SRC = 100,
-       NF_DN_PRI_DNRTMSG = 200,
-       NF_DN_PRI_LAST = INT_MAX,
-};
-
-struct nf_dn_rtmsg {
-       int nfdn_ifindex;
-};
-
-#define NFDN_RTMSG(r) ((unsigned char *)(r) + NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)))
-
-#ifndef __KERNEL__
-/* backwards compatibility for userspace */
-#define DNRMG_L1_GROUP 0x01
-#define DNRMG_L2_GROUP 0x02
-#endif
-
-enum {
-       DNRNG_NLGRP_NONE,
-#define DNRNG_NLGRP_NONE       DNRNG_NLGRP_NONE
-       DNRNG_NLGRP_L1,
-#define DNRNG_NLGRP_L1         DNRNG_NLGRP_L1
-       DNRNG_NLGRP_L2,
-#define DNRNG_NLGRP_L2         DNRNG_NLGRP_L2
-       __DNRNG_NLGRP_MAX
-};
-#define DNRNG_NLGRP_MAX        (__DNRNG_NLGRP_MAX - 1)
-
-#endif /*__LINUX_DECNET_NETFILTER_H*/
index 855dffb..e0689db 100644 (file)
@@ -20,7 +20,7 @@
 #define NETLINK_CONNECTOR      11
 #define NETLINK_NETFILTER      12      /* netfilter subsystem */
 #define NETLINK_IP6_FW         13
-#define NETLINK_DNRTMSG                14      /* DECnet routing messages */
+#define NETLINK_DNRTMSG                14      /* DECnet routing messages (obsolete) */
 #define NETLINK_KOBJECT_UEVENT 15      /* Kernel messages to userspace */
 #define NETLINK_GENERIC                16
 /* leave room for NETLINK_DM (DM Events) */
@@ -41,12 +41,20 @@ struct sockaddr_nl {
                __u32           nl_groups;      /* multicast groups mask */
 };
 
+/**
+ * struct nlmsghdr - fixed format metadata header of Netlink messages
+ * @nlmsg_len:   Length of message including header
+ * @nlmsg_type:  Message content type
+ * @nlmsg_flags: Additional flags
+ * @nlmsg_seq:   Sequence number
+ * @nlmsg_pid:   Sending process port ID
+ */
 struct nlmsghdr {
-       __u32           nlmsg_len;      /* Length of message including header */
-       __u16           nlmsg_type;     /* Message content */
-       __u16           nlmsg_flags;    /* Additional flags */
-       __u32           nlmsg_seq;      /* Sequence number */
-       __u32           nlmsg_pid;      /* Sending process port ID */
+       __u32           nlmsg_len;
+       __u16           nlmsg_type;
+       __u16           nlmsg_flags;
+       __u32           nlmsg_seq;
+       __u32           nlmsg_pid;
 };
 
 /* Flags values */
@@ -132,6 +140,10 @@ struct nlmsgerr {
  *     be used - in the success case - to identify a created
  *     object or operation or similar (binary)
  * @NLMSGERR_ATTR_POLICY: policy for a rejected attribute
+ * @NLMSGERR_ATTR_MISS_TYPE: type of a missing required attribute,
+ *     %NLMSGERR_ATTR_MISS_NEST will not be present if the attribute was
+ *     missing at the message level
+ * @NLMSGERR_ATTR_MISS_NEST: offset of the nest where attribute was missing
  * @__NLMSGERR_ATTR_MAX: number of attributes
  * @NLMSGERR_ATTR_MAX: highest attribute number
  */
@@ -141,6 +153,8 @@ enum nlmsgerr_attrs {
        NLMSGERR_ATTR_OFFS,
        NLMSGERR_ATTR_COOKIE,
        NLMSGERR_ATTR_POLICY,
+       NLMSGERR_ATTR_MISS_TYPE,
+       NLMSGERR_ATTR_MISS_NEST,
 
        __NLMSGERR_ATTR_MAX,
        NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1
@@ -337,6 +351,9 @@ enum netlink_attribute_type {
  *     bitfield32 type (U32)
  * @NL_POLICY_TYPE_ATTR_MASK: mask of valid bits for unsigned integers (U64)
  * @NL_POLICY_TYPE_ATTR_PAD: pad attribute for 64-bit alignment
+ *
+ * @__NL_POLICY_TYPE_ATTR_MAX: number of attributes
+ * @NL_POLICY_TYPE_ATTR_MAX: highest attribute number
  */
 enum netlink_policy_type_attr {
        NL_POLICY_TYPE_ATTR_UNSPEC,
index ffb7c57..c32e761 100644 (file)
  *     the non-transmitting interfaces are deleted as well.
  *
  * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified
- *     by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC.
+ *     by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC
+ *     represents peer's MLD address for MLO pairwise key. For MLO group key,
+ *     the link is identified by %NL80211_ATTR_MLO_LINK_ID.
  * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT,
  *     %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD.
+ *     For MLO connection, the link to set default key is identified by
+ *     %NL80211_ATTR_MLO_LINK_ID.
  * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA,
  *     %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER,
- *     and %NL80211_ATTR_KEY_SEQ attributes.
+ *     and %NL80211_ATTR_KEY_SEQ attributes. %NL80211_ATTR_MAC represents
+ *     peer's MLD address for MLO pairwise key. The link to add MLO
+ *     group key is identified by %NL80211_ATTR_MLO_LINK_ID.
  * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX
- *     or %NL80211_ATTR_MAC.
+ *     or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC represents peer's MLD address
+ *     for MLO pairwise key. The link to delete group key is identified by
+ *     %NL80211_ATTR_MLO_LINK_ID.
  *
  * @NL80211_CMD_GET_BEACON: (not used)
  * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface
@@ -4951,6 +4959,7 @@ enum nl80211_bss_scan_width {
  *     using the nesting index as the antenna number.
  * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz
  * @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8).
+ * @NL80211_BSS_MLD_ADDR: MLD address of this BSS if connected to it.
  * @__NL80211_BSS_AFTER_LAST: internal
  * @NL80211_BSS_MAX: highest BSS attribute
  */
@@ -4977,6 +4986,7 @@ enum nl80211_bss {
        NL80211_BSS_CHAIN_SIGNAL,
        NL80211_BSS_FREQUENCY_OFFSET,
        NL80211_BSS_MLO_LINK_ID,
+       NL80211_BSS_MLD_ADDR,
 
        /* keep last */
        __NL80211_BSS_AFTER_LAST,
@@ -6273,6 +6283,14 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC
  *     detection.
  *
+ * @NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE: Device can perform a MAC address
+ *     change without having to bring the underlying network device down
+ *     first. For example, in station mode this can be used to vary the
+ *     origin MAC address prior to a connection to a new AP for privacy
+ *     or other reasons. Note that certain driver specific restrictions
+ *     might apply, e.g. no scans in progress, no offchannel operations
+ *     in progress, and no active connections.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -6340,6 +6358,7 @@ enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_BSS_COLOR,
        NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD,
        NL80211_EXT_FEATURE_RADAR_BACKGROUND,
+       NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
index ce3e173..94066f8 100644 (file)
@@ -76,6 +76,8 @@ enum ovs_datapath_cmd {
  * datapath.  Always present in notifications.
  * @OVS_DP_ATTR_MEGAFLOW_STATS: Statistics about mega flow masks usage for the
  * datapath. Always present in notifications.
+ * @OVS_DP_ATTR_IFINDEX: Interface index for a new datapath netdev. Only
+ * valid for %OVS_DP_CMD_NEW requests.
  *
  * These attributes follow the &struct ovs_header within the Generic Netlink
  * payload for %OVS_DP_* commands.
@@ -92,6 +94,7 @@ enum ovs_datapath_attr {
        OVS_DP_ATTR_PER_CPU_PIDS,   /* Netlink PIDS to receive upcalls in
                                     * per-cpu dispatch mode
                                     */
+       OVS_DP_ATTR_IFINDEX,
        __OVS_DP_ATTR_MAX
 };
 
index 29ced55..6cb842e 100644 (file)
@@ -56,7 +56,7 @@
 #define VIRTIO_NET_F_MQ        22      /* Device supports Receive Flow
                                         * Steering */
 #define VIRTIO_NET_F_CTRL_MAC_ADDR 23  /* Set MAC address */
-#define VIRTIO_NET_F_NOTF_COAL 53      /* Guest can handle notifications coalescing */
+#define VIRTIO_NET_F_NOTF_COAL 53      /* Device supports notifications coalescing */
 #define VIRTIO_NET_F_HASH_REPORT  57   /* Supports hash report */
 #define VIRTIO_NET_F_RSS         60    /* Supports RSS RX steering */
 #define VIRTIO_NET_F_RSC_EXT     61    /* extended coalescing info */
@@ -364,24 +364,24 @@ struct virtio_net_hash_config {
  */
 #define VIRTIO_NET_CTRL_NOTF_COAL              6
 /*
- * Set the tx-usecs/tx-max-packets patameters.
- * tx-usecs - Maximum number of usecs to delay a TX notification.
- * tx-max-packets - Maximum number of packets to send before a TX notification.
+ * Set the tx-usecs/tx-max-packets parameters.
  */
 struct virtio_net_ctrl_coal_tx {
+       /* Maximum number of packets to send before a TX notification */
        __le32 tx_max_packets;
+       /* Maximum number of usecs to delay a TX notification */
        __le32 tx_usecs;
 };
 
 #define VIRTIO_NET_CTRL_NOTF_COAL_TX_SET               0
 
 /*
- * Set the rx-usecs/rx-max-packets patameters.
- * rx-usecs - Maximum number of usecs to delay a RX notification.
- * rx-max-frames - Maximum number of packets to receive before a RX notification.
+ * Set the rx-usecs/rx-max-packets parameters.
  */
 struct virtio_net_ctrl_coal_rx {
+       /* Maximum number of packets to receive before a RX notification */
        __le32 rx_max_packets;
+       /* Maximum number of usecs to delay a RX notification */
        __le32 rx_usecs;
 };
 
index f81aa95..f525566 100644 (file)
@@ -135,11 +135,7 @@ static inline u32 ufshci_version(u32 major, u32 minor)
 
 #define UFSHCD_UIC_MASK                (UIC_COMMAND_COMPL | UFSHCD_UIC_PWR_MASK)
 
-#define UFSHCD_ERROR_MASK      (UIC_ERROR |\
-                               DEVICE_FATAL_ERROR |\
-                               CONTROLLER_FATAL_ERROR |\
-                               SYSTEM_BUS_FATAL_ERROR |\
-                               CRYPTO_ENGINE_FATAL_ERROR)
+#define UFSHCD_ERROR_MASK      (UIC_ERROR | INT_FATAL_ERRORS)
 
 #define INT_FATAL_ERRORS       (DEVICE_FATAL_ERROR |\
                                CONTROLLER_FATAL_ERROR |\
index 91642a4..1fe7942 100644 (file)
@@ -1446,13 +1446,25 @@ static noinline void __init kernel_init_freeable(void);
 
 #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX)
 bool rodata_enabled __ro_after_init = true;
+
+#ifndef arch_parse_debug_rodata
+static inline bool arch_parse_debug_rodata(char *str) { return false; }
+#endif
+
 static int __init set_debug_rodata(char *str)
 {
-       if (strtobool(str, &rodata_enabled))
+       if (arch_parse_debug_rodata(str))
+               return 0;
+
+       if (str && !strcmp(str, "on"))
+               rodata_enabled = true;
+       else if (str && !strcmp(str, "off"))
+               rodata_enabled = false;
+       else
                pr_warn("Invalid option string for rodata: '%s'\n", str);
-       return 1;
+       return 0;
 }
-__setup("rodata=", set_debug_rodata);
+early_param("rodata", set_debug_rodata);
 #endif
 
 #ifdef CONFIG_STRICT_KERNEL_RWX
index e4e1dc0..5fc5d3e 100644 (file)
@@ -218,7 +218,7 @@ static int __io_sync_cancel(struct io_uring_task *tctx,
            (cd->flags & IORING_ASYNC_CANCEL_FD_FIXED)) {
                unsigned long file_ptr;
 
-               if (unlikely(fd > ctx->nr_user_files))
+               if (unlikely(fd >= ctx->nr_user_files))
                        return -EBADF;
                fd = array_index_nospec(fd, ctx->nr_user_files);
                file_ptr = io_fixed_file_slot(&ctx->file_table, fd)->file_ptr;
index ebfdb22..7761627 100644 (file)
@@ -1450,9 +1450,10 @@ int io_req_prep_async(struct io_kiocb *req)
                return 0;
        if (WARN_ON_ONCE(req_has_async_data(req)))
                return -EFAULT;
-       if (io_alloc_async_data(req))
-               return -EAGAIN;
-
+       if (!io_op_defs[req->opcode].manual_alloc) {
+               if (io_alloc_async_data(req))
+                       return -EAGAIN;
+       }
        return def->prep_async(req);
 }
 
index f8cdf1d..0af8a02 100644 (file)
@@ -182,6 +182,37 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
                                        &iomsg->free_iov);
 }
 
+int io_sendzc_prep_async(struct io_kiocb *req)
+{
+       struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
+       struct io_async_msghdr *io;
+       int ret;
+
+       if (!zc->addr || req_has_async_data(req))
+               return 0;
+       if (io_alloc_async_data(req))
+               return -ENOMEM;
+
+       io = req->async_data;
+       ret = move_addr_to_kernel(zc->addr, zc->addr_len, &io->addr);
+       return ret;
+}
+
+static int io_setup_async_addr(struct io_kiocb *req,
+                             struct sockaddr_storage *addr,
+                             unsigned int issue_flags)
+{
+       struct io_async_msghdr *io;
+
+       if (!addr || req_has_async_data(req))
+               return -EAGAIN;
+       if (io_alloc_async_data(req))
+               return -ENOMEM;
+       io = req->async_data;
+       memcpy(&io->addr, addr, sizeof(io->addr));
+       return -EAGAIN;
+}
+
 int io_sendmsg_prep_async(struct io_kiocb *req)
 {
        int ret;
@@ -944,7 +975,7 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
 
 int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
 {
-       struct sockaddr_storage address;
+       struct sockaddr_storage __address, *addr = NULL;
        struct io_ring_ctx *ctx = req->ctx;
        struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
        struct io_notif_slot *notif_slot;
@@ -978,10 +1009,17 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
        msg.msg_namelen = 0;
 
        if (zc->addr) {
-               ret = move_addr_to_kernel(zc->addr, zc->addr_len, &address);
-               if (unlikely(ret < 0))
-                       return ret;
-               msg.msg_name = (struct sockaddr *)&address;
+               if (req_has_async_data(req)) {
+                       struct io_async_msghdr *io = req->async_data;
+
+                       msg.msg_name = addr = &io->addr;
+               } else {
+                       ret = move_addr_to_kernel(zc->addr, zc->addr_len, &__address);
+                       if (unlikely(ret < 0))
+                               return ret;
+                       msg.msg_name = (struct sockaddr *)&__address;
+                       addr = &__address;
+               }
                msg.msg_namelen = zc->addr_len;
        }
 
@@ -989,7 +1027,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                ret = io_import_fixed(WRITE, &msg.msg_iter, req->imu,
                                        (u64)(uintptr_t)zc->buf, zc->len);
                if (unlikely(ret))
-                               return ret;
+                       return ret;
        } else {
                ret = import_single_range(WRITE, zc->buf, zc->len, &iov,
                                          &msg.msg_iter);
@@ -1013,16 +1051,18 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
 
        if (unlikely(ret < min_ret)) {
                if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
-                       return -EAGAIN;
+                       return io_setup_async_addr(req, addr, issue_flags);
+
                if (ret > 0 && io_net_retry(sock, msg.msg_flags)) {
                        zc->len -= ret;
                        zc->buf += ret;
                        zc->done_io += ret;
                        req->flags |= REQ_F_PARTIAL_IO;
-                       return -EAGAIN;
+                       return io_setup_async_addr(req, addr, issue_flags);
                }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
+               req_set_fail(req);
        } else if (zc->flags & IORING_RECVSEND_NOTIF_FLUSH) {
                io_notif_slot_flush_submit(notif_slot, 0);
        }
index 7c438d3..f91f56c 100644 (file)
@@ -31,6 +31,7 @@ struct io_async_connect {
 int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
 int io_shutdown(struct io_kiocb *req, unsigned int issue_flags);
 
+int io_sendzc_prep_async(struct io_kiocb *req);
 int io_sendmsg_prep_async(struct io_kiocb *req);
 void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req);
 int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
index 977736e..96f076b 100644 (file)
@@ -73,7 +73,7 @@ struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx,
 }
 
 void io_notif_slot_flush(struct io_notif_slot *slot)
-       __must_hold(&ctx->uring_lock)
+       __must_hold(&slot->notif->ctx->uring_lock)
 {
        struct io_kiocb *notif = slot->notif;
        struct io_notif_data *nd = io_notif_to_data(notif);
@@ -81,8 +81,10 @@ void io_notif_slot_flush(struct io_notif_slot *slot)
        slot->notif = NULL;
 
        /* drop slot's master ref */
-       if (refcount_dec_and_test(&nd->uarg.refcnt))
-               io_notif_complete(notif);
+       if (refcount_dec_and_test(&nd->uarg.refcnt)) {
+               notif->io_task_work.func = __io_notif_complete_tw;
+               io_req_task_work_add(notif);
+       }
 }
 
 __cold int io_notif_unregister(struct io_ring_ctx *ctx)
index 72dd2b2..4141012 100644 (file)
@@ -478,13 +478,15 @@ const struct io_op_def io_op_defs[] = {
                .pollout                = 1,
                .audit_skip             = 1,
                .ioprio                 = 1,
+               .manual_alloc           = 1,
 #if defined(CONFIG_NET)
+               .async_size             = sizeof(struct io_async_msghdr),
                .prep                   = io_sendzc_prep,
                .issue                  = io_sendzc,
+               .prep_async             = io_sendzc_prep_async,
 #else
                .prep                   = io_eopnotsupp_prep,
 #endif
-
        },
 };
 
index ece8ed4..763c6e5 100644 (file)
@@ -25,6 +25,8 @@ struct io_op_def {
        unsigned                ioprio : 1;
        /* supports iopoll */
        unsigned                iopoll : 1;
+       /* opcode specific path will handle ->async_data allocation if needed */
+       unsigned                manual_alloc : 1;
        /* size of async data needed, if any */
        unsigned short          async_size;
 
index 8e0cc2d..e78b6f9 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/io_uring.h>
+#include <linux/security.h>
 
 #include <uapi/linux/io_uring.h>
 
@@ -88,6 +89,10 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
        if (!req->file->f_op->uring_cmd)
                return -EOPNOTSUPP;
 
+       ret = security_uring_cmd(ioucmd);
+       if (ret)
+               return ret;
+
        if (ctx->flags & IORING_SETUP_SQE128)
                issue_flags |= IO_URING_F_SQE128;
        if (ctx->flags & IORING_SETUP_CQE32)
@@ -112,7 +117,7 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
                if (ret < 0)
                        req_set_fail(req);
                io_req_set_res(req, ret, 0);
-               return IOU_OK;
+               return ret;
        }
 
        return IOU_ISSUE_SKIP_COMPLETE;
index dd8d9ab..79a5da1 100644 (file)
@@ -1940,6 +1940,7 @@ void __audit_uring_exit(int success, long code)
                goto out;
        }
 
+       audit_return_fixup(ctx, success, code);
        if (ctx->context == AUDIT_CTX_SYSCALL) {
                /*
                 * NOTE: See the note in __audit_uring_entry() about the case
@@ -1981,7 +1982,6 @@ void __audit_uring_exit(int success, long code)
        audit_filter_inodes(current, ctx);
        if (ctx->current_state != AUDIT_STATE_RECORD)
                goto out;
-       audit_return_fixup(ctx, success, code);
        audit_log_exit();
 
 out:
@@ -2065,13 +2065,13 @@ void __audit_syscall_exit(int success, long return_code)
        if (!list_empty(&context->killed_trees))
                audit_kill_trees(context);
 
+       audit_return_fixup(context, success, return_code);
        /* run through both filters to ensure we set the filterkey properly */
        audit_filter_syscall(current, context);
        audit_filter_inodes(current, context);
        if (context->current_state < AUDIT_STATE_RECORD)
                goto out;
 
-       audit_return_fixup(context, success, return_code);
        audit_log_exit();
 
 out:
index 24b755e..97bb574 100644 (file)
@@ -202,6 +202,11 @@ static ssize_t bpf_seq_read(struct file *file, char __user *buf, size_t size,
        }
 stop:
        offs = seq->count;
+       if (IS_ERR(p)) {
+               seq->op->stop(seq, NULL);
+               err = PTR_ERR(p);
+               goto done;
+       }
        /* bpf program called if !p */
        seq->op->stop(seq, p);
        if (!p) {
index 8ce40fd..4ee2e72 100644 (file)
@@ -582,7 +582,7 @@ void bpf_local_storage_map_free(struct bpf_local_storage_map *smap,
        synchronize_rcu();
 
        kvfree(smap->buckets);
-       kfree(smap);
+       bpf_map_area_free(smap);
 }
 
 int bpf_local_storage_map_alloc_check(union bpf_attr *attr)
@@ -610,7 +610,7 @@ struct bpf_local_storage_map *bpf_local_storage_map_alloc(union bpf_attr *attr)
        unsigned int i;
        u32 nbuckets;
 
-       smap = kzalloc(sizeof(*smap), GFP_USER | __GFP_NOWARN | __GFP_ACCOUNT);
+       smap = bpf_map_area_alloc(sizeof(*smap), NUMA_NO_NODE);
        if (!smap)
                return ERR_PTR(-ENOMEM);
        bpf_map_init_from_attr(&smap->map, attr);
@@ -623,7 +623,7 @@ struct bpf_local_storage_map *bpf_local_storage_map_alloc(union bpf_attr *attr)
        smap->buckets = kvcalloc(sizeof(*smap->buckets), nbuckets,
                                 GFP_USER | __GFP_NOWARN | __GFP_ACCOUNT);
        if (!smap->buckets) {
-               kfree(smap);
+               bpf_map_area_free(smap);
                return ERR_PTR(-ENOMEM);
        }
 
index 7e64447..903719b 100644 (file)
@@ -5864,26 +5864,25 @@ again:
 }
 
 static int __get_type_size(struct btf *btf, u32 btf_id,
-                          const struct btf_type **bad_type)
+                          const struct btf_type **ret_type)
 {
        const struct btf_type *t;
 
+       *ret_type = btf_type_by_id(btf, 0);
        if (!btf_id)
                /* void */
                return 0;
        t = btf_type_by_id(btf, btf_id);
        while (t && btf_type_is_modifier(t))
                t = btf_type_by_id(btf, t->type);
-       if (!t) {
-               *bad_type = btf_type_by_id(btf, 0);
+       if (!t)
                return -EINVAL;
-       }
+       *ret_type = t;
        if (btf_type_is_ptr(t))
                /* kernel size of pointer. Not BPF's size of pointer*/
                return sizeof(void *);
        if (btf_type_is_int(t) || btf_is_any_enum(t))
                return t->size;
-       *bad_type = t;
        return -EINVAL;
 }
 
@@ -6175,6 +6174,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
 {
        enum bpf_prog_type prog_type = resolve_prog_type(env->prog);
        bool rel = false, kptr_get = false, trusted_arg = false;
+       bool sleepable = false;
        struct bpf_verifier_log *log = &env->log;
        u32 i, nargs, ref_id, ref_obj_id = 0;
        bool is_kfunc = btf_is_kernel(btf);
@@ -6212,6 +6212,7 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
                rel = kfunc_flags & KF_RELEASE;
                kptr_get = kfunc_flags & KF_KPTR_GET;
                trusted_arg = kfunc_flags & KF_TRUSTED_ARGS;
+               sleepable = kfunc_flags & KF_SLEEPABLE;
        }
 
        /* check that BTF function arguments match actual types that the
@@ -6419,6 +6420,13 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env,
                        func_name);
                return -EINVAL;
        }
+
+       if (sleepable && !env->prog->aux->sleepable) {
+               bpf_log(log, "kernel function %s is sleepable but the program is not\n",
+                       func_name);
+               return -EINVAL;
+       }
+
        /* returns argument register number > 0 in case of reference release kfunc */
        return rel ? ref_regno : 0;
 }
index 59b7eb6..4a400cd 100644 (file)
@@ -921,8 +921,10 @@ static void purge_effective_progs(struct cgroup *cgrp, struct bpf_prog *prog,
                                pos++;
                        }
                }
+
+               /* no link or prog match, skip the cgroup of this layer */
+               continue;
 found:
-               BUG_ON(!cg);
                progs = rcu_dereference_protected(
                                desc->bpf.effective[atype],
                                lockdep_is_held(&cgroup_mutex));
index c1e10d0..d1be78c 100644 (file)
@@ -971,7 +971,7 @@ pure_initcall(bpf_jit_charge_init);
 
 int bpf_jit_charge_modmem(u32 size)
 {
-       if (atomic_long_add_return(size, &bpf_jit_current) > bpf_jit_limit) {
+       if (atomic_long_add_return(size, &bpf_jit_current) > READ_ONCE(bpf_jit_limit)) {
                if (!bpf_capable()) {
                        atomic_long_sub(size, &bpf_jit_current);
                        return -EPERM;
@@ -2623,6 +2623,7 @@ const struct bpf_func_proto bpf_get_numa_node_id_proto __weak;
 const struct bpf_func_proto bpf_ktime_get_ns_proto __weak;
 const struct bpf_func_proto bpf_ktime_get_boot_ns_proto __weak;
 const struct bpf_func_proto bpf_ktime_get_coarse_ns_proto __weak;
+const struct bpf_func_proto bpf_ktime_get_tai_ns_proto __weak;
 
 const struct bpf_func_proto bpf_get_current_pid_tgid_proto __weak;
 const struct bpf_func_proto bpf_get_current_uid_gid_proto __weak;
index f4860ac..b5ba34d 100644 (file)
@@ -97,7 +97,7 @@ static struct bpf_map *cpu_map_alloc(union bpf_attr *attr)
            attr->map_flags & ~BPF_F_NUMA_NODE)
                return ERR_PTR(-EINVAL);
 
-       cmap = kzalloc(sizeof(*cmap), GFP_USER | __GFP_ACCOUNT);
+       cmap = bpf_map_area_alloc(sizeof(*cmap), NUMA_NO_NODE);
        if (!cmap)
                return ERR_PTR(-ENOMEM);
 
@@ -118,7 +118,7 @@ static struct bpf_map *cpu_map_alloc(union bpf_attr *attr)
 
        return &cmap->map;
 free_cmap:
-       kfree(cmap);
+       bpf_map_area_free(cmap);
        return ERR_PTR(err);
 }
 
@@ -623,7 +623,7 @@ static void cpu_map_free(struct bpf_map *map)
                __cpu_map_entry_replace(cmap, i, NULL); /* call_rcu */
        }
        bpf_map_area_free(cmap->cpu_map);
-       kfree(cmap);
+       bpf_map_area_free(cmap);
 }
 
 /* Elements are kept alive by RCU; either by rcu_read_lock() (from syscall) or
index a0e02b0..f9a87dc 100644 (file)
@@ -163,13 +163,13 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
        if (!capable(CAP_NET_ADMIN))
                return ERR_PTR(-EPERM);
 
-       dtab = kzalloc(sizeof(*dtab), GFP_USER | __GFP_ACCOUNT);
+       dtab = bpf_map_area_alloc(sizeof(*dtab), NUMA_NO_NODE);
        if (!dtab)
                return ERR_PTR(-ENOMEM);
 
        err = dev_map_init_map(dtab, attr);
        if (err) {
-               kfree(dtab);
+               bpf_map_area_free(dtab);
                return ERR_PTR(err);
        }
 
@@ -240,7 +240,7 @@ static void dev_map_free(struct bpf_map *map)
                bpf_map_area_free(dtab->netdev_map);
        }
 
-       kfree(dtab);
+       bpf_map_area_free(dtab);
 }
 
 static int dev_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
index 6c530a5..b301a63 100644 (file)
@@ -491,7 +491,7 @@ static struct bpf_map *htab_map_alloc(union bpf_attr *attr)
        struct bpf_htab *htab;
        int err, i;
 
-       htab = kzalloc(sizeof(*htab), GFP_USER | __GFP_ACCOUNT);
+       htab = bpf_map_area_alloc(sizeof(*htab), NUMA_NO_NODE);
        if (!htab)
                return ERR_PTR(-ENOMEM);
 
@@ -575,7 +575,7 @@ free_map_locked:
        bpf_map_area_free(htab->buckets);
 free_htab:
        lockdep_unregister_key(&htab->lockdep_key);
-       kfree(htab);
+       bpf_map_area_free(htab);
        return ERR_PTR(err);
 }
 
@@ -1492,7 +1492,7 @@ static void htab_map_free(struct bpf_map *map)
        for (i = 0; i < HASHTAB_MAP_LOCK_COUNT; i++)
                free_percpu(htab->map_locked[i]);
        lockdep_unregister_key(&htab->lockdep_key);
-       kfree(htab);
+       bpf_map_area_free(htab);
 }
 
 static void htab_map_seq_show_elem(struct bpf_map *map, void *key,
index 1f961f9..3c1b9bb 100644 (file)
@@ -198,6 +198,18 @@ const struct bpf_func_proto bpf_ktime_get_coarse_ns_proto = {
        .ret_type       = RET_INTEGER,
 };
 
+BPF_CALL_0(bpf_ktime_get_tai_ns)
+{
+       /* NMI safe access to clock tai */
+       return ktime_get_tai_fast_ns();
+}
+
+const struct bpf_func_proto bpf_ktime_get_tai_ns_proto = {
+       .func           = bpf_ktime_get_tai_ns,
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+};
+
 BPF_CALL_0(bpf_get_current_pid_tgid)
 {
        struct task_struct *task = current;
@@ -1617,6 +1629,8 @@ bpf_base_func_proto(enum bpf_func_id func_id)
                return &bpf_ktime_get_ns_proto;
        case BPF_FUNC_ktime_get_boot_ns:
                return &bpf_ktime_get_boot_ns_proto;
+       case BPF_FUNC_ktime_get_tai_ns:
+               return &bpf_ktime_get_tai_ns_proto;
        case BPF_FUNC_ringbuf_output:
                return &bpf_ringbuf_output_proto;
        case BPF_FUNC_ringbuf_reserve:
@@ -1711,3 +1725,21 @@ bpf_base_func_proto(enum bpf_func_id func_id)
                return NULL;
        }
 }
+
+BTF_SET8_START(tracing_btf_ids)
+#ifdef CONFIG_KEXEC_CORE
+BTF_ID_FLAGS(func, crash_kexec, KF_DESTRUCTIVE)
+#endif
+BTF_SET8_END(tracing_btf_ids)
+
+static const struct btf_kfunc_id_set tracing_kfunc_set = {
+       .owner = THIS_MODULE,
+       .set   = &tracing_btf_ids,
+};
+
+static int __init kfunc_init(void)
+{
+       return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &tracing_kfunc_set);
+}
+
+late_initcall(kfunc_init);
index 49ef0ce..098cf33 100644 (file)
@@ -313,8 +313,7 @@ static struct bpf_map *cgroup_storage_map_alloc(union bpf_attr *attr)
                /* max_entries is not used and enforced to be 0 */
                return ERR_PTR(-EINVAL);
 
-       map = kmalloc_node(sizeof(struct bpf_cgroup_storage_map),
-                          __GFP_ZERO | GFP_USER | __GFP_ACCOUNT, numa_node);
+       map = bpf_map_area_alloc(sizeof(struct bpf_cgroup_storage_map), numa_node);
        if (!map)
                return ERR_PTR(-ENOMEM);
 
@@ -346,7 +345,7 @@ static void cgroup_storage_map_free(struct bpf_map *_map)
        WARN_ON(!RB_EMPTY_ROOT(&map->root));
        WARN_ON(!list_empty(&map->list));
 
-       kfree(map);
+       bpf_map_area_free(map);
 }
 
 static int cgroup_storage_delete_elem(struct bpf_map *map, void *key)
index d789e3b..d833496 100644 (file)
@@ -558,7 +558,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
            attr->value_size > LPM_VAL_SIZE_MAX)
                return ERR_PTR(-EINVAL);
 
-       trie = kzalloc(sizeof(*trie), GFP_USER | __GFP_NOWARN | __GFP_ACCOUNT);
+       trie = bpf_map_area_alloc(sizeof(*trie), NUMA_NO_NODE);
        if (!trie)
                return ERR_PTR(-ENOMEM);
 
@@ -609,7 +609,7 @@ static void trie_free(struct bpf_map *map)
        }
 
 out:
-       kfree(trie);
+       bpf_map_area_free(trie);
 }
 
 static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
index bd09290..13e4efc 100644 (file)
@@ -372,7 +372,7 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
            attr->map_type != BPF_MAP_TYPE_HASH)
                return ERR_PTR(-EINVAL);
 
-       offmap = kzalloc(sizeof(*offmap), GFP_USER);
+       offmap = bpf_map_area_alloc(sizeof(*offmap), NUMA_NO_NODE);
        if (!offmap)
                return ERR_PTR(-ENOMEM);
 
@@ -404,7 +404,7 @@ struct bpf_map *bpf_map_offload_map_alloc(union bpf_attr *attr)
 err_unlock:
        up_write(&bpf_devs_lock);
        rtnl_unlock();
-       kfree(offmap);
+       bpf_map_area_free(offmap);
        return ERR_PTR(err);
 }
 
@@ -428,7 +428,7 @@ void bpf_map_offload_map_free(struct bpf_map *map)
        up_write(&bpf_devs_lock);
        rtnl_unlock();
 
-       kfree(offmap);
+       bpf_map_area_free(offmap);
 }
 
 int bpf_map_offload_lookup_elem(struct bpf_map *map, void *key, void *value)
index a1c0794..8a5e060 100644 (file)
@@ -78,8 +78,6 @@ static struct bpf_map *queue_stack_map_alloc(union bpf_attr *attr)
        if (!qs)
                return ERR_PTR(-ENOMEM);
 
-       memset(qs, 0, sizeof(*qs));
-
        bpf_map_init_from_attr(&qs->map, attr);
 
        qs->size = size;
index ded4fae..b483aea 100644 (file)
@@ -116,7 +116,7 @@ static struct bpf_ringbuf *bpf_ringbuf_area_alloc(size_t data_sz, int numa_node)
 err_free_pages:
        for (i = 0; i < nr_pages; i++)
                __free_page(pages[i]);
-       kvfree(pages);
+       bpf_map_area_free(pages);
        return NULL;
 }
 
@@ -164,7 +164,7 @@ static struct bpf_map *ringbuf_map_alloc(union bpf_attr *attr)
                return ERR_PTR(-E2BIG);
 #endif
 
-       rb_map = kzalloc(sizeof(*rb_map), GFP_USER | __GFP_ACCOUNT);
+       rb_map = bpf_map_area_alloc(sizeof(*rb_map), NUMA_NO_NODE);
        if (!rb_map)
                return ERR_PTR(-ENOMEM);
 
@@ -172,7 +172,7 @@ static struct bpf_map *ringbuf_map_alloc(union bpf_attr *attr)
 
        rb_map->rb = bpf_ringbuf_alloc(attr->max_entries, rb_map->map.numa_node);
        if (!rb_map->rb) {
-               kfree(rb_map);
+               bpf_map_area_free(rb_map);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -190,7 +190,7 @@ static void bpf_ringbuf_free(struct bpf_ringbuf *rb)
        vunmap(rb);
        for (i = 0; i < nr_pages; i++)
                __free_page(pages[i]);
-       kvfree(pages);
+       bpf_map_area_free(pages);
 }
 
 static void ringbuf_map_free(struct bpf_map *map)
@@ -199,7 +199,7 @@ static void ringbuf_map_free(struct bpf_map *map)
 
        rb_map = container_of(map, struct bpf_ringbuf_map, map);
        bpf_ringbuf_free(rb_map->rb);
-       kfree(rb_map);
+       bpf_map_area_free(rb_map);
 }
 
 static void *ringbuf_map_lookup_elem(struct bpf_map *map, void *key)
index a4d40d9..2776062 100644 (file)
@@ -5197,7 +5197,7 @@ syscall_prog_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
 {
        switch (func_id) {
        case BPF_FUNC_sys_bpf:
-               return &bpf_sys_bpf_proto;
+               return !perfmon_capable() ? NULL : &bpf_sys_bpf_proto;
        case BPF_FUNC_btf_find_by_name_kind:
                return &bpf_btf_find_by_name_kind_proto;
        case BPF_FUNC_sys_close:
index 096fdac..8d07493 100644 (file)
@@ -427,6 +427,7 @@ static void verbose_invalid_scalar(struct bpf_verifier_env *env,
 
 static bool type_is_pkt_pointer(enum bpf_reg_type type)
 {
+       type = base_type(type);
        return type == PTR_TO_PACKET ||
               type == PTR_TO_PACKET_META;
 }
@@ -456,10 +457,9 @@ static bool reg_may_point_to_spin_lock(const struct bpf_reg_state *reg)
 
 static bool reg_type_may_be_refcounted_or_null(enum bpf_reg_type type)
 {
-       return base_type(type) == PTR_TO_SOCKET ||
-               base_type(type) == PTR_TO_TCP_SOCK ||
-               base_type(type) == PTR_TO_MEM ||
-               base_type(type) == PTR_TO_BTF_ID;
+       type = base_type(type);
+       return type == PTR_TO_SOCKET || type == PTR_TO_TCP_SOCK ||
+               type == PTR_TO_MEM || type == PTR_TO_BTF_ID;
 }
 
 static bool type_is_rdonly_mem(u32 type)
@@ -467,25 +467,11 @@ static bool type_is_rdonly_mem(u32 type)
        return type & MEM_RDONLY;
 }
 
-static bool arg_type_may_be_refcounted(enum bpf_arg_type type)
-{
-       return type == ARG_PTR_TO_SOCK_COMMON;
-}
-
 static bool type_may_be_null(u32 type)
 {
        return type & PTR_MAYBE_NULL;
 }
 
-static bool may_be_acquire_function(enum bpf_func_id func_id)
-{
-       return func_id == BPF_FUNC_sk_lookup_tcp ||
-               func_id == BPF_FUNC_sk_lookup_udp ||
-               func_id == BPF_FUNC_skc_lookup_tcp ||
-               func_id == BPF_FUNC_map_lookup_elem ||
-               func_id == BPF_FUNC_ringbuf_reserve;
-}
-
 static bool is_acquire_function(enum bpf_func_id func_id,
                                const struct bpf_map *map)
 {
@@ -518,6 +504,26 @@ static bool is_ptr_cast_function(enum bpf_func_id func_id)
                func_id == BPF_FUNC_skc_to_tcp_request_sock;
 }
 
+static bool is_dynptr_ref_function(enum bpf_func_id func_id)
+{
+       return func_id == BPF_FUNC_dynptr_data;
+}
+
+static bool helper_multiple_ref_obj_use(enum bpf_func_id func_id,
+                                       const struct bpf_map *map)
+{
+       int ref_obj_uses = 0;
+
+       if (is_ptr_cast_function(func_id))
+               ref_obj_uses++;
+       if (is_acquire_function(func_id, map))
+               ref_obj_uses++;
+       if (is_dynptr_ref_function(func_id))
+               ref_obj_uses++;
+
+       return ref_obj_uses > 1;
+}
+
 static bool is_cmpxchg_insn(const struct bpf_insn *insn)
 {
        return BPF_CLASS(insn->code) == BPF_STX &&
@@ -6066,6 +6072,9 @@ skip_type_check:
                        return -EACCES;
                }
                meta->mem_size = reg->var_off.value;
+               err = mark_chain_precision(env, regno);
+               if (err)
+                       return err;
                break;
        case ARG_PTR_TO_INT:
        case ARG_PTR_TO_LONG:
@@ -6453,33 +6462,6 @@ static bool check_arg_pair_ok(const struct bpf_func_proto *fn)
        return true;
 }
 
-static bool check_refcount_ok(const struct bpf_func_proto *fn, int func_id)
-{
-       int count = 0;
-
-       if (arg_type_may_be_refcounted(fn->arg1_type))
-               count++;
-       if (arg_type_may_be_refcounted(fn->arg2_type))
-               count++;
-       if (arg_type_may_be_refcounted(fn->arg3_type))
-               count++;
-       if (arg_type_may_be_refcounted(fn->arg4_type))
-               count++;
-       if (arg_type_may_be_refcounted(fn->arg5_type))
-               count++;
-
-       /* A reference acquiring function cannot acquire
-        * another refcounted ptr.
-        */
-       if (may_be_acquire_function(func_id) && count)
-               return false;
-
-       /* We only support one arg being unreferenced at the moment,
-        * which is sufficient for the helper functions we have right now.
-        */
-       return count <= 1;
-}
-
 static bool check_btf_id_ok(const struct bpf_func_proto *fn)
 {
        int i;
@@ -6498,13 +6480,11 @@ static bool check_btf_id_ok(const struct bpf_func_proto *fn)
        return true;
 }
 
-static int check_func_proto(const struct bpf_func_proto *fn, int func_id,
-                           struct bpf_call_arg_meta *meta)
+static int check_func_proto(const struct bpf_func_proto *fn, int func_id)
 {
        return check_raw_mode_ok(fn) &&
               check_arg_pair_ok(fn) &&
-              check_btf_id_ok(fn) &&
-              check_refcount_ok(fn, func_id) ? 0 : -EINVAL;
+              check_btf_id_ok(fn) ? 0 : -EINVAL;
 }
 
 /* Packet data might have moved, any old PTR_TO_PACKET[_META,_END]
@@ -7030,8 +7010,7 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
        struct bpf_insn_aux_data *aux = &env->insn_aux_data[insn_idx];
        struct bpf_reg_state *regs = cur_regs(env), *reg;
        struct bpf_map *map = meta->map_ptr;
-       struct tnum range;
-       u64 val;
+       u64 val, max;
        int err;
 
        if (func_id != BPF_FUNC_tail_call)
@@ -7041,10 +7020,11 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
                return -EINVAL;
        }
 
-       range = tnum_range(0, map->max_entries - 1);
        reg = &regs[BPF_REG_3];
+       val = reg->var_off.value;
+       max = map->max_entries;
 
-       if (!register_is_const(reg) || !tnum_in(range, reg->var_off)) {
+       if (!(register_is_const(reg) && val < max)) {
                bpf_map_key_store(aux, BPF_MAP_KEY_POISON);
                return 0;
        }
@@ -7052,8 +7032,6 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
        err = mark_chain_precision(env, BPF_REG_3);
        if (err)
                return err;
-
-       val = reg->var_off.value;
        if (bpf_map_key_unseen(aux))
                bpf_map_key_store(aux, val);
        else if (!bpf_map_key_poisoned(aux) &&
@@ -7218,7 +7196,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
        memset(&meta, 0, sizeof(meta));
        meta.pkt_access = fn->pkt_access;
 
-       err = check_func_proto(fn, func_id, &meta);
+       err = check_func_proto(fn, func_id);
        if (err) {
                verbose(env, "kernel subsystem misconfigured func %s#%d\n",
                        func_id_name(func_id), func_id);
@@ -7343,6 +7321,23 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                        }
                }
                break;
+       case BPF_FUNC_dynptr_data:
+               for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
+                       if (arg_type_is_dynptr(fn->arg_type[i])) {
+                               if (meta.ref_obj_id) {
+                                       verbose(env, "verifier internal error: meta.ref_obj_id already set\n");
+                                       return -EFAULT;
+                               }
+                               /* Find the id of the dynptr we're tracking the reference of */
+                               meta.ref_obj_id = stack_slot_get_id(env, &regs[BPF_REG_1 + i]);
+                               break;
+                       }
+               }
+               if (i == MAX_BPF_FUNC_REG_ARGS) {
+                       verbose(env, "verifier internal error: no dynptr in bpf_dynptr_data()\n");
+                       return -EFAULT;
+               }
+               break;
        }
 
        if (err)
@@ -7359,13 +7354,17 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
 
        /* update return register (already marked as written above) */
        ret_type = fn->ret_type;
-       ret_flag = type_flag(fn->ret_type);
-       if (ret_type == RET_INTEGER) {
+       ret_flag = type_flag(ret_type);
+
+       switch (base_type(ret_type)) {
+       case RET_INTEGER:
                /* sets type to SCALAR_VALUE */
                mark_reg_unknown(env, regs, BPF_REG_0);
-       } else if (ret_type == RET_VOID) {
+               break;
+       case RET_VOID:
                regs[BPF_REG_0].type = NOT_INIT;
-       } else if (base_type(ret_type) == RET_PTR_TO_MAP_VALUE) {
+               break;
+       case RET_PTR_TO_MAP_VALUE:
                /* There is no offset yet applied, variable or fixed */
                mark_reg_known_zero(env, regs, BPF_REG_0);
                /* remember map_ptr, so that check_map_access()
@@ -7384,20 +7383,26 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                    map_value_has_spin_lock(meta.map_ptr)) {
                        regs[BPF_REG_0].id = ++env->id_gen;
                }
-       } else if (base_type(ret_type) == RET_PTR_TO_SOCKET) {
+               break;
+       case RET_PTR_TO_SOCKET:
                mark_reg_known_zero(env, regs, BPF_REG_0);
                regs[BPF_REG_0].type = PTR_TO_SOCKET | ret_flag;
-       } else if (base_type(ret_type) == RET_PTR_TO_SOCK_COMMON) {
+               break;
+       case RET_PTR_TO_SOCK_COMMON:
                mark_reg_known_zero(env, regs, BPF_REG_0);
                regs[BPF_REG_0].type = PTR_TO_SOCK_COMMON | ret_flag;
-       } else if (base_type(ret_type) == RET_PTR_TO_TCP_SOCK) {
+               break;
+       case RET_PTR_TO_TCP_SOCK:
                mark_reg_known_zero(env, regs, BPF_REG_0);
                regs[BPF_REG_0].type = PTR_TO_TCP_SOCK | ret_flag;
-       } else if (base_type(ret_type) == RET_PTR_TO_ALLOC_MEM) {
+               break;
+       case RET_PTR_TO_ALLOC_MEM:
                mark_reg_known_zero(env, regs, BPF_REG_0);
                regs[BPF_REG_0].type = PTR_TO_MEM | ret_flag;
                regs[BPF_REG_0].mem_size = meta.mem_size;
-       } else if (base_type(ret_type) == RET_PTR_TO_MEM_OR_BTF_ID) {
+               break;
+       case RET_PTR_TO_MEM_OR_BTF_ID:
+       {
                const struct btf_type *t;
 
                mark_reg_known_zero(env, regs, BPF_REG_0);
@@ -7429,7 +7434,10 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                        regs[BPF_REG_0].btf = meta.ret_btf;
                        regs[BPF_REG_0].btf_id = meta.ret_btf_id;
                }
-       } else if (base_type(ret_type) == RET_PTR_TO_BTF_ID) {
+               break;
+       }
+       case RET_PTR_TO_BTF_ID:
+       {
                struct btf *ret_btf;
                int ret_btf_id;
 
@@ -7450,7 +7458,9 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                }
                regs[BPF_REG_0].btf = ret_btf;
                regs[BPF_REG_0].btf_id = ret_btf_id;
-       } else {
+               break;
+       }
+       default:
                verbose(env, "unknown return type %u of func %s#%d\n",
                        base_type(ret_type), func_id_name(func_id), func_id);
                return -EINVAL;
@@ -7459,7 +7469,13 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
        if (type_may_be_null(regs[BPF_REG_0].type))
                regs[BPF_REG_0].id = ++env->id_gen;
 
-       if (is_ptr_cast_function(func_id)) {
+       if (helper_multiple_ref_obj_use(func_id, meta.map_ptr)) {
+               verbose(env, "verifier internal error: func %s#%d sets ref_obj_id more than once\n",
+                       func_id_name(func_id), func_id);
+               return -EFAULT;
+       }
+
+       if (is_ptr_cast_function(func_id) || is_dynptr_ref_function(func_id)) {
                /* For release_reference() */
                regs[BPF_REG_0].ref_obj_id = meta.ref_obj_id;
        } else if (is_acquire_function(func_id, meta.map_ptr)) {
@@ -7471,21 +7487,6 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
                regs[BPF_REG_0].id = id;
                /* For release_reference() */
                regs[BPF_REG_0].ref_obj_id = id;
-       } else if (func_id == BPF_FUNC_dynptr_data) {
-               int dynptr_id = 0, i;
-
-               /* Find the id of the dynptr we're acquiring a reference to */
-               for (i = 0; i < MAX_BPF_FUNC_REG_ARGS; i++) {
-                       if (arg_type_is_dynptr(fn->arg_type[i])) {
-                               if (dynptr_id) {
-                                       verbose(env, "verifier internal error: multiple dynptr args in func\n");
-                                       return -EFAULT;
-                               }
-                               dynptr_id = stack_slot_get_id(env, &regs[BPF_REG_1 + i]);
-                       }
-               }
-               /* For release_reference() */
-               regs[BPF_REG_0].ref_obj_id = dynptr_id;
        }
 
        do_refine_retval_range(regs, fn->ret_type, func_id, &meta);
@@ -7584,6 +7585,11 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
                        func_name);
                return -EACCES;
        }
+       if (*kfunc_flags & KF_DESTRUCTIVE && !capable(CAP_SYS_BOOT)) {
+               verbose(env, "destructive kfunc calls require CAP_SYS_BOOT capabilities\n");
+               return -EACCES;
+       }
+
        acq = *kfunc_flags & KF_ACQUIRE;
 
        /* Check the arguments */
index e4bb5d5..2ddae57 100644 (file)
@@ -6164,11 +6164,6 @@ static struct cgroup *cgroup_get_from_file(struct file *f)
                return ERR_CAST(css);
 
        cgrp = css->cgroup;
-       if (!cgroup_on_dfl(cgrp)) {
-               cgroup_put(cgrp);
-               return ERR_PTR(-EBADF);
-       }
-
        return cgrp;
 }
 
index 07b26df..a0eb4d5 100644 (file)
@@ -494,6 +494,7 @@ static int __init crash_save_vmcoreinfo_init(void)
 
 #ifdef CONFIG_KALLSYMS
        VMCOREINFO_SYMBOL(kallsyms_names);
+       VMCOREINFO_SYMBOL(kallsyms_num_syms);
        VMCOREINFO_SYMBOL(kallsyms_token_table);
        VMCOREINFO_SYMBOL(kallsyms_token_index);
 #ifdef CONFIG_KALLSYMS_BASE_RELATIVE
index d4788f8..0b1cd98 100644 (file)
@@ -47,7 +47,7 @@ __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_
                prepare_to_wait(wq_head, &wbq_entry->wq_entry, mode);
                if (test_bit(wbq_entry->key.bit_nr, wbq_entry->key.flags))
                        ret = (*action)(&wbq_entry->key, mode);
-       } while (test_bit(wbq_entry->key.bit_nr, wbq_entry->key.flags) && !ret);
+       } while (test_bit_acquire(wbq_entry->key.bit_nr, wbq_entry->key.flags) && !ret);
 
        finish_wait(wq_head, &wbq_entry->wq_entry);
 
index f7e2463..8ce3fa0 100644 (file)
@@ -688,6 +688,7 @@ static struct genl_family family __ro_after_init = {
        .module         = THIS_MODULE,
        .ops            = taskstats_ops,
        .n_ops          = ARRAY_SIZE(taskstats_ops),
+       .resv_start_op  = CGROUPSTATS_CMD_GET + 1,
        .netnsok        = true,
 };
 
index 072e4b2..bcbe60d 100644 (file)
@@ -2029,13 +2029,16 @@ config LKDTM
        Documentation on how to use the module can be found in
        Documentation/fault-injection/provoke-crashes.rst
 
-config TEST_CPUMASK
-       tristate "cpumask tests" if !KUNIT_ALL_TESTS
+config CPUMASK_KUNIT_TEST
+       tristate "KUnit test for cpumask" if !KUNIT_ALL_TESTS
        depends on KUNIT
        default KUNIT_ALL_TESTS
        help
          Enable to turn on cpumask tests, running at boot or module load time.
 
+         For more information on KUnit and unit tests in general, please refer
+         to the KUnit documentation in Documentation/dev-tools/kunit/.
+
          If unsure, say N.
 
 config TEST_LIST_SORT
index 5927d7f..ffabc30 100644 (file)
@@ -60,6 +60,7 @@ obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
 obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
 CFLAGS_test_bitops.o += -Werror
+obj-$(CONFIG_CPUMASK_KUNIT_TEST) += cpumask_kunit.o
 obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
 obj-$(CONFIG_TEST_SIPHASH) += test_siphash.o
 obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o
@@ -100,7 +101,6 @@ obj-$(CONFIG_TEST_HMM) += test_hmm.o
 obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o
 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
 obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o
-obj-$(CONFIG_TEST_CPUMASK) += test_cpumask.o
 CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE)
 obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o
 #
diff --git a/lib/cpumask_kunit.c b/lib/cpumask_kunit.c
new file mode 100644 (file)
index 0000000..ecbeec7
--- /dev/null
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * KUnit tests for cpumask.
+ *
+ * Author: Sander Vanheule <sander@svanheule.net>
+ */
+
+#include <kunit/test.h>
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+
+#define MASK_MSG(m) \
+       "%s contains %sCPUs %*pbl", #m, (cpumask_weight(m) ? "" : "no "), \
+       nr_cpumask_bits, cpumask_bits(m)
+
+#define EXPECT_FOR_EACH_CPU_EQ(test, mask)                     \
+       do {                                                    \
+               const cpumask_t *m = (mask);                    \
+               int mask_weight = cpumask_weight(m);            \
+               int cpu, iter = 0;                              \
+               for_each_cpu(cpu, m)                            \
+                       iter++;                                 \
+               KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(mask)); \
+       } while (0)
+
+#define EXPECT_FOR_EACH_CPU_NOT_EQ(test, mask)                                 \
+       do {                                                                    \
+               const cpumask_t *m = (mask);                                    \
+               int mask_weight = cpumask_weight(m);                            \
+               int cpu, iter = 0;                                              \
+               for_each_cpu_not(cpu, m)                                        \
+                       iter++;                                                 \
+               KUNIT_EXPECT_EQ_MSG((test), nr_cpu_ids - mask_weight, iter, MASK_MSG(mask));    \
+       } while (0)
+
+#define EXPECT_FOR_EACH_CPU_WRAP_EQ(test, mask)                        \
+       do {                                                    \
+               const cpumask_t *m = (mask);                    \
+               int mask_weight = cpumask_weight(m);            \
+               int cpu, iter = 0;                              \
+               for_each_cpu_wrap(cpu, m, nr_cpu_ids / 2)       \
+                       iter++;                                 \
+               KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(mask)); \
+       } while (0)
+
+#define EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, name)             \
+       do {                                                    \
+               int mask_weight = num_##name##_cpus();          \
+               int cpu, iter = 0;                              \
+               for_each_##name##_cpu(cpu)                      \
+                       iter++;                                 \
+               KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(cpu_##name##_mask));    \
+       } while (0)
+
+static cpumask_t mask_empty;
+static cpumask_t mask_all;
+
+static void test_cpumask_weight(struct kunit *test)
+{
+       KUNIT_EXPECT_TRUE_MSG(test, cpumask_empty(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_TRUE_MSG(test, cpumask_full(&mask_all), MASK_MSG(&mask_all));
+
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_weight(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids, cpumask_weight(cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+       KUNIT_EXPECT_EQ_MSG(test, nr_cpumask_bits, cpumask_weight(&mask_all), MASK_MSG(&mask_all));
+}
+
+static void test_cpumask_first(struct kunit *test)
+{
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_first(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_first(cpu_possible_mask), MASK_MSG(cpu_possible_mask));
+
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_first_zero(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_first_zero(cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+}
+
+static void test_cpumask_last(struct kunit *test)
+{
+       KUNIT_EXPECT_LE_MSG(test, nr_cpumask_bits, cpumask_last(&mask_empty),
+                           MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids - 1, cpumask_last(cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+}
+
+static void test_cpumask_next(struct kunit *test)
+{
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_next_zero(-1, &mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_next_zero(-1, cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_next(-1, &mask_empty),
+                           MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_next(-1, cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+}
+
+static void test_cpumask_iterators(struct kunit *test)
+{
+       EXPECT_FOR_EACH_CPU_EQ(test, &mask_empty);
+       EXPECT_FOR_EACH_CPU_NOT_EQ(test, &mask_empty);
+       EXPECT_FOR_EACH_CPU_WRAP_EQ(test, &mask_empty);
+
+       EXPECT_FOR_EACH_CPU_EQ(test, cpu_possible_mask);
+       EXPECT_FOR_EACH_CPU_NOT_EQ(test, cpu_possible_mask);
+       EXPECT_FOR_EACH_CPU_WRAP_EQ(test, cpu_possible_mask);
+}
+
+static void test_cpumask_iterators_builtin(struct kunit *test)
+{
+       EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, possible);
+
+       /* Ensure the dynamic masks are stable while running the tests */
+       cpu_hotplug_disable();
+
+       EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, online);
+       EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, present);
+
+       cpu_hotplug_enable();
+}
+
+static int test_cpumask_init(struct kunit *test)
+{
+       cpumask_clear(&mask_empty);
+       cpumask_setall(&mask_all);
+
+       return 0;
+}
+
+static struct kunit_case test_cpumask_cases[] = {
+       KUNIT_CASE(test_cpumask_weight),
+       KUNIT_CASE(test_cpumask_first),
+       KUNIT_CASE(test_cpumask_last),
+       KUNIT_CASE(test_cpumask_next),
+       KUNIT_CASE(test_cpumask_iterators),
+       KUNIT_CASE(test_cpumask_iterators_builtin),
+       {}
+};
+
+static struct kunit_suite test_cpumask_suite = {
+       .name = "cpumask",
+       .init = test_cpumask_init,
+       .test_cases = test_cpumask_cases,
+};
+kunit_test_suite(test_cpumask_suite);
+
+MODULE_LICENSE("GPL");
index 9ff549f..47816af 100644 (file)
@@ -33,7 +33,6 @@ config CRYPTO_ARCH_HAVE_LIB_CHACHA
 
 config CRYPTO_LIB_CHACHA_GENERIC
        tristate
-       select XOR_BLOCKS
        help
          This symbol can be depended upon by arch implementations of the
          ChaCha library interface that require the generic code as a
diff --git a/lib/test_cpumask.c b/lib/test_cpumask.c
deleted file mode 100644 (file)
index a31a162..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * KUnit tests for cpumask.
- *
- * Author: Sander Vanheule <sander@svanheule.net>
- */
-
-#include <kunit/test.h>
-#include <linux/cpu.h>
-#include <linux/cpumask.h>
-
-#define EXPECT_FOR_EACH_CPU_EQ(test, mask)                     \
-       do {                                                    \
-               const cpumask_t *m = (mask);                    \
-               int mask_weight = cpumask_weight(m);            \
-               int cpu, iter = 0;                              \
-               for_each_cpu(cpu, m)                            \
-                       iter++;                                 \
-               KUNIT_EXPECT_EQ((test), mask_weight, iter);     \
-       } while (0)
-
-#define EXPECT_FOR_EACH_CPU_NOT_EQ(test, mask)                                 \
-       do {                                                                    \
-               const cpumask_t *m = (mask);                                    \
-               int mask_weight = cpumask_weight(m);                            \
-               int cpu, iter = 0;                                              \
-               for_each_cpu_not(cpu, m)                                        \
-                       iter++;                                                 \
-               KUNIT_EXPECT_EQ((test), nr_cpu_ids - mask_weight, iter);        \
-       } while (0)
-
-#define EXPECT_FOR_EACH_CPU_WRAP_EQ(test, mask)                        \
-       do {                                                    \
-               const cpumask_t *m = (mask);                    \
-               int mask_weight = cpumask_weight(m);            \
-               int cpu, iter = 0;                              \
-               for_each_cpu_wrap(cpu, m, nr_cpu_ids / 2)       \
-                       iter++;                                 \
-               KUNIT_EXPECT_EQ((test), mask_weight, iter);     \
-       } while (0)
-
-#define EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, name)             \
-       do {                                                    \
-               int mask_weight = num_##name##_cpus();          \
-               int cpu, iter = 0;                              \
-               for_each_##name##_cpu(cpu)                      \
-                       iter++;                                 \
-               KUNIT_EXPECT_EQ((test), mask_weight, iter);     \
-       } while (0)
-
-static cpumask_t mask_empty;
-static cpumask_t mask_all;
-
-static void test_cpumask_weight(struct kunit *test)
-{
-       KUNIT_EXPECT_TRUE(test, cpumask_empty(&mask_empty));
-       KUNIT_EXPECT_TRUE(test, cpumask_full(cpu_possible_mask));
-       KUNIT_EXPECT_TRUE(test, cpumask_full(&mask_all));
-
-       KUNIT_EXPECT_EQ(test, 0, cpumask_weight(&mask_empty));
-       KUNIT_EXPECT_EQ(test, nr_cpu_ids, cpumask_weight(cpu_possible_mask));
-       KUNIT_EXPECT_EQ(test, nr_cpumask_bits, cpumask_weight(&mask_all));
-}
-
-static void test_cpumask_first(struct kunit *test)
-{
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_first(&mask_empty));
-       KUNIT_EXPECT_EQ(test, 0, cpumask_first(cpu_possible_mask));
-
-       KUNIT_EXPECT_EQ(test, 0, cpumask_first_zero(&mask_empty));
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_first_zero(cpu_possible_mask));
-}
-
-static void test_cpumask_last(struct kunit *test)
-{
-       KUNIT_EXPECT_LE(test, nr_cpumask_bits, cpumask_last(&mask_empty));
-       KUNIT_EXPECT_EQ(test, nr_cpumask_bits - 1, cpumask_last(cpu_possible_mask));
-}
-
-static void test_cpumask_next(struct kunit *test)
-{
-       KUNIT_EXPECT_EQ(test, 0, cpumask_next_zero(-1, &mask_empty));
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_next_zero(-1, cpu_possible_mask));
-
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_next(-1, &mask_empty));
-       KUNIT_EXPECT_EQ(test, 0, cpumask_next(-1, cpu_possible_mask));
-}
-
-static void test_cpumask_iterators(struct kunit *test)
-{
-       EXPECT_FOR_EACH_CPU_EQ(test, &mask_empty);
-       EXPECT_FOR_EACH_CPU_NOT_EQ(test, &mask_empty);
-       EXPECT_FOR_EACH_CPU_WRAP_EQ(test, &mask_empty);
-
-       EXPECT_FOR_EACH_CPU_EQ(test, cpu_possible_mask);
-       EXPECT_FOR_EACH_CPU_NOT_EQ(test, cpu_possible_mask);
-       EXPECT_FOR_EACH_CPU_WRAP_EQ(test, cpu_possible_mask);
-}
-
-static void test_cpumask_iterators_builtin(struct kunit *test)
-{
-       EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, possible);
-
-       /* Ensure the dynamic masks are stable while running the tests */
-       cpu_hotplug_disable();
-
-       EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, online);
-       EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, present);
-
-       cpu_hotplug_enable();
-}
-
-static int test_cpumask_init(struct kunit *test)
-{
-       cpumask_clear(&mask_empty);
-       cpumask_setall(&mask_all);
-
-       return 0;
-}
-
-static struct kunit_case test_cpumask_cases[] = {
-       KUNIT_CASE(test_cpumask_weight),
-       KUNIT_CASE(test_cpumask_first),
-       KUNIT_CASE(test_cpumask_last),
-       KUNIT_CASE(test_cpumask_next),
-       KUNIT_CASE(test_cpumask_iterators),
-       KUNIT_CASE(test_cpumask_iterators_builtin),
-       {}
-};
-
-static struct kunit_suite test_cpumask_suite = {
-       .name = "cpumask",
-       .init = test_cpumask_init,
-       .test_cases = test_cpumask_cases,
-};
-kunit_test_suite(test_cpumask_suite);
-
-MODULE_LICENSE("GPL");
index 95550b8..de65cb1 100644 (file)
@@ -260,10 +260,10 @@ void wb_wakeup_delayed(struct bdi_writeback *wb)
        unsigned long timeout;
 
        timeout = msecs_to_jiffies(dirty_writeback_interval * 10);
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (test_bit(WB_registered, &wb->state))
                queue_delayed_work(bdi_wq, &wb->dwork, timeout);
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 }
 
 static void wb_update_bandwidth_workfn(struct work_struct *work)
@@ -334,12 +334,12 @@ static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb);
 static void wb_shutdown(struct bdi_writeback *wb)
 {
        /* Make sure nobody queues further work */
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (!test_and_clear_bit(WB_registered, &wb->state)) {
-               spin_unlock_bh(&wb->work_lock);
+               spin_unlock_irq(&wb->work_lock);
                return;
        }
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 
        cgwb_remove_from_bdi_list(wb);
        /*
index f18a631..b1efebf 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/memblock.h>
 #include <linux/bootmem_info.h>
 #include <linux/memory_hotplug.h>
+#include <linux/kmemleak.h>
 
 void get_page_bootmem(unsigned long info, struct page *page, unsigned long type)
 {
@@ -33,6 +34,7 @@ void put_page_bootmem(struct page *page)
                ClearPagePrivate(page);
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
+               kmemleak_free_part(page_to_virt(page), PAGE_SIZE);
                free_reserved_page(page);
        }
 }
index cb8a7e9..cfdf631 100644 (file)
@@ -818,6 +818,9 @@ static int dbgfs_mk_context(char *name)
                return -ENOENT;
 
        new_dir = debugfs_create_dir(name, root);
+       /* Below check is required for a potential duplicated name case */
+       if (IS_ERR(new_dir))
+               return PTR_ERR(new_dir);
        dbgfs_dirs[dbgfs_nr_ctxs] = new_dir;
 
        new_ctx = dbgfs_new_ctx();
index 2480ba6..e070b85 100644 (file)
@@ -6041,7 +6041,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
        if (!huge_pte_none_mostly(huge_ptep_get(dst_pte)))
                goto out_release_unlock;
 
-       if (vm_shared) {
+       if (page_in_pagecache) {
                page_dup_file_rmap(page, true);
        } else {
                ClearHPageRestoreReserve(page);
index 3a23dde..bc6bddd 100644 (file)
@@ -196,10 +196,11 @@ static unsigned long change_pte_range(struct mmu_gather *tlb,
                        pages++;
                } else if (is_swap_pte(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
-                       struct page *page = pfn_swap_entry_to_page(entry);
                        pte_t newpte;
 
                        if (is_writable_migration_entry(entry)) {
+                               struct page *page = pfn_swap_entry_to_page(entry);
+
                                /*
                                 * A protection check is difficult so
                                 * just be safe and disable write
index d0d466a..032a7bf 100644 (file)
@@ -2892,6 +2892,7 @@ static void wb_inode_writeback_start(struct bdi_writeback *wb)
 
 static void wb_inode_writeback_end(struct bdi_writeback *wb)
 {
+       unsigned long flags;
        atomic_dec(&wb->writeback_inodes);
        /*
         * Make sure estimate of writeback throughput gets updated after
@@ -2900,7 +2901,10 @@ static void wb_inode_writeback_end(struct bdi_writeback *wb)
         * that if multiple inodes end writeback at a similar time, they get
         * batched into one bandwidth update.
         */
-       queue_delayed_work(bdi_wq, &wb->bw_dwork, BANDWIDTH_INTERVAL);
+       spin_lock_irqsave(&wb->work_lock, flags);
+       if (test_bit(WB_registered, &wb->state))
+               queue_delayed_work(bdi_wq, &wb->bw_dwork, BANDWIDTH_INTERVAL);
+       spin_unlock_irqrestore(&wb->work_lock, flags);
 }
 
 bool __folio_end_writeback(struct folio *folio)
index edc06c5..93d5a6f 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -93,7 +93,8 @@ static inline struct anon_vma *anon_vma_alloc(void)
        anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
        if (anon_vma) {
                atomic_set(&anon_vma->refcount, 1);
-               anon_vma->degree = 1;   /* Reference for first vma */
+               anon_vma->num_children = 0;
+               anon_vma->num_active_vmas = 0;
                anon_vma->parent = anon_vma;
                /*
                 * Initialise the anon_vma root to point to itself. If called
@@ -201,6 +202,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
                anon_vma = anon_vma_alloc();
                if (unlikely(!anon_vma))
                        goto out_enomem_free_avc;
+               anon_vma->num_children++; /* self-parent link for new root */
                allocated = anon_vma;
        }
 
@@ -210,8 +212,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
        if (likely(!vma->anon_vma)) {
                vma->anon_vma = anon_vma;
                anon_vma_chain_link(vma, avc, anon_vma);
-               /* vma reference or self-parent link for new root */
-               anon_vma->degree++;
+               anon_vma->num_active_vmas++;
                allocated = NULL;
                avc = NULL;
        }
@@ -296,19 +297,19 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
                anon_vma_chain_link(dst, avc, anon_vma);
 
                /*
-                * Reuse existing anon_vma if its degree lower than two,
-                * that means it has no vma and only one anon_vma child.
+                * Reuse existing anon_vma if it has no vma and only one
+                * anon_vma child.
                 *
-                * Do not choose parent anon_vma, otherwise first child
-                * will always reuse it. Root anon_vma is never reused:
+                * Root anon_vma is never reused:
                 * it has self-parent reference and at least one child.
                 */
                if (!dst->anon_vma && src->anon_vma &&
-                   anon_vma != src->anon_vma && anon_vma->degree < 2)
+                   anon_vma->num_children < 2 &&
+                   anon_vma->num_active_vmas == 0)
                        dst->anon_vma = anon_vma;
        }
        if (dst->anon_vma)
-               dst->anon_vma->degree++;
+               dst->anon_vma->num_active_vmas++;
        unlock_anon_vma_root(root);
        return 0;
 
@@ -358,6 +359,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        anon_vma = anon_vma_alloc();
        if (!anon_vma)
                goto out_error;
+       anon_vma->num_active_vmas++;
        avc = anon_vma_chain_alloc(GFP_KERNEL);
        if (!avc)
                goto out_error_free_anon_vma;
@@ -378,7 +380,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        vma->anon_vma = anon_vma;
        anon_vma_lock_write(anon_vma);
        anon_vma_chain_link(vma, avc, anon_vma);
-       anon_vma->parent->degree++;
+       anon_vma->parent->num_children++;
        anon_vma_unlock_write(anon_vma);
 
        return 0;
@@ -410,7 +412,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
                 * to free them outside the lock.
                 */
                if (RB_EMPTY_ROOT(&anon_vma->rb_root.rb_root)) {
-                       anon_vma->parent->degree--;
+                       anon_vma->parent->num_children--;
                        continue;
                }
 
@@ -418,7 +420,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
                anon_vma_chain_free(avc);
        }
        if (vma->anon_vma) {
-               vma->anon_vma->degree--;
+               vma->anon_vma->num_active_vmas--;
 
                /*
                 * vma would still be needed after unlink, and anon_vma will be prepared
@@ -436,7 +438,8 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
        list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
                struct anon_vma *anon_vma = avc->anon_vma;
 
-               VM_WARN_ON(anon_vma->degree);
+               VM_WARN_ON(anon_vma->num_children);
+               VM_WARN_ON(anon_vma->num_active_vmas);
                put_anon_vma(anon_vma);
 
                list_del(&avc->same_vma);
index d075dd2..42e5888 100644 (file)
@@ -1782,6 +1782,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
 
        if (shmem_should_replace_folio(folio, gfp)) {
                error = shmem_replace_page(&page, gfp, info, index);
+               folio = page_folio(page);
                if (error)
                        goto failed;
        }
index 1799664..07b9482 100644 (file)
@@ -392,6 +392,28 @@ kmem_cache_create(const char *name, unsigned int size, unsigned int align,
 }
 EXPORT_SYMBOL(kmem_cache_create);
 
+#ifdef SLAB_SUPPORTS_SYSFS
+/*
+ * For a given kmem_cache, kmem_cache_destroy() should only be called
+ * once or there will be a use-after-free problem. The actual deletion
+ * and release of the kobject does not need slab_mutex or cpu_hotplug_lock
+ * protection. So they are now done without holding those locks.
+ *
+ * Note that there will be a slight delay in the deletion of sysfs files
+ * if kmem_cache_release() is called indrectly from a work function.
+ */
+static void kmem_cache_release(struct kmem_cache *s)
+{
+       sysfs_slab_unlink(s);
+       sysfs_slab_release(s);
+}
+#else
+static void kmem_cache_release(struct kmem_cache *s)
+{
+       slab_kmem_cache_release(s);
+}
+#endif
+
 static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work)
 {
        LIST_HEAD(to_destroy);
@@ -418,11 +440,7 @@ static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work)
        list_for_each_entry_safe(s, s2, &to_destroy, list) {
                debugfs_slab_release(s);
                kfence_shutdown_cache(s);
-#ifdef SLAB_SUPPORTS_SYSFS
-               sysfs_slab_release(s);
-#else
-               slab_kmem_cache_release(s);
-#endif
+               kmem_cache_release(s);
        }
 }
 
@@ -437,20 +455,11 @@ static int shutdown_cache(struct kmem_cache *s)
        list_del(&s->list);
 
        if (s->flags & SLAB_TYPESAFE_BY_RCU) {
-#ifdef SLAB_SUPPORTS_SYSFS
-               sysfs_slab_unlink(s);
-#endif
                list_add_tail(&s->list, &slab_caches_to_rcu_destroy);
                schedule_work(&slab_caches_to_rcu_destroy_work);
        } else {
                kfence_shutdown_cache(s);
                debugfs_slab_release(s);
-#ifdef SLAB_SUPPORTS_SYSFS
-               sysfs_slab_unlink(s);
-               sysfs_slab_release(s);
-#else
-               slab_kmem_cache_release(s);
-#endif
        }
 
        return 0;
@@ -465,14 +474,16 @@ void slab_kmem_cache_release(struct kmem_cache *s)
 
 void kmem_cache_destroy(struct kmem_cache *s)
 {
+       int refcnt;
+
        if (unlikely(!s) || !kasan_check_byte(s))
                return;
 
        cpus_read_lock();
        mutex_lock(&slab_mutex);
 
-       s->refcount--;
-       if (s->refcount)
+       refcnt = --s->refcount;
+       if (refcnt)
                goto out_unlock;
 
        WARN(shutdown_cache(s),
@@ -481,6 +492,8 @@ void kmem_cache_destroy(struct kmem_cache *s)
 out_unlock:
        mutex_unlock(&slab_mutex);
        cpus_read_unlock();
+       if (!refcnt && !(s->flags & SLAB_TYPESAFE_BY_RCU))
+               kmem_cache_release(s);
 }
 EXPORT_SYMBOL(kmem_cache_destroy);
 
index 34f784a..907c9b1 100644 (file)
@@ -1487,7 +1487,7 @@ void zs_free(struct zs_pool *pool, unsigned long handle)
        struct size_class *class;
        enum fullness_group fullness;
 
-       if (unlikely(!handle))
+       if (IS_ERR_OR_NULL((void *)handle))
                return;
 
        /*
index 5aa8144..0beb44f 100644 (file)
@@ -467,12 +467,9 @@ static struct sk_buff *vlan_gro_receive(struct list_head *head,
 
        off_vlan = skb_gro_offset(skb);
        hlen = off_vlan + sizeof(*vhdr);
-       vhdr = skb_gro_header_fast(skb, off_vlan);
-       if (skb_gro_header_hard(skb, hlen)) {
-               vhdr = skb_gro_header_slow(skb, hlen, off_vlan);
-               if (unlikely(!vhdr))
-                       goto out;
-       }
+       vhdr = skb_gro_header(skb, hlen, off_vlan);
+       if (unlikely(!vhdr))
+               goto out;
 
        type = vhdr->h_vlan_encapsulated_proto;
 
index 035812b..e1bb41a 100644 (file)
@@ -674,9 +674,9 @@ static int vlan_ethtool_get_link_ksettings(struct net_device *dev,
 static void vlan_ethtool_get_drvinfo(struct net_device *dev,
                                     struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, vlan_fullname, sizeof(info->driver));
-       strlcpy(info->version, vlan_version, sizeof(info->version));
-       strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
+       strscpy(info->driver, vlan_fullname, sizeof(info->driver));
+       strscpy(info->version, vlan_version, sizeof(info->version));
+       strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
 }
 
 static int vlan_ethtool_get_ts_info(struct net_device *dev,
index 6b78f69..48c33c2 100644 (file)
@@ -204,7 +204,6 @@ config BRIDGE_NETFILTER
 source "net/netfilter/Kconfig"
 source "net/ipv4/netfilter/Kconfig"
 source "net/ipv6/netfilter/Kconfig"
-source "net/decnet/netfilter/Kconfig"
 source "net/bridge/netfilter/Kconfig"
 
 endif
@@ -221,7 +220,6 @@ source "net/802/Kconfig"
 source "net/bridge/Kconfig"
 source "net/dsa/Kconfig"
 source "net/8021q/Kconfig"
-source "net/decnet/Kconfig"
 source "net/llc/Kconfig"
 source "drivers/net/appletalk/Kconfig"
 source "net/x25/Kconfig"
index fbfeb8a..6a62e5b 100644 (file)
@@ -38,7 +38,6 @@ obj-$(CONFIG_AF_KCM)          += kcm/
 obj-$(CONFIG_STREAM_PARSER)    += strparser/
 obj-$(CONFIG_ATM)              += atm/
 obj-$(CONFIG_L2TP)             += l2tp/
-obj-$(CONFIG_DECNET)           += decnet/
 obj-$(CONFIG_PHONET)           += phonet/
 ifneq ($(CONFIG_VLAN_8021Q),)
 obj-y                          += 8021q/
index d82a51e..6b4c25a 100644 (file)
@@ -778,7 +778,7 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname,
                ax25_dev = ax25->ax25_dev;
 
                if (ax25_dev != NULL && ax25_dev->dev != NULL) {
-                       strlcpy(devname, ax25_dev->dev->name, sizeof(devname));
+                       strscpy(devname, ax25_dev->dev->name, sizeof(devname));
                        length = strlen(devname) + 1;
                } else {
                        *devname = '\0';
index 00875e1..a5e4a4e 100644 (file)
@@ -1493,6 +1493,7 @@ struct genl_family batadv_netlink_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = batadv_netlink_ops,
        .n_small_ops = ARRAY_SIZE(batadv_netlink_ops),
+       .resv_start_op = BATADV_CMD_SET_VLAN + 1,
        .mcgrps = batadv_netlink_mcgrps,
        .n_mcgrps = ARRAY_SIZE(batadv_netlink_mcgrps),
 };
index 485c814..6643c9c 100644 (file)
@@ -4179,6 +4179,17 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
                }
        }
 
+       if (i == ARRAY_SIZE(hci_cc_table)) {
+               /* Unknown opcode, assume byte 0 contains the status, so
+                * that e.g. __hci_cmd_sync() properly returns errors
+                * for vendor specific commands send by HCI drivers.
+                * If a vendor doesn't actually follow this convention we may
+                * need to introduce a vendor CC table in order to properly set
+                * the status.
+                */
+               *status = skb->data[0];
+       }
+
        handle_cmd_cnt_and_timer(hdev, ev->ncmd);
 
        hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
@@ -5790,7 +5801,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
         */
        hci_dev_clear_flag(hdev, HCI_LE_ADV);
 
-       conn = hci_lookup_le_connect(hdev);
+       conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, bdaddr);
        if (!conn) {
                /* In case of error status and there is no connection pending
                 * just unlock as there is nothing to cleanup.
index e6d804b..1877864 100644 (file)
@@ -4773,9 +4773,11 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason)
                /* Cleanup hci_conn object if it cannot be cancelled as it
                 * likelly means the controller and host stack are out of sync.
                 */
-               if (err)
+               if (err) {
+                       hci_dev_lock(hdev);
                        hci_conn_failed(conn, err);
-
+                       hci_dev_unlock(hdev);
+               }
                return err;
        case BT_CONNECT2:
                return hci_reject_conn_sync(hdev, conn, reason);
@@ -5288,17 +5290,21 @@ int hci_suspend_sync(struct hci_dev *hdev)
        /* Prevent disconnects from causing scanning to be re-enabled */
        hci_pause_scan_sync(hdev);
 
-       /* Soft disconnect everything (power off) */
-       err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
-       if (err) {
-               /* Set state to BT_RUNNING so resume doesn't notify */
-               hdev->suspend_state = BT_RUNNING;
-               hci_resume_sync(hdev);
-               return err;
-       }
+       if (hci_conn_count(hdev)) {
+               /* Soft disconnect everything (power off) */
+               err = hci_disconnect_all_sync(hdev, HCI_ERROR_REMOTE_POWER_OFF);
+               if (err) {
+                       /* Set state to BT_RUNNING so resume doesn't notify */
+                       hdev->suspend_state = BT_RUNNING;
+                       hci_resume_sync(hdev);
+                       return err;
+               }
 
-       /* Update event mask so only the allowed event can wakeup the host */
-       hci_set_event_mask_sync(hdev);
+               /* Update event mask so only the allowed event can wakeup the
+                * host.
+                */
+               hci_set_event_mask_sync(hdev);
+       }
 
        /* Only configure accept list if disconnect succeeded and wake
         * isn't being prevented.
index 5940744..cc20e70 100644 (file)
@@ -83,14 +83,14 @@ static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo
                ci->product = session->input->id.product;
                ci->version = session->input->id.version;
                if (session->input->name)
-                       strlcpy(ci->name, session->input->name, 128);
+                       strscpy(ci->name, session->input->name, 128);
                else
-                       strlcpy(ci->name, "HID Boot Device", 128);
+                       strscpy(ci->name, "HID Boot Device", 128);
        } else if (session->hid) {
                ci->vendor  = session->hid->vendor;
                ci->product = session->hid->product;
                ci->version = session->hid->version;
-               strlcpy(ci->name, session->hid->name, 128);
+               strscpy(ci->name, session->hid->name, 128);
        }
 }
 
index ced8ad4..613039b 100644 (file)
@@ -1309,7 +1309,7 @@ static int iso_sock_shutdown(struct socket *sock, int how)
        struct sock *sk = sock->sk;
        int err = 0;
 
-       BT_DBG("sock %p, sk %p", sock, sk);
+       BT_DBG("sock %p, sk %p, how %d", sock, sk, how);
 
        if (!sk)
                return 0;
@@ -1317,17 +1317,32 @@ static int iso_sock_shutdown(struct socket *sock, int how)
        sock_hold(sk);
        lock_sock(sk);
 
-       if (!sk->sk_shutdown) {
-               sk->sk_shutdown = SHUTDOWN_MASK;
-               iso_sock_clear_timer(sk);
-               __iso_sock_close(sk);
-
-               if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
-                   !(current->flags & PF_EXITING))
-                       err = bt_sock_wait_state(sk, BT_CLOSED,
-                                                sk->sk_lingertime);
+       switch (how) {
+       case SHUT_RD:
+               if (sk->sk_shutdown & RCV_SHUTDOWN)
+                       goto unlock;
+               sk->sk_shutdown |= RCV_SHUTDOWN;
+               break;
+       case SHUT_WR:
+               if (sk->sk_shutdown & SEND_SHUTDOWN)
+                       goto unlock;
+               sk->sk_shutdown |= SEND_SHUTDOWN;
+               break;
+       case SHUT_RDWR:
+               if (sk->sk_shutdown & SHUTDOWN_MASK)
+                       goto unlock;
+               sk->sk_shutdown |= SHUTDOWN_MASK;
+               break;
        }
 
+       iso_sock_clear_timer(sk);
+       __iso_sock_close(sk);
+
+       if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime &&
+           !(current->flags & PF_EXITING))
+               err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
+
+unlock:
        release_sock(sk);
        sock_put(sk);
 
index cbe0cae..2c9de67 100644 (file)
@@ -1992,11 +1992,11 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
                        src_match = !bacmp(&c->src, src);
                        dst_match = !bacmp(&c->dst, dst);
                        if (src_match && dst_match) {
-                               c = l2cap_chan_hold_unless_zero(c);
-                               if (c) {
-                                       read_unlock(&chan_list_lock);
-                                       return c;
-                               }
+                               if (!l2cap_chan_hold_unless_zero(c))
+                                       continue;
+
+                               read_unlock(&chan_list_lock);
+                               return c;
                        }
 
                        /* Closest match */
index 6e31023..72e6595 100644 (file)
@@ -4547,6 +4547,22 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
                               MGMT_STATUS_NOT_SUPPORTED);
 }
 
+static u32 get_params_flags(struct hci_dev *hdev,
+                           struct hci_conn_params *params)
+{
+       u32 flags = hdev->conn_flags;
+
+       /* Devices using RPAs can only be programmed in the acceptlist if
+        * LL Privacy has been enable otherwise they cannot mark
+        * HCI_CONN_FLAG_REMOTE_WAKEUP.
+        */
+       if ((flags & HCI_CONN_FLAG_REMOTE_WAKEUP) && !use_ll_privacy(hdev) &&
+           hci_find_irk_by_addr(hdev, &params->addr, params->addr_type))
+               flags &= ~HCI_CONN_FLAG_REMOTE_WAKEUP;
+
+       return flags;
+}
+
 static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
                            u16 data_len)
 {
@@ -4578,10 +4594,10 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
        } else {
                params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
                                                le_addr_type(cp->addr.type));
-
                if (!params)
                        goto done;
 
+               supported_flags = get_params_flags(hdev, params);
                current_flags = params->flags;
        }
 
@@ -4649,38 +4665,35 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
                        bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
                                    &cp->addr.bdaddr, cp->addr.type);
                }
-       } else {
-               params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
-                                               le_addr_type(cp->addr.type));
-               if (params) {
-                       /* Devices using RPAs can only be programmed in the
-                        * acceptlist LL Privacy has been enable otherwise they
-                        * cannot mark HCI_CONN_FLAG_REMOTE_WAKEUP.
-                        */
-                       if ((current_flags & HCI_CONN_FLAG_REMOTE_WAKEUP) &&
-                           !use_ll_privacy(hdev) &&
-                           hci_find_irk_by_addr(hdev, &params->addr,
-                                                params->addr_type)) {
-                               bt_dev_warn(hdev,
-                                           "Cannot set wakeable for RPA");
-                               goto unlock;
-                       }
 
-                       params->flags = current_flags;
-                       status = MGMT_STATUS_SUCCESS;
+               goto unlock;
+       }
 
-                       /* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
-                        * has been set.
-                        */
-                       if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
-                               hci_update_passive_scan(hdev);
-               } else {
-                       bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
-                                   &cp->addr.bdaddr,
-                                   le_addr_type(cp->addr.type));
-               }
+       params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
+                                       le_addr_type(cp->addr.type));
+       if (!params) {
+               bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
+                           &cp->addr.bdaddr, le_addr_type(cp->addr.type));
+               goto unlock;
        }
 
+       supported_flags = get_params_flags(hdev, params);
+
+       if ((supported_flags | current_flags) != supported_flags) {
+               bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
+                           current_flags, supported_flags);
+               goto unlock;
+       }
+
+       params->flags = current_flags;
+       status = MGMT_STATUS_SUCCESS;
+
+       /* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
+        * has been set.
+        */
+       if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
+               hci_update_passive_scan(hdev);
+
 unlock:
        hci_dev_unlock(hdev);
 
@@ -5054,7 +5067,6 @@ static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
                else
                        status = MGMT_STATUS_FAILED;
 
-               mgmt_pending_remove(cmd);
                goto unlock;
        }
 
index d112093..25d8ecf 100644 (file)
@@ -695,6 +695,10 @@ noinline void bpf_kfunc_call_test_ref(struct prog_test_ref_kfunc *p)
 {
 }
 
+noinline void bpf_kfunc_call_test_destructive(void)
+{
+}
+
 __diag_pop();
 
 ALLOW_ERROR_INJECTION(bpf_modify_return_test, ERRNO);
@@ -719,6 +723,7 @@ BTF_ID_FLAGS(func, bpf_kfunc_call_test_mem_len_pass1)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test_mem_len_fail1)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test_mem_len_fail2)
 BTF_ID_FLAGS(func, bpf_kfunc_call_test_ref, KF_TRUSTED_ARGS)
+BTF_ID_FLAGS(func, bpf_kfunc_call_test_destructive, KF_DESTRUCTIVE)
 BTF_SET8_END(test_sk_check_kfunc_ids)
 
 static void *bpf_test_init(const union bpf_attr *kattr, u32 user_size,
index 58a4f70..b82906f 100644 (file)
@@ -251,10 +251,10 @@ static int br_set_mac_address(struct net_device *dev, void *p)
 
 static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "bridge", sizeof(info->driver));
-       strlcpy(info->version, BR_VERSION, sizeof(info->version));
-       strlcpy(info->fw_version, "N/A", sizeof(info->fw_version));
-       strlcpy(info->bus_info, "N/A", sizeof(info->bus_info));
+       strscpy(info->driver, "bridge", sizeof(info->driver));
+       strscpy(info->version, BR_VERSION, sizeof(info->version));
+       strscpy(info->fw_version, "N/A", sizeof(info->fw_version));
+       strscpy(info->bus_info, "N/A", sizeof(info->bus_info));
 }
 
 static int br_get_link_ksettings(struct net_device *dev,
index a84a7cf..efbd93e 100644 (file)
@@ -568,26 +568,6 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
            !is_valid_ether_addr(dev->dev_addr))
                return -EINVAL;
 
-       /* Also don't allow bridging of net devices that are DSA masters, since
-        * the bridge layer rx_handler prevents the DSA fake ethertype handler
-        * to be invoked, so we don't get the chance to strip off and parse the
-        * DSA switch tag protocol header (the bridge layer just returns
-        * RX_HANDLER_CONSUMED, stopping RX processing for these frames).
-        * The only case where that would not be an issue is when bridging can
-        * already be offloaded, such as when the DSA master is itself a DSA
-        * or plain switchdev port, and is bridged only with other ports from
-        * the same hardware device.
-        */
-       if (netdev_uses_dsa(dev)) {
-               list_for_each_entry(p, &br->port_list, list) {
-                       if (!netdev_port_same_parent_id(dev, p->dev)) {
-                               NL_SET_ERR_MSG(extack,
-                                              "Cannot do software bridging with a DSA master");
-                               return -EINVAL;
-                       }
-               }
-       }
-
        /* No bridging of bridges */
        if (dev->netdev_ops->ndo_start_xmit == br_dev_xmit) {
                NL_SET_ERR_MSG(extack,
index 07fa760..74fdd81 100644 (file)
@@ -384,7 +384,7 @@ int br_sysfs_addif(struct net_bridge_port *p)
                        return err;
        }
 
-       strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
+       strscpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
        return sysfs_create_link(br->ifobj, &p->kobj, p->sysfs_name);
 }
 
@@ -406,7 +406,7 @@ int br_sysfs_renameif(struct net_bridge_port *p)
                netdev_notice(br->dev, "unable to rename link %s to %s",
                              p->sysfs_name, p->dev->name);
        else
-               strlcpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
+               strscpy(p->sysfs_name, p->dev->name, IFNAMSIZ);
 
        return err;
 }
index 9a0ae59..8f6639e 100644 (file)
@@ -1440,7 +1440,7 @@ static inline int ebt_obj_to_user(char __user *um, const char *_name,
        /* ebtables expects 31 bytes long names but xt_match names are 29 bytes
         * long. Copy 29 bytes and fill remaining bytes with zeroes.
         */
-       strlcpy(name, _name, sizeof(name));
+       strscpy(name, _name, sizeof(name));
        if (copy_to_user(um, name, EBT_EXTENSION_MAXNAMELEN) ||
            put_user(revision, (u8 __user *)(um + EBT_EXTENSION_MAXNAMELEN)) ||
            put_user(datasize, (int __user *)(um + EBT_EXTENSION_MAXNAMELEN + 1)) ||
index 52dd0b6..6a0cba4 100644 (file)
@@ -342,7 +342,7 @@ int caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
        mutex_lock(&caifdevs->lock);
        list_add_rcu(&caifd->list, &caifdevs->list);
 
-       strlcpy(caifd->layer.name, dev->name,
+       strscpy(caifd->layer.name, dev->name,
                sizeof(caifd->layer.name));
        caifd->layer.transmit = transmit;
        res = cfcnfg_add_phy_layer(cfg,
index 4be6b04..ebc202f 100644 (file)
@@ -184,7 +184,7 @@ static int cfusbl_device_notify(struct notifier_block *me, unsigned long what,
                dev_add_pack(&caif_usb_type);
        pack_added = true;
 
-       strlcpy(layer->name, dev->name, sizeof(layer->name));
+       strscpy(layer->name, dev->name, sizeof(layer->name));
 
        return 0;
 err:
index 23267c8..52509e1 100644 (file)
@@ -268,14 +268,14 @@ static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
        case CAIFPROTO_RFM:
                l->linktype = CFCTRL_SRV_RFM;
                l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
-               strlcpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
+               strscpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
                        sizeof(l->u.rfm.volume));
                break;
        case CAIFPROTO_UTIL:
                l->linktype = CFCTRL_SRV_UTIL;
                l->endpoint = 0x00;
                l->chtype = 0x00;
-               strlcpy(l->u.utility.name, s->sockaddr.u.util.service,
+               strscpy(l->u.utility.name, s->sockaddr.u.util.service,
                        sizeof(l->u.utility.name));
                caif_assert(sizeof(l->u.utility.name) > 10);
                l->u.utility.paramlen = s->param.size;
index 2809cbd..cc405d8 100644 (file)
@@ -258,7 +258,7 @@ int cfctrl_linkup_request(struct cflayer *layer,
                tmp16 = cpu_to_le16(param->u.utility.fifosize_bufs);
                cfpkt_add_body(pkt, &tmp16, 2);
                memset(utility_name, 0, sizeof(utility_name));
-               strlcpy(utility_name, param->u.utility.name,
+               strscpy(utility_name, param->u.utility.name,
                        UTILITY_NAME_LENGTH);
                cfpkt_add_body(pkt, utility_name, UTILITY_NAME_LENGTH);
                tmp8 = param->u.utility.paramlen;
index 56c8b09..d66c73c 100644 (file)
@@ -1100,7 +1100,7 @@ static int dev_alloc_name_ns(struct net *net,
        BUG_ON(!net);
        ret = __dev_alloc_name(net, name, buf);
        if (ret >= 0)
-               strlcpy(dev->name, buf, IFNAMSIZ);
+               strscpy(dev->name, buf, IFNAMSIZ);
        return ret;
 }
 
@@ -1137,7 +1137,7 @@ static int dev_get_valid_name(struct net *net, struct net_device *dev,
        else if (netdev_name_in_use(net, name))
                return -EEXIST;
        else if (dev->name != name)
-               strlcpy(dev->name, name, IFNAMSIZ);
+               strscpy(dev->name, name, IFNAMSIZ);
 
        return 0;
 }
@@ -10370,9 +10370,7 @@ void netdev_run_todo(void)
                BUG_ON(!list_empty(&dev->ptype_specific));
                WARN_ON(rcu_access_pointer(dev->ip_ptr));
                WARN_ON(rcu_access_pointer(dev->ip6_ptr));
-#if IS_ENABLED(CONFIG_DECNET)
-               WARN_ON(dev->dn_ptr);
-#endif
+
                if (dev->priv_destructor)
                        dev->priv_destructor(dev);
                if (dev->needs_free_netdev)
index b50bcc1..7776dc8 100644 (file)
@@ -1710,7 +1710,7 @@ static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
        struct devlink *devlink = info->user_ptr[0];
        u32 count;
 
-       if (!info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PORT_SPLIT_COUNT))
                return -EINVAL;
        if (!devlink->ops->port_split)
                return -EOPNOTSUPP;
@@ -1838,7 +1838,7 @@ static int devlink_nl_cmd_port_del_doit(struct sk_buff *skb,
        if (!devlink->ops->port_del)
                return -EOPNOTSUPP;
 
-       if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PORT_INDEX)) {
                NL_SET_ERR_MSG_MOD(extack, "Port index is not specified");
                return -EINVAL;
        }
@@ -2690,7 +2690,7 @@ static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
        if (err)
                return err;
 
-       if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_POOL_SIZE))
                return -EINVAL;
 
        size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
@@ -2900,7 +2900,7 @@ static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
        if (err)
                return err;
 
-       if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
                return -EINVAL;
 
        threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
@@ -3156,7 +3156,7 @@ static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
        if (err)
                return err;
 
-       if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SB_THRESHOLD))
                return -EINVAL;
 
        threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
@@ -3845,7 +3845,7 @@ static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
        struct devlink_dpipe_table *table;
        const char *table_name;
 
-       if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME))
                return -EINVAL;
 
        table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
@@ -4029,8 +4029,9 @@ static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
        const char *table_name;
        bool counters_enable;
 
-       if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
-           !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_DPIPE_TABLE_NAME) ||
+           GENL_REQ_ATTR_CHECK(info,
+                               DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED))
                return -EINVAL;
 
        table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
@@ -4119,8 +4120,8 @@ static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
        u64 size;
        int err;
 
-       if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
-           !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_ID) ||
+           GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_SIZE))
                return -EINVAL;
        resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
 
@@ -4742,10 +4743,76 @@ void devlink_flash_update_timeout_notify(struct devlink *devlink,
 }
 EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);
 
+struct devlink_info_req {
+       struct sk_buff *msg;
+       void (*version_cb)(const char *version_name,
+                          enum devlink_info_version_type version_type,
+                          void *version_cb_priv);
+       void *version_cb_priv;
+};
+
+struct devlink_flash_component_lookup_ctx {
+       const char *lookup_name;
+       bool lookup_name_found;
+};
+
+static void
+devlink_flash_component_lookup_cb(const char *version_name,
+                                 enum devlink_info_version_type version_type,
+                                 void *version_cb_priv)
+{
+       struct devlink_flash_component_lookup_ctx *lookup_ctx = version_cb_priv;
+
+       if (version_type != DEVLINK_INFO_VERSION_TYPE_COMPONENT ||
+           lookup_ctx->lookup_name_found)
+               return;
+
+       lookup_ctx->lookup_name_found =
+               !strcmp(lookup_ctx->lookup_name, version_name);
+}
+
+static int devlink_flash_component_get(struct devlink *devlink,
+                                      struct nlattr *nla_component,
+                                      const char **p_component,
+                                      struct netlink_ext_ack *extack)
+{
+       struct devlink_flash_component_lookup_ctx lookup_ctx = {};
+       struct devlink_info_req req = {};
+       const char *component;
+       int ret;
+
+       if (!nla_component)
+               return 0;
+
+       component = nla_data(nla_component);
+
+       if (!devlink->ops->info_get) {
+               NL_SET_ERR_MSG_ATTR(extack, nla_component,
+                                   "component update is not supported by this device");
+               return -EOPNOTSUPP;
+       }
+
+       lookup_ctx.lookup_name = component;
+       req.version_cb = devlink_flash_component_lookup_cb;
+       req.version_cb_priv = &lookup_ctx;
+
+       ret = devlink->ops->info_get(devlink, &req, NULL);
+       if (ret)
+               return ret;
+
+       if (!lookup_ctx.lookup_name_found) {
+               NL_SET_ERR_MSG_ATTR(extack, nla_component,
+                                   "selected component is not supported by this device");
+               return -EINVAL;
+       }
+       *p_component = component;
+       return 0;
+}
+
 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
                                       struct genl_info *info)
 {
-       struct nlattr *nla_component, *nla_overwrite_mask, *nla_file_name;
+       struct nlattr *nla_overwrite_mask, *nla_file_name;
        struct devlink_flash_update_params params = {};
        struct devlink *devlink = info->user_ptr[0];
        const char *file_name;
@@ -4755,20 +4822,16 @@ static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
        if (!devlink->ops->flash_update)
                return -EOPNOTSUPP;
 
-       if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME))
                return -EINVAL;
 
-       supported_params = devlink->ops->supported_flash_update_params;
+       ret = devlink_flash_component_get(devlink,
+                                         info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT],
+                                         &params.component, info->extack);
+       if (ret)
+               return ret;
 
-       nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
-       if (nla_component) {
-               if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_COMPONENT)) {
-                       NL_SET_ERR_MSG_ATTR(info->extack, nla_component,
-                                           "component update is not supported by this device");
-                       return -EOPNOTSUPP;
-               }
-               params.component = nla_data(nla_component);
-       }
+       supported_params = devlink->ops->supported_flash_update_params;
 
        nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK];
        if (nla_overwrite_mask) {
@@ -4936,10 +4999,8 @@ static int devlink_nl_cmd_selftests_run(struct sk_buff *skb,
        if (!devlink->ops->selftest_run || !devlink->ops->selftest_check)
                return -EOPNOTSUPP;
 
-       if (!info->attrs[DEVLINK_ATTR_SELFTESTS]) {
-               NL_SET_ERR_MSG_MOD(info->extack, "selftest required");
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SELFTESTS))
                return -EINVAL;
-       }
 
        attrs = info->attrs[DEVLINK_ATTR_SELFTESTS];
 
@@ -5393,7 +5454,7 @@ static int
 devlink_param_type_get_from_info(struct genl_info *info,
                                 enum devlink_param_type *param_type)
 {
-       if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
                return -EINVAL;
 
        switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
@@ -5470,7 +5531,7 @@ devlink_param_get_from_info(struct list_head *param_list,
 {
        char *param_name;
 
-       if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
                return NULL;
 
        param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
@@ -5536,7 +5597,7 @@ static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
                        return err;
        }
 
-       if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
                return -EINVAL;
        cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
        if (!devlink_param_cmode_is_supported(param, cmode))
@@ -5574,89 +5635,22 @@ static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
 static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
                                                struct netlink_callback *cb)
 {
-       struct devlink_param_item *param_item;
-       struct devlink_port *devlink_port;
-       struct devlink *devlink;
-       int start = cb->args[0];
-       unsigned long index;
-       int idx = 0;
-       int err = 0;
-
-       devlinks_xa_for_each_registered_get(sock_net(msg->sk), index, devlink) {
-               devl_lock(devlink);
-               list_for_each_entry(devlink_port, &devlink->port_list, list) {
-                       list_for_each_entry(param_item,
-                                           &devlink_port->param_list, list) {
-                               if (idx < start) {
-                                       idx++;
-                                       continue;
-                               }
-                               err = devlink_nl_param_fill(msg,
-                                               devlink_port->devlink,
-                                               devlink_port->index, param_item,
-                                               DEVLINK_CMD_PORT_PARAM_GET,
-                                               NETLINK_CB(cb->skb).portid,
-                                               cb->nlh->nlmsg_seq,
-                                               NLM_F_MULTI);
-                               if (err == -EOPNOTSUPP) {
-                                       err = 0;
-                               } else if (err) {
-                                       devl_unlock(devlink);
-                                       devlink_put(devlink);
-                                       goto out;
-                               }
-                               idx++;
-                       }
-               }
-               devl_unlock(devlink);
-               devlink_put(devlink);
-       }
-out:
-       if (err != -EMSGSIZE)
-               return err;
-
-       cb->args[0] = idx;
+       NL_SET_ERR_MSG_MOD(cb->extack, "Port params are not supported");
        return msg->len;
 }
 
 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
                                              struct genl_info *info)
 {
-       struct devlink_port *devlink_port = info->user_ptr[1];
-       struct devlink_param_item *param_item;
-       struct sk_buff *msg;
-       int err;
-
-       param_item = devlink_param_get_from_info(&devlink_port->param_list,
-                                                info);
-       if (!param_item)
-               return -EINVAL;
-
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (!msg)
-               return -ENOMEM;
-
-       err = devlink_nl_param_fill(msg, devlink_port->devlink,
-                                   devlink_port->index, param_item,
-                                   DEVLINK_CMD_PORT_PARAM_GET,
-                                   info->snd_portid, info->snd_seq, 0);
-       if (err) {
-               nlmsg_free(msg);
-               return err;
-       }
-
-       return genlmsg_reply(msg, info);
+       NL_SET_ERR_MSG_MOD(info->extack, "Port params are not supported");
+       return -EINVAL;
 }
 
 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
                                              struct genl_info *info)
 {
-       struct devlink_port *devlink_port = info->user_ptr[1];
-
-       return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
-                                              devlink_port->index,
-                                              &devlink_port->param_list, info,
-                                              DEVLINK_CMD_PORT_PARAM_NEW);
+       NL_SET_ERR_MSG_MOD(info->extack, "Port params are not supported");
+       return -EINVAL;
 }
 
 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
@@ -6056,7 +6050,7 @@ static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
        unsigned int index;
        int err;
 
-       if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
                return -EINVAL;
 
        if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
@@ -6189,8 +6183,8 @@ static int devlink_nl_cmd_region_del(struct sk_buff *skb,
        unsigned int index;
        u32 snapshot_id;
 
-       if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
-           !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
+           GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
                return -EINVAL;
 
        region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
@@ -6238,7 +6232,7 @@ devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
        u8 *data;
        int err;
 
-       if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) {
+       if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
                NL_SET_ERR_MSG_MOD(info->extack, "No region name provided");
                return -EINVAL;
        }
@@ -6553,18 +6547,18 @@ out_unlock:
        return err;
 }
 
-struct devlink_info_req {
-       struct sk_buff *msg;
-};
-
 int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
 {
+       if (!req->msg)
+               return 0;
        return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
 }
 EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
 
 int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
 {
+       if (!req->msg)
+               return 0;
        return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
 }
 EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
@@ -6572,6 +6566,8 @@ EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
 int devlink_info_board_serial_number_put(struct devlink_info_req *req,
                                         const char *bsn)
 {
+       if (!req->msg)
+               return 0;
        return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
                              bsn);
 }
@@ -6579,11 +6575,19 @@ EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put);
 
 static int devlink_info_version_put(struct devlink_info_req *req, int attr,
                                    const char *version_name,
-                                   const char *version_value)
+                                   const char *version_value,
+                                   enum devlink_info_version_type version_type)
 {
        struct nlattr *nest;
        int err;
 
+       if (req->version_cb)
+               req->version_cb(version_name, version_type,
+                               req->version_cb_priv);
+
+       if (!req->msg)
+               return 0;
+
        nest = nla_nest_start_noflag(req->msg, attr);
        if (!nest)
                return -EMSGSIZE;
@@ -6612,7 +6616,8 @@ int devlink_info_version_fixed_put(struct devlink_info_req *req,
                                   const char *version_value)
 {
        return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
-                                       version_name, version_value);
+                                       version_name, version_value,
+                                       DEVLINK_INFO_VERSION_TYPE_NONE);
 }
 EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
 
@@ -6621,25 +6626,49 @@ int devlink_info_version_stored_put(struct devlink_info_req *req,
                                    const char *version_value)
 {
        return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
-                                       version_name, version_value);
+                                       version_name, version_value,
+                                       DEVLINK_INFO_VERSION_TYPE_NONE);
 }
 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
 
+int devlink_info_version_stored_put_ext(struct devlink_info_req *req,
+                                       const char *version_name,
+                                       const char *version_value,
+                                       enum devlink_info_version_type version_type)
+{
+       return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
+                                       version_name, version_value,
+                                       version_type);
+}
+EXPORT_SYMBOL_GPL(devlink_info_version_stored_put_ext);
+
 int devlink_info_version_running_put(struct devlink_info_req *req,
                                     const char *version_name,
                                     const char *version_value)
 {
        return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
-                                       version_name, version_value);
+                                       version_name, version_value,
+                                       DEVLINK_INFO_VERSION_TYPE_NONE);
 }
 EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
 
+int devlink_info_version_running_put_ext(struct devlink_info_req *req,
+                                        const char *version_name,
+                                        const char *version_value,
+                                        enum devlink_info_version_type version_type)
+{
+       return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
+                                       version_name, version_value,
+                                       version_type);
+}
+EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);
+
 static int
 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
                     enum devlink_command cmd, u32 portid,
                     u32 seq, int flags, struct netlink_ext_ack *extack)
 {
-       struct devlink_info_req req;
+       struct devlink_info_req req = {};
        void *hdr;
        int err;
 
@@ -9513,6 +9542,7 @@ static struct genl_family devlink_nl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = devlink_nl_ops,
        .n_small_ops    = ARRAY_SIZE(devlink_nl_ops),
+       .resv_start_op  = DEVLINK_CMD_SELFTESTS_RUN + 1,
        .mcgrps         = devlink_nl_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(devlink_nl_mcgrps),
 };
@@ -9846,7 +9876,6 @@ int devl_port_register(struct devlink *devlink,
        INIT_LIST_HEAD(&devlink_port->reporter_list);
        mutex_init(&devlink_port->reporters_lock);
        list_add_tail(&devlink_port->list, &devlink->port_list);
-       INIT_LIST_HEAD(&devlink_port->param_list);
        INIT_LIST_HEAD(&devlink_port->region_list);
 
        INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
@@ -12306,8 +12335,8 @@ EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);
 static void __devlink_compat_running_version(struct devlink *devlink,
                                             char *buf, size_t len)
 {
+       struct devlink_info_req req = {};
        const struct nlattr *nlattr;
-       struct devlink_info_req req;
        struct sk_buff *msg;
        int rem, err;
 
index 75501e1..f084a4a 100644 (file)
@@ -464,7 +464,7 @@ net_dm_hw_trap_summary_probe(void *ignore, const struct devlink *devlink,
                goto out;
 
        hw_entry = &hw_entries->entries[hw_entries->num_entries];
-       strlcpy(hw_entry->trap_name, metadata->trap_name,
+       strscpy(hw_entry->trap_name, metadata->trap_name,
                NET_DM_MAX_HW_TRAP_NAME_LEN - 1);
        hw_entry->count = 1;
        hw_entries->num_entries++;
@@ -1645,6 +1645,7 @@ static struct genl_family net_drop_monitor_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = dropmon_ops,
        .n_small_ops    = ARRAY_SIZE(dropmon_ops),
+       .resv_start_op  = NET_DM_CMD_STATS_GET + 1,
        .mcgrps         = dropmon_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(dropmon_mcgrps),
 };
index 78cc8fb..e93edb8 100644 (file)
@@ -1853,9 +1853,6 @@ static struct neigh_table *neigh_find_table(int family)
        case AF_INET6:
                tbl = neigh_tables[NEIGH_ND_TABLE];
                break;
-       case AF_DECnet:
-               tbl = neigh_tables[NEIGH_DN_TABLE];
-               break;
        }
 
        return tbl;
index 1a6a866..d6a70ae 100644 (file)
@@ -66,7 +66,7 @@ struct update_classid_context {
 
 #define UPDATE_CLASSID_BATCH 1000
 
-static int update_classid_sock(const void *v, struct file *file, unsigned n)
+static int update_classid_sock(const void *v, struct file *file, unsigned int n)
 {
        struct update_classid_context *ctx = (void *)v;
        struct socket *sock = sock_from_file(file);
index 5d27067..9be762e 100644 (file)
@@ -556,7 +556,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
                if ((delim = strchr(cur, ',')) == NULL)
                        goto parse_failed;
                *delim = 0;
-               strlcpy(np->dev_name, cur, sizeof(np->dev_name));
+               strscpy(np->dev_name, cur, sizeof(np->dev_name));
                cur = delim;
        }
        cur++;
@@ -610,7 +610,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev)
        int err;
 
        np->dev = ndev;
-       strlcpy(np->dev_name, ndev->name, IFNAMSIZ);
+       strscpy(np->dev_name, ndev->name, IFNAMSIZ);
 
        if (ndev->priv_flags & IFF_DISABLE_NETPOLL) {
                np_err(np, "%s doesn't support polling, aborting\n",
index 4b5b15c..f5e87fe 100644 (file)
@@ -866,14 +866,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
                break;
 
        case IF_OPER_TESTING:
-               if (operstate == IF_OPER_UP ||
-                   operstate == IF_OPER_UNKNOWN)
+               if (netif_oper_up(dev))
                        operstate = IF_OPER_TESTING;
                break;
 
        case IF_OPER_DORMANT:
-               if (operstate == IF_OPER_UP ||
-                   operstate == IF_OPER_UNKNOWN)
+               if (netif_oper_up(dev))
                        operstate = IF_OPER_DORMANT;
                break;
        }
index 84bb5e1..48ecfbf 100644 (file)
@@ -777,9 +777,10 @@ EXPORT_SYMBOL(__kfree_skb);
  *     hit zero. Meanwhile, pass the drop reason to 'kfree_skb'
  *     tracepoint.
  */
-void kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
+void __fix_address
+kfree_skb_reason(struct sk_buff *skb, enum skb_drop_reason reason)
 {
-       if (!skb_unref(skb))
+       if (unlikely(!skb_unref(skb)))
                return;
 
        DEBUG_NET_WARN_ON_ONCE(reason <= 0 || reason >= SKB_DROP_REASON_MAX);
index 59e75ff..188f855 100644 (file)
@@ -461,7 +461,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
 
                        if (copied == len)
                                break;
-               } while (!sg_is_last(sge));
+               } while ((i != msg_rx->sg.end) && !sg_is_last(sge));
 
                if (unlikely(peek)) {
                        msg_rx = sk_psock_next_msg(psock, msg_rx);
@@ -471,7 +471,7 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
                }
 
                msg_rx->sg.start = i;
-               if (!sge->length && sg_is_last(sge)) {
+               if (!sge->length && (i == msg_rx->sg.end || sg_is_last(sge))) {
                        msg_rx = sk_psock_dequeue_msg(psock);
                        kfree_sk_msg(msg_rx);
                }
index 9a9fb94..a660bae 100644 (file)
@@ -41,7 +41,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
            attr->map_flags & ~SOCK_CREATE_FLAG_MASK)
                return ERR_PTR(-EINVAL);
 
-       stab = kzalloc(sizeof(*stab), GFP_USER | __GFP_ACCOUNT);
+       stab = bpf_map_area_alloc(sizeof(*stab), NUMA_NO_NODE);
        if (!stab)
                return ERR_PTR(-ENOMEM);
 
@@ -52,7 +52,7 @@ static struct bpf_map *sock_map_alloc(union bpf_attr *attr)
                                       sizeof(struct sock *),
                                       stab->map.numa_node);
        if (!stab->sks) {
-               kfree(stab);
+               bpf_map_area_free(stab);
                return ERR_PTR(-ENOMEM);
        }
 
@@ -361,7 +361,7 @@ static void sock_map_free(struct bpf_map *map)
        synchronize_rcu();
 
        bpf_map_area_free(stab->sks);
-       kfree(stab);
+       bpf_map_area_free(stab);
 }
 
 static void sock_map_release_progs(struct bpf_map *map)
@@ -1085,7 +1085,7 @@ static struct bpf_map *sock_hash_alloc(union bpf_attr *attr)
        if (attr->key_size > MAX_BPF_STACK)
                return ERR_PTR(-E2BIG);
 
-       htab = kzalloc(sizeof(*htab), GFP_USER | __GFP_ACCOUNT);
+       htab = bpf_map_area_alloc(sizeof(*htab), NUMA_NO_NODE);
        if (!htab)
                return ERR_PTR(-ENOMEM);
 
@@ -1115,7 +1115,7 @@ static struct bpf_map *sock_hash_alloc(union bpf_attr *attr)
 
        return &htab->map;
 free_htab:
-       kfree(htab);
+       bpf_map_area_free(htab);
        return ERR_PTR(err);
 }
 
@@ -1168,7 +1168,7 @@ static void sock_hash_free(struct bpf_map *map)
        synchronize_rcu();
 
        bpf_map_area_free(htab->buckets);
-       kfree(htab);
+       bpf_map_area_free(htab);
 }
 
 static void *sock_hash_lookup_sys(struct bpf_map *map, void *key)
index da6e3b2..6a6e121 100644 (file)
@@ -45,10 +45,11 @@ static unsigned int dccp_v4_pernet_id __read_mostly;
 int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
        const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
+       struct inet_bind_hashbucket *prev_addr_hashbucket = NULL;
+       __be32 daddr, nexthop, prev_sk_rcv_saddr;
        struct inet_sock *inet = inet_sk(sk);
        struct dccp_sock *dp = dccp_sk(sk);
        __be16 orig_sport, orig_dport;
-       __be32 daddr, nexthop;
        struct flowi4 *fl4;
        struct rtable *rt;
        int err;
@@ -89,9 +90,29 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (inet_opt == NULL || !inet_opt->opt.srr)
                daddr = fl4->daddr;
 
-       if (inet->inet_saddr == 0)
+       if (inet->inet_saddr == 0) {
+               if (inet_csk(sk)->icsk_bind2_hash) {
+                       prev_addr_hashbucket =
+                               inet_bhashfn_portaddr(&dccp_hashinfo, sk,
+                                                     sock_net(sk),
+                                                     inet->inet_num);
+                       prev_sk_rcv_saddr = sk->sk_rcv_saddr;
+               }
                inet->inet_saddr = fl4->saddr;
+       }
+
        sk_rcv_saddr_set(sk, inet->inet_saddr);
+
+       if (prev_addr_hashbucket) {
+               err = inet_bhash2_update_saddr(prev_addr_hashbucket, sk);
+               if (err) {
+                       inet->inet_saddr = 0;
+                       sk_rcv_saddr_set(sk, prev_sk_rcv_saddr);
+                       ip_rt_put(rt);
+                       return err;
+               }
+       }
+
        inet->inet_dport = usin->sin_port;
        sk_daddr_set(sk, daddr);
 
index fd44638..e57b430 100644 (file)
@@ -934,8 +934,26 @@ static int dccp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        }
 
        if (saddr == NULL) {
+               struct inet_bind_hashbucket *prev_addr_hashbucket = NULL;
+               struct in6_addr prev_v6_rcv_saddr;
+
+               if (icsk->icsk_bind2_hash) {
+                       prev_addr_hashbucket = inet_bhashfn_portaddr(&dccp_hashinfo,
+                                                                    sk, sock_net(sk),
+                                                                    inet->inet_num);
+                       prev_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+               }
+
                saddr = &fl6.saddr;
                sk->sk_v6_rcv_saddr = *saddr;
+
+               if (prev_addr_hashbucket) {
+                       err = inet_bhash2_update_saddr(prev_addr_hashbucket, sk);
+                       if (err) {
+                               sk->sk_v6_rcv_saddr = prev_v6_rcv_saddr;
+                               goto failure;
+                       }
+               }
        }
 
        /* set the source address */
index e13641c..7cd4a6c 100644 (file)
@@ -1120,6 +1120,12 @@ static int __init dccp_init(void)
                                  SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL);
        if (!dccp_hashinfo.bind_bucket_cachep)
                goto out_free_hashinfo2;
+       dccp_hashinfo.bind2_bucket_cachep =
+               kmem_cache_create("dccp_bind2_bucket",
+                                 sizeof(struct inet_bind2_bucket), 0,
+                                 SLAB_HWCACHE_ALIGN | SLAB_ACCOUNT, NULL);
+       if (!dccp_hashinfo.bind2_bucket_cachep)
+               goto out_free_bind_bucket_cachep;
 
        /*
         * Size and allocate the main established and bind bucket
@@ -1150,7 +1156,7 @@ static int __init dccp_init(void)
 
        if (!dccp_hashinfo.ehash) {
                DCCP_CRIT("Failed to allocate DCCP established hash table");
-               goto out_free_bind_bucket_cachep;
+               goto out_free_bind2_bucket_cachep;
        }
 
        for (i = 0; i <= dccp_hashinfo.ehash_mask; i++)
@@ -1176,14 +1182,24 @@ static int __init dccp_init(void)
                goto out_free_dccp_locks;
        }
 
+       dccp_hashinfo.bhash2 = (struct inet_bind_hashbucket *)
+               __get_free_pages(GFP_ATOMIC | __GFP_NOWARN, bhash_order);
+
+       if (!dccp_hashinfo.bhash2) {
+               DCCP_CRIT("Failed to allocate DCCP bind2 hash table");
+               goto out_free_dccp_bhash;
+       }
+
        for (i = 0; i < dccp_hashinfo.bhash_size; i++) {
                spin_lock_init(&dccp_hashinfo.bhash[i].lock);
                INIT_HLIST_HEAD(&dccp_hashinfo.bhash[i].chain);
+               spin_lock_init(&dccp_hashinfo.bhash2[i].lock);
+               INIT_HLIST_HEAD(&dccp_hashinfo.bhash2[i].chain);
        }
 
        rc = dccp_mib_init();
        if (rc)
-               goto out_free_dccp_bhash;
+               goto out_free_dccp_bhash2;
 
        rc = dccp_ackvec_init();
        if (rc)
@@ -1207,30 +1223,38 @@ out_ackvec_exit:
        dccp_ackvec_exit();
 out_free_dccp_mib:
        dccp_mib_exit();
+out_free_dccp_bhash2:
+       free_pages((unsigned long)dccp_hashinfo.bhash2, bhash_order);
 out_free_dccp_bhash:
        free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
 out_free_dccp_locks:
        inet_ehash_locks_free(&dccp_hashinfo);
 out_free_dccp_ehash:
        free_pages((unsigned long)dccp_hashinfo.ehash, ehash_order);
+out_free_bind2_bucket_cachep:
+       kmem_cache_destroy(dccp_hashinfo.bind2_bucket_cachep);
 out_free_bind_bucket_cachep:
        kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep);
 out_free_hashinfo2:
        inet_hashinfo2_free_mod(&dccp_hashinfo);
 out_fail:
        dccp_hashinfo.bhash = NULL;
+       dccp_hashinfo.bhash2 = NULL;
        dccp_hashinfo.ehash = NULL;
        dccp_hashinfo.bind_bucket_cachep = NULL;
+       dccp_hashinfo.bind2_bucket_cachep = NULL;
        return rc;
 }
 
 static void __exit dccp_fini(void)
 {
+       int bhash_order = get_order(dccp_hashinfo.bhash_size *
+                                   sizeof(struct inet_bind_hashbucket));
+
        ccid_cleanup_builtins();
        dccp_mib_exit();
-       free_pages((unsigned long)dccp_hashinfo.bhash,
-                  get_order(dccp_hashinfo.bhash_size *
-                            sizeof(struct inet_bind_hashbucket)));
+       free_pages((unsigned long)dccp_hashinfo.bhash, bhash_order);
+       free_pages((unsigned long)dccp_hashinfo.bhash2, bhash_order);
        free_pages((unsigned long)dccp_hashinfo.ehash,
                   get_order((dccp_hashinfo.ehash_mask + 1) *
                             sizeof(struct inet_ehash_bucket)));
diff --git a/net/decnet/Kconfig b/net/decnet/Kconfig
deleted file mode 100644 (file)
index 24336bd..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# DECnet configuration
-#
-config DECNET
-       tristate "DECnet Support"
-       help
-         The DECnet networking protocol was used in many products made by
-         Digital (now Compaq).  It provides reliable stream and sequenced
-         packet communications over which run a variety of services similar
-         to those which run over TCP/IP.
-
-         To find some tools to use with the kernel layer support, please
-         look at Patrick Caulfield's web site:
-         <http://linux-decnet.sourceforge.net/>.
-
-         More detailed documentation is available in
-         <file:Documentation/networking/decnet.rst>.
-
-         Be sure to say Y to "/proc file system support" and "Sysctl support"
-         below when using DECnet, since you will need sysctl support to aid
-         in configuration at run time.
-
-         The DECnet code is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called decnet.
-
-config DECNET_ROUTER
-       bool "DECnet: router support"
-       depends on DECNET
-       select FIB_RULES
-       help
-         Add support for turning your DECnet Endnode into a level 1 or 2
-         router.  This is an experimental, but functional option.  If you
-         do say Y here, then make sure that you also say Y to "Kernel/User
-         network link driver", "Routing messages" and "Network packet
-         filtering".  The first two are required to allow configuration via
-         rtnetlink (you will need Alexey Kuznetsov's iproute2 package
-         from <ftp://ftp.tux.org/pub/net/ip-routing/>). The "Network packet
-         filtering" option will be required for the forthcoming routing daemon
-         to work.
-
-         See <file:Documentation/networking/decnet.rst> for more information.
diff --git a/net/decnet/Makefile b/net/decnet/Makefile
deleted file mode 100644 (file)
index 07b38e4..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_DECNET) += decnet.o
-
-decnet-y := af_decnet.o dn_nsp_in.o dn_nsp_out.o \
-           dn_route.o dn_dev.o dn_neigh.o dn_timer.o
-decnet-$(CONFIG_DECNET_ROUTER) += dn_fib.o dn_rules.o dn_table.o
-decnet-y += sysctl_net_decnet.o
-
-obj-$(CONFIG_NETFILTER) += netfilter/
diff --git a/net/decnet/README b/net/decnet/README
deleted file mode 100644 (file)
index 60e7ec8..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-                       Linux DECnet Project
-                      ======================
-
-The documentation for this kernel subsystem is available in the
-Documentation/networking subdirectory of this distribution and also
-on line at http://www.chygwyn.com/DECnet/
-
-Steve Whitehouse <SteveW@ACM.org>
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c
deleted file mode 100644 (file)
index 6582dfd..0000000
+++ /dev/null
@@ -1,2404 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Socket Layer Interface
- *
- * Authors:     Eduardo Marcelo Serrat <emserrat@geocities.com>
- *              Patrick Caulfield <patrick@pandh.demon.co.uk>
- *
- * Changes:
- *        Steve Whitehouse: Copied from Eduardo Serrat and Patrick Caulfield's
- *                          version of the code. Original copyright preserved
- *                          below.
- *        Steve Whitehouse: Some bug fixes, cleaning up some code to make it
- *                          compatible with my routing layer.
- *        Steve Whitehouse: Merging changes from Eduardo Serrat and Patrick
- *                          Caulfield.
- *        Steve Whitehouse: Further bug fixes, checking module code still works
- *                          with new routing layer.
- *        Steve Whitehouse: Additional set/get_sockopt() calls.
- *        Steve Whitehouse: Fixed TIOCINQ ioctl to be same as Eduardo's new
- *                          code.
- *        Steve Whitehouse: recvmsg() changed to try and behave in a POSIX like
- *                          way. Didn't manage it entirely, but its better.
- *        Steve Whitehouse: ditto for sendmsg().
- *        Steve Whitehouse: A selection of bug fixes to various things.
- *        Steve Whitehouse: Added TIOCOUTQ ioctl.
- *        Steve Whitehouse: Fixes to username2sockaddr & sockaddr2username.
- *        Steve Whitehouse: Fixes to connect() error returns.
- *       Patrick Caulfield: Fixes to delayed acceptance logic.
- *         David S. Miller: New socket locking
- *        Steve Whitehouse: Socket list hashing/locking
- *         Arnaldo C. Melo: use capable, not suser
- *        Steve Whitehouse: Removed unused code. Fix to use sk->allocation
- *                          when required.
- *       Patrick Caulfield: /proc/net/decnet now has object name/number
- *        Steve Whitehouse: Fixed local port allocation, hashed sk list
- *          Matthew Wilcox: Fixes for dn_ioctl()
- *        Steve Whitehouse: New connect/accept logic to allow timeouts and
- *                          prepare for sendpage etc.
- */
-
-
-/******************************************************************************
-    (c) 1995-1998 E.M. Serrat          emserrat@geocities.com
-
-
-HISTORY:
-
-Version           Kernel     Date       Author/Comments
--------           ------     ----       ---------------
-Version 0.0.1     2.0.30    01-dic-97  Eduardo Marcelo Serrat
-                                       (emserrat@geocities.com)
-
-                                       First Development of DECnet Socket La-
-                                       yer for Linux. Only supports outgoing
-                                       connections.
-
-Version 0.0.2    2.1.105   20-jun-98   Patrick J. Caulfield
-                                       (patrick@pandh.demon.co.uk)
-
-                                       Port to new kernel development version.
-
-Version 0.0.3     2.1.106   25-jun-98   Eduardo Marcelo Serrat
-                                       (emserrat@geocities.com)
-                                       _
-                                       Added support for incoming connections
-                                       so we can start developing server apps
-                                       on Linux.
-                                       -
-                                       Module Support
-Version 0.0.4     2.1.109   21-jul-98   Eduardo Marcelo Serrat
-                                      (emserrat@geocities.com)
-                                      _
-                                       Added support for X11R6.4. Now we can
-                                       use DECnet transport for X on Linux!!!
-                                      -
-Version 0.0.5    2.1.110   01-aug-98   Eduardo Marcelo Serrat
-                                      (emserrat@geocities.com)
-                                      Removed bugs on flow control
-                                      Removed bugs on incoming accessdata
-                                      order
-                                      -
-Version 0.0.6    2.1.110   07-aug-98   Eduardo Marcelo Serrat
-                                      dn_recvmsg fixes
-
-                                       Patrick J. Caulfield
-                                      dn_bind fixes
-*******************************************************************************/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/sched/signal.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/inet.h>
-#include <linux/route.h>
-#include <linux/netfilter.h>
-#include <linux/seq_file.h>
-#include <net/sock.h>
-#include <net/tcp_states.h>
-#include <net/flow.h>
-#include <asm/ioctls.h>
-#include <linux/capability.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/jiffies.h>
-#include <net/net_namespace.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/fib_rules.h>
-#include <net/tcp.h>
-#include <net/dn.h>
-#include <net/dn_nsp.h>
-#include <net/dn_dev.h>
-#include <net/dn_route.h>
-#include <net/dn_fib.h>
-#include <net/dn_neigh.h>
-
-struct dn_sock {
-       struct sock sk;
-       struct dn_scp scp;
-};
-
-static void dn_keepalive(struct sock *sk);
-
-#define DN_SK_HASH_SHIFT 8
-#define DN_SK_HASH_SIZE (1 << DN_SK_HASH_SHIFT)
-#define DN_SK_HASH_MASK (DN_SK_HASH_SIZE - 1)
-
-
-static const struct proto_ops dn_proto_ops;
-static DEFINE_RWLOCK(dn_hash_lock);
-static struct hlist_head dn_sk_hash[DN_SK_HASH_SIZE];
-static struct hlist_head dn_wild_sk;
-static atomic_long_t decnet_memory_allocated;
-static DEFINE_PER_CPU(int, decnet_memory_per_cpu_fw_alloc);
-
-static int __dn_setsockopt(struct socket *sock, int level, int optname,
-               sockptr_t optval, unsigned int optlen, int flags);
-static int __dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen, int flags);
-
-static struct hlist_head *dn_find_list(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (scp->addr.sdn_flags & SDF_WILD)
-               return hlist_empty(&dn_wild_sk) ? &dn_wild_sk : NULL;
-
-       return &dn_sk_hash[le16_to_cpu(scp->addrloc) & DN_SK_HASH_MASK];
-}
-
-/*
- * Valid ports are those greater than zero and not already in use.
- */
-static int check_port(__le16 port)
-{
-       struct sock *sk;
-
-       if (port == 0)
-               return -1;
-
-       sk_for_each(sk, &dn_sk_hash[le16_to_cpu(port) & DN_SK_HASH_MASK]) {
-               struct dn_scp *scp = DN_SK(sk);
-               if (scp->addrloc == port)
-                       return -1;
-       }
-       return 0;
-}
-
-static unsigned short port_alloc(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       static unsigned short port = 0x2000;
-       unsigned short i_port = port;
-
-       while(check_port(cpu_to_le16(++port)) != 0) {
-               if (port == i_port)
-                       return 0;
-       }
-
-       scp->addrloc = cpu_to_le16(port);
-
-       return 1;
-}
-
-/*
- * Since this is only ever called from user
- * level, we don't need a write_lock() version
- * of this.
- */
-static int dn_hash_sock(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct hlist_head *list;
-       int rv = -EUSERS;
-
-       BUG_ON(sk_hashed(sk));
-
-       write_lock_bh(&dn_hash_lock);
-
-       if (!scp->addrloc && !port_alloc(sk))
-               goto out;
-
-       rv = -EADDRINUSE;
-       if ((list = dn_find_list(sk)) == NULL)
-               goto out;
-
-       sk_add_node(sk, list);
-       rv = 0;
-out:
-       write_unlock_bh(&dn_hash_lock);
-       return rv;
-}
-
-static void dn_unhash_sock(struct sock *sk)
-{
-       write_lock(&dn_hash_lock);
-       sk_del_node_init(sk);
-       write_unlock(&dn_hash_lock);
-}
-
-static void dn_unhash_sock_bh(struct sock *sk)
-{
-       write_lock_bh(&dn_hash_lock);
-       sk_del_node_init(sk);
-       write_unlock_bh(&dn_hash_lock);
-}
-
-static struct hlist_head *listen_hash(struct sockaddr_dn *addr)
-{
-       int i;
-       unsigned int hash = addr->sdn_objnum;
-
-       if (hash == 0) {
-               hash = addr->sdn_objnamel;
-               for(i = 0; i < le16_to_cpu(addr->sdn_objnamel); i++) {
-                       hash ^= addr->sdn_objname[i];
-                       hash ^= (hash << 3);
-               }
-       }
-
-       return &dn_sk_hash[hash & DN_SK_HASH_MASK];
-}
-
-/*
- * Called to transform a socket from bound (i.e. with a local address)
- * into a listening socket (doesn't need a local port number) and rehashes
- * based upon the object name/number.
- */
-static void dn_rehash_sock(struct sock *sk)
-{
-       struct hlist_head *list;
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (scp->addr.sdn_flags & SDF_WILD)
-               return;
-
-       write_lock_bh(&dn_hash_lock);
-       sk_del_node_init(sk);
-       DN_SK(sk)->addrloc = 0;
-       list = listen_hash(&DN_SK(sk)->addr);
-       sk_add_node(sk, list);
-       write_unlock_bh(&dn_hash_lock);
-}
-
-int dn_sockaddr2username(struct sockaddr_dn *sdn, unsigned char *buf, unsigned char type)
-{
-       int len = 2;
-
-       *buf++ = type;
-
-       switch (type) {
-       case 0:
-               *buf++ = sdn->sdn_objnum;
-               break;
-       case 1:
-               *buf++ = 0;
-               *buf++ = le16_to_cpu(sdn->sdn_objnamel);
-               memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
-               len = 3 + le16_to_cpu(sdn->sdn_objnamel);
-               break;
-       case 2:
-               memset(buf, 0, 5);
-               buf += 5;
-               *buf++ = le16_to_cpu(sdn->sdn_objnamel);
-               memcpy(buf, sdn->sdn_objname, le16_to_cpu(sdn->sdn_objnamel));
-               len = 7 + le16_to_cpu(sdn->sdn_objnamel);
-               break;
-       }
-
-       return len;
-}
-
-/*
- * On reception of usernames, we handle types 1 and 0 for destination
- * addresses only. Types 2 and 4 are used for source addresses, but the
- * UIC, GIC are ignored and they are both treated the same way. Type 3
- * is never used as I've no idea what its purpose might be or what its
- * format is.
- */
-int dn_username2sockaddr(unsigned char *data, int len, struct sockaddr_dn *sdn, unsigned char *fmt)
-{
-       unsigned char type;
-       int size = len;
-       int namel = 12;
-
-       sdn->sdn_objnum = 0;
-       sdn->sdn_objnamel = cpu_to_le16(0);
-       memset(sdn->sdn_objname, 0, DN_MAXOBJL);
-
-       if (len < 2)
-               return -1;
-
-       len -= 2;
-       *fmt = *data++;
-       type = *data++;
-
-       switch (*fmt) {
-       case 0:
-               sdn->sdn_objnum = type;
-               return 2;
-       case 1:
-               namel = 16;
-               break;
-       case 2:
-               len  -= 4;
-               data += 4;
-               break;
-       case 4:
-               len  -= 8;
-               data += 8;
-               break;
-       default:
-               return -1;
-       }
-
-       len -= 1;
-
-       if (len < 0)
-               return -1;
-
-       sdn->sdn_objnamel = cpu_to_le16(*data++);
-       len -= le16_to_cpu(sdn->sdn_objnamel);
-
-       if ((len < 0) || (le16_to_cpu(sdn->sdn_objnamel) > namel))
-               return -1;
-
-       memcpy(sdn->sdn_objname, data, le16_to_cpu(sdn->sdn_objnamel));
-
-       return size - len;
-}
-
-struct sock *dn_sklist_find_listener(struct sockaddr_dn *addr)
-{
-       struct hlist_head *list = listen_hash(addr);
-       struct sock *sk;
-
-       read_lock(&dn_hash_lock);
-       sk_for_each(sk, list) {
-               struct dn_scp *scp = DN_SK(sk);
-               if (sk->sk_state != TCP_LISTEN)
-                       continue;
-               if (scp->addr.sdn_objnum) {
-                       if (scp->addr.sdn_objnum != addr->sdn_objnum)
-                               continue;
-               } else {
-                       if (addr->sdn_objnum)
-                               continue;
-                       if (scp->addr.sdn_objnamel != addr->sdn_objnamel)
-                               continue;
-                       if (memcmp(scp->addr.sdn_objname, addr->sdn_objname, le16_to_cpu(addr->sdn_objnamel)) != 0)
-                               continue;
-               }
-               sock_hold(sk);
-               read_unlock(&dn_hash_lock);
-               return sk;
-       }
-
-       sk = sk_head(&dn_wild_sk);
-       if (sk) {
-               if (sk->sk_state == TCP_LISTEN)
-                       sock_hold(sk);
-               else
-                       sk = NULL;
-       }
-
-       read_unlock(&dn_hash_lock);
-       return sk;
-}
-
-struct sock *dn_find_by_skb(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct sock *sk;
-       struct dn_scp *scp;
-
-       read_lock(&dn_hash_lock);
-       sk_for_each(sk, &dn_sk_hash[le16_to_cpu(cb->dst_port) & DN_SK_HASH_MASK]) {
-               scp = DN_SK(sk);
-               if (cb->src != dn_saddr2dn(&scp->peer))
-                       continue;
-               if (cb->dst_port != scp->addrloc)
-                       continue;
-               if (scp->addrrem && (cb->src_port != scp->addrrem))
-                       continue;
-               sock_hold(sk);
-               goto found;
-       }
-       sk = NULL;
-found:
-       read_unlock(&dn_hash_lock);
-       return sk;
-}
-
-
-
-static void dn_destruct(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       skb_queue_purge(&scp->data_xmit_queue);
-       skb_queue_purge(&scp->other_xmit_queue);
-       skb_queue_purge(&scp->other_receive_queue);
-
-       dst_release(rcu_dereference_protected(sk->sk_dst_cache, 1));
-}
-
-static unsigned long dn_memory_pressure;
-
-static void dn_enter_memory_pressure(struct sock *sk)
-{
-       if (!dn_memory_pressure) {
-               dn_memory_pressure = 1;
-       }
-}
-
-static struct proto dn_proto = {
-       .name                   = "NSP",
-       .owner                  = THIS_MODULE,
-       .enter_memory_pressure  = dn_enter_memory_pressure,
-       .memory_pressure        = &dn_memory_pressure,
-
-       .memory_allocated       = &decnet_memory_allocated,
-       .per_cpu_fw_alloc       = &decnet_memory_per_cpu_fw_alloc,
-
-       .sysctl_mem             = sysctl_decnet_mem,
-       .sysctl_wmem            = sysctl_decnet_wmem,
-       .sysctl_rmem            = sysctl_decnet_rmem,
-       .max_header             = DN_MAX_NSP_DATA_HEADER + 64,
-       .obj_size               = sizeof(struct dn_sock),
-};
-
-static struct sock *dn_alloc_sock(struct net *net, struct socket *sock, gfp_t gfp, int kern)
-{
-       struct dn_scp *scp;
-       struct sock *sk = sk_alloc(net, PF_DECnet, gfp, &dn_proto, kern);
-
-       if  (!sk)
-               goto out;
-
-       if (sock)
-               sock->ops = &dn_proto_ops;
-       sock_init_data(sock, sk);
-
-       sk->sk_backlog_rcv = dn_nsp_backlog_rcv;
-       sk->sk_destruct    = dn_destruct;
-       sk->sk_no_check_tx = 1;
-       sk->sk_family      = PF_DECnet;
-       sk->sk_protocol    = 0;
-       sk->sk_allocation  = gfp;
-       sk->sk_sndbuf      = READ_ONCE(sysctl_decnet_wmem[1]);
-       sk->sk_rcvbuf      = READ_ONCE(sysctl_decnet_rmem[1]);
-
-       /* Initialization of DECnet Session Control Port                */
-       scp = DN_SK(sk);
-       scp->state      = DN_O;         /* Open                 */
-       scp->numdat     = 1;            /* Next data seg to tx  */
-       scp->numoth     = 1;            /* Next oth data to tx  */
-       scp->ackxmt_dat = 0;            /* Last data seg ack'ed */
-       scp->ackxmt_oth = 0;            /* Last oth data ack'ed */
-       scp->ackrcv_dat = 0;            /* Highest data ack recv*/
-       scp->ackrcv_oth = 0;            /* Last oth data ack rec*/
-       scp->flowrem_sw = DN_SEND;
-       scp->flowloc_sw = DN_SEND;
-       scp->flowrem_dat = 0;
-       scp->flowrem_oth = 1;
-       scp->flowloc_dat = 0;
-       scp->flowloc_oth = 1;
-       scp->services_rem = 0;
-       scp->services_loc = 1 | NSP_FC_NONE;
-       scp->info_rem = 0;
-       scp->info_loc = 0x03; /* NSP version 4.1 */
-       scp->segsize_rem = 230 - DN_MAX_NSP_DATA_HEADER; /* Default: Updated by remote segsize */
-       scp->nonagle = 0;
-       scp->multi_ireq = 1;
-       scp->accept_mode = ACC_IMMED;
-       scp->addr.sdn_family    = AF_DECnet;
-       scp->peer.sdn_family    = AF_DECnet;
-       scp->accessdata.acc_accl = 5;
-       memcpy(scp->accessdata.acc_acc, "LINUX", 5);
-
-       scp->max_window   = NSP_MAX_WINDOW;
-       scp->snd_window   = NSP_MIN_WINDOW;
-       scp->nsp_srtt     = NSP_INITIAL_SRTT;
-       scp->nsp_rttvar   = NSP_INITIAL_RTTVAR;
-       scp->nsp_rxtshift = 0;
-
-       skb_queue_head_init(&scp->data_xmit_queue);
-       skb_queue_head_init(&scp->other_xmit_queue);
-       skb_queue_head_init(&scp->other_receive_queue);
-
-       scp->persist = 0;
-       scp->persist_fxn = NULL;
-       scp->keepalive = 10 * HZ;
-       scp->keepalive_fxn = dn_keepalive;
-
-       dn_start_slow_timer(sk);
-out:
-       return sk;
-}
-
-/*
- * Keepalive timer.
- * FIXME: Should respond to SO_KEEPALIVE etc.
- */
-static void dn_keepalive(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       /*
-        * By checking the other_data transmit queue is empty
-        * we are double checking that we are not sending too
-        * many of these keepalive frames.
-        */
-       if (skb_queue_empty(&scp->other_xmit_queue))
-               dn_nsp_send_link(sk, DN_NOCHANGE, 0);
-}
-
-
-/*
- * Timer for shutdown/destroyed sockets.
- * When socket is dead & no packets have been sent for a
- * certain amount of time, they are removed by this
- * routine. Also takes care of sending out DI & DC
- * frames at correct times.
- */
-int dn_destroy_timer(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       scp->persist = dn_nsp_persist(sk);
-
-       switch (scp->state) {
-       case DN_DI:
-               dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
-               if (scp->nsp_rxtshift >= decnet_di_count)
-                       scp->state = DN_CN;
-               return 0;
-
-       case DN_DR:
-               dn_nsp_send_disc(sk, NSP_DISCINIT, 0, GFP_ATOMIC);
-               if (scp->nsp_rxtshift >= decnet_dr_count)
-                       scp->state = DN_DRC;
-               return 0;
-
-       case DN_DN:
-               if (scp->nsp_rxtshift < decnet_dn_count) {
-                       /* printk(KERN_DEBUG "dn_destroy_timer: DN\n"); */
-                       dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
-                                        GFP_ATOMIC);
-                       return 0;
-               }
-       }
-
-       scp->persist = (HZ * decnet_time_wait);
-
-       if (sk->sk_socket)
-               return 0;
-
-       if (time_after_eq(jiffies, scp->stamp + HZ * decnet_time_wait)) {
-               dn_unhash_sock(sk);
-               sock_put(sk);
-               return 1;
-       }
-
-       return 0;
-}
-
-static void dn_destroy_sock(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       scp->nsp_rxtshift = 0; /* reset back off */
-
-       if (sk->sk_socket) {
-               if (sk->sk_socket->state != SS_UNCONNECTED)
-                       sk->sk_socket->state = SS_DISCONNECTING;
-       }
-
-       sk->sk_state = TCP_CLOSE;
-
-       switch (scp->state) {
-       case DN_DN:
-               dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC,
-                                sk->sk_allocation);
-               scp->persist_fxn = dn_destroy_timer;
-               scp->persist = dn_nsp_persist(sk);
-               break;
-       case DN_CR:
-               scp->state = DN_DR;
-               goto disc_reject;
-       case DN_RUN:
-               scp->state = DN_DI;
-               fallthrough;
-       case DN_DI:
-       case DN_DR:
-disc_reject:
-               dn_nsp_send_disc(sk, NSP_DISCINIT, 0, sk->sk_allocation);
-               fallthrough;
-       case DN_NC:
-       case DN_NR:
-       case DN_RJ:
-       case DN_DIC:
-       case DN_CN:
-       case DN_DRC:
-       case DN_CI:
-       case DN_CD:
-               scp->persist_fxn = dn_destroy_timer;
-               scp->persist = dn_nsp_persist(sk);
-               break;
-       default:
-               printk(KERN_DEBUG "DECnet: dn_destroy_sock passed socket in invalid state\n");
-               fallthrough;
-       case DN_O:
-               dn_stop_slow_timer(sk);
-
-               dn_unhash_sock_bh(sk);
-               sock_put(sk);
-
-               break;
-       }
-}
-
-char *dn_addr2asc(__u16 addr, char *buf)
-{
-       unsigned short node, area;
-
-       node = addr & 0x03ff;
-       area = addr >> 10;
-       sprintf(buf, "%hd.%hd", area, node);
-
-       return buf;
-}
-
-
-
-static int dn_create(struct net *net, struct socket *sock, int protocol,
-                    int kern)
-{
-       struct sock *sk;
-
-       if (protocol < 0 || protocol > U8_MAX)
-               return -EINVAL;
-
-       if (!net_eq(net, &init_net))
-               return -EAFNOSUPPORT;
-
-       switch (sock->type) {
-       case SOCK_SEQPACKET:
-               if (protocol != DNPROTO_NSP)
-                       return -EPROTONOSUPPORT;
-               break;
-       case SOCK_STREAM:
-               break;
-       default:
-               return -ESOCKTNOSUPPORT;
-       }
-
-
-       if ((sk = dn_alloc_sock(net, sock, GFP_KERNEL, kern)) == NULL)
-               return -ENOBUFS;
-
-       sk->sk_protocol = protocol;
-
-       return 0;
-}
-
-
-static int
-dn_release(struct socket *sock)
-{
-       struct sock *sk = sock->sk;
-
-       if (sk) {
-               sock_orphan(sk);
-               sock_hold(sk);
-               lock_sock(sk);
-               dn_destroy_sock(sk);
-               release_sock(sk);
-               sock_put(sk);
-       }
-
-       return 0;
-}
-
-static int dn_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       struct sockaddr_dn *saddr = (struct sockaddr_dn *)uaddr;
-       struct net_device *dev, *ldev;
-       int rv;
-
-       if (addr_len != sizeof(struct sockaddr_dn))
-               return -EINVAL;
-
-       if (saddr->sdn_family != AF_DECnet)
-               return -EINVAL;
-
-       if (le16_to_cpu(saddr->sdn_nodeaddrl) && (le16_to_cpu(saddr->sdn_nodeaddrl) != 2))
-               return -EINVAL;
-
-       if (le16_to_cpu(saddr->sdn_objnamel) > DN_MAXOBJL)
-               return -EINVAL;
-
-       if (saddr->sdn_flags & ~SDF_WILD)
-               return -EINVAL;
-
-       if (!capable(CAP_NET_BIND_SERVICE) && (saddr->sdn_objnum ||
-           (saddr->sdn_flags & SDF_WILD)))
-               return -EACCES;
-
-       if (!(saddr->sdn_flags & SDF_WILD)) {
-               if (le16_to_cpu(saddr->sdn_nodeaddrl)) {
-                       rcu_read_lock();
-                       ldev = NULL;
-                       for_each_netdev_rcu(&init_net, dev) {
-                               if (!dev->dn_ptr)
-                                       continue;
-                               if (dn_dev_islocal(dev, dn_saddr2dn(saddr))) {
-                                       ldev = dev;
-                                       break;
-                               }
-                       }
-                       rcu_read_unlock();
-                       if (ldev == NULL)
-                               return -EADDRNOTAVAIL;
-               }
-       }
-
-       rv = -EINVAL;
-       lock_sock(sk);
-       if (sock_flag(sk, SOCK_ZAPPED)) {
-               memcpy(&scp->addr, saddr, addr_len);
-               sock_reset_flag(sk, SOCK_ZAPPED);
-
-               rv = dn_hash_sock(sk);
-               if (rv)
-                       sock_set_flag(sk, SOCK_ZAPPED);
-       }
-       release_sock(sk);
-
-       return rv;
-}
-
-
-static int dn_auto_bind(struct socket *sock)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       int rv;
-
-       sock_reset_flag(sk, SOCK_ZAPPED);
-
-       scp->addr.sdn_flags  = 0;
-       scp->addr.sdn_objnum = 0;
-
-       /*
-        * This stuff is to keep compatibility with Eduardo's
-        * patch. I hope I can dispense with it shortly...
-        */
-       if ((scp->accessdata.acc_accl != 0) &&
-               (scp->accessdata.acc_accl <= 12)) {
-
-               scp->addr.sdn_objnamel = cpu_to_le16(scp->accessdata.acc_accl);
-               memcpy(scp->addr.sdn_objname, scp->accessdata.acc_acc, le16_to_cpu(scp->addr.sdn_objnamel));
-
-               scp->accessdata.acc_accl = 0;
-               memset(scp->accessdata.acc_acc, 0, 40);
-       }
-       /* End of compatibility stuff */
-
-       scp->addr.sdn_add.a_len = cpu_to_le16(2);
-       rv = dn_dev_bind_default((__le16 *)scp->addr.sdn_add.a_addr);
-       if (rv == 0) {
-               rv = dn_hash_sock(sk);
-               if (rv)
-                       sock_set_flag(sk, SOCK_ZAPPED);
-       }
-
-       return rv;
-}
-
-static int dn_confirm_accept(struct sock *sk, long *timeo, gfp_t allocation)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       DEFINE_WAIT_FUNC(wait, woken_wake_function);
-       int err;
-
-       if (scp->state != DN_CR)
-               return -EINVAL;
-
-       scp->state = DN_CC;
-       scp->segsize_loc = dst_metric_advmss(__sk_dst_get(sk));
-       dn_send_conn_conf(sk, allocation);
-
-       add_wait_queue(sk_sleep(sk), &wait);
-       for(;;) {
-               release_sock(sk);
-               if (scp->state == DN_CC)
-                       *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo);
-               lock_sock(sk);
-               err = 0;
-               if (scp->state == DN_RUN)
-                       break;
-               err = sock_error(sk);
-               if (err)
-                       break;
-               err = sock_intr_errno(*timeo);
-               if (signal_pending(current))
-                       break;
-               err = -EAGAIN;
-               if (!*timeo)
-                       break;
-       }
-       remove_wait_queue(sk_sleep(sk), &wait);
-       if (err == 0) {
-               sk->sk_socket->state = SS_CONNECTED;
-       } else if (scp->state != DN_CC) {
-               sk->sk_socket->state = SS_UNCONNECTED;
-       }
-       return err;
-}
-
-static int dn_wait_run(struct sock *sk, long *timeo)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       DEFINE_WAIT_FUNC(wait, woken_wake_function);
-       int err = 0;
-
-       if (scp->state == DN_RUN)
-               goto out;
-
-       if (!*timeo)
-               return -EALREADY;
-
-       add_wait_queue(sk_sleep(sk), &wait);
-       for(;;) {
-               release_sock(sk);
-               if (scp->state == DN_CI || scp->state == DN_CC)
-                       *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo);
-               lock_sock(sk);
-               err = 0;
-               if (scp->state == DN_RUN)
-                       break;
-               err = sock_error(sk);
-               if (err)
-                       break;
-               err = sock_intr_errno(*timeo);
-               if (signal_pending(current))
-                       break;
-               err = -ETIMEDOUT;
-               if (!*timeo)
-                       break;
-       }
-       remove_wait_queue(sk_sleep(sk), &wait);
-out:
-       if (err == 0) {
-               sk->sk_socket->state = SS_CONNECTED;
-       } else if (scp->state != DN_CI && scp->state != DN_CC) {
-               sk->sk_socket->state = SS_UNCONNECTED;
-       }
-       return err;
-}
-
-static int __dn_connect(struct sock *sk, struct sockaddr_dn *addr, int addrlen, long *timeo, int flags)
-{
-       struct socket *sock = sk->sk_socket;
-       struct dn_scp *scp = DN_SK(sk);
-       int err = -EISCONN;
-       struct flowidn fld;
-       struct dst_entry *dst;
-
-       if (sock->state == SS_CONNECTED)
-               goto out;
-
-       if (sock->state == SS_CONNECTING) {
-               err = 0;
-               if (scp->state == DN_RUN) {
-                       sock->state = SS_CONNECTED;
-                       goto out;
-               }
-               err = -ECONNREFUSED;
-               if (scp->state != DN_CI && scp->state != DN_CC) {
-                       sock->state = SS_UNCONNECTED;
-                       goto out;
-               }
-               return dn_wait_run(sk, timeo);
-       }
-
-       err = -EINVAL;
-       if (scp->state != DN_O)
-               goto out;
-
-       if (addr == NULL || addrlen != sizeof(struct sockaddr_dn))
-               goto out;
-       if (addr->sdn_family != AF_DECnet)
-               goto out;
-       if (addr->sdn_flags & SDF_WILD)
-               goto out;
-
-       if (sock_flag(sk, SOCK_ZAPPED)) {
-               err = dn_auto_bind(sk->sk_socket);
-               if (err)
-                       goto out;
-       }
-
-       memcpy(&scp->peer, addr, sizeof(struct sockaddr_dn));
-
-       err = -EHOSTUNREACH;
-       memset(&fld, 0, sizeof(fld));
-       fld.flowidn_oif = sk->sk_bound_dev_if;
-       fld.daddr = dn_saddr2dn(&scp->peer);
-       fld.saddr = dn_saddr2dn(&scp->addr);
-       dn_sk_ports_copy(&fld, scp);
-       fld.flowidn_proto = DNPROTO_NSP;
-       if (dn_route_output_sock(&sk->sk_dst_cache, &fld, sk, flags) < 0)
-               goto out;
-       dst = __sk_dst_get(sk);
-       sk->sk_route_caps = dst->dev->features;
-       sock->state = SS_CONNECTING;
-       scp->state = DN_CI;
-       scp->segsize_loc = dst_metric_advmss(dst);
-
-       dn_nsp_send_conninit(sk, NSP_CI);
-       err = -EINPROGRESS;
-       if (*timeo) {
-               err = dn_wait_run(sk, timeo);
-       }
-out:
-       return err;
-}
-
-static int dn_connect(struct socket *sock, struct sockaddr *uaddr, int addrlen, int flags)
-{
-       struct sockaddr_dn *addr = (struct sockaddr_dn *)uaddr;
-       struct sock *sk = sock->sk;
-       int err;
-       long timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
-
-       lock_sock(sk);
-       err = __dn_connect(sk, addr, addrlen, &timeo, 0);
-       release_sock(sk);
-
-       return err;
-}
-
-static inline int dn_check_state(struct sock *sk, struct sockaddr_dn *addr, int addrlen, long *timeo, int flags)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       switch (scp->state) {
-       case DN_RUN:
-               return 0;
-       case DN_CR:
-               return dn_confirm_accept(sk, timeo, sk->sk_allocation);
-       case DN_CI:
-       case DN_CC:
-               return dn_wait_run(sk, timeo);
-       case DN_O:
-               return __dn_connect(sk, addr, addrlen, timeo, flags);
-       }
-
-       return -EINVAL;
-}
-
-
-static void dn_access_copy(struct sk_buff *skb, struct accessdata_dn *acc)
-{
-       unsigned char *ptr = skb->data;
-
-       acc->acc_userl = *ptr++;
-       memcpy(&acc->acc_user, ptr, acc->acc_userl);
-       ptr += acc->acc_userl;
-
-       acc->acc_passl = *ptr++;
-       memcpy(&acc->acc_pass, ptr, acc->acc_passl);
-       ptr += acc->acc_passl;
-
-       acc->acc_accl = *ptr++;
-       memcpy(&acc->acc_acc, ptr, acc->acc_accl);
-
-       skb_pull(skb, acc->acc_accl + acc->acc_passl + acc->acc_userl + 3);
-
-}
-
-static void dn_user_copy(struct sk_buff *skb, struct optdata_dn *opt)
-{
-       unsigned char *ptr = skb->data;
-       u16 len = *ptr++; /* yes, it's 8bit on the wire */
-
-       BUG_ON(len > 16); /* we've checked the contents earlier */
-       opt->opt_optl   = cpu_to_le16(len);
-       opt->opt_status = 0;
-       memcpy(opt->opt_data, ptr, len);
-       skb_pull(skb, len + 1);
-}
-
-static struct sk_buff *dn_wait_for_connect(struct sock *sk, long *timeo)
-{
-       DEFINE_WAIT_FUNC(wait, woken_wake_function);
-       struct sk_buff *skb = NULL;
-       int err = 0;
-
-       add_wait_queue(sk_sleep(sk), &wait);
-       for(;;) {
-               release_sock(sk);
-               skb = skb_dequeue(&sk->sk_receive_queue);
-               if (skb == NULL) {
-                       *timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, *timeo);
-                       skb = skb_dequeue(&sk->sk_receive_queue);
-               }
-               lock_sock(sk);
-               if (skb != NULL)
-                       break;
-               err = -EINVAL;
-               if (sk->sk_state != TCP_LISTEN)
-                       break;
-               err = sock_intr_errno(*timeo);
-               if (signal_pending(current))
-                       break;
-               err = -EAGAIN;
-               if (!*timeo)
-                       break;
-       }
-       remove_wait_queue(sk_sleep(sk), &wait);
-
-       return skb == NULL ? ERR_PTR(err) : skb;
-}
-
-static int dn_accept(struct socket *sock, struct socket *newsock, int flags,
-                    bool kern)
-{
-       struct sock *sk = sock->sk, *newsk;
-       struct sk_buff *skb = NULL;
-       struct dn_skb_cb *cb;
-       unsigned char menuver;
-       int err = 0;
-       unsigned char type;
-       long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
-       struct dst_entry *dst;
-
-       lock_sock(sk);
-
-       if (sk->sk_state != TCP_LISTEN || DN_SK(sk)->state != DN_O) {
-               release_sock(sk);
-               return -EINVAL;
-       }
-
-       skb = skb_dequeue(&sk->sk_receive_queue);
-       if (skb == NULL) {
-               skb = dn_wait_for_connect(sk, &timeo);
-               if (IS_ERR(skb)) {
-                       release_sock(sk);
-                       return PTR_ERR(skb);
-               }
-       }
-
-       cb = DN_SKB_CB(skb);
-       sk_acceptq_removed(sk);
-       newsk = dn_alloc_sock(sock_net(sk), newsock, sk->sk_allocation, kern);
-       if (newsk == NULL) {
-               release_sock(sk);
-               kfree_skb(skb);
-               return -ENOBUFS;
-       }
-       release_sock(sk);
-
-       dst = skb_dst(skb);
-       sk_dst_set(newsk, dst);
-       skb_dst_set(skb, NULL);
-
-       DN_SK(newsk)->state        = DN_CR;
-       DN_SK(newsk)->addrrem      = cb->src_port;
-       DN_SK(newsk)->services_rem = cb->services;
-       DN_SK(newsk)->info_rem     = cb->info;
-       DN_SK(newsk)->segsize_rem  = cb->segsize;
-       DN_SK(newsk)->accept_mode  = DN_SK(sk)->accept_mode;
-
-       if (DN_SK(newsk)->segsize_rem < 230)
-               DN_SK(newsk)->segsize_rem = 230;
-
-       if ((DN_SK(newsk)->services_rem & NSP_FC_MASK) == NSP_FC_NONE)
-               DN_SK(newsk)->max_window = decnet_no_fc_max_cwnd;
-
-       newsk->sk_state  = TCP_LISTEN;
-       memcpy(&(DN_SK(newsk)->addr), &(DN_SK(sk)->addr), sizeof(struct sockaddr_dn));
-
-       /*
-        * If we are listening on a wild socket, we don't want
-        * the newly created socket on the wrong hash queue.
-        */
-       DN_SK(newsk)->addr.sdn_flags &= ~SDF_WILD;
-
-       skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->addr), &type));
-       skb_pull(skb, dn_username2sockaddr(skb->data, skb->len, &(DN_SK(newsk)->peer), &type));
-       *(__le16 *)(DN_SK(newsk)->peer.sdn_add.a_addr) = cb->src;
-       *(__le16 *)(DN_SK(newsk)->addr.sdn_add.a_addr) = cb->dst;
-
-       menuver = *skb->data;
-       skb_pull(skb, 1);
-
-       if (menuver & DN_MENUVER_ACC)
-               dn_access_copy(skb, &(DN_SK(newsk)->accessdata));
-
-       if (menuver & DN_MENUVER_USR)
-               dn_user_copy(skb, &(DN_SK(newsk)->conndata_in));
-
-       if (menuver & DN_MENUVER_PRX)
-               DN_SK(newsk)->peer.sdn_flags |= SDF_PROXY;
-
-       if (menuver & DN_MENUVER_UIC)
-               DN_SK(newsk)->peer.sdn_flags |= SDF_UICPROXY;
-
-       kfree_skb(skb);
-
-       memcpy(&(DN_SK(newsk)->conndata_out), &(DN_SK(sk)->conndata_out),
-               sizeof(struct optdata_dn));
-       memcpy(&(DN_SK(newsk)->discdata_out), &(DN_SK(sk)->discdata_out),
-               sizeof(struct optdata_dn));
-
-       lock_sock(newsk);
-       err = dn_hash_sock(newsk);
-       if (err == 0) {
-               sock_reset_flag(newsk, SOCK_ZAPPED);
-               dn_send_conn_ack(newsk);
-
-               /*
-                * Here we use sk->sk_allocation since although the conn conf is
-                * for the newsk, the context is the old socket.
-                */
-               if (DN_SK(newsk)->accept_mode == ACC_IMMED)
-                       err = dn_confirm_accept(newsk, &timeo,
-                                               sk->sk_allocation);
-       }
-       release_sock(newsk);
-       return err;
-}
-
-
-static int dn_getname(struct socket *sock, struct sockaddr *uaddr,int peer)
-{
-       struct sockaddr_dn *sa = (struct sockaddr_dn *)uaddr;
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-
-       lock_sock(sk);
-
-       if (peer) {
-               if ((sock->state != SS_CONNECTED &&
-                    sock->state != SS_CONNECTING) &&
-                   scp->accept_mode == ACC_IMMED) {
-                       release_sock(sk);
-                       return -ENOTCONN;
-               }
-
-               memcpy(sa, &scp->peer, sizeof(struct sockaddr_dn));
-       } else {
-               memcpy(sa, &scp->addr, sizeof(struct sockaddr_dn));
-       }
-
-       release_sock(sk);
-
-       return sizeof(struct sockaddr_dn);
-}
-
-
-static __poll_t dn_poll(struct file *file, struct socket *sock, poll_table  *wait)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       __poll_t mask = datagram_poll(file, sock, wait);
-
-       if (!skb_queue_empty_lockless(&scp->other_receive_queue))
-               mask |= EPOLLRDBAND;
-
-       return mask;
-}
-
-static int dn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       int err = -EOPNOTSUPP;
-       long amount = 0;
-       struct sk_buff *skb;
-       int val;
-
-       switch(cmd)
-       {
-       case SIOCGIFADDR:
-       case SIOCSIFADDR:
-               return dn_dev_ioctl(cmd, (void __user *)arg);
-
-       case SIOCATMARK:
-               lock_sock(sk);
-               val = !skb_queue_empty(&scp->other_receive_queue);
-               if (scp->state != DN_RUN)
-                       val = -ENOTCONN;
-               release_sock(sk);
-               return val;
-
-       case TIOCOUTQ:
-               amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
-               if (amount < 0)
-                       amount = 0;
-               err = put_user(amount, (int __user *)arg);
-               break;
-
-       case TIOCINQ:
-               lock_sock(sk);
-               skb = skb_peek(&scp->other_receive_queue);
-               if (skb) {
-                       amount = skb->len;
-               } else {
-                       skb_queue_walk(&sk->sk_receive_queue, skb)
-                               amount += skb->len;
-               }
-               release_sock(sk);
-               err = put_user(amount, (int __user *)arg);
-               break;
-
-       default:
-               err = -ENOIOCTLCMD;
-               break;
-       }
-
-       return err;
-}
-
-static int dn_listen(struct socket *sock, int backlog)
-{
-       struct sock *sk = sock->sk;
-       int err = -EINVAL;
-
-       lock_sock(sk);
-
-       if (sock_flag(sk, SOCK_ZAPPED))
-               goto out;
-
-       if ((DN_SK(sk)->state != DN_O) || (sk->sk_state == TCP_LISTEN))
-               goto out;
-
-       sk->sk_max_ack_backlog = backlog;
-       sk->sk_ack_backlog     = 0;
-       sk->sk_state           = TCP_LISTEN;
-       err                 = 0;
-       dn_rehash_sock(sk);
-
-out:
-       release_sock(sk);
-
-       return err;
-}
-
-
-static int dn_shutdown(struct socket *sock, int how)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       int err = -ENOTCONN;
-
-       lock_sock(sk);
-
-       if (sock->state == SS_UNCONNECTED)
-               goto out;
-
-       err = 0;
-       if (sock->state == SS_DISCONNECTING)
-               goto out;
-
-       err = -EINVAL;
-       if (scp->state == DN_O)
-               goto out;
-
-       if (how != SHUT_RDWR)
-               goto out;
-
-       sk->sk_shutdown = SHUTDOWN_MASK;
-       dn_destroy_sock(sk);
-       err = 0;
-
-out:
-       release_sock(sk);
-
-       return err;
-}
-
-static int dn_setsockopt(struct socket *sock, int level, int optname,
-               sockptr_t optval, unsigned int optlen)
-{
-       struct sock *sk = sock->sk;
-       int err;
-
-       lock_sock(sk);
-       err = __dn_setsockopt(sock, level, optname, optval, optlen, 0);
-       release_sock(sk);
-#ifdef CONFIG_NETFILTER
-       /* we need to exclude all possible ENOPROTOOPTs except default case */
-       if (err == -ENOPROTOOPT && optname != DSO_LINKINFO &&
-           optname != DSO_STREAM && optname != DSO_SEQPACKET)
-               err = nf_setsockopt(sk, PF_DECnet, optname, optval, optlen);
-#endif
-
-       return err;
-}
-
-static int __dn_setsockopt(struct socket *sock, int level, int optname,
-               sockptr_t optval, unsigned int optlen, int flags)
-{
-       struct  sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       long timeo;
-       union {
-               struct optdata_dn opt;
-               struct accessdata_dn acc;
-               int mode;
-               unsigned long win;
-               int val;
-               unsigned char services;
-               unsigned char info;
-       } u;
-       int err;
-
-       if (optlen && sockptr_is_null(optval))
-               return -EINVAL;
-
-       if (optlen > sizeof(u))
-               return -EINVAL;
-
-       if (copy_from_sockptr(&u, optval, optlen))
-               return -EFAULT;
-
-       switch (optname) {
-       case DSO_CONDATA:
-               if (sock->state == SS_CONNECTED)
-                       return -EISCONN;
-               if ((scp->state != DN_O) && (scp->state != DN_CR))
-                       return -EINVAL;
-
-               if (optlen != sizeof(struct optdata_dn))
-                       return -EINVAL;
-
-               if (le16_to_cpu(u.opt.opt_optl) > 16)
-                       return -EINVAL;
-
-               memcpy(&scp->conndata_out, &u.opt, optlen);
-               break;
-
-       case DSO_DISDATA:
-               if (sock->state != SS_CONNECTED &&
-                   scp->accept_mode == ACC_IMMED)
-                       return -ENOTCONN;
-
-               if (optlen != sizeof(struct optdata_dn))
-                       return -EINVAL;
-
-               if (le16_to_cpu(u.opt.opt_optl) > 16)
-                       return -EINVAL;
-
-               memcpy(&scp->discdata_out, &u.opt, optlen);
-               break;
-
-       case DSO_CONACCESS:
-               if (sock->state == SS_CONNECTED)
-                       return -EISCONN;
-               if (scp->state != DN_O)
-                       return -EINVAL;
-
-               if (optlen != sizeof(struct accessdata_dn))
-                       return -EINVAL;
-
-               if ((u.acc.acc_accl > DN_MAXACCL) ||
-                   (u.acc.acc_passl > DN_MAXACCL) ||
-                   (u.acc.acc_userl > DN_MAXACCL))
-                       return -EINVAL;
-
-               memcpy(&scp->accessdata, &u.acc, optlen);
-               break;
-
-       case DSO_ACCEPTMODE:
-               if (sock->state == SS_CONNECTED)
-                       return -EISCONN;
-               if (scp->state != DN_O)
-                       return -EINVAL;
-
-               if (optlen != sizeof(int))
-                       return -EINVAL;
-
-               if ((u.mode != ACC_IMMED) && (u.mode != ACC_DEFER))
-                       return -EINVAL;
-
-               scp->accept_mode = (unsigned char)u.mode;
-               break;
-
-       case DSO_CONACCEPT:
-               if (scp->state != DN_CR)
-                       return -EINVAL;
-               timeo = sock_rcvtimeo(sk, 0);
-               err = dn_confirm_accept(sk, &timeo, sk->sk_allocation);
-               return err;
-
-       case DSO_CONREJECT:
-               if (scp->state != DN_CR)
-                       return -EINVAL;
-
-               scp->state = DN_DR;
-               sk->sk_shutdown = SHUTDOWN_MASK;
-               dn_nsp_send_disc(sk, 0x38, 0, sk->sk_allocation);
-               break;
-
-       case DSO_MAXWINDOW:
-               if (optlen != sizeof(unsigned long))
-                       return -EINVAL;
-               if (u.win > NSP_MAX_WINDOW)
-                       u.win = NSP_MAX_WINDOW;
-               if (u.win == 0)
-                       return -EINVAL;
-               scp->max_window = u.win;
-               if (scp->snd_window > u.win)
-                       scp->snd_window = u.win;
-               break;
-
-       case DSO_NODELAY:
-               if (optlen != sizeof(int))
-                       return -EINVAL;
-               if (scp->nonagle == TCP_NAGLE_CORK)
-                       return -EINVAL;
-               scp->nonagle = (u.val == 0) ? 0 : TCP_NAGLE_OFF;
-               /* if (scp->nonagle == 1) { Push pending frames } */
-               break;
-
-       case DSO_CORK:
-               if (optlen != sizeof(int))
-                       return -EINVAL;
-               if (scp->nonagle == TCP_NAGLE_OFF)
-                       return -EINVAL;
-               scp->nonagle = (u.val == 0) ? 0 : TCP_NAGLE_CORK;
-               /* if (scp->nonagle == 0) { Push pending frames } */
-               break;
-
-       case DSO_SERVICES:
-               if (optlen != sizeof(unsigned char))
-                       return -EINVAL;
-               if ((u.services & ~NSP_FC_MASK) != 0x01)
-                       return -EINVAL;
-               if ((u.services & NSP_FC_MASK) == NSP_FC_MASK)
-                       return -EINVAL;
-               scp->services_loc = u.services;
-               break;
-
-       case DSO_INFO:
-               if (optlen != sizeof(unsigned char))
-                       return -EINVAL;
-               if (u.info & 0xfc)
-                       return -EINVAL;
-               scp->info_loc = u.info;
-               break;
-
-       case DSO_LINKINFO:
-       case DSO_STREAM:
-       case DSO_SEQPACKET:
-       default:
-               return -ENOPROTOOPT;
-       }
-
-       return 0;
-}
-
-static int dn_getsockopt(struct socket *sock, int level, int optname, char __user *optval, int __user *optlen)
-{
-       struct sock *sk = sock->sk;
-       int err;
-
-       lock_sock(sk);
-       err = __dn_getsockopt(sock, level, optname, optval, optlen, 0);
-       release_sock(sk);
-#ifdef CONFIG_NETFILTER
-       if (err == -ENOPROTOOPT && optname != DSO_STREAM &&
-           optname != DSO_SEQPACKET && optname != DSO_CONACCEPT &&
-           optname != DSO_CONREJECT) {
-               int len;
-
-               if (get_user(len, optlen))
-                       return -EFAULT;
-
-               err = nf_getsockopt(sk, PF_DECnet, optname, optval, &len);
-               if (err >= 0)
-                       err = put_user(len, optlen);
-       }
-#endif
-
-       return err;
-}
-
-static int __dn_getsockopt(struct socket *sock, int level,int optname, char __user *optval,int __user *optlen, int flags)
-{
-       struct  sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       struct linkinfo_dn link;
-       unsigned int r_len;
-       void *r_data = NULL;
-       unsigned int val;
-
-       if(get_user(r_len , optlen))
-               return -EFAULT;
-
-       switch (optname) {
-       case DSO_CONDATA:
-               if (r_len > sizeof(struct optdata_dn))
-                       r_len = sizeof(struct optdata_dn);
-               r_data = &scp->conndata_in;
-               break;
-
-       case DSO_DISDATA:
-               if (r_len > sizeof(struct optdata_dn))
-                       r_len = sizeof(struct optdata_dn);
-               r_data = &scp->discdata_in;
-               break;
-
-       case DSO_CONACCESS:
-               if (r_len > sizeof(struct accessdata_dn))
-                       r_len = sizeof(struct accessdata_dn);
-               r_data = &scp->accessdata;
-               break;
-
-       case DSO_ACCEPTMODE:
-               if (r_len > sizeof(unsigned char))
-                       r_len = sizeof(unsigned char);
-               r_data = &scp->accept_mode;
-               break;
-
-       case DSO_LINKINFO:
-               if (r_len > sizeof(struct linkinfo_dn))
-                       r_len = sizeof(struct linkinfo_dn);
-
-               memset(&link, 0, sizeof(link));
-
-               switch (sock->state) {
-               case SS_CONNECTING:
-                       link.idn_linkstate = LL_CONNECTING;
-                       break;
-               case SS_DISCONNECTING:
-                       link.idn_linkstate = LL_DISCONNECTING;
-                       break;
-               case SS_CONNECTED:
-                       link.idn_linkstate = LL_RUNNING;
-                       break;
-               default:
-                       link.idn_linkstate = LL_INACTIVE;
-               }
-
-               link.idn_segsize = scp->segsize_rem;
-               r_data = &link;
-               break;
-
-       case DSO_MAXWINDOW:
-               if (r_len > sizeof(unsigned long))
-                       r_len = sizeof(unsigned long);
-               r_data = &scp->max_window;
-               break;
-
-       case DSO_NODELAY:
-               if (r_len > sizeof(int))
-                       r_len = sizeof(int);
-               val = (scp->nonagle == TCP_NAGLE_OFF);
-               r_data = &val;
-               break;
-
-       case DSO_CORK:
-               if (r_len > sizeof(int))
-                       r_len = sizeof(int);
-               val = (scp->nonagle == TCP_NAGLE_CORK);
-               r_data = &val;
-               break;
-
-       case DSO_SERVICES:
-               if (r_len > sizeof(unsigned char))
-                       r_len = sizeof(unsigned char);
-               r_data = &scp->services_rem;
-               break;
-
-       case DSO_INFO:
-               if (r_len > sizeof(unsigned char))
-                       r_len = sizeof(unsigned char);
-               r_data = &scp->info_rem;
-               break;
-
-       case DSO_STREAM:
-       case DSO_SEQPACKET:
-       case DSO_CONACCEPT:
-       case DSO_CONREJECT:
-       default:
-               return -ENOPROTOOPT;
-       }
-
-       if (r_data) {
-               if (copy_to_user(optval, r_data, r_len))
-                       return -EFAULT;
-               if (put_user(r_len, optlen))
-                       return -EFAULT;
-       }
-
-       return 0;
-}
-
-
-static int dn_data_ready(struct sock *sk, struct sk_buff_head *q, int flags, int target)
-{
-       struct sk_buff *skb;
-       int len = 0;
-
-       if (flags & MSG_OOB)
-               return !skb_queue_empty(q) ? 1 : 0;
-
-       skb_queue_walk(q, skb) {
-               struct dn_skb_cb *cb = DN_SKB_CB(skb);
-               len += skb->len;
-
-               if (cb->nsp_flags & 0x40) {
-                       /* SOCK_SEQPACKET reads to EOM */
-                       if (sk->sk_type == SOCK_SEQPACKET)
-                               return 1;
-                       /* so does SOCK_STREAM unless WAITALL is specified */
-                       if (!(flags & MSG_WAITALL))
-                               return 1;
-               }
-
-               /* minimum data length for read exceeded */
-               if (len >= target)
-                       return 1;
-       }
-
-       return 0;
-}
-
-
-static int dn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
-                     int flags)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       struct sk_buff_head *queue = &sk->sk_receive_queue;
-       size_t target = size > 1 ? 1 : 0;
-       size_t copied = 0;
-       int rv = 0;
-       struct sk_buff *skb, *n;
-       struct dn_skb_cb *cb = NULL;
-       unsigned char eor = 0;
-       long timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
-
-       lock_sock(sk);
-
-       if (sock_flag(sk, SOCK_ZAPPED)) {
-               rv = -EADDRNOTAVAIL;
-               goto out;
-       }
-
-       if (sk->sk_shutdown & RCV_SHUTDOWN) {
-               rv = 0;
-               goto out;
-       }
-
-       rv = dn_check_state(sk, NULL, 0, &timeo, flags);
-       if (rv)
-               goto out;
-
-       if (flags & ~(MSG_CMSG_COMPAT|MSG_PEEK|MSG_OOB|MSG_WAITALL|MSG_DONTWAIT|MSG_NOSIGNAL)) {
-               rv = -EOPNOTSUPP;
-               goto out;
-       }
-
-       if (flags & MSG_OOB)
-               queue = &scp->other_receive_queue;
-
-       if (flags & MSG_WAITALL)
-               target = size;
-
-
-       /*
-        * See if there is data ready to read, sleep if there isn't
-        */
-       for(;;) {
-               DEFINE_WAIT_FUNC(wait, woken_wake_function);
-
-               if (sk->sk_err)
-                       goto out;
-
-               if (!skb_queue_empty(&scp->other_receive_queue)) {
-                       if (!(flags & MSG_OOB)) {
-                               msg->msg_flags |= MSG_OOB;
-                               if (!scp->other_report) {
-                                       scp->other_report = 1;
-                                       goto out;
-                               }
-                       }
-               }
-
-               if (scp->state != DN_RUN)
-                       goto out;
-
-               if (signal_pending(current)) {
-                       rv = sock_intr_errno(timeo);
-                       goto out;
-               }
-
-               if (dn_data_ready(sk, queue, flags, target))
-                       break;
-
-               if (flags & MSG_DONTWAIT) {
-                       rv = -EWOULDBLOCK;
-                       goto out;
-               }
-
-               add_wait_queue(sk_sleep(sk), &wait);
-               sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-               sk_wait_event(sk, &timeo, dn_data_ready(sk, queue, flags, target), &wait);
-               sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-               remove_wait_queue(sk_sleep(sk), &wait);
-       }
-
-       skb_queue_walk_safe(queue, skb, n) {
-               unsigned int chunk = skb->len;
-               cb = DN_SKB_CB(skb);
-
-               if ((chunk + copied) > size)
-                       chunk = size - copied;
-
-               if (memcpy_to_msg(msg, skb->data, chunk)) {
-                       rv = -EFAULT;
-                       break;
-               }
-               copied += chunk;
-
-               if (!(flags & MSG_PEEK))
-                       skb_pull(skb, chunk);
-
-               eor = cb->nsp_flags & 0x40;
-
-               if (skb->len == 0) {
-                       skb_unlink(skb, queue);
-                       kfree_skb(skb);
-                       /*
-                        * N.B. Don't refer to skb or cb after this point
-                        * in loop.
-                        */
-                       if ((scp->flowloc_sw == DN_DONTSEND) && !dn_congested(sk)) {
-                               scp->flowloc_sw = DN_SEND;
-                               dn_nsp_send_link(sk, DN_SEND, 0);
-                       }
-               }
-
-               if (eor) {
-                       if (sk->sk_type == SOCK_SEQPACKET)
-                               break;
-                       if (!(flags & MSG_WAITALL))
-                               break;
-               }
-
-               if (flags & MSG_OOB)
-                       break;
-
-               if (copied >= target)
-                       break;
-       }
-
-       rv = copied;
-
-
-       if (eor && (sk->sk_type == SOCK_SEQPACKET))
-               msg->msg_flags |= MSG_EOR;
-
-out:
-       if (rv == 0)
-               rv = (flags & MSG_PEEK) ? -sk->sk_err : sock_error(sk);
-
-       if ((rv >= 0) && msg->msg_name) {
-               __sockaddr_check_size(sizeof(struct sockaddr_dn));
-               memcpy(msg->msg_name, &scp->peer, sizeof(struct sockaddr_dn));
-               msg->msg_namelen = sizeof(struct sockaddr_dn);
-       }
-
-       release_sock(sk);
-
-       return rv;
-}
-
-
-static inline int dn_queue_too_long(struct dn_scp *scp, struct sk_buff_head *queue, int flags)
-{
-       unsigned char fctype = scp->services_rem & NSP_FC_MASK;
-       if (skb_queue_len(queue) >= scp->snd_window)
-               return 1;
-       if (fctype != NSP_FC_NONE) {
-               if (flags & MSG_OOB) {
-                       if (scp->flowrem_oth == 0)
-                               return 1;
-               } else {
-                       if (scp->flowrem_dat == 0)
-                               return 1;
-               }
-       }
-       return 0;
-}
-
-/*
- * The DECnet spec requires that the "routing layer" accepts packets which
- * are at least 230 bytes in size. This excludes any headers which the NSP
- * layer might add, so we always assume that we'll be using the maximal
- * length header on data packets. The variation in length is due to the
- * inclusion (or not) of the two 16 bit acknowledgement fields so it doesn't
- * make much practical difference.
- */
-unsigned int dn_mss_from_pmtu(struct net_device *dev, int mtu)
-{
-       unsigned int mss = 230 - DN_MAX_NSP_DATA_HEADER;
-       if (dev) {
-               struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-               mtu -= LL_RESERVED_SPACE(dev);
-               if (dn_db->use_long)
-                       mtu -= 21;
-               else
-                       mtu -= 6;
-               mtu -= DN_MAX_NSP_DATA_HEADER;
-       } else {
-               /*
-                * 21 = long header, 16 = guess at MAC header length
-                */
-               mtu -= (21 + DN_MAX_NSP_DATA_HEADER + 16);
-       }
-       if (mtu > mss)
-               mss = mtu;
-       return mss;
-}
-
-static inline unsigned int dn_current_mss(struct sock *sk, int flags)
-{
-       struct dst_entry *dst = __sk_dst_get(sk);
-       struct dn_scp *scp = DN_SK(sk);
-       int mss_now = min_t(int, scp->segsize_loc, scp->segsize_rem);
-
-       /* Other data messages are limited to 16 bytes per packet */
-       if (flags & MSG_OOB)
-               return 16;
-
-       /* This works out the maximum size of segment we can send out */
-       if (dst) {
-               u32 mtu = dst_mtu(dst);
-               mss_now = min_t(int, dn_mss_from_pmtu(dst->dev, mtu), mss_now);
-       }
-
-       return mss_now;
-}
-
-/*
- * N.B. We get the timeout wrong here, but then we always did get it
- * wrong before and this is another step along the road to correcting
- * it. It ought to get updated each time we pass through the routine,
- * but in practise it probably doesn't matter too much for now.
- */
-static inline struct sk_buff *dn_alloc_send_pskb(struct sock *sk,
-                             unsigned long datalen, int noblock,
-                             int *errcode)
-{
-       struct sk_buff *skb = sock_alloc_send_skb(sk, datalen,
-                                                  noblock, errcode);
-       if (skb) {
-               skb->protocol = htons(ETH_P_DNA_RT);
-               skb->pkt_type = PACKET_OUTGOING;
-       }
-       return skb;
-}
-
-static int dn_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
-{
-       struct sock *sk = sock->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       size_t mss;
-       struct sk_buff_head *queue = &scp->data_xmit_queue;
-       int flags = msg->msg_flags;
-       int err = 0;
-       size_t sent = 0;
-       int addr_len = msg->msg_namelen;
-       DECLARE_SOCKADDR(struct sockaddr_dn *, addr, msg->msg_name);
-       struct sk_buff *skb = NULL;
-       struct dn_skb_cb *cb;
-       size_t len;
-       unsigned char fctype;
-       long timeo;
-
-       if (flags & ~(MSG_TRYHARD|MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_NOSIGNAL|MSG_MORE|MSG_CMSG_COMPAT))
-               return -EOPNOTSUPP;
-
-       if (addr_len && (addr_len != sizeof(struct sockaddr_dn)))
-               return -EINVAL;
-
-       lock_sock(sk);
-       timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);
-       /*
-        * The only difference between stream sockets and sequenced packet
-        * sockets is that the stream sockets always behave as if MSG_EOR
-        * has been set.
-        */
-       if (sock->type == SOCK_STREAM) {
-               if (flags & MSG_EOR) {
-                       err = -EINVAL;
-                       goto out;
-               }
-               flags |= MSG_EOR;
-       }
-
-
-       err = dn_check_state(sk, addr, addr_len, &timeo, flags);
-       if (err)
-               goto out_err;
-
-       if (sk->sk_shutdown & SEND_SHUTDOWN) {
-               err = -EPIPE;
-               if (!(flags & MSG_NOSIGNAL))
-                       send_sig(SIGPIPE, current, 0);
-               goto out_err;
-       }
-
-       if ((flags & MSG_TRYHARD) && sk->sk_dst_cache)
-               dst_negative_advice(sk);
-
-       mss = scp->segsize_rem;
-       fctype = scp->services_rem & NSP_FC_MASK;
-
-       mss = dn_current_mss(sk, flags);
-
-       if (flags & MSG_OOB) {
-               queue = &scp->other_xmit_queue;
-               if (size > mss) {
-                       err = -EMSGSIZE;
-                       goto out;
-               }
-       }
-
-       scp->persist_fxn = dn_nsp_xmit_timeout;
-
-       while(sent < size) {
-               err = sock_error(sk);
-               if (err)
-                       goto out;
-
-               if (signal_pending(current)) {
-                       err = sock_intr_errno(timeo);
-                       goto out;
-               }
-
-               /*
-                * Calculate size that we wish to send.
-                */
-               len = size - sent;
-
-               if (len > mss)
-                       len = mss;
-
-               /*
-                * Wait for queue size to go down below the window
-                * size.
-                */
-               if (dn_queue_too_long(scp, queue, flags)) {
-                       DEFINE_WAIT_FUNC(wait, woken_wake_function);
-
-                       if (flags & MSG_DONTWAIT) {
-                               err = -EWOULDBLOCK;
-                               goto out;
-                       }
-
-                       add_wait_queue(sk_sleep(sk), &wait);
-                       sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-                       sk_wait_event(sk, &timeo,
-                                     !dn_queue_too_long(scp, queue, flags), &wait);
-                       sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
-                       remove_wait_queue(sk_sleep(sk), &wait);
-                       continue;
-               }
-
-               /*
-                * Get a suitably sized skb.
-                * 64 is a bit of a hack really, but its larger than any
-                * link-layer headers and has served us well as a good
-                * guess as to their real length.
-                */
-               skb = dn_alloc_send_pskb(sk, len + 64 + DN_MAX_NSP_DATA_HEADER,
-                                        flags & MSG_DONTWAIT, &err);
-
-               if (err)
-                       break;
-
-               if (!skb)
-                       continue;
-
-               cb = DN_SKB_CB(skb);
-
-               skb_reserve(skb, 64 + DN_MAX_NSP_DATA_HEADER);
-
-               if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
-                       err = -EFAULT;
-                       goto out;
-               }
-
-               if (flags & MSG_OOB) {
-                       cb->nsp_flags = 0x30;
-                       if (fctype != NSP_FC_NONE)
-                               scp->flowrem_oth--;
-               } else {
-                       cb->nsp_flags = 0x00;
-                       if (scp->seg_total == 0)
-                               cb->nsp_flags |= 0x20;
-
-                       scp->seg_total += len;
-
-                       if (((sent + len) == size) && (flags & MSG_EOR)) {
-                               cb->nsp_flags |= 0x40;
-                               scp->seg_total = 0;
-                               if (fctype == NSP_FC_SCMC)
-                                       scp->flowrem_dat--;
-                       }
-                       if (fctype == NSP_FC_SRC)
-                               scp->flowrem_dat--;
-               }
-
-               sent += len;
-               dn_nsp_queue_xmit(sk, skb, sk->sk_allocation, flags & MSG_OOB);
-               skb = NULL;
-
-               scp->persist = dn_nsp_persist(sk);
-
-       }
-out:
-
-       kfree_skb(skb);
-
-       release_sock(sk);
-
-       return sent ? sent : err;
-
-out_err:
-       err = sk_stream_error(sk, flags, err);
-       release_sock(sk);
-       return err;
-}
-
-static int dn_device_event(struct notifier_block *this, unsigned long event,
-                          void *ptr)
-{
-       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-
-       if (!net_eq(dev_net(dev), &init_net))
-               return NOTIFY_DONE;
-
-       switch (event) {
-       case NETDEV_UP:
-               dn_dev_up(dev);
-               break;
-       case NETDEV_DOWN:
-               dn_dev_down(dev);
-               break;
-       default:
-               break;
-       }
-
-       return NOTIFY_DONE;
-}
-
-static struct notifier_block dn_dev_notifier = {
-       .notifier_call = dn_device_event,
-};
-
-static struct packet_type dn_dix_packet_type __read_mostly = {
-       .type =         cpu_to_be16(ETH_P_DNA_RT),
-       .func =         dn_route_rcv,
-};
-
-#ifdef CONFIG_PROC_FS
-struct dn_iter_state {
-       int bucket;
-};
-
-static struct sock *dn_socket_get_first(struct seq_file *seq)
-{
-       struct dn_iter_state *state = seq->private;
-       struct sock *n = NULL;
-
-       for(state->bucket = 0;
-           state->bucket < DN_SK_HASH_SIZE;
-           ++state->bucket) {
-               n = sk_head(&dn_sk_hash[state->bucket]);
-               if (n)
-                       break;
-       }
-
-       return n;
-}
-
-static struct sock *dn_socket_get_next(struct seq_file *seq,
-                                      struct sock *n)
-{
-       struct dn_iter_state *state = seq->private;
-
-       n = sk_next(n);
-       while (!n) {
-               if (++state->bucket >= DN_SK_HASH_SIZE)
-                       break;
-               n = sk_head(&dn_sk_hash[state->bucket]);
-       }
-       return n;
-}
-
-static struct sock *socket_get_idx(struct seq_file *seq, loff_t *pos)
-{
-       struct sock *sk = dn_socket_get_first(seq);
-
-       if (sk) {
-               while(*pos && (sk = dn_socket_get_next(seq, sk)))
-                       --*pos;
-       }
-       return *pos ? NULL : sk;
-}
-
-static void *dn_socket_get_idx(struct seq_file *seq, loff_t pos)
-{
-       void *rc;
-       read_lock_bh(&dn_hash_lock);
-       rc = socket_get_idx(seq, &pos);
-       if (!rc) {
-               read_unlock_bh(&dn_hash_lock);
-       }
-       return rc;
-}
-
-static void *dn_socket_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       return *pos ? dn_socket_get_idx(seq, *pos - 1) : SEQ_START_TOKEN;
-}
-
-static void *dn_socket_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       void *rc;
-
-       if (v == SEQ_START_TOKEN) {
-               rc = dn_socket_get_idx(seq, 0);
-               goto out;
-       }
-
-       rc = dn_socket_get_next(seq, v);
-       if (rc)
-               goto out;
-       read_unlock_bh(&dn_hash_lock);
-out:
-       ++*pos;
-       return rc;
-}
-
-static void dn_socket_seq_stop(struct seq_file *seq, void *v)
-{
-       if (v && v != SEQ_START_TOKEN)
-               read_unlock_bh(&dn_hash_lock);
-}
-
-#define IS_NOT_PRINTABLE(x) ((x) < 32 || (x) > 126)
-
-static void dn_printable_object(struct sockaddr_dn *dn, unsigned char *buf)
-{
-       int i;
-
-       switch (le16_to_cpu(dn->sdn_objnamel)) {
-       case 0:
-               sprintf(buf, "%d", dn->sdn_objnum);
-               break;
-       default:
-               for (i = 0; i < le16_to_cpu(dn->sdn_objnamel); i++) {
-                       buf[i] = dn->sdn_objname[i];
-                       if (IS_NOT_PRINTABLE(buf[i]))
-                               buf[i] = '.';
-               }
-               buf[i] = 0;
-       }
-}
-
-static char *dn_state2asc(unsigned char state)
-{
-       switch (state) {
-       case DN_O:
-               return "OPEN";
-       case DN_CR:
-               return "  CR";
-       case DN_DR:
-               return "  DR";
-       case DN_DRC:
-               return " DRC";
-       case DN_CC:
-               return "  CC";
-       case DN_CI:
-               return "  CI";
-       case DN_NR:
-               return "  NR";
-       case DN_NC:
-               return "  NC";
-       case DN_CD:
-               return "  CD";
-       case DN_RJ:
-               return "  RJ";
-       case DN_RUN:
-               return " RUN";
-       case DN_DI:
-               return "  DI";
-       case DN_DIC:
-               return " DIC";
-       case DN_DN:
-               return "  DN";
-       case DN_CL:
-               return "  CL";
-       case DN_CN:
-               return "  CN";
-       }
-
-       return "????";
-}
-
-static inline void dn_socket_format_entry(struct seq_file *seq, struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       char buf1[DN_ASCBUF_LEN];
-       char buf2[DN_ASCBUF_LEN];
-       char local_object[DN_MAXOBJL+3];
-       char remote_object[DN_MAXOBJL+3];
-
-       dn_printable_object(&scp->addr, local_object);
-       dn_printable_object(&scp->peer, remote_object);
-
-       seq_printf(seq,
-                  "%6s/%04X %04d:%04d %04d:%04d %01d %-16s "
-                  "%6s/%04X %04d:%04d %04d:%04d %01d %-16s %4s %s\n",
-                  dn_addr2asc(le16_to_cpu(dn_saddr2dn(&scp->addr)), buf1),
-                  scp->addrloc,
-                  scp->numdat,
-                  scp->numoth,
-                  scp->ackxmt_dat,
-                  scp->ackxmt_oth,
-                  scp->flowloc_sw,
-                  local_object,
-                  dn_addr2asc(le16_to_cpu(dn_saddr2dn(&scp->peer)), buf2),
-                  scp->addrrem,
-                  scp->numdat_rcv,
-                  scp->numoth_rcv,
-                  scp->ackrcv_dat,
-                  scp->ackrcv_oth,
-                  scp->flowrem_sw,
-                  remote_object,
-                  dn_state2asc(scp->state),
-                  ((scp->accept_mode == ACC_IMMED) ? "IMMED" : "DEFER"));
-}
-
-static int dn_socket_seq_show(struct seq_file *seq, void *v)
-{
-       if (v == SEQ_START_TOKEN) {
-               seq_puts(seq, "Local                                              Remote\n");
-       } else {
-               dn_socket_format_entry(seq, v);
-       }
-       return 0;
-}
-
-static const struct seq_operations dn_socket_seq_ops = {
-       .start  = dn_socket_seq_start,
-       .next   = dn_socket_seq_next,
-       .stop   = dn_socket_seq_stop,
-       .show   = dn_socket_seq_show,
-};
-#endif
-
-static const struct net_proto_family   dn_family_ops = {
-       .family =       AF_DECnet,
-       .create =       dn_create,
-       .owner  =       THIS_MODULE,
-};
-
-static const struct proto_ops dn_proto_ops = {
-       .family =       AF_DECnet,
-       .owner =        THIS_MODULE,
-       .release =      dn_release,
-       .bind =         dn_bind,
-       .connect =      dn_connect,
-       .socketpair =   sock_no_socketpair,
-       .accept =       dn_accept,
-       .getname =      dn_getname,
-       .poll =         dn_poll,
-       .ioctl =        dn_ioctl,
-       .listen =       dn_listen,
-       .shutdown =     dn_shutdown,
-       .setsockopt =   dn_setsockopt,
-       .getsockopt =   dn_getsockopt,
-       .sendmsg =      dn_sendmsg,
-       .recvmsg =      dn_recvmsg,
-       .mmap =         sock_no_mmap,
-       .sendpage =     sock_no_sendpage,
-};
-
-MODULE_DESCRIPTION("The Linux DECnet Network Protocol");
-MODULE_AUTHOR("Linux DECnet Project Team");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_NETPROTO(PF_DECnet);
-
-static const char banner[] __initconst = KERN_INFO
-"NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n";
-
-static int __init decnet_init(void)
-{
-       int rc;
-
-       printk(banner);
-
-       rc = proto_register(&dn_proto, 1);
-       if (rc != 0)
-               goto out;
-
-       dn_neigh_init();
-       dn_dev_init();
-       dn_route_init();
-       dn_fib_init();
-
-       sock_register(&dn_family_ops);
-       dev_add_pack(&dn_dix_packet_type);
-       register_netdevice_notifier(&dn_dev_notifier);
-
-       proc_create_seq_private("decnet", 0444, init_net.proc_net,
-                       &dn_socket_seq_ops, sizeof(struct dn_iter_state),
-                       NULL);
-       dn_register_sysctl();
-out:
-       return rc;
-
-}
-module_init(decnet_init);
-
-/*
- * Prevent DECnet module unloading until its fixed properly.
- * Requires an audit of the code to check for memory leaks and
- * initialisation problems etc.
- */
-#if 0
-static void __exit decnet_exit(void)
-{
-       sock_unregister(AF_DECnet);
-       rtnl_unregister_all(PF_DECnet);
-       dev_remove_pack(&dn_dix_packet_type);
-
-       dn_unregister_sysctl();
-
-       unregister_netdevice_notifier(&dn_dev_notifier);
-
-       dn_route_cleanup();
-       dn_dev_cleanup();
-       dn_neigh_cleanup();
-       dn_fib_cleanup();
-
-       remove_proc_entry("decnet", init_net.proc_net);
-
-       proto_unregister(&dn_proto);
-
-       rcu_barrier(); /* Wait for completion of call_rcu()'s */
-}
-module_exit(decnet_exit);
-#endif
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c
deleted file mode 100644 (file)
index a09ba64..0000000
+++ /dev/null
@@ -1,1433 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Device Layer
- *
- * Authors:     Steve Whitehouse <SteveW@ACM.org>
- *              Eduardo Marcelo Serrat <emserrat@geocities.com>
- *
- * Changes:
- *          Steve Whitehouse : Devices now see incoming frames so they
- *                             can mark on who it came from.
- *          Steve Whitehouse : Fixed bug in creating neighbours. Each neighbour
- *                             can now have a device specific setup func.
- *          Steve Whitehouse : Added /proc/sys/net/decnet/conf/<dev>/
- *          Steve Whitehouse : Fixed bug which sometimes killed timer
- *          Steve Whitehouse : Multiple ifaddr support
- *          Steve Whitehouse : SIOCGIFCONF is now a compile time option
- *          Steve Whitehouse : /proc/sys/net/decnet/conf/<sys>/forwarding
- *          Steve Whitehouse : Removed timer1 - it's a user space issue now
- *         Patrick Caulfield : Fixed router hello message format
- *          Steve Whitehouse : Got rid of constant sizes for blksize for
- *                             devices. All mtu based now.
- */
-
-#include <linux/capability.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/if_addr.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/skbuff.h>
-#include <linux/sysctl.h>
-#include <linux/notifier.h>
-#include <linux/slab.h>
-#include <linux/jiffies.h>
-#include <linux/uaccess.h>
-#include <net/net_namespace.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/fib_rules.h>
-#include <net/netlink.h>
-#include <net/dn.h>
-#include <net/dn_dev.h>
-#include <net/dn_route.h>
-#include <net/dn_neigh.h>
-#include <net/dn_fib.h>
-
-#define DN_IFREQ_SIZE (offsetof(struct ifreq, ifr_ifru) + sizeof(struct sockaddr_dn))
-
-static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
-static char dn_rt_all_rt_mcast[ETH_ALEN]  = {0xAB,0x00,0x00,0x03,0x00,0x00};
-static char dn_hiord[ETH_ALEN]            = {0xAA,0x00,0x04,0x00,0x00,0x00};
-static unsigned char dn_eco_version[3]    = {0x02,0x00,0x00};
-
-extern struct neigh_table dn_neigh_table;
-
-/*
- * decnet_address is kept in network order.
- */
-__le16 decnet_address = 0;
-
-static DEFINE_SPINLOCK(dndev_lock);
-static struct net_device *decnet_default_device;
-static BLOCKING_NOTIFIER_HEAD(dnaddr_chain);
-
-static struct dn_dev *dn_dev_create(struct net_device *dev, int *err);
-static void dn_dev_delete(struct net_device *dev);
-static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa);
-
-static int dn_eth_up(struct net_device *);
-static void dn_eth_down(struct net_device *);
-static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa);
-static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa);
-
-static struct dn_dev_parms dn_dev_list[] =  {
-{
-       .type =         ARPHRD_ETHER, /* Ethernet */
-       .mode =         DN_DEV_BCAST,
-       .state =        DN_DEV_S_RU,
-       .t2 =           1,
-       .t3 =           10,
-       .name =         "ethernet",
-       .up =           dn_eth_up,
-       .down =         dn_eth_down,
-       .timer3 =       dn_send_brd_hello,
-},
-{
-       .type =         ARPHRD_IPGRE, /* DECnet tunneled over GRE in IP */
-       .mode =         DN_DEV_BCAST,
-       .state =        DN_DEV_S_RU,
-       .t2 =           1,
-       .t3 =           10,
-       .name =         "ipgre",
-       .timer3 =       dn_send_brd_hello,
-},
-#if 0
-{
-       .type =         ARPHRD_X25, /* Bog standard X.25 */
-       .mode =         DN_DEV_UCAST,
-       .state =        DN_DEV_S_DS,
-       .t2 =           1,
-       .t3 =           120,
-       .name =         "x25",
-       .timer3 =       dn_send_ptp_hello,
-},
-#endif
-#if 0
-{
-       .type =         ARPHRD_PPP, /* DECnet over PPP */
-       .mode =         DN_DEV_BCAST,
-       .state =        DN_DEV_S_RU,
-       .t2 =           1,
-       .t3 =           10,
-       .name =         "ppp",
-       .timer3 =       dn_send_brd_hello,
-},
-#endif
-{
-       .type =         ARPHRD_DDCMP, /* DECnet over DDCMP */
-       .mode =         DN_DEV_UCAST,
-       .state =        DN_DEV_S_DS,
-       .t2 =           1,
-       .t3 =           120,
-       .name =         "ddcmp",
-       .timer3 =       dn_send_ptp_hello,
-},
-{
-       .type =         ARPHRD_LOOPBACK, /* Loopback interface - always last */
-       .mode =         DN_DEV_BCAST,
-       .state =        DN_DEV_S_RU,
-       .t2 =           1,
-       .t3 =           10,
-       .name =         "loopback",
-       .timer3 =       dn_send_brd_hello,
-}
-};
-
-#define DN_DEV_LIST_SIZE ARRAY_SIZE(dn_dev_list)
-
-#define DN_DEV_PARMS_OFFSET(x) offsetof(struct dn_dev_parms, x)
-
-#ifdef CONFIG_SYSCTL
-
-static int min_t2[] = { 1 };
-static int max_t2[] = { 60 }; /* No max specified, but this seems sensible */
-static int min_t3[] = { 1 };
-static int max_t3[] = { 8191 }; /* Must fit in 16 bits when multiplied by BCT3MULT or T3MULT */
-
-static int min_priority[1];
-static int max_priority[] = { 127 }; /* From DECnet spec */
-
-static int dn_forwarding_proc(struct ctl_table *, int, void *, size_t *,
-               loff_t *);
-static struct dn_dev_sysctl_table {
-       struct ctl_table_header *sysctl_header;
-       struct ctl_table dn_dev_vars[5];
-} dn_dev_sysctl = {
-       NULL,
-       {
-       {
-               .procname = "forwarding",
-               .data = (void *)DN_DEV_PARMS_OFFSET(forwarding),
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = dn_forwarding_proc,
-       },
-       {
-               .procname = "priority",
-               .data = (void *)DN_DEV_PARMS_OFFSET(priority),
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_priority,
-               .extra2 = &max_priority
-       },
-       {
-               .procname = "t2",
-               .data = (void *)DN_DEV_PARMS_OFFSET(t2),
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_t2,
-               .extra2 = &max_t2
-       },
-       {
-               .procname = "t3",
-               .data = (void *)DN_DEV_PARMS_OFFSET(t3),
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_t3,
-               .extra2 = &max_t3
-       },
-       { }
-       },
-};
-
-static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
-{
-       struct dn_dev_sysctl_table *t;
-       int i;
-
-       char path[sizeof("net/decnet/conf/") + IFNAMSIZ];
-
-       t = kmemdup(&dn_dev_sysctl, sizeof(*t), GFP_KERNEL);
-       if (t == NULL)
-               return;
-
-       for(i = 0; i < ARRAY_SIZE(t->dn_dev_vars) - 1; i++) {
-               long offset = (long)t->dn_dev_vars[i].data;
-               t->dn_dev_vars[i].data = ((char *)parms) + offset;
-       }
-
-       snprintf(path, sizeof(path), "net/decnet/conf/%s",
-               dev? dev->name : parms->name);
-
-       t->dn_dev_vars[0].extra1 = (void *)dev;
-
-       t->sysctl_header = register_net_sysctl(&init_net, path, t->dn_dev_vars);
-       if (t->sysctl_header == NULL)
-               kfree(t);
-       else
-               parms->sysctl = t;
-}
-
-static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
-{
-       if (parms->sysctl) {
-               struct dn_dev_sysctl_table *t = parms->sysctl;
-               parms->sysctl = NULL;
-               unregister_net_sysctl_table(t->sysctl_header);
-               kfree(t);
-       }
-}
-
-static int dn_forwarding_proc(struct ctl_table *table, int write,
-               void *buffer, size_t *lenp, loff_t *ppos)
-{
-#ifdef CONFIG_DECNET_ROUTER
-       struct net_device *dev = table->extra1;
-       struct dn_dev *dn_db;
-       int err;
-       int tmp, old;
-
-       if (table->extra1 == NULL)
-               return -EINVAL;
-
-       dn_db = rcu_dereference_raw(dev->dn_ptr);
-       old = dn_db->parms.forwarding;
-
-       err = proc_dointvec(table, write, buffer, lenp, ppos);
-
-       if ((err >= 0) && write) {
-               if (dn_db->parms.forwarding < 0)
-                       dn_db->parms.forwarding = 0;
-               if (dn_db->parms.forwarding > 2)
-                       dn_db->parms.forwarding = 2;
-               /*
-                * What an ugly hack this is... its works, just. It
-                * would be nice if sysctl/proc were just that little
-                * bit more flexible so I don't have to write a special
-                * routine, or suffer hacks like this - SJW
-                */
-               tmp = dn_db->parms.forwarding;
-               dn_db->parms.forwarding = old;
-               if (dn_db->parms.down)
-                       dn_db->parms.down(dev);
-               dn_db->parms.forwarding = tmp;
-               if (dn_db->parms.up)
-                       dn_db->parms.up(dev);
-       }
-
-       return err;
-#else
-       return -EINVAL;
-#endif
-}
-
-#else /* CONFIG_SYSCTL */
-static void dn_dev_sysctl_unregister(struct dn_dev_parms *parms)
-{
-}
-static void dn_dev_sysctl_register(struct net_device *dev, struct dn_dev_parms *parms)
-{
-}
-
-#endif /* CONFIG_SYSCTL */
-
-static inline __u16 mtu2blksize(struct net_device *dev)
-{
-       u32 blksize = dev->mtu;
-       if (blksize > 0xffff)
-               blksize = 0xffff;
-
-       if (dev->type == ARPHRD_ETHER ||
-           dev->type == ARPHRD_PPP ||
-           dev->type == ARPHRD_IPGRE ||
-           dev->type == ARPHRD_LOOPBACK)
-               blksize -= 2;
-
-       return (__u16)blksize;
-}
-
-static struct dn_ifaddr *dn_dev_alloc_ifa(void)
-{
-       struct dn_ifaddr *ifa;
-
-       ifa = kzalloc(sizeof(*ifa), GFP_KERNEL);
-
-       return ifa;
-}
-
-static void dn_dev_free_ifa(struct dn_ifaddr *ifa)
-{
-       kfree_rcu(ifa, rcu);
-}
-
-static void dn_dev_del_ifa(struct dn_dev *dn_db, struct dn_ifaddr __rcu **ifap, int destroy)
-{
-       struct dn_ifaddr *ifa1 = rtnl_dereference(*ifap);
-       unsigned char mac_addr[6];
-       struct net_device *dev = dn_db->dev;
-
-       ASSERT_RTNL();
-
-       *ifap = ifa1->ifa_next;
-
-       if (dn_db->dev->type == ARPHRD_ETHER) {
-               if (ifa1->ifa_local != dn_eth2dn(dev->dev_addr)) {
-                       dn_dn2eth(mac_addr, ifa1->ifa_local);
-                       dev_mc_del(dev, mac_addr);
-               }
-       }
-
-       dn_ifaddr_notify(RTM_DELADDR, ifa1);
-       blocking_notifier_call_chain(&dnaddr_chain, NETDEV_DOWN, ifa1);
-       if (destroy) {
-               dn_dev_free_ifa(ifa1);
-
-               if (dn_db->ifa_list == NULL)
-                       dn_dev_delete(dn_db->dev);
-       }
-}
-
-static int dn_dev_insert_ifa(struct dn_dev *dn_db, struct dn_ifaddr *ifa)
-{
-       struct net_device *dev = dn_db->dev;
-       struct dn_ifaddr *ifa1;
-       unsigned char mac_addr[6];
-
-       ASSERT_RTNL();
-
-       /* Check for duplicates */
-       for (ifa1 = rtnl_dereference(dn_db->ifa_list);
-            ifa1 != NULL;
-            ifa1 = rtnl_dereference(ifa1->ifa_next)) {
-               if (ifa1->ifa_local == ifa->ifa_local)
-                       return -EEXIST;
-       }
-
-       if (dev->type == ARPHRD_ETHER) {
-               if (ifa->ifa_local != dn_eth2dn(dev->dev_addr)) {
-                       dn_dn2eth(mac_addr, ifa->ifa_local);
-                       dev_mc_add(dev, mac_addr);
-               }
-       }
-
-       ifa->ifa_next = dn_db->ifa_list;
-       rcu_assign_pointer(dn_db->ifa_list, ifa);
-
-       dn_ifaddr_notify(RTM_NEWADDR, ifa);
-       blocking_notifier_call_chain(&dnaddr_chain, NETDEV_UP, ifa);
-
-       return 0;
-}
-
-static int dn_dev_set_ifa(struct net_device *dev, struct dn_ifaddr *ifa)
-{
-       struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
-       int rv;
-
-       if (dn_db == NULL) {
-               int err;
-               dn_db = dn_dev_create(dev, &err);
-               if (dn_db == NULL)
-                       return err;
-       }
-
-       ifa->ifa_dev = dn_db;
-
-       if (dev->flags & IFF_LOOPBACK)
-               ifa->ifa_scope = RT_SCOPE_HOST;
-
-       rv = dn_dev_insert_ifa(dn_db, ifa);
-       if (rv)
-               dn_dev_free_ifa(ifa);
-       return rv;
-}
-
-
-int dn_dev_ioctl(unsigned int cmd, void __user *arg)
-{
-       char buffer[DN_IFREQ_SIZE];
-       struct ifreq *ifr = (struct ifreq *)buffer;
-       struct sockaddr_dn *sdn = (struct sockaddr_dn *)&ifr->ifr_addr;
-       struct dn_dev *dn_db;
-       struct net_device *dev;
-       struct dn_ifaddr *ifa = NULL;
-       struct dn_ifaddr __rcu **ifap = NULL;
-       int ret = 0;
-
-       if (copy_from_user(ifr, arg, DN_IFREQ_SIZE))
-               return -EFAULT;
-       ifr->ifr_name[IFNAMSIZ-1] = 0;
-
-       dev_load(&init_net, ifr->ifr_name);
-
-       switch (cmd) {
-       case SIOCGIFADDR:
-               break;
-       case SIOCSIFADDR:
-               if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
-               if (sdn->sdn_family != AF_DECnet)
-                       return -EINVAL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       rtnl_lock();
-
-       if ((dev = __dev_get_by_name(&init_net, ifr->ifr_name)) == NULL) {
-               ret = -ENODEV;
-               goto done;
-       }
-
-       if ((dn_db = rtnl_dereference(dev->dn_ptr)) != NULL) {
-               for (ifap = &dn_db->ifa_list;
-                    (ifa = rtnl_dereference(*ifap)) != NULL;
-                    ifap = &ifa->ifa_next)
-                       if (strcmp(ifr->ifr_name, ifa->ifa_label) == 0)
-                               break;
-       }
-
-       if (ifa == NULL && cmd != SIOCSIFADDR) {
-               ret = -EADDRNOTAVAIL;
-               goto done;
-       }
-
-       switch (cmd) {
-       case SIOCGIFADDR:
-               *((__le16 *)sdn->sdn_nodeaddr) = ifa->ifa_local;
-               if (copy_to_user(arg, ifr, DN_IFREQ_SIZE))
-                       ret = -EFAULT;
-               break;
-
-       case SIOCSIFADDR:
-               if (!ifa) {
-                       if ((ifa = dn_dev_alloc_ifa()) == NULL) {
-                               ret = -ENOBUFS;
-                               break;
-                       }
-                       memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
-               } else {
-                       if (ifa->ifa_local == dn_saddr2dn(sdn))
-                               break;
-                       dn_dev_del_ifa(dn_db, ifap, 0);
-               }
-
-               ifa->ifa_local = ifa->ifa_address = dn_saddr2dn(sdn);
-
-               ret = dn_dev_set_ifa(dev, ifa);
-       }
-done:
-       rtnl_unlock();
-
-       return ret;
-}
-
-struct net_device *dn_dev_get_default(void)
-{
-       struct net_device *dev;
-
-       spin_lock(&dndev_lock);
-       dev = decnet_default_device;
-       if (dev) {
-               if (dev->dn_ptr)
-                       dev_hold(dev);
-               else
-                       dev = NULL;
-       }
-       spin_unlock(&dndev_lock);
-
-       return dev;
-}
-
-int dn_dev_set_default(struct net_device *dev, int force)
-{
-       struct net_device *old = NULL;
-       int rv = -EBUSY;
-       if (!dev->dn_ptr)
-               return -ENODEV;
-
-       spin_lock(&dndev_lock);
-       if (force || decnet_default_device == NULL) {
-               old = decnet_default_device;
-               decnet_default_device = dev;
-               rv = 0;
-       }
-       spin_unlock(&dndev_lock);
-
-       dev_put(old);
-       return rv;
-}
-
-static void dn_dev_check_default(struct net_device *dev)
-{
-       spin_lock(&dndev_lock);
-       if (dev == decnet_default_device) {
-               decnet_default_device = NULL;
-       } else {
-               dev = NULL;
-       }
-       spin_unlock(&dndev_lock);
-
-       dev_put(dev);
-}
-
-/*
- * Called with RTNL
- */
-static struct dn_dev *dn_dev_by_index(int ifindex)
-{
-       struct net_device *dev;
-       struct dn_dev *dn_dev = NULL;
-
-       dev = __dev_get_by_index(&init_net, ifindex);
-       if (dev)
-               dn_dev = rtnl_dereference(dev->dn_ptr);
-
-       return dn_dev;
-}
-
-static const struct nla_policy dn_ifa_policy[IFA_MAX+1] = {
-       [IFA_ADDRESS]           = { .type = NLA_U16 },
-       [IFA_LOCAL]             = { .type = NLA_U16 },
-       [IFA_LABEL]             = { .type = NLA_STRING,
-                                   .len = IFNAMSIZ - 1 },
-       [IFA_FLAGS]             = { .type = NLA_U32 },
-};
-
-static int dn_nl_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
-                        struct netlink_ext_ack *extack)
-{
-       struct net *net = sock_net(skb->sk);
-       struct nlattr *tb[IFA_MAX+1];
-       struct dn_dev *dn_db;
-       struct ifaddrmsg *ifm;
-       struct dn_ifaddr *ifa;
-       struct dn_ifaddr __rcu **ifap;
-       int err = -EINVAL;
-
-       if (!netlink_capable(skb, CAP_NET_ADMIN))
-               return -EPERM;
-
-       if (!net_eq(net, &init_net))
-               goto errout;
-
-       err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
-                                    dn_ifa_policy, extack);
-       if (err < 0)
-               goto errout;
-
-       err = -ENODEV;
-       ifm = nlmsg_data(nlh);
-       if ((dn_db = dn_dev_by_index(ifm->ifa_index)) == NULL)
-               goto errout;
-
-       err = -EADDRNOTAVAIL;
-       for (ifap = &dn_db->ifa_list;
-            (ifa = rtnl_dereference(*ifap)) != NULL;
-            ifap = &ifa->ifa_next) {
-               if (tb[IFA_LOCAL] &&
-                   nla_memcmp(tb[IFA_LOCAL], &ifa->ifa_local, 2))
-                       continue;
-
-               if (tb[IFA_LABEL] && nla_strcmp(tb[IFA_LABEL], ifa->ifa_label))
-                       continue;
-
-               dn_dev_del_ifa(dn_db, ifap, 1);
-               return 0;
-       }
-
-errout:
-       return err;
-}
-
-static int dn_nl_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
-                        struct netlink_ext_ack *extack)
-{
-       struct net *net = sock_net(skb->sk);
-       struct nlattr *tb[IFA_MAX+1];
-       struct net_device *dev;
-       struct dn_dev *dn_db;
-       struct ifaddrmsg *ifm;
-       struct dn_ifaddr *ifa;
-       int err;
-
-       if (!netlink_capable(skb, CAP_NET_ADMIN))
-               return -EPERM;
-
-       if (!net_eq(net, &init_net))
-               return -EINVAL;
-
-       err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
-                                    dn_ifa_policy, extack);
-       if (err < 0)
-               return err;
-
-       if (tb[IFA_LOCAL] == NULL)
-               return -EINVAL;
-
-       ifm = nlmsg_data(nlh);
-       if ((dev = __dev_get_by_index(&init_net, ifm->ifa_index)) == NULL)
-               return -ENODEV;
-
-       if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) {
-               dn_db = dn_dev_create(dev, &err);
-               if (!dn_db)
-                       return err;
-       }
-
-       if ((ifa = dn_dev_alloc_ifa()) == NULL)
-               return -ENOBUFS;
-
-       if (tb[IFA_ADDRESS] == NULL)
-               tb[IFA_ADDRESS] = tb[IFA_LOCAL];
-
-       ifa->ifa_local = nla_get_le16(tb[IFA_LOCAL]);
-       ifa->ifa_address = nla_get_le16(tb[IFA_ADDRESS]);
-       ifa->ifa_flags = tb[IFA_FLAGS] ? nla_get_u32(tb[IFA_FLAGS]) :
-                                        ifm->ifa_flags;
-       ifa->ifa_scope = ifm->ifa_scope;
-       ifa->ifa_dev = dn_db;
-
-       if (tb[IFA_LABEL])
-               nla_strscpy(ifa->ifa_label, tb[IFA_LABEL], IFNAMSIZ);
-       else
-               memcpy(ifa->ifa_label, dev->name, IFNAMSIZ);
-
-       err = dn_dev_insert_ifa(dn_db, ifa);
-       if (err)
-               dn_dev_free_ifa(ifa);
-
-       return err;
-}
-
-static inline size_t dn_ifaddr_nlmsg_size(void)
-{
-       return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
-              + nla_total_size(IFNAMSIZ) /* IFA_LABEL */
-              + nla_total_size(2) /* IFA_ADDRESS */
-              + nla_total_size(2) /* IFA_LOCAL */
-              + nla_total_size(4); /* IFA_FLAGS */
-}
-
-static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
-                            u32 portid, u32 seq, int event, unsigned int flags)
-{
-       struct ifaddrmsg *ifm;
-       struct nlmsghdr *nlh;
-       u32 ifa_flags = ifa->ifa_flags | IFA_F_PERMANENT;
-
-       nlh = nlmsg_put(skb, portid, seq, event, sizeof(*ifm), flags);
-       if (nlh == NULL)
-               return -EMSGSIZE;
-
-       ifm = nlmsg_data(nlh);
-       ifm->ifa_family = AF_DECnet;
-       ifm->ifa_prefixlen = 16;
-       ifm->ifa_flags = ifa_flags;
-       ifm->ifa_scope = ifa->ifa_scope;
-       ifm->ifa_index = ifa->ifa_dev->dev->ifindex;
-
-       if ((ifa->ifa_address &&
-            nla_put_le16(skb, IFA_ADDRESS, ifa->ifa_address)) ||
-           (ifa->ifa_local &&
-            nla_put_le16(skb, IFA_LOCAL, ifa->ifa_local)) ||
-           (ifa->ifa_label[0] &&
-            nla_put_string(skb, IFA_LABEL, ifa->ifa_label)) ||
-            nla_put_u32(skb, IFA_FLAGS, ifa_flags))
-               goto nla_put_failure;
-       nlmsg_end(skb, nlh);
-       return 0;
-
-nla_put_failure:
-       nlmsg_cancel(skb, nlh);
-       return -EMSGSIZE;
-}
-
-static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
-{
-       struct sk_buff *skb;
-       int err = -ENOBUFS;
-
-       skb = alloc_skb(dn_ifaddr_nlmsg_size(), GFP_KERNEL);
-       if (skb == NULL)
-               goto errout;
-
-       err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
-       if (err < 0) {
-               /* -EMSGSIZE implies BUG in dn_ifaddr_nlmsg_size() */
-               WARN_ON(err == -EMSGSIZE);
-               kfree_skb(skb);
-               goto errout;
-       }
-       rtnl_notify(skb, &init_net, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
-       return;
-errout:
-       if (err < 0)
-               rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_IFADDR, err);
-}
-
-static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
-{
-       struct net *net = sock_net(skb->sk);
-       int idx, dn_idx = 0, skip_ndevs, skip_naddr;
-       struct net_device *dev;
-       struct dn_dev *dn_db;
-       struct dn_ifaddr *ifa;
-
-       if (!net_eq(net, &init_net))
-               return 0;
-
-       skip_ndevs = cb->args[0];
-       skip_naddr = cb->args[1];
-
-       idx = 0;
-       rcu_read_lock();
-       for_each_netdev_rcu(&init_net, dev) {
-               if (idx < skip_ndevs)
-                       goto cont;
-               else if (idx > skip_ndevs) {
-                       /* Only skip over addresses for first dev dumped
-                        * in this iteration (idx == skip_ndevs) */
-                       skip_naddr = 0;
-               }
-
-               if ((dn_db = rcu_dereference(dev->dn_ptr)) == NULL)
-                       goto cont;
-
-               for (ifa = rcu_dereference(dn_db->ifa_list), dn_idx = 0; ifa;
-                    ifa = rcu_dereference(ifa->ifa_next), dn_idx++) {
-                       if (dn_idx < skip_naddr)
-                               continue;
-
-                       if (dn_nl_fill_ifaddr(skb, ifa, NETLINK_CB(cb->skb).portid,
-                                             cb->nlh->nlmsg_seq, RTM_NEWADDR,
-                                             NLM_F_MULTI) < 0)
-                               goto done;
-               }
-cont:
-               idx++;
-       }
-done:
-       rcu_read_unlock();
-       cb->args[0] = idx;
-       cb->args[1] = dn_idx;
-
-       return skb->len;
-}
-
-static int dn_dev_get_first(struct net_device *dev, __le16 *addr)
-{
-       struct dn_dev *dn_db;
-       struct dn_ifaddr *ifa;
-       int rv = -ENODEV;
-
-       rcu_read_lock();
-       dn_db = rcu_dereference(dev->dn_ptr);
-       if (dn_db == NULL)
-               goto out;
-
-       ifa = rcu_dereference(dn_db->ifa_list);
-       if (ifa != NULL) {
-               *addr = ifa->ifa_local;
-               rv = 0;
-       }
-out:
-       rcu_read_unlock();
-       return rv;
-}
-
-/*
- * Find a default address to bind to.
- *
- * This is one of those areas where the initial VMS concepts don't really
- * map onto the Linux concepts, and since we introduced multiple addresses
- * per interface we have to cope with slightly odd ways of finding out what
- * "our address" really is. Mostly it's not a problem; for this we just guess
- * a sensible default. Eventually the routing code will take care of all the
- * nasties for us I hope.
- */
-int dn_dev_bind_default(__le16 *addr)
-{
-       struct net_device *dev;
-       int rv;
-       dev = dn_dev_get_default();
-last_chance:
-       if (dev) {
-               rv = dn_dev_get_first(dev, addr);
-               dev_put(dev);
-               if (rv == 0 || dev == init_net.loopback_dev)
-                       return rv;
-       }
-       dev = init_net.loopback_dev;
-       dev_hold(dev);
-       goto last_chance;
-}
-
-static void dn_send_endnode_hello(struct net_device *dev, struct dn_ifaddr *ifa)
-{
-       struct endnode_hello_message *msg;
-       struct sk_buff *skb = NULL;
-       __le16 *pktlen;
-       struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-
-       if ((skb = dn_alloc_skb(NULL, sizeof(*msg), GFP_ATOMIC)) == NULL)
-               return;
-
-       skb->dev = dev;
-
-       msg = skb_put(skb, sizeof(*msg));
-
-       msg->msgflg  = 0x0D;
-       memcpy(msg->tiver, dn_eco_version, 3);
-       dn_dn2eth(msg->id, ifa->ifa_local);
-       msg->iinfo   = DN_RT_INFO_ENDN;
-       msg->blksize = cpu_to_le16(mtu2blksize(dev));
-       msg->area    = 0x00;
-       memset(msg->seed, 0, 8);
-       memcpy(msg->neighbor, dn_hiord, ETH_ALEN);
-
-       if (dn_db->router) {
-               struct dn_neigh *dn = container_of(dn_db->router, struct dn_neigh, n);
-               dn_dn2eth(msg->neighbor, dn->addr);
-       }
-
-       msg->timer   = cpu_to_le16((unsigned short)dn_db->parms.t3);
-       msg->mpd     = 0x00;
-       msg->datalen = 0x02;
-       memset(msg->data, 0xAA, 2);
-
-       pktlen = skb_push(skb, 2);
-       *pktlen = cpu_to_le16(skb->len - 2);
-
-       skb_reset_network_header(skb);
-
-       dn_rt_finish_output(skb, dn_rt_all_rt_mcast, msg->id);
-}
-
-
-#define DRDELAY (5 * HZ)
-
-static int dn_am_i_a_router(struct dn_neigh *dn, struct dn_dev *dn_db, struct dn_ifaddr *ifa)
-{
-       /* First check time since device went up */
-       if (time_before(jiffies, dn_db->uptime + DRDELAY))
-               return 0;
-
-       /* If there is no router, then yes... */
-       if (!dn_db->router)
-               return 1;
-
-       /* otherwise only if we have a higher priority or.. */
-       if (dn->priority < dn_db->parms.priority)
-               return 1;
-
-       /* if we have equal priority and a higher node number */
-       if (dn->priority != dn_db->parms.priority)
-               return 0;
-
-       if (le16_to_cpu(dn->addr) < le16_to_cpu(ifa->ifa_local))
-               return 1;
-
-       return 0;
-}
-
-static void dn_send_router_hello(struct net_device *dev, struct dn_ifaddr *ifa)
-{
-       int n;
-       struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-       struct dn_neigh *dn = container_of(dn_db->router, struct dn_neigh, n);
-       struct sk_buff *skb;
-       size_t size;
-       unsigned char *ptr;
-       unsigned char *i1, *i2;
-       __le16 *pktlen;
-       char *src;
-
-       if (mtu2blksize(dev) < (26 + 7))
-               return;
-
-       n = mtu2blksize(dev) - 26;
-       n /= 7;
-
-       if (n > 32)
-               n = 32;
-
-       size = 2 + 26 + 7 * n;
-
-       if ((skb = dn_alloc_skb(NULL, size, GFP_ATOMIC)) == NULL)
-               return;
-
-       skb->dev = dev;
-       ptr = skb_put(skb, size);
-
-       *ptr++ = DN_RT_PKT_CNTL | DN_RT_PKT_ERTH;
-       *ptr++ = 2; /* ECO */
-       *ptr++ = 0;
-       *ptr++ = 0;
-       dn_dn2eth(ptr, ifa->ifa_local);
-       src = ptr;
-       ptr += ETH_ALEN;
-       *ptr++ = dn_db->parms.forwarding == 1 ?
-                       DN_RT_INFO_L1RT : DN_RT_INFO_L2RT;
-       *((__le16 *)ptr) = cpu_to_le16(mtu2blksize(dev));
-       ptr += 2;
-       *ptr++ = dn_db->parms.priority; /* Priority */
-       *ptr++ = 0; /* Area: Reserved */
-       *((__le16 *)ptr) = cpu_to_le16((unsigned short)dn_db->parms.t3);
-       ptr += 2;
-       *ptr++ = 0; /* MPD: Reserved */
-       i1 = ptr++;
-       memset(ptr, 0, 7); /* Name: Reserved */
-       ptr += 7;
-       i2 = ptr++;
-
-       n = dn_neigh_elist(dev, ptr, n);
-
-       *i2 = 7 * n;
-       *i1 = 8 + *i2;
-
-       skb_trim(skb, (27 + *i2));
-
-       pktlen = skb_push(skb, 2);
-       *pktlen = cpu_to_le16(skb->len - 2);
-
-       skb_reset_network_header(skb);
-
-       if (dn_am_i_a_router(dn, dn_db, ifa)) {
-               struct sk_buff *skb2 = skb_copy(skb, GFP_ATOMIC);
-               if (skb2) {
-                       dn_rt_finish_output(skb2, dn_rt_all_end_mcast, src);
-               }
-       }
-
-       dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
-}
-
-static void dn_send_brd_hello(struct net_device *dev, struct dn_ifaddr *ifa)
-{
-       struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-
-       if (dn_db->parms.forwarding == 0)
-               dn_send_endnode_hello(dev, ifa);
-       else
-               dn_send_router_hello(dev, ifa);
-}
-
-static void dn_send_ptp_hello(struct net_device *dev, struct dn_ifaddr *ifa)
-{
-       int tdlen = 16;
-       int size = dev->hard_header_len + 2 + 4 + tdlen;
-       struct sk_buff *skb = dn_alloc_skb(NULL, size, GFP_ATOMIC);
-       int i;
-       unsigned char *ptr;
-       char src[ETH_ALEN];
-
-       if (skb == NULL)
-               return ;
-
-       skb->dev = dev;
-       skb_push(skb, dev->hard_header_len);
-       ptr = skb_put(skb, 2 + 4 + tdlen);
-
-       *ptr++ = DN_RT_PKT_HELO;
-       *((__le16 *)ptr) = ifa->ifa_local;
-       ptr += 2;
-       *ptr++ = tdlen;
-
-       for(i = 0; i < tdlen; i++)
-               *ptr++ = 0252;
-
-       dn_dn2eth(src, ifa->ifa_local);
-       dn_rt_finish_output(skb, dn_rt_all_rt_mcast, src);
-}
-
-static int dn_eth_up(struct net_device *dev)
-{
-       struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-
-       if (dn_db->parms.forwarding == 0)
-               dev_mc_add(dev, dn_rt_all_end_mcast);
-       else
-               dev_mc_add(dev, dn_rt_all_rt_mcast);
-
-       dn_db->use_long = 1;
-
-       return 0;
-}
-
-static void dn_eth_down(struct net_device *dev)
-{
-       struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-
-       if (dn_db->parms.forwarding == 0)
-               dev_mc_del(dev, dn_rt_all_end_mcast);
-       else
-               dev_mc_del(dev, dn_rt_all_rt_mcast);
-}
-
-static void dn_dev_set_timer(struct net_device *dev);
-
-static void dn_dev_timer_func(struct timer_list *t)
-{
-       struct dn_dev *dn_db = from_timer(dn_db, t, timer);
-       struct net_device *dev;
-       struct dn_ifaddr *ifa;
-
-       rcu_read_lock();
-       dev = dn_db->dev;
-       if (dn_db->t3 <= dn_db->parms.t2) {
-               if (dn_db->parms.timer3) {
-                       for (ifa = rcu_dereference(dn_db->ifa_list);
-                            ifa;
-                            ifa = rcu_dereference(ifa->ifa_next)) {
-                               if (!(ifa->ifa_flags & IFA_F_SECONDARY))
-                                       dn_db->parms.timer3(dev, ifa);
-                       }
-               }
-               dn_db->t3 = dn_db->parms.t3;
-       } else {
-               dn_db->t3 -= dn_db->parms.t2;
-       }
-       rcu_read_unlock();
-       dn_dev_set_timer(dev);
-}
-
-static void dn_dev_set_timer(struct net_device *dev)
-{
-       struct dn_dev *dn_db = rcu_dereference_raw(dev->dn_ptr);
-
-       if (dn_db->parms.t2 > dn_db->parms.t3)
-               dn_db->parms.t2 = dn_db->parms.t3;
-
-       dn_db->timer.expires = jiffies + (dn_db->parms.t2 * HZ);
-
-       add_timer(&dn_db->timer);
-}
-
-static struct dn_dev *dn_dev_create(struct net_device *dev, int *err)
-{
-       int i;
-       struct dn_dev_parms *p = dn_dev_list;
-       struct dn_dev *dn_db;
-
-       for(i = 0; i < DN_DEV_LIST_SIZE; i++, p++) {
-               if (p->type == dev->type)
-                       break;
-       }
-
-       *err = -ENODEV;
-       if (i == DN_DEV_LIST_SIZE)
-               return NULL;
-
-       *err = -ENOBUFS;
-       if ((dn_db = kzalloc(sizeof(struct dn_dev), GFP_ATOMIC)) == NULL)
-               return NULL;
-
-       memcpy(&dn_db->parms, p, sizeof(struct dn_dev_parms));
-
-       rcu_assign_pointer(dev->dn_ptr, dn_db);
-       dn_db->dev = dev;
-       timer_setup(&dn_db->timer, dn_dev_timer_func, 0);
-
-       dn_db->uptime = jiffies;
-
-       dn_db->neigh_parms = neigh_parms_alloc(dev, &dn_neigh_table);
-       if (!dn_db->neigh_parms) {
-               RCU_INIT_POINTER(dev->dn_ptr, NULL);
-               kfree(dn_db);
-               return NULL;
-       }
-
-       if (dn_db->parms.up) {
-               if (dn_db->parms.up(dev) < 0) {
-                       neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
-                       dev->dn_ptr = NULL;
-                       kfree(dn_db);
-                       return NULL;
-               }
-       }
-
-       dn_dev_sysctl_register(dev, &dn_db->parms);
-
-       dn_dev_set_timer(dev);
-
-       *err = 0;
-       return dn_db;
-}
-
-
-/*
- * This processes a device up event. We only start up
- * the loopback device & ethernet devices with correct
- * MAC addresses automatically. Others must be started
- * specifically.
- *
- * FIXME: How should we configure the loopback address ? If we could dispense
- * with using decnet_address here and for autobind, it will be one less thing
- * for users to worry about setting up.
- */
-
-void dn_dev_up(struct net_device *dev)
-{
-       struct dn_ifaddr *ifa;
-       __le16 addr = decnet_address;
-       int maybe_default = 0;
-       struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
-
-       if ((dev->type != ARPHRD_ETHER) && (dev->type != ARPHRD_LOOPBACK))
-               return;
-
-       /*
-        * Need to ensure that loopback device has a dn_db attached to it
-        * to allow creation of neighbours against it, even though it might
-        * not have a local address of its own. Might as well do the same for
-        * all autoconfigured interfaces.
-        */
-       if (dn_db == NULL) {
-               int err;
-               dn_db = dn_dev_create(dev, &err);
-               if (dn_db == NULL)
-                       return;
-       }
-
-       if (dev->type == ARPHRD_ETHER) {
-               if (memcmp(dev->dev_addr, dn_hiord, 4) != 0)
-                       return;
-               addr = dn_eth2dn(dev->dev_addr);
-               maybe_default = 1;
-       }
-
-       if (addr == 0)
-               return;
-
-       if ((ifa = dn_dev_alloc_ifa()) == NULL)
-               return;
-
-       ifa->ifa_local = ifa->ifa_address = addr;
-       ifa->ifa_flags = 0;
-       ifa->ifa_scope = RT_SCOPE_UNIVERSE;
-       strcpy(ifa->ifa_label, dev->name);
-
-       dn_dev_set_ifa(dev, ifa);
-
-       /*
-        * Automagically set the default device to the first automatically
-        * configured ethernet card in the system.
-        */
-       if (maybe_default) {
-               dev_hold(dev);
-               if (dn_dev_set_default(dev, 0))
-                       dev_put(dev);
-       }
-}
-
-static void dn_dev_delete(struct net_device *dev)
-{
-       struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
-
-       if (dn_db == NULL)
-               return;
-
-       del_timer_sync(&dn_db->timer);
-       dn_dev_sysctl_unregister(&dn_db->parms);
-       dn_dev_check_default(dev);
-       neigh_ifdown(&dn_neigh_table, dev);
-
-       if (dn_db->parms.down)
-               dn_db->parms.down(dev);
-
-       dev->dn_ptr = NULL;
-
-       neigh_parms_release(&dn_neigh_table, dn_db->neigh_parms);
-       neigh_ifdown(&dn_neigh_table, dev);
-
-       if (dn_db->router)
-               neigh_release(dn_db->router);
-       if (dn_db->peer)
-               neigh_release(dn_db->peer);
-
-       kfree(dn_db);
-}
-
-void dn_dev_down(struct net_device *dev)
-{
-       struct dn_dev *dn_db = rtnl_dereference(dev->dn_ptr);
-       struct dn_ifaddr *ifa;
-
-       if (dn_db == NULL)
-               return;
-
-       while ((ifa = rtnl_dereference(dn_db->ifa_list)) != NULL) {
-               dn_dev_del_ifa(dn_db, &dn_db->ifa_list, 0);
-               dn_dev_free_ifa(ifa);
-       }
-
-       dn_dev_delete(dev);
-}
-
-void dn_dev_init_pkt(struct sk_buff *skb)
-{
-}
-
-void dn_dev_veri_pkt(struct sk_buff *skb)
-{
-}
-
-void dn_dev_hello(struct sk_buff *skb)
-{
-}
-
-void dn_dev_devices_off(void)
-{
-       struct net_device *dev;
-
-       rtnl_lock();
-       for_each_netdev(&init_net, dev)
-               dn_dev_down(dev);
-       rtnl_unlock();
-
-}
-
-void dn_dev_devices_on(void)
-{
-       struct net_device *dev;
-
-       rtnl_lock();
-       for_each_netdev(&init_net, dev) {
-               if (dev->flags & IFF_UP)
-                       dn_dev_up(dev);
-       }
-       rtnl_unlock();
-}
-
-int register_dnaddr_notifier(struct notifier_block *nb)
-{
-       return blocking_notifier_chain_register(&dnaddr_chain, nb);
-}
-
-int unregister_dnaddr_notifier(struct notifier_block *nb)
-{
-       return blocking_notifier_chain_unregister(&dnaddr_chain, nb);
-}
-
-#ifdef CONFIG_PROC_FS
-static inline int is_dn_dev(struct net_device *dev)
-{
-       return dev->dn_ptr != NULL;
-}
-
-static void *dn_dev_seq_start(struct seq_file *seq, loff_t *pos)
-       __acquires(RCU)
-{
-       int i;
-       struct net_device *dev;
-
-       rcu_read_lock();
-
-       if (*pos == 0)
-               return SEQ_START_TOKEN;
-
-       i = 1;
-       for_each_netdev_rcu(&init_net, dev) {
-               if (!is_dn_dev(dev))
-                       continue;
-
-               if (i++ == *pos)
-                       return dev;
-       }
-
-       return NULL;
-}
-
-static void *dn_dev_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct net_device *dev;
-
-       ++*pos;
-
-       dev = v;
-       if (v == SEQ_START_TOKEN)
-               dev = net_device_entry(&init_net.dev_base_head);
-
-       for_each_netdev_continue_rcu(&init_net, dev) {
-               if (!is_dn_dev(dev))
-                       continue;
-
-               return dev;
-       }
-
-       return NULL;
-}
-
-static void dn_dev_seq_stop(struct seq_file *seq, void *v)
-       __releases(RCU)
-{
-       rcu_read_unlock();
-}
-
-static char *dn_type2asc(char type)
-{
-       switch (type) {
-       case DN_DEV_BCAST:
-               return "B";
-       case DN_DEV_UCAST:
-               return "U";
-       case DN_DEV_MPOINT:
-               return "M";
-       }
-
-       return "?";
-}
-
-static int dn_dev_seq_show(struct seq_file *seq, void *v)
-{
-       if (v == SEQ_START_TOKEN)
-               seq_puts(seq, "Name     Flags T1   Timer1 T3   Timer3 BlkSize Pri State DevType    Router Peer\n");
-       else {
-               struct net_device *dev = v;
-               char peer_buf[DN_ASCBUF_LEN];
-               char router_buf[DN_ASCBUF_LEN];
-               struct dn_dev *dn_db = rcu_dereference(dev->dn_ptr);
-
-               seq_printf(seq, "%-8s %1s     %04u %04u   %04lu %04lu"
-                               "   %04hu    %03d %02x    %-10s %-7s %-7s\n",
-                               dev->name,
-                               dn_type2asc(dn_db->parms.mode),
-                               0, 0,
-                               dn_db->t3, dn_db->parms.t3,
-                               mtu2blksize(dev),
-                               dn_db->parms.priority,
-                               dn_db->parms.state, dn_db->parms.name,
-                               dn_db->router ? dn_addr2asc(le16_to_cpu(*(__le16 *)dn_db->router->primary_key), router_buf) : "",
-                               dn_db->peer ? dn_addr2asc(le16_to_cpu(*(__le16 *)dn_db->peer->primary_key), peer_buf) : "");
-       }
-       return 0;
-}
-
-static const struct seq_operations dn_dev_seq_ops = {
-       .start  = dn_dev_seq_start,
-       .next   = dn_dev_seq_next,
-       .stop   = dn_dev_seq_stop,
-       .show   = dn_dev_seq_show,
-};
-#endif /* CONFIG_PROC_FS */
-
-static int addr[2];
-module_param_array(addr, int, NULL, 0444);
-MODULE_PARM_DESC(addr, "The DECnet address of this machine: area,node");
-
-void __init dn_dev_init(void)
-{
-       if (addr[0] > 63 || addr[0] < 0) {
-               printk(KERN_ERR "DECnet: Area must be between 0 and 63");
-               return;
-       }
-
-       if (addr[1] > 1023 || addr[1] < 0) {
-               printk(KERN_ERR "DECnet: Node must be between 0 and 1023");
-               return;
-       }
-
-       decnet_address = cpu_to_le16((addr[0] << 10) | addr[1]);
-
-       dn_dev_devices_on();
-
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_NEWADDR,
-                            dn_nl_newaddr, NULL, 0);
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_DELADDR,
-                            dn_nl_deladdr, NULL, 0);
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_GETADDR,
-                            NULL, dn_nl_dump_ifaddr, 0);
-
-       proc_create_seq("decnet_dev", 0444, init_net.proc_net, &dn_dev_seq_ops);
-
-#ifdef CONFIG_SYSCTL
-       {
-               int i;
-               for(i = 0; i < DN_DEV_LIST_SIZE; i++)
-                       dn_dev_sysctl_register(NULL, &dn_dev_list[i]);
-       }
-#endif /* CONFIG_SYSCTL */
-}
-
-void __exit dn_dev_cleanup(void)
-{
-#ifdef CONFIG_SYSCTL
-       {
-               int i;
-               for(i = 0; i < DN_DEV_LIST_SIZE; i++)
-                       dn_dev_sysctl_unregister(&dn_dev_list[i]);
-       }
-#endif /* CONFIG_SYSCTL */
-
-       remove_proc_entry("decnet_dev", init_net.proc_net);
-
-       dn_dev_devices_off();
-}
diff --git a/net/decnet/dn_fib.c b/net/decnet/dn_fib.c
deleted file mode 100644 (file)
index 269c029..0000000
+++ /dev/null
@@ -1,798 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Routing Forwarding Information Base (Glue/Info List)
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *
- *
- * Changes:
- *              Alexey Kuznetsov : SMP locking changes
- *              Steve Whitehouse : Rewrote it... Well to be more correct, I
- *                                 copied most of it from the ipv4 fib code.
- *              Steve Whitehouse : Updated it in style and fixed a few bugs
- *                                 which were fixed in the ipv4 code since
- *                                 this code was copied from it.
- *
- */
-#include <linux/string.h>
-#include <linux/net.h>
-#include <linux/socket.h>
-#include <linux/slab.h>
-#include <linux/sockios.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/proc_fs.h>
-#include <linux/netdevice.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-#include <linux/uaccess.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/fib_rules.h>
-#include <net/dn.h>
-#include <net/dn_route.h>
-#include <net/dn_fib.h>
-#include <net/dn_neigh.h>
-#include <net/dn_dev.h>
-#include <net/rtnh.h>
-
-#define RT_MIN_TABLE 1
-
-#define for_fib_info() { struct dn_fib_info *fi;\
-       for(fi = dn_fib_info_list; fi; fi = fi->fib_next)
-#define endfor_fib_info() }
-
-#define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
-       for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
-
-#define change_nexthops(fi) { int nhsel; struct dn_fib_nh *nh;\
-       for(nhsel = 0, nh = (struct dn_fib_nh *)((fi)->fib_nh); nhsel < (fi)->fib_nhs; nh++, nhsel++)
-
-#define endfor_nexthops(fi) }
-
-static DEFINE_SPINLOCK(dn_fib_multipath_lock);
-static struct dn_fib_info *dn_fib_info_list;
-static DEFINE_SPINLOCK(dn_fib_info_lock);
-
-static struct
-{
-       int error;
-       u8 scope;
-} dn_fib_props[RTN_MAX+1] = {
-       [RTN_UNSPEC] =      { .error = 0,       .scope = RT_SCOPE_NOWHERE },
-       [RTN_UNICAST] =     { .error = 0,       .scope = RT_SCOPE_UNIVERSE },
-       [RTN_LOCAL] =       { .error = 0,       .scope = RT_SCOPE_HOST },
-       [RTN_BROADCAST] =   { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
-       [RTN_ANYCAST] =     { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
-       [RTN_MULTICAST] =   { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
-       [RTN_BLACKHOLE] =   { .error = -EINVAL, .scope = RT_SCOPE_UNIVERSE },
-       [RTN_UNREACHABLE] = { .error = -EHOSTUNREACH, .scope = RT_SCOPE_UNIVERSE },
-       [RTN_PROHIBIT] =    { .error = -EACCES, .scope = RT_SCOPE_UNIVERSE },
-       [RTN_THROW] =       { .error = -EAGAIN, .scope = RT_SCOPE_UNIVERSE },
-       [RTN_NAT] =         { .error = 0,       .scope = RT_SCOPE_NOWHERE },
-       [RTN_XRESOLVE] =    { .error = -EINVAL, .scope = RT_SCOPE_NOWHERE },
-};
-
-static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force);
-static int dn_fib_sync_up(struct net_device *dev);
-
-void dn_fib_free_info(struct dn_fib_info *fi)
-{
-       if (fi->fib_dead == 0) {
-               printk(KERN_DEBUG "DECnet: BUG! Attempt to free alive dn_fib_info\n");
-               return;
-       }
-
-       change_nexthops(fi) {
-               dev_put(nh->nh_dev);
-               nh->nh_dev = NULL;
-       } endfor_nexthops(fi);
-       kfree(fi);
-}
-
-void dn_fib_release_info(struct dn_fib_info *fi)
-{
-       spin_lock(&dn_fib_info_lock);
-       if (fi && refcount_dec_and_test(&fi->fib_treeref)) {
-               if (fi->fib_next)
-                       fi->fib_next->fib_prev = fi->fib_prev;
-               if (fi->fib_prev)
-                       fi->fib_prev->fib_next = fi->fib_next;
-               if (fi == dn_fib_info_list)
-                       dn_fib_info_list = fi->fib_next;
-               fi->fib_dead = 1;
-               dn_fib_info_put(fi);
-       }
-       spin_unlock(&dn_fib_info_lock);
-}
-
-static inline int dn_fib_nh_comp(const struct dn_fib_info *fi, const struct dn_fib_info *ofi)
-{
-       const struct dn_fib_nh *onh = ofi->fib_nh;
-
-       for_nexthops(fi) {
-               if (nh->nh_oif != onh->nh_oif ||
-                       nh->nh_gw != onh->nh_gw ||
-                       nh->nh_scope != onh->nh_scope ||
-                       nh->nh_weight != onh->nh_weight ||
-                       ((nh->nh_flags^onh->nh_flags)&~RTNH_F_DEAD))
-                               return -1;
-               onh++;
-       } endfor_nexthops(fi);
-       return 0;
-}
-
-static inline struct dn_fib_info *dn_fib_find_info(const struct dn_fib_info *nfi)
-{
-       for_fib_info() {
-               if (fi->fib_nhs != nfi->fib_nhs)
-                       continue;
-               if (nfi->fib_protocol == fi->fib_protocol &&
-                       nfi->fib_prefsrc == fi->fib_prefsrc &&
-                       nfi->fib_priority == fi->fib_priority &&
-                       memcmp(nfi->fib_metrics, fi->fib_metrics, sizeof(fi->fib_metrics)) == 0 &&
-                       ((nfi->fib_flags^fi->fib_flags)&~RTNH_F_DEAD) == 0 &&
-                       (nfi->fib_nhs == 0 || dn_fib_nh_comp(fi, nfi) == 0))
-                               return fi;
-       } endfor_fib_info();
-       return NULL;
-}
-
-static int dn_fib_count_nhs(const struct nlattr *attr)
-{
-       struct rtnexthop *nhp = nla_data(attr);
-       int nhs = 0, nhlen = nla_len(attr);
-
-       while (rtnh_ok(nhp, nhlen)) {
-               nhs++;
-               nhp = rtnh_next(nhp, &nhlen);
-       }
-
-       /* leftover implies invalid nexthop configuration, discard it */
-       return nhlen > 0 ? 0 : nhs;
-}
-
-static int dn_fib_get_nhs(struct dn_fib_info *fi, const struct nlattr *attr,
-                         const struct rtmsg *r)
-{
-       struct rtnexthop *nhp = nla_data(attr);
-       int nhlen = nla_len(attr);
-
-       change_nexthops(fi) {
-               int attrlen;
-
-               if (!rtnh_ok(nhp, nhlen))
-                       return -EINVAL;
-
-               nh->nh_flags  = (r->rtm_flags&~0xFF) | nhp->rtnh_flags;
-               nh->nh_oif    = nhp->rtnh_ifindex;
-               nh->nh_weight = nhp->rtnh_hops + 1;
-
-               attrlen = rtnh_attrlen(nhp);
-               if (attrlen > 0) {
-                       struct nlattr *gw_attr;
-
-                       gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
-                       nh->nh_gw = gw_attr ? nla_get_le16(gw_attr) : 0;
-               }
-
-               nhp = rtnh_next(nhp, &nhlen);
-       } endfor_nexthops(fi);
-
-       return 0;
-}
-
-
-static int dn_fib_check_nh(const struct rtmsg *r, struct dn_fib_info *fi, struct dn_fib_nh *nh)
-{
-       int err;
-
-       if (nh->nh_gw) {
-               struct flowidn fld;
-               struct dn_fib_res res;
-
-               if (nh->nh_flags&RTNH_F_ONLINK) {
-                       struct net_device *dev;
-
-                       if (r->rtm_scope >= RT_SCOPE_LINK)
-                               return -EINVAL;
-                       if (dnet_addr_type(nh->nh_gw) != RTN_UNICAST)
-                               return -EINVAL;
-                       if ((dev = __dev_get_by_index(&init_net, nh->nh_oif)) == NULL)
-                               return -ENODEV;
-                       if (!(dev->flags&IFF_UP))
-                               return -ENETDOWN;
-                       nh->nh_dev = dev;
-                       dev_hold(dev);
-                       nh->nh_scope = RT_SCOPE_LINK;
-                       return 0;
-               }
-
-               memset(&fld, 0, sizeof(fld));
-               fld.daddr = nh->nh_gw;
-               fld.flowidn_oif = nh->nh_oif;
-               fld.flowidn_scope = r->rtm_scope + 1;
-
-               if (fld.flowidn_scope < RT_SCOPE_LINK)
-                       fld.flowidn_scope = RT_SCOPE_LINK;
-
-               if ((err = dn_fib_lookup(&fld, &res)) != 0)
-                       return err;
-
-               err = -EINVAL;
-               if (res.type != RTN_UNICAST && res.type != RTN_LOCAL)
-                       goto out;
-               nh->nh_scope = res.scope;
-               nh->nh_oif = DN_FIB_RES_OIF(res);
-               nh->nh_dev = DN_FIB_RES_DEV(res);
-               if (nh->nh_dev == NULL)
-                       goto out;
-               dev_hold(nh->nh_dev);
-               err = -ENETDOWN;
-               if (!(nh->nh_dev->flags & IFF_UP))
-                       goto out;
-               err = 0;
-out:
-               dn_fib_res_put(&res);
-               return err;
-       } else {
-               struct net_device *dev;
-
-               if (nh->nh_flags&(RTNH_F_PERVASIVE|RTNH_F_ONLINK))
-                       return -EINVAL;
-
-               dev = __dev_get_by_index(&init_net, nh->nh_oif);
-               if (dev == NULL || dev->dn_ptr == NULL)
-                       return -ENODEV;
-               if (!(dev->flags&IFF_UP))
-                       return -ENETDOWN;
-               nh->nh_dev = dev;
-               dev_hold(nh->nh_dev);
-               nh->nh_scope = RT_SCOPE_HOST;
-       }
-
-       return 0;
-}
-
-
-struct dn_fib_info *dn_fib_create_info(const struct rtmsg *r, struct nlattr *attrs[],
-                                      const struct nlmsghdr *nlh, int *errp)
-{
-       int err;
-       struct dn_fib_info *fi = NULL;
-       struct dn_fib_info *ofi;
-       int nhs = 1;
-
-       if (r->rtm_type > RTN_MAX)
-               goto err_inval;
-
-       if (dn_fib_props[r->rtm_type].scope > r->rtm_scope)
-               goto err_inval;
-
-       if (attrs[RTA_MULTIPATH] &&
-           (nhs = dn_fib_count_nhs(attrs[RTA_MULTIPATH])) == 0)
-               goto err_inval;
-
-       fi = kzalloc(struct_size(fi, fib_nh, nhs), GFP_KERNEL);
-       err = -ENOBUFS;
-       if (fi == NULL)
-               goto failure;
-
-       fi->fib_protocol = r->rtm_protocol;
-       fi->fib_nhs = nhs;
-       fi->fib_flags = r->rtm_flags;
-
-       if (attrs[RTA_PRIORITY])
-               fi->fib_priority = nla_get_u32(attrs[RTA_PRIORITY]);
-
-       if (attrs[RTA_METRICS]) {
-               struct nlattr *attr;
-               int rem;
-
-               nla_for_each_nested(attr, attrs[RTA_METRICS], rem) {
-                       int type = nla_type(attr);
-
-                       if (type) {
-                               if (type > RTAX_MAX || type == RTAX_CC_ALGO ||
-                                   nla_len(attr) < 4)
-                                       goto err_inval;
-
-                               fi->fib_metrics[type-1] = nla_get_u32(attr);
-                       }
-               }
-       }
-
-       if (attrs[RTA_PREFSRC])
-               fi->fib_prefsrc = nla_get_le16(attrs[RTA_PREFSRC]);
-
-       if (attrs[RTA_MULTIPATH]) {
-               if ((err = dn_fib_get_nhs(fi, attrs[RTA_MULTIPATH], r)) != 0)
-                       goto failure;
-
-               if (attrs[RTA_OIF] &&
-                   fi->fib_nh->nh_oif != nla_get_u32(attrs[RTA_OIF]))
-                       goto err_inval;
-
-               if (attrs[RTA_GATEWAY] &&
-                   fi->fib_nh->nh_gw != nla_get_le16(attrs[RTA_GATEWAY]))
-                       goto err_inval;
-       } else {
-               struct dn_fib_nh *nh = fi->fib_nh;
-
-               if (attrs[RTA_OIF])
-                       nh->nh_oif = nla_get_u32(attrs[RTA_OIF]);
-
-               if (attrs[RTA_GATEWAY])
-                       nh->nh_gw = nla_get_le16(attrs[RTA_GATEWAY]);
-
-               nh->nh_flags = r->rtm_flags;
-               nh->nh_weight = 1;
-       }
-
-       if (r->rtm_type == RTN_NAT) {
-               if (!attrs[RTA_GATEWAY] || nhs != 1 || attrs[RTA_OIF])
-                       goto err_inval;
-
-               fi->fib_nh->nh_gw = nla_get_le16(attrs[RTA_GATEWAY]);
-               goto link_it;
-       }
-
-       if (dn_fib_props[r->rtm_type].error) {
-               if (attrs[RTA_GATEWAY] || attrs[RTA_OIF] || attrs[RTA_MULTIPATH])
-                       goto err_inval;
-
-               goto link_it;
-       }
-
-       if (r->rtm_scope > RT_SCOPE_HOST)
-               goto err_inval;
-
-       if (r->rtm_scope == RT_SCOPE_HOST) {
-               struct dn_fib_nh *nh = fi->fib_nh;
-
-               /* Local address is added */
-               if (nhs != 1 || nh->nh_gw)
-                       goto err_inval;
-               nh->nh_scope = RT_SCOPE_NOWHERE;
-               nh->nh_dev = dev_get_by_index(&init_net, fi->fib_nh->nh_oif);
-               err = -ENODEV;
-               if (nh->nh_dev == NULL)
-                       goto failure;
-       } else {
-               change_nexthops(fi) {
-                       if ((err = dn_fib_check_nh(r, fi, nh)) != 0)
-                               goto failure;
-               } endfor_nexthops(fi)
-       }
-
-       if (fi->fib_prefsrc) {
-               if (r->rtm_type != RTN_LOCAL || !attrs[RTA_DST] ||
-                   fi->fib_prefsrc != nla_get_le16(attrs[RTA_DST]))
-                       if (dnet_addr_type(fi->fib_prefsrc) != RTN_LOCAL)
-                               goto err_inval;
-       }
-
-link_it:
-       if ((ofi = dn_fib_find_info(fi)) != NULL) {
-               fi->fib_dead = 1;
-               dn_fib_free_info(fi);
-               refcount_inc(&ofi->fib_treeref);
-               return ofi;
-       }
-
-       refcount_set(&fi->fib_treeref, 1);
-       refcount_set(&fi->fib_clntref, 1);
-       spin_lock(&dn_fib_info_lock);
-       fi->fib_next = dn_fib_info_list;
-       fi->fib_prev = NULL;
-       if (dn_fib_info_list)
-               dn_fib_info_list->fib_prev = fi;
-       dn_fib_info_list = fi;
-       spin_unlock(&dn_fib_info_lock);
-       return fi;
-
-err_inval:
-       err = -EINVAL;
-
-failure:
-       *errp = err;
-       if (fi) {
-               fi->fib_dead = 1;
-               dn_fib_free_info(fi);
-       }
-
-       return NULL;
-}
-
-int dn_fib_semantic_match(int type, struct dn_fib_info *fi, const struct flowidn *fld, struct dn_fib_res *res)
-{
-       int err = dn_fib_props[type].error;
-
-       if (err == 0) {
-               if (fi->fib_flags & RTNH_F_DEAD)
-                       return 1;
-
-               res->fi = fi;
-
-               switch (type) {
-               case RTN_NAT:
-                       DN_FIB_RES_RESET(*res);
-                       refcount_inc(&fi->fib_clntref);
-                       return 0;
-               case RTN_UNICAST:
-               case RTN_LOCAL:
-                       for_nexthops(fi) {
-                               if (nh->nh_flags & RTNH_F_DEAD)
-                                       continue;
-                               if (!fld->flowidn_oif ||
-                                   fld->flowidn_oif == nh->nh_oif)
-                                       break;
-                       }
-                       if (nhsel < fi->fib_nhs) {
-                               res->nh_sel = nhsel;
-                               refcount_inc(&fi->fib_clntref);
-                               return 0;
-                       }
-                       endfor_nexthops(fi);
-                       res->fi = NULL;
-                       return 1;
-               default:
-                       net_err_ratelimited("DECnet: impossible routing event : dn_fib_semantic_match type=%d\n",
-                                           type);
-                       res->fi = NULL;
-                       return -EINVAL;
-               }
-       }
-       return err;
-}
-
-void dn_fib_select_multipath(const struct flowidn *fld, struct dn_fib_res *res)
-{
-       struct dn_fib_info *fi = res->fi;
-       int w;
-
-       spin_lock_bh(&dn_fib_multipath_lock);
-       if (fi->fib_power <= 0) {
-               int power = 0;
-               change_nexthops(fi) {
-                       if (!(nh->nh_flags&RTNH_F_DEAD)) {
-                               power += nh->nh_weight;
-                               nh->nh_power = nh->nh_weight;
-                       }
-               } endfor_nexthops(fi);
-               fi->fib_power = power;
-               if (power < 0) {
-                       spin_unlock_bh(&dn_fib_multipath_lock);
-                       res->nh_sel = 0;
-                       return;
-               }
-       }
-
-       w = jiffies % fi->fib_power;
-
-       change_nexthops(fi) {
-               if (!(nh->nh_flags&RTNH_F_DEAD) && nh->nh_power) {
-                       if ((w -= nh->nh_power) <= 0) {
-                               nh->nh_power--;
-                               fi->fib_power--;
-                               res->nh_sel = nhsel;
-                               spin_unlock_bh(&dn_fib_multipath_lock);
-                               return;
-                       }
-               }
-       } endfor_nexthops(fi);
-       res->nh_sel = 0;
-       spin_unlock_bh(&dn_fib_multipath_lock);
-}
-
-static inline u32 rtm_get_table(struct nlattr *attrs[], u8 table)
-{
-       if (attrs[RTA_TABLE])
-               table = nla_get_u32(attrs[RTA_TABLE]);
-
-       return table;
-}
-
-static int dn_fib_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh,
-                              struct netlink_ext_ack *extack)
-{
-       struct net *net = sock_net(skb->sk);
-       struct dn_fib_table *tb;
-       struct rtmsg *r = nlmsg_data(nlh);
-       struct nlattr *attrs[RTA_MAX+1];
-       int err;
-
-       if (!netlink_capable(skb, CAP_NET_ADMIN))
-               return -EPERM;
-
-       if (!net_eq(net, &init_net))
-               return -EINVAL;
-
-       err = nlmsg_parse_deprecated(nlh, sizeof(*r), attrs, RTA_MAX,
-                                    rtm_dn_policy, extack);
-       if (err < 0)
-               return err;
-
-       tb = dn_fib_get_table(rtm_get_table(attrs, r->rtm_table), 0);
-       if (!tb)
-               return -ESRCH;
-
-       return tb->delete(tb, r, attrs, nlh, &NETLINK_CB(skb));
-}
-
-static int dn_fib_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
-                              struct netlink_ext_ack *extack)
-{
-       struct net *net = sock_net(skb->sk);
-       struct dn_fib_table *tb;
-       struct rtmsg *r = nlmsg_data(nlh);
-       struct nlattr *attrs[RTA_MAX+1];
-       int err;
-
-       if (!netlink_capable(skb, CAP_NET_ADMIN))
-               return -EPERM;
-
-       if (!net_eq(net, &init_net))
-               return -EINVAL;
-
-       err = nlmsg_parse_deprecated(nlh, sizeof(*r), attrs, RTA_MAX,
-                                    rtm_dn_policy, extack);
-       if (err < 0)
-               return err;
-
-       tb = dn_fib_get_table(rtm_get_table(attrs, r->rtm_table), 1);
-       if (!tb)
-               return -ENOBUFS;
-
-       return tb->insert(tb, r, attrs, nlh, &NETLINK_CB(skb));
-}
-
-static void fib_magic(int cmd, int type, __le16 dst, int dst_len, struct dn_ifaddr *ifa)
-{
-       struct dn_fib_table *tb;
-       struct {
-               struct nlmsghdr nlh;
-               struct rtmsg rtm;
-       } req;
-       struct {
-               struct nlattr hdr;
-               __le16 dst;
-       } dst_attr = {
-               .dst = dst,
-       };
-       struct {
-               struct nlattr hdr;
-               __le16 prefsrc;
-       } prefsrc_attr = {
-               .prefsrc = ifa->ifa_local,
-       };
-       struct {
-               struct nlattr hdr;
-               u32 oif;
-       } oif_attr = {
-               .oif = ifa->ifa_dev->dev->ifindex,
-       };
-       struct nlattr *attrs[RTA_MAX+1] = {
-               [RTA_DST] = (struct nlattr *) &dst_attr,
-               [RTA_PREFSRC] = (struct nlattr * ) &prefsrc_attr,
-               [RTA_OIF] = (struct nlattr *) &oif_attr,
-       };
-
-       memset(&req.rtm, 0, sizeof(req.rtm));
-
-       if (type == RTN_UNICAST)
-               tb = dn_fib_get_table(RT_MIN_TABLE, 1);
-       else
-               tb = dn_fib_get_table(RT_TABLE_LOCAL, 1);
-
-       if (tb == NULL)
-               return;
-
-       req.nlh.nlmsg_len = sizeof(req);
-       req.nlh.nlmsg_type = cmd;
-       req.nlh.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE|NLM_F_APPEND;
-       req.nlh.nlmsg_pid = 0;
-       req.nlh.nlmsg_seq = 0;
-
-       req.rtm.rtm_dst_len = dst_len;
-       req.rtm.rtm_table = tb->n;
-       req.rtm.rtm_protocol = RTPROT_KERNEL;
-       req.rtm.rtm_scope = (type != RTN_LOCAL ? RT_SCOPE_LINK : RT_SCOPE_HOST);
-       req.rtm.rtm_type = type;
-
-       if (cmd == RTM_NEWROUTE)
-               tb->insert(tb, &req.rtm, attrs, &req.nlh, NULL);
-       else
-               tb->delete(tb, &req.rtm, attrs, &req.nlh, NULL);
-}
-
-static void dn_fib_add_ifaddr(struct dn_ifaddr *ifa)
-{
-
-       fib_magic(RTM_NEWROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
-
-#if 0
-       if (!(dev->flags&IFF_UP))
-               return;
-       /* In the future, we will want to add default routes here */
-
-#endif
-}
-
-static void dn_fib_del_ifaddr(struct dn_ifaddr *ifa)
-{
-       int found_it = 0;
-       struct net_device *dev;
-       struct dn_dev *dn_db;
-       struct dn_ifaddr *ifa2;
-
-       ASSERT_RTNL();
-
-       /* Scan device list */
-       rcu_read_lock();
-       for_each_netdev_rcu(&init_net, dev) {
-               dn_db = rcu_dereference(dev->dn_ptr);
-               if (dn_db == NULL)
-                       continue;
-               for (ifa2 = rcu_dereference(dn_db->ifa_list);
-                    ifa2 != NULL;
-                    ifa2 = rcu_dereference(ifa2->ifa_next)) {
-                       if (ifa2->ifa_local == ifa->ifa_local) {
-                               found_it = 1;
-                               break;
-                       }
-               }
-       }
-       rcu_read_unlock();
-
-       if (found_it == 0) {
-               fib_magic(RTM_DELROUTE, RTN_LOCAL, ifa->ifa_local, 16, ifa);
-
-               if (dnet_addr_type(ifa->ifa_local) != RTN_LOCAL) {
-                       if (dn_fib_sync_down(ifa->ifa_local, NULL, 0))
-                               dn_fib_flush();
-               }
-       }
-}
-
-static void dn_fib_disable_addr(struct net_device *dev, int force)
-{
-       if (dn_fib_sync_down(0, dev, force))
-               dn_fib_flush();
-       dn_rt_cache_flush(0);
-       neigh_ifdown(&dn_neigh_table, dev);
-}
-
-static int dn_fib_dnaddr_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
-       struct dn_ifaddr *ifa = (struct dn_ifaddr *)ptr;
-
-       switch (event) {
-       case NETDEV_UP:
-               dn_fib_add_ifaddr(ifa);
-               dn_fib_sync_up(ifa->ifa_dev->dev);
-               dn_rt_cache_flush(-1);
-               break;
-       case NETDEV_DOWN:
-               dn_fib_del_ifaddr(ifa);
-               if (ifa->ifa_dev && ifa->ifa_dev->ifa_list == NULL) {
-                       dn_fib_disable_addr(ifa->ifa_dev->dev, 1);
-               } else {
-                       dn_rt_cache_flush(-1);
-               }
-               break;
-       }
-       return NOTIFY_DONE;
-}
-
-static int dn_fib_sync_down(__le16 local, struct net_device *dev, int force)
-{
-       int ret = 0;
-       int scope = RT_SCOPE_NOWHERE;
-
-       if (force)
-               scope = -1;
-
-       for_fib_info() {
-               /*
-                * This makes no sense for DECnet.... we will almost
-                * certainly have more than one local address the same
-                * over all our interfaces. It needs thinking about
-                * some more.
-                */
-               if (local && fi->fib_prefsrc == local) {
-                       fi->fib_flags |= RTNH_F_DEAD;
-                       ret++;
-               } else if (dev && fi->fib_nhs) {
-                       int dead = 0;
-
-                       change_nexthops(fi) {
-                               if (nh->nh_flags&RTNH_F_DEAD)
-                                       dead++;
-                               else if (nh->nh_dev == dev &&
-                                               nh->nh_scope != scope) {
-                                       spin_lock_bh(&dn_fib_multipath_lock);
-                                       nh->nh_flags |= RTNH_F_DEAD;
-                                       fi->fib_power -= nh->nh_power;
-                                       nh->nh_power = 0;
-                                       spin_unlock_bh(&dn_fib_multipath_lock);
-                                       dead++;
-                               }
-                       } endfor_nexthops(fi)
-                       if (dead == fi->fib_nhs) {
-                               fi->fib_flags |= RTNH_F_DEAD;
-                               ret++;
-                       }
-               }
-       } endfor_fib_info();
-       return ret;
-}
-
-
-static int dn_fib_sync_up(struct net_device *dev)
-{
-       int ret = 0;
-
-       if (!(dev->flags&IFF_UP))
-               return 0;
-
-       for_fib_info() {
-               int alive = 0;
-
-               change_nexthops(fi) {
-                       if (!(nh->nh_flags&RTNH_F_DEAD)) {
-                               alive++;
-                               continue;
-                       }
-                       if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
-                               continue;
-                       if (nh->nh_dev != dev || dev->dn_ptr == NULL)
-                               continue;
-                       alive++;
-                       spin_lock_bh(&dn_fib_multipath_lock);
-                       nh->nh_power = 0;
-                       nh->nh_flags &= ~RTNH_F_DEAD;
-                       spin_unlock_bh(&dn_fib_multipath_lock);
-               } endfor_nexthops(fi);
-
-               if (alive > 0) {
-                       fi->fib_flags &= ~RTNH_F_DEAD;
-                       ret++;
-               }
-       } endfor_fib_info();
-       return ret;
-}
-
-static struct notifier_block dn_fib_dnaddr_notifier = {
-       .notifier_call = dn_fib_dnaddr_event,
-};
-
-void __exit dn_fib_cleanup(void)
-{
-       dn_fib_table_cleanup();
-       dn_fib_rules_cleanup();
-
-       unregister_dnaddr_notifier(&dn_fib_dnaddr_notifier);
-}
-
-
-void __init dn_fib_init(void)
-{
-       dn_fib_table_init();
-       dn_fib_rules_init();
-
-       register_dnaddr_notifier(&dn_fib_dnaddr_notifier);
-
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_NEWROUTE,
-                            dn_fib_rtm_newroute, NULL, 0);
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_DELROUTE,
-                            dn_fib_rtm_delroute, NULL, 0);
-}
diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c
deleted file mode 100644 (file)
index 7c569bc..0000000
+++ /dev/null
@@ -1,607 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Neighbour Functions (Adjacency Database and
- *                                                        On-Ethernet Cache)
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *
- *
- * Changes:
- *     Steve Whitehouse     : Fixed router listing routine
- *     Steve Whitehouse     : Added error_report functions
- *     Steve Whitehouse     : Added default router detection
- *     Steve Whitehouse     : Hop counts in outgoing messages
- *     Steve Whitehouse     : Fixed src/dst in outgoing messages so
- *                            forwarding now stands a good chance of
- *                            working.
- *     Steve Whitehouse     : Fixed neighbour states (for now anyway).
- *     Steve Whitehouse     : Made error_report functions dummies. This
- *                            is not the right place to return skbs.
- *     Steve Whitehouse     : Convert to seq_file
- *
- */
-
-#include <linux/net.h>
-#include <linux/module.h>
-#include <linux/socket.h>
-#include <linux/if_arp.h>
-#include <linux/slab.h>
-#include <linux/if_ether.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/netfilter_decnet.h>
-#include <linux/spinlock.h>
-#include <linux/seq_file.h>
-#include <linux/rcupdate.h>
-#include <linux/jhash.h>
-#include <linux/atomic.h>
-#include <net/net_namespace.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/dn.h>
-#include <net/dn_dev.h>
-#include <net/dn_neigh.h>
-#include <net/dn_route.h>
-
-static int dn_neigh_construct(struct neighbour *);
-static void dn_neigh_error_report(struct neighbour *, struct sk_buff *);
-static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb);
-
-/*
- * Operations for adding the link layer header.
- */
-static const struct neigh_ops dn_neigh_ops = {
-       .family =               AF_DECnet,
-       .error_report =         dn_neigh_error_report,
-       .output =               dn_neigh_output,
-       .connected_output =     dn_neigh_output,
-};
-
-static u32 dn_neigh_hash(const void *pkey,
-                        const struct net_device *dev,
-                        __u32 *hash_rnd)
-{
-       return jhash_2words(*(__u16 *)pkey, 0, hash_rnd[0]);
-}
-
-static bool dn_key_eq(const struct neighbour *neigh, const void *pkey)
-{
-       return neigh_key_eq16(neigh, pkey);
-}
-
-struct neigh_table dn_neigh_table = {
-       .family =                       PF_DECnet,
-       .entry_size =                   NEIGH_ENTRY_SIZE(sizeof(struct dn_neigh)),
-       .key_len =                      sizeof(__le16),
-       .protocol =                     cpu_to_be16(ETH_P_DNA_RT),
-       .hash =                         dn_neigh_hash,
-       .key_eq =                       dn_key_eq,
-       .constructor =                  dn_neigh_construct,
-       .id =                           "dn_neigh_cache",
-       .parms ={
-               .tbl =                  &dn_neigh_table,
-               .reachable_time =       30 * HZ,
-               .data = {
-                       [NEIGH_VAR_MCAST_PROBES] = 0,
-                       [NEIGH_VAR_UCAST_PROBES] = 0,
-                       [NEIGH_VAR_APP_PROBES] = 0,
-                       [NEIGH_VAR_RETRANS_TIME] = 1 * HZ,
-                       [NEIGH_VAR_BASE_REACHABLE_TIME] = 30 * HZ,
-                       [NEIGH_VAR_DELAY_PROBE_TIME] = 5 * HZ,
-                       [NEIGH_VAR_INTERVAL_PROBE_TIME_MS] = 5 * HZ,
-                       [NEIGH_VAR_GC_STALETIME] = 60 * HZ,
-                       [NEIGH_VAR_QUEUE_LEN_BYTES] = SK_WMEM_MAX,
-                       [NEIGH_VAR_PROXY_QLEN] = 0,
-                       [NEIGH_VAR_ANYCAST_DELAY] = 0,
-                       [NEIGH_VAR_PROXY_DELAY] = 0,
-                       [NEIGH_VAR_LOCKTIME] = 1 * HZ,
-               },
-       },
-       .gc_interval =                  30 * HZ,
-       .gc_thresh1 =                   128,
-       .gc_thresh2 =                   512,
-       .gc_thresh3 =                   1024,
-};
-
-static int dn_neigh_construct(struct neighbour *neigh)
-{
-       struct net_device *dev = neigh->dev;
-       struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
-       struct dn_dev *dn_db;
-       struct neigh_parms *parms;
-
-       rcu_read_lock();
-       dn_db = rcu_dereference(dev->dn_ptr);
-       if (dn_db == NULL) {
-               rcu_read_unlock();
-               return -EINVAL;
-       }
-
-       parms = dn_db->neigh_parms;
-       if (!parms) {
-               rcu_read_unlock();
-               return -EINVAL;
-       }
-
-       __neigh_parms_put(neigh->parms);
-       neigh->parms = neigh_parms_clone(parms);
-       rcu_read_unlock();
-
-       neigh->ops = &dn_neigh_ops;
-       neigh->nud_state = NUD_NOARP;
-       neigh->output = neigh->ops->connected_output;
-
-       if ((dev->type == ARPHRD_IPGRE) || (dev->flags & IFF_POINTOPOINT))
-               memcpy(neigh->ha, dev->broadcast, dev->addr_len);
-       else if ((dev->type == ARPHRD_ETHER) || (dev->type == ARPHRD_LOOPBACK))
-               dn_dn2eth(neigh->ha, dn->addr);
-       else {
-               net_dbg_ratelimited("Trying to create neigh for hw %d\n",
-                                   dev->type);
-               return -EINVAL;
-       }
-
-       /*
-        * Make an estimate of the remote block size by assuming that its
-        * two less then the device mtu, which it true for ethernet (and
-        * other things which support long format headers) since there is
-        * an extra length field (of 16 bits) which isn't part of the
-        * ethernet headers and which the DECnet specs won't admit is part
-        * of the DECnet routing headers either.
-        *
-        * If we over estimate here its no big deal, the NSP negotiations
-        * will prevent us from sending packets which are too large for the
-        * remote node to handle. In any case this figure is normally updated
-        * by a hello message in most cases.
-        */
-       dn->blksize = dev->mtu - 2;
-
-       return 0;
-}
-
-static void dn_neigh_error_report(struct neighbour *neigh, struct sk_buff *skb)
-{
-       printk(KERN_DEBUG "dn_neigh_error_report: called\n");
-       kfree_skb(skb);
-}
-
-static int dn_neigh_output(struct neighbour *neigh, struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb_dst(skb);
-       struct dn_route *rt = (struct dn_route *)dst;
-       struct net_device *dev = neigh->dev;
-       char mac_addr[ETH_ALEN];
-       unsigned int seq;
-       int err;
-
-       dn_dn2eth(mac_addr, rt->rt_local_src);
-       do {
-               seq = read_seqbegin(&neigh->ha_lock);
-               err = dev_hard_header(skb, dev, ntohs(skb->protocol),
-                                     neigh->ha, mac_addr, skb->len);
-       } while (read_seqretry(&neigh->ha_lock, seq));
-
-       if (err >= 0)
-               err = dev_queue_xmit(skb);
-       else {
-               kfree_skb(skb);
-               err = -EINVAL;
-       }
-       return err;
-}
-
-static int dn_neigh_output_packet(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb_dst(skb);
-       struct dn_route *rt = (struct dn_route *)dst;
-       struct neighbour *neigh = rt->n;
-
-       return neigh->output(neigh, skb);
-}
-
-/*
- * For talking to broadcast devices: Ethernet & PPP
- */
-static int dn_long_output(struct neighbour *neigh, struct sock *sk,
-                         struct sk_buff *skb)
-{
-       struct net_device *dev = neigh->dev;
-       int headroom = dev->hard_header_len + sizeof(struct dn_long_packet) + 3;
-       unsigned char *data;
-       struct dn_long_packet *lp;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-
-       if (skb_headroom(skb) < headroom) {
-               struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
-               if (skb2 == NULL) {
-                       net_crit_ratelimited("dn_long_output: no memory\n");
-                       kfree_skb(skb);
-                       return -ENOBUFS;
-               }
-               consume_skb(skb);
-               skb = skb2;
-               net_info_ratelimited("dn_long_output: Increasing headroom\n");
-       }
-
-       data = skb_push(skb, sizeof(struct dn_long_packet) + 3);
-       lp = (struct dn_long_packet *)(data+3);
-
-       *((__le16 *)data) = cpu_to_le16(skb->len - 2);
-       *(data + 2) = 1 | DN_RT_F_PF; /* Padding */
-
-       lp->msgflg   = DN_RT_PKT_LONG|(cb->rt_flags&(DN_RT_F_IE|DN_RT_F_RQR|DN_RT_F_RTS));
-       lp->d_area   = lp->d_subarea = 0;
-       dn_dn2eth(lp->d_id, cb->dst);
-       lp->s_area   = lp->s_subarea = 0;
-       dn_dn2eth(lp->s_id, cb->src);
-       lp->nl2      = 0;
-       lp->visit_ct = cb->hops & 0x3f;
-       lp->s_class  = 0;
-       lp->pt       = 0;
-
-       skb_reset_network_header(skb);
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
-                      &init_net, sk, skb, NULL, neigh->dev,
-                      dn_neigh_output_packet);
-}
-
-/*
- * For talking to pointopoint and multidrop devices: DDCMP and X.25
- */
-static int dn_short_output(struct neighbour *neigh, struct sock *sk,
-                          struct sk_buff *skb)
-{
-       struct net_device *dev = neigh->dev;
-       int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
-       struct dn_short_packet *sp;
-       unsigned char *data;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-
-       if (skb_headroom(skb) < headroom) {
-               struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
-               if (skb2 == NULL) {
-                       net_crit_ratelimited("dn_short_output: no memory\n");
-                       kfree_skb(skb);
-                       return -ENOBUFS;
-               }
-               consume_skb(skb);
-               skb = skb2;
-               net_info_ratelimited("dn_short_output: Increasing headroom\n");
-       }
-
-       data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
-       *((__le16 *)data) = cpu_to_le16(skb->len - 2);
-       sp = (struct dn_short_packet *)(data+2);
-
-       sp->msgflg     = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
-       sp->dstnode    = cb->dst;
-       sp->srcnode    = cb->src;
-       sp->forward    = cb->hops & 0x3f;
-
-       skb_reset_network_header(skb);
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
-                      &init_net, sk, skb, NULL, neigh->dev,
-                      dn_neigh_output_packet);
-}
-
-/*
- * For talking to DECnet phase III nodes
- * Phase 3 output is the same as short output, execpt that
- * it clears the area bits before transmission.
- */
-static int dn_phase3_output(struct neighbour *neigh, struct sock *sk,
-                           struct sk_buff *skb)
-{
-       struct net_device *dev = neigh->dev;
-       int headroom = dev->hard_header_len + sizeof(struct dn_short_packet) + 2;
-       struct dn_short_packet *sp;
-       unsigned char *data;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-       if (skb_headroom(skb) < headroom) {
-               struct sk_buff *skb2 = skb_realloc_headroom(skb, headroom);
-               if (skb2 == NULL) {
-                       net_crit_ratelimited("dn_phase3_output: no memory\n");
-                       kfree_skb(skb);
-                       return -ENOBUFS;
-               }
-               consume_skb(skb);
-               skb = skb2;
-               net_info_ratelimited("dn_phase3_output: Increasing headroom\n");
-       }
-
-       data = skb_push(skb, sizeof(struct dn_short_packet) + 2);
-       *((__le16 *)data) = cpu_to_le16(skb->len - 2);
-       sp = (struct dn_short_packet *)(data + 2);
-
-       sp->msgflg   = DN_RT_PKT_SHORT|(cb->rt_flags&(DN_RT_F_RQR|DN_RT_F_RTS));
-       sp->dstnode  = cb->dst & cpu_to_le16(0x03ff);
-       sp->srcnode  = cb->src & cpu_to_le16(0x03ff);
-       sp->forward  = cb->hops & 0x3f;
-
-       skb_reset_network_header(skb);
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_POST_ROUTING,
-                      &init_net, sk, skb, NULL, neigh->dev,
-                      dn_neigh_output_packet);
-}
-
-int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb_dst(skb);
-       struct dn_route *rt = (struct dn_route *) dst;
-       struct neighbour *neigh = rt->n;
-       struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
-       struct dn_dev *dn_db;
-       bool use_long;
-
-       rcu_read_lock();
-       dn_db = rcu_dereference(neigh->dev->dn_ptr);
-       if (dn_db == NULL) {
-               rcu_read_unlock();
-               return -EINVAL;
-       }
-       use_long = dn_db->use_long;
-       rcu_read_unlock();
-
-       if (dn->flags & DN_NDFLAG_P3)
-               return dn_phase3_output(neigh, sk, skb);
-       if (use_long)
-               return dn_long_output(neigh, sk, skb);
-       else
-               return dn_short_output(neigh, sk, skb);
-}
-
-/*
- * Unfortunately, the neighbour code uses the device in its hash
- * function, so we don't get any advantage from it. This function
- * basically does a neigh_lookup(), but without comparing the device
- * field. This is required for the On-Ethernet cache
- */
-
-/*
- * Pointopoint link receives a hello message
- */
-void dn_neigh_pointopoint_hello(struct sk_buff *skb)
-{
-       kfree_skb(skb);
-}
-
-/*
- * Ethernet router hello message received
- */
-int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct rtnode_hello_message *msg = (struct rtnode_hello_message *)skb->data;
-
-       struct neighbour *neigh;
-       struct dn_neigh *dn;
-       struct dn_dev *dn_db;
-       __le16 src;
-
-       src = dn_eth2dn(msg->id);
-
-       neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
-
-       dn = container_of(neigh, struct dn_neigh, n);
-
-       if (neigh) {
-               write_lock(&neigh->lock);
-
-               neigh->used = jiffies;
-               dn_db = rcu_dereference(neigh->dev->dn_ptr);
-
-               if (!(neigh->nud_state & NUD_PERMANENT)) {
-                       neigh->updated = jiffies;
-
-                       if (neigh->dev->type == ARPHRD_ETHER)
-                               memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
-
-                       dn->blksize  = le16_to_cpu(msg->blksize);
-                       dn->priority = msg->priority;
-
-                       dn->flags &= ~DN_NDFLAG_P3;
-
-                       switch (msg->iinfo & DN_RT_INFO_TYPE) {
-                       case DN_RT_INFO_L1RT:
-                               dn->flags &=~DN_NDFLAG_R2;
-                               dn->flags |= DN_NDFLAG_R1;
-                               break;
-                       case DN_RT_INFO_L2RT:
-                               dn->flags |= DN_NDFLAG_R2;
-                       }
-               }
-
-               /* Only use routers in our area */
-               if ((le16_to_cpu(src)>>10) == (le16_to_cpu((decnet_address))>>10)) {
-                       if (!dn_db->router) {
-                               dn_db->router = neigh_clone(neigh);
-                       } else {
-                               if (msg->priority > container_of(dn_db->router,
-                                                                struct dn_neigh, n)->priority)
-                                       neigh_release(xchg(&dn_db->router, neigh_clone(neigh)));
-                       }
-               }
-               write_unlock(&neigh->lock);
-               neigh_release(neigh);
-       }
-
-       kfree_skb(skb);
-       return 0;
-}
-
-/*
- * Endnode hello message received
- */
-int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct endnode_hello_message *msg = (struct endnode_hello_message *)skb->data;
-       struct neighbour *neigh;
-       struct dn_neigh *dn;
-       __le16 src;
-
-       src = dn_eth2dn(msg->id);
-
-       neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
-
-       dn = container_of(neigh, struct dn_neigh, n);
-
-       if (neigh) {
-               write_lock(&neigh->lock);
-
-               neigh->used = jiffies;
-
-               if (!(neigh->nud_state & NUD_PERMANENT)) {
-                       neigh->updated = jiffies;
-
-                       if (neigh->dev->type == ARPHRD_ETHER)
-                               memcpy(neigh->ha, &eth_hdr(skb)->h_source, ETH_ALEN);
-                       dn->flags   &= ~(DN_NDFLAG_R1 | DN_NDFLAG_R2);
-                       dn->blksize  = le16_to_cpu(msg->blksize);
-                       dn->priority = 0;
-               }
-
-               write_unlock(&neigh->lock);
-               neigh_release(neigh);
-       }
-
-       kfree_skb(skb);
-       return 0;
-}
-
-static char *dn_find_slot(char *base, int max, int priority)
-{
-       int i;
-       unsigned char *min = NULL;
-
-       base += 6; /* skip first id */
-
-       for(i = 0; i < max; i++) {
-               if (!min || (*base < *min))
-                       min = base;
-               base += 7; /* find next priority */
-       }
-
-       if (!min)
-               return NULL;
-
-       return (*min < priority) ? (min - 6) : NULL;
-}
-
-struct elist_cb_state {
-       struct net_device *dev;
-       unsigned char *ptr;
-       unsigned char *rs;
-       int t, n;
-};
-
-static void neigh_elist_cb(struct neighbour *neigh, void *_info)
-{
-       struct elist_cb_state *s = _info;
-       struct dn_neigh *dn;
-
-       if (neigh->dev != s->dev)
-               return;
-
-       dn = container_of(neigh, struct dn_neigh, n);
-       if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
-               return;
-
-       if (s->t == s->n)
-               s->rs = dn_find_slot(s->ptr, s->n, dn->priority);
-       else
-               s->t++;
-       if (s->rs == NULL)
-               return;
-
-       dn_dn2eth(s->rs, dn->addr);
-       s->rs += 6;
-       *(s->rs) = neigh->nud_state & NUD_CONNECTED ? 0x80 : 0x0;
-       *(s->rs) |= dn->priority;
-       s->rs++;
-}
-
-int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
-{
-       struct elist_cb_state state;
-
-       state.dev = dev;
-       state.t = 0;
-       state.n = n;
-       state.ptr = ptr;
-       state.rs = ptr;
-
-       neigh_for_each(&dn_neigh_table, neigh_elist_cb, &state);
-
-       return state.t;
-}
-
-
-#ifdef CONFIG_PROC_FS
-
-static inline void dn_neigh_format_entry(struct seq_file *seq,
-                                        struct neighbour *n)
-{
-       struct dn_neigh *dn = container_of(n, struct dn_neigh, n);
-       char buf[DN_ASCBUF_LEN];
-
-       read_lock(&n->lock);
-       seq_printf(seq, "%-7s %s%s%s   %02x    %02d  %07ld %-8s\n",
-                  dn_addr2asc(le16_to_cpu(dn->addr), buf),
-                  (dn->flags&DN_NDFLAG_R1) ? "1" : "-",
-                  (dn->flags&DN_NDFLAG_R2) ? "2" : "-",
-                  (dn->flags&DN_NDFLAG_P3) ? "3" : "-",
-                  dn->n.nud_state,
-                  refcount_read(&dn->n.refcnt),
-                  dn->blksize,
-                  (dn->n.dev) ? dn->n.dev->name : "?");
-       read_unlock(&n->lock);
-}
-
-static int dn_neigh_seq_show(struct seq_file *seq, void *v)
-{
-       if (v == SEQ_START_TOKEN) {
-               seq_puts(seq, "Addr    Flags State Use Blksize Dev\n");
-       } else {
-               dn_neigh_format_entry(seq, v);
-       }
-
-       return 0;
-}
-
-static void *dn_neigh_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       return neigh_seq_start(seq, pos, &dn_neigh_table,
-                              NEIGH_SEQ_NEIGH_ONLY);
-}
-
-static const struct seq_operations dn_neigh_seq_ops = {
-       .start = dn_neigh_seq_start,
-       .next  = neigh_seq_next,
-       .stop  = neigh_seq_stop,
-       .show  = dn_neigh_seq_show,
-};
-#endif
-
-void __init dn_neigh_init(void)
-{
-       neigh_table_init(NEIGH_DN_TABLE, &dn_neigh_table);
-       proc_create_net("decnet_neigh", 0444, init_net.proc_net,
-                       &dn_neigh_seq_ops, sizeof(struct neigh_seq_state));
-}
-
-void __exit dn_neigh_cleanup(void)
-{
-       remove_proc_entry("decnet_neigh", init_net.proc_net);
-       neigh_table_clear(NEIGH_DN_TABLE, &dn_neigh_table);
-}
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c
deleted file mode 100644 (file)
index c59be5b..0000000
+++ /dev/null
@@ -1,907 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Network Services Protocol (Input)
- *
- * Author:      Eduardo Marcelo Serrat <emserrat@geocities.com>
- *
- * Changes:
- *
- *    Steve Whitehouse:  Split into dn_nsp_in.c and dn_nsp_out.c from
- *                       original dn_nsp.c.
- *    Steve Whitehouse:  Updated to work with my new routing architecture.
- *    Steve Whitehouse:  Add changes from Eduardo Serrat's patches.
- *    Steve Whitehouse:  Put all ack handling code in a common routine.
- *    Steve Whitehouse:  Put other common bits into dn_nsp_rx()
- *    Steve Whitehouse:  More checks on skb->len to catch bogus packets
- *                       Fixed various race conditions and possible nasties.
- *    Steve Whitehouse:  Now handles returned conninit frames.
- *     David S. Miller:  New socket locking
- *    Steve Whitehouse:  Fixed lockup when socket filtering was enabled.
- *         Paul Koning:  Fix to push CC sockets into RUN when acks are
- *                       received.
- *    Steve Whitehouse:
- *   Patrick Caulfield:  Checking conninits for correctness & sending of error
- *                       responses.
- *    Steve Whitehouse:  Added backlog congestion level return codes.
- *   Patrick Caulfield:
- *    Steve Whitehouse:  Added flow control support (outbound)
- *    Steve Whitehouse:  Prepare for nonlinear skbs
- */
-
-/******************************************************************************
-    (c) 1995-1998 E.M. Serrat          emserrat@geocities.com
-
-*******************************************************************************/
-
-#include <linux/errno.h>
-#include <linux/filter.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/inet.h>
-#include <linux/route.h>
-#include <linux/slab.h>
-#include <net/sock.h>
-#include <net/tcp_states.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/termios.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/netfilter_decnet.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/dn.h>
-#include <net/dn_nsp.h>
-#include <net/dn_dev.h>
-#include <net/dn_route.h>
-
-extern int decnet_log_martians;
-
-static void dn_log_martian(struct sk_buff *skb, const char *msg)
-{
-       if (decnet_log_martians) {
-               char *devname = skb->dev ? skb->dev->name : "???";
-               struct dn_skb_cb *cb = DN_SKB_CB(skb);
-               net_info_ratelimited("DECnet: Martian packet (%s) dev=%s src=0x%04hx dst=0x%04hx srcport=0x%04hx dstport=0x%04hx\n",
-                                    msg, devname,
-                                    le16_to_cpu(cb->src),
-                                    le16_to_cpu(cb->dst),
-                                    le16_to_cpu(cb->src_port),
-                                    le16_to_cpu(cb->dst_port));
-       }
-}
-
-/*
- * For this function we've flipped the cross-subchannel bit
- * if the message is an otherdata or linkservice message. Thus
- * we can use it to work out what to update.
- */
-static void dn_ack(struct sock *sk, struct sk_buff *skb, unsigned short ack)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       unsigned short type = ((ack >> 12) & 0x0003);
-       int wakeup = 0;
-
-       switch (type) {
-       case 0: /* ACK - Data */
-               if (dn_after(ack, scp->ackrcv_dat)) {
-                       scp->ackrcv_dat = ack & 0x0fff;
-                       wakeup |= dn_nsp_check_xmit_queue(sk, skb,
-                                                         &scp->data_xmit_queue,
-                                                         ack);
-               }
-               break;
-       case 1: /* NAK - Data */
-               break;
-       case 2: /* ACK - OtherData */
-               if (dn_after(ack, scp->ackrcv_oth)) {
-                       scp->ackrcv_oth = ack & 0x0fff;
-                       wakeup |= dn_nsp_check_xmit_queue(sk, skb,
-                                                         &scp->other_xmit_queue,
-                                                         ack);
-               }
-               break;
-       case 3: /* NAK - OtherData */
-               break;
-       }
-
-       if (wakeup && !sock_flag(sk, SOCK_DEAD))
-               sk->sk_state_change(sk);
-}
-
-/*
- * This function is a universal ack processor.
- */
-static int dn_process_ack(struct sock *sk, struct sk_buff *skb, int oth)
-{
-       __le16 *ptr = (__le16 *)skb->data;
-       int len = 0;
-       unsigned short ack;
-
-       if (skb->len < 2)
-               return len;
-
-       if ((ack = le16_to_cpu(*ptr)) & 0x8000) {
-               skb_pull(skb, 2);
-               ptr++;
-               len += 2;
-               if ((ack & 0x4000) == 0) {
-                       if (oth)
-                               ack ^= 0x2000;
-                       dn_ack(sk, skb, ack);
-               }
-       }
-
-       if (skb->len < 2)
-               return len;
-
-       if ((ack = le16_to_cpu(*ptr)) & 0x8000) {
-               skb_pull(skb, 2);
-               len += 2;
-               if ((ack & 0x4000) == 0) {
-                       if (oth)
-                               ack ^= 0x2000;
-                       dn_ack(sk, skb, ack);
-               }
-       }
-
-       return len;
-}
-
-
-/**
- * dn_check_idf - Check an image data field format is correct.
- * @pptr: Pointer to pointer to image data
- * @len: Pointer to length of image data
- * @max: The maximum allowed length of the data in the image data field
- * @follow_on: Check that this many bytes exist beyond the end of the image data
- *
- * Returns: 0 if ok, -1 on error
- */
-static inline int dn_check_idf(unsigned char **pptr, int *len, unsigned char max, unsigned char follow_on)
-{
-       unsigned char *ptr = *pptr;
-       unsigned char flen = *ptr++;
-
-       (*len)--;
-       if (flen > max)
-               return -1;
-       if ((flen + follow_on) > *len)
-               return -1;
-
-       *len -= flen;
-       *pptr = ptr + flen;
-       return 0;
-}
-
-/*
- * Table of reason codes to pass back to node which sent us a badly
- * formed message, plus text messages for the log. A zero entry in
- * the reason field means "don't reply" otherwise a disc init is sent with
- * the specified reason code.
- */
-static struct {
-       unsigned short reason;
-       const char *text;
-} ci_err_table[] = {
- { 0,             "CI: Truncated message" },
- { NSP_REASON_ID, "CI: Destination username error" },
- { NSP_REASON_ID, "CI: Destination username type" },
- { NSP_REASON_US, "CI: Source username error" },
- { 0,             "CI: Truncated at menuver" },
- { 0,             "CI: Truncated before access or user data" },
- { NSP_REASON_IO, "CI: Access data format error" },
- { NSP_REASON_IO, "CI: User data format error" }
-};
-
-/*
- * This function uses a slightly different lookup method
- * to find its sockets, since it searches on object name/number
- * rather than port numbers. Various tests are done to ensure that
- * the incoming data is in the correct format before it is queued to
- * a socket.
- */
-static struct sock *dn_find_listener(struct sk_buff *skb, unsigned short *reason)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct nsp_conn_init_msg *msg = (struct nsp_conn_init_msg *)skb->data;
-       struct sockaddr_dn dstaddr;
-       struct sockaddr_dn srcaddr;
-       unsigned char type = 0;
-       int dstlen;
-       int srclen;
-       unsigned char *ptr;
-       int len;
-       int err = 0;
-       unsigned char menuver;
-
-       memset(&dstaddr, 0, sizeof(struct sockaddr_dn));
-       memset(&srcaddr, 0, sizeof(struct sockaddr_dn));
-
-       /*
-        * 1. Decode & remove message header
-        */
-       cb->src_port = msg->srcaddr;
-       cb->dst_port = msg->dstaddr;
-       cb->services = msg->services;
-       cb->info     = msg->info;
-       cb->segsize  = le16_to_cpu(msg->segsize);
-
-       if (!pskb_may_pull(skb, sizeof(*msg)))
-               goto err_out;
-
-       skb_pull(skb, sizeof(*msg));
-
-       len = skb->len;
-       ptr = skb->data;
-
-       /*
-        * 2. Check destination end username format
-        */
-       dstlen = dn_username2sockaddr(ptr, len, &dstaddr, &type);
-       err++;
-       if (dstlen < 0)
-               goto err_out;
-
-       err++;
-       if (type > 1)
-               goto err_out;
-
-       len -= dstlen;
-       ptr += dstlen;
-
-       /*
-        * 3. Check source end username format
-        */
-       srclen = dn_username2sockaddr(ptr, len, &srcaddr, &type);
-       err++;
-       if (srclen < 0)
-               goto err_out;
-
-       len -= srclen;
-       ptr += srclen;
-       err++;
-       if (len < 1)
-               goto err_out;
-
-       menuver = *ptr;
-       ptr++;
-       len--;
-
-       /*
-        * 4. Check that optional data actually exists if menuver says it does
-        */
-       err++;
-       if ((menuver & (DN_MENUVER_ACC | DN_MENUVER_USR)) && (len < 1))
-               goto err_out;
-
-       /*
-        * 5. Check optional access data format
-        */
-       err++;
-       if (menuver & DN_MENUVER_ACC) {
-               if (dn_check_idf(&ptr, &len, 39, 1))
-                       goto err_out;
-               if (dn_check_idf(&ptr, &len, 39, 1))
-                       goto err_out;
-               if (dn_check_idf(&ptr, &len, 39, (menuver & DN_MENUVER_USR) ? 1 : 0))
-                       goto err_out;
-       }
-
-       /*
-        * 6. Check optional user data format
-        */
-       err++;
-       if (menuver & DN_MENUVER_USR) {
-               if (dn_check_idf(&ptr, &len, 16, 0))
-                       goto err_out;
-       }
-
-       /*
-        * 7. Look up socket based on destination end username
-        */
-       return dn_sklist_find_listener(&dstaddr);
-err_out:
-       dn_log_martian(skb, ci_err_table[err].text);
-       *reason = ci_err_table[err].reason;
-       return NULL;
-}
-
-
-static void dn_nsp_conn_init(struct sock *sk, struct sk_buff *skb)
-{
-       if (sk_acceptq_is_full(sk)) {
-               kfree_skb(skb);
-               return;
-       }
-
-       sk_acceptq_added(sk);
-       skb_queue_tail(&sk->sk_receive_queue, skb);
-       sk->sk_state_change(sk);
-}
-
-static void dn_nsp_conn_conf(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct dn_scp *scp = DN_SK(sk);
-       unsigned char *ptr;
-
-       if (skb->len < 4)
-               goto out;
-
-       ptr = skb->data;
-       cb->services = *ptr++;
-       cb->info = *ptr++;
-       cb->segsize = le16_to_cpu(*(__le16 *)ptr);
-
-       if ((scp->state == DN_CI) || (scp->state == DN_CD)) {
-               scp->persist = 0;
-               scp->addrrem = cb->src_port;
-               sk->sk_state = TCP_ESTABLISHED;
-               scp->state = DN_RUN;
-               scp->services_rem = cb->services;
-               scp->info_rem = cb->info;
-               scp->segsize_rem = cb->segsize;
-
-               if ((scp->services_rem & NSP_FC_MASK) == NSP_FC_NONE)
-                       scp->max_window = decnet_no_fc_max_cwnd;
-
-               if (skb->len > 0) {
-                       u16 dlen = *skb->data;
-                       if ((dlen <= 16) && (dlen <= skb->len)) {
-                               scp->conndata_in.opt_optl = cpu_to_le16(dlen);
-                               skb_copy_from_linear_data_offset(skb, 1,
-                                             scp->conndata_in.opt_data, dlen);
-                       }
-               }
-               dn_nsp_send_link(sk, DN_NOCHANGE, 0);
-               if (!sock_flag(sk, SOCK_DEAD))
-                       sk->sk_state_change(sk);
-       }
-
-out:
-       kfree_skb(skb);
-}
-
-static void dn_nsp_conn_ack(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (scp->state == DN_CI) {
-               scp->state = DN_CD;
-               scp->persist = 0;
-       }
-
-       kfree_skb(skb);
-}
-
-static void dn_nsp_disc_init(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       unsigned short reason;
-
-       if (skb->len < 2)
-               goto out;
-
-       reason = le16_to_cpu(*(__le16 *)skb->data);
-       skb_pull(skb, 2);
-
-       scp->discdata_in.opt_status = cpu_to_le16(reason);
-       scp->discdata_in.opt_optl   = 0;
-       memset(scp->discdata_in.opt_data, 0, 16);
-
-       if (skb->len > 0) {
-               u16 dlen = *skb->data;
-               if ((dlen <= 16) && (dlen <= skb->len)) {
-                       scp->discdata_in.opt_optl = cpu_to_le16(dlen);
-                       skb_copy_from_linear_data_offset(skb, 1, scp->discdata_in.opt_data, dlen);
-               }
-       }
-
-       scp->addrrem = cb->src_port;
-       sk->sk_state = TCP_CLOSE;
-
-       switch (scp->state) {
-       case DN_CI:
-       case DN_CD:
-               scp->state = DN_RJ;
-               sk->sk_err = ECONNREFUSED;
-               break;
-       case DN_RUN:
-               sk->sk_shutdown |= SHUTDOWN_MASK;
-               scp->state = DN_DN;
-               break;
-       case DN_DI:
-               scp->state = DN_DIC;
-               break;
-       }
-
-       if (!sock_flag(sk, SOCK_DEAD)) {
-               if (sk->sk_socket->state != SS_UNCONNECTED)
-                       sk->sk_socket->state = SS_DISCONNECTING;
-               sk->sk_state_change(sk);
-       }
-
-       /*
-        * It appears that its possible for remote machines to send disc
-        * init messages with no port identifier if we are in the CI and
-        * possibly also the CD state. Obviously we shouldn't reply with
-        * a message if we don't know what the end point is.
-        */
-       if (scp->addrrem) {
-               dn_nsp_send_disc(sk, NSP_DISCCONF, NSP_REASON_DC, GFP_ATOMIC);
-       }
-       scp->persist_fxn = dn_destroy_timer;
-       scp->persist = dn_nsp_persist(sk);
-
-out:
-       kfree_skb(skb);
-}
-
-/*
- * disc_conf messages are also called no_resources or no_link
- * messages depending upon the "reason" field.
- */
-static void dn_nsp_disc_conf(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       unsigned short reason;
-
-       if (skb->len != 2)
-               goto out;
-
-       reason = le16_to_cpu(*(__le16 *)skb->data);
-
-       sk->sk_state = TCP_CLOSE;
-
-       switch (scp->state) {
-       case DN_CI:
-               scp->state = DN_NR;
-               break;
-       case DN_DR:
-               if (reason == NSP_REASON_DC)
-                       scp->state = DN_DRC;
-               if (reason == NSP_REASON_NL)
-                       scp->state = DN_CN;
-               break;
-       case DN_DI:
-               scp->state = DN_DIC;
-               break;
-       case DN_RUN:
-               sk->sk_shutdown |= SHUTDOWN_MASK;
-               fallthrough;
-       case DN_CC:
-               scp->state = DN_CN;
-       }
-
-       if (!sock_flag(sk, SOCK_DEAD)) {
-               if (sk->sk_socket->state != SS_UNCONNECTED)
-                       sk->sk_socket->state = SS_DISCONNECTING;
-               sk->sk_state_change(sk);
-       }
-
-       scp->persist_fxn = dn_destroy_timer;
-       scp->persist = dn_nsp_persist(sk);
-
-out:
-       kfree_skb(skb);
-}
-
-static void dn_nsp_linkservice(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       unsigned short segnum;
-       unsigned char lsflags;
-       signed char fcval;
-       int wake_up = 0;
-       char *ptr = skb->data;
-       unsigned char fctype = scp->services_rem & NSP_FC_MASK;
-
-       if (skb->len != 4)
-               goto out;
-
-       segnum = le16_to_cpu(*(__le16 *)ptr);
-       ptr += 2;
-       lsflags = *(unsigned char *)ptr++;
-       fcval = *ptr;
-
-       /*
-        * Here we ignore erroneous packets which should really
-        * should cause a connection abort. It is not critical
-        * for now though.
-        */
-       if (lsflags & 0xf8)
-               goto out;
-
-       if (seq_next(scp->numoth_rcv, segnum)) {
-               seq_add(&scp->numoth_rcv, 1);
-               switch(lsflags & 0x04) { /* FCVAL INT */
-               case 0x00: /* Normal Request */
-                       switch(lsflags & 0x03) { /* FCVAL MOD */
-                       case 0x00: /* Request count */
-                               if (fcval < 0) {
-                                       unsigned char p_fcval = -fcval;
-                                       if ((scp->flowrem_dat > p_fcval) &&
-                                           (fctype == NSP_FC_SCMC)) {
-                                               scp->flowrem_dat -= p_fcval;
-                                       }
-                               } else if (fcval > 0) {
-                                       scp->flowrem_dat += fcval;
-                                       wake_up = 1;
-                               }
-                               break;
-                       case 0x01: /* Stop outgoing data */
-                               scp->flowrem_sw = DN_DONTSEND;
-                               break;
-                       case 0x02: /* Ok to start again */
-                               scp->flowrem_sw = DN_SEND;
-                               dn_nsp_output(sk);
-                               wake_up = 1;
-                       }
-                       break;
-               case 0x04: /* Interrupt Request */
-                       if (fcval > 0) {
-                               scp->flowrem_oth += fcval;
-                               wake_up = 1;
-                       }
-                       break;
-               }
-               if (wake_up && !sock_flag(sk, SOCK_DEAD))
-                       sk->sk_state_change(sk);
-       }
-
-       dn_nsp_send_oth_ack(sk);
-
-out:
-       kfree_skb(skb);
-}
-
-/*
- * Copy of sock_queue_rcv_skb (from sock.h) without
- * bh_lock_sock() (its already held when this is called) which
- * also allows data and other data to be queued to a socket.
- */
-static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue)
-{
-       int err;
-
-       /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces
-          number of warnings when compiling with -W --ANK
-        */
-       if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >=
-           (unsigned int)sk->sk_rcvbuf) {
-               err = -ENOMEM;
-               goto out;
-       }
-
-       err = sk_filter(sk, skb);
-       if (err)
-               goto out;
-
-       skb_set_owner_r(skb, sk);
-       skb_queue_tail(queue, skb);
-
-       if (!sock_flag(sk, SOCK_DEAD))
-               sk->sk_data_ready(sk);
-out:
-       return err;
-}
-
-static void dn_nsp_otherdata(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       unsigned short segnum;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       int queued = 0;
-
-       if (skb->len < 2)
-               goto out;
-
-       cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data);
-       skb_pull(skb, 2);
-
-       if (seq_next(scp->numoth_rcv, segnum)) {
-
-               if (dn_queue_skb(sk, skb, SIGURG, &scp->other_receive_queue) == 0) {
-                       seq_add(&scp->numoth_rcv, 1);
-                       scp->other_report = 0;
-                       queued = 1;
-               }
-       }
-
-       dn_nsp_send_oth_ack(sk);
-out:
-       if (!queued)
-               kfree_skb(skb);
-}
-
-static void dn_nsp_data(struct sock *sk, struct sk_buff *skb)
-{
-       int queued = 0;
-       unsigned short segnum;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (skb->len < 2)
-               goto out;
-
-       cb->segnum = segnum = le16_to_cpu(*(__le16 *)skb->data);
-       skb_pull(skb, 2);
-
-       if (seq_next(scp->numdat_rcv, segnum)) {
-               if (dn_queue_skb(sk, skb, SIGIO, &sk->sk_receive_queue) == 0) {
-                       seq_add(&scp->numdat_rcv, 1);
-                       queued = 1;
-               }
-
-               if ((scp->flowloc_sw == DN_SEND) && dn_congested(sk)) {
-                       scp->flowloc_sw = DN_DONTSEND;
-                       dn_nsp_send_link(sk, DN_DONTSEND, 0);
-               }
-       }
-
-       dn_nsp_send_data_ack(sk);
-out:
-       if (!queued)
-               kfree_skb(skb);
-}
-
-/*
- * If one of our conninit messages is returned, this function
- * deals with it. It puts the socket into the NO_COMMUNICATION
- * state.
- */
-static void dn_returned_conn_init(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (scp->state == DN_CI) {
-               scp->state = DN_NC;
-               sk->sk_state = TCP_CLOSE;
-               if (!sock_flag(sk, SOCK_DEAD))
-                       sk->sk_state_change(sk);
-       }
-
-       kfree_skb(skb);
-}
-
-static int dn_nsp_no_socket(struct sk_buff *skb, unsigned short reason)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       int ret = NET_RX_DROP;
-
-       /* Must not reply to returned packets */
-       if (cb->rt_flags & DN_RT_F_RTS)
-               goto out;
-
-       if ((reason != NSP_REASON_OK) && ((cb->nsp_flags & 0x0c) == 0x08)) {
-               switch (cb->nsp_flags & 0x70) {
-               case 0x10:
-               case 0x60: /* (Retransmitted) Connect Init */
-                       dn_nsp_return_disc(skb, NSP_DISCINIT, reason);
-                       ret = NET_RX_SUCCESS;
-                       break;
-               case 0x20: /* Connect Confirm */
-                       dn_nsp_return_disc(skb, NSP_DISCCONF, reason);
-                       ret = NET_RX_SUCCESS;
-                       break;
-               }
-       }
-
-out:
-       kfree_skb(skb);
-       return ret;
-}
-
-static int dn_nsp_rx_packet(struct net *net, struct sock *sk2,
-                           struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct sock *sk = NULL;
-       unsigned char *ptr = (unsigned char *)skb->data;
-       unsigned short reason = NSP_REASON_NL;
-
-       if (!pskb_may_pull(skb, 2))
-               goto free_out;
-
-       skb_reset_transport_header(skb);
-       cb->nsp_flags = *ptr++;
-
-       if (decnet_debug_level & 2)
-               printk(KERN_DEBUG "dn_nsp_rx: Message type 0x%02x\n", (int)cb->nsp_flags);
-
-       if (cb->nsp_flags & 0x83)
-               goto free_out;
-
-       /*
-        * Filter out conninits and useless packet types
-        */
-       if ((cb->nsp_flags & 0x0c) == 0x08) {
-               switch (cb->nsp_flags & 0x70) {
-               case 0x00: /* NOP */
-               case 0x70: /* Reserved */
-               case 0x50: /* Reserved, Phase II node init */
-                       goto free_out;
-               case 0x10:
-               case 0x60:
-                       if (unlikely(cb->rt_flags & DN_RT_F_RTS))
-                               goto free_out;
-                       sk = dn_find_listener(skb, &reason);
-                       goto got_it;
-               }
-       }
-
-       if (!pskb_may_pull(skb, 3))
-               goto free_out;
-
-       /*
-        * Grab the destination address.
-        */
-       cb->dst_port = *(__le16 *)ptr;
-       cb->src_port = 0;
-       ptr += 2;
-
-       /*
-        * If not a connack, grab the source address too.
-        */
-       if (pskb_may_pull(skb, 5)) {
-               cb->src_port = *(__le16 *)ptr;
-               ptr += 2;
-               skb_pull(skb, 5);
-       }
-
-       /*
-        * Returned packets...
-        * Swap src & dst and look up in the normal way.
-        */
-       if (unlikely(cb->rt_flags & DN_RT_F_RTS)) {
-               swap(cb->dst_port, cb->src_port);
-               swap(cb->dst, cb->src);
-       }
-
-       /*
-        * Find the socket to which this skb is destined.
-        */
-       sk = dn_find_by_skb(skb);
-got_it:
-       if (sk != NULL) {
-               struct dn_scp *scp = DN_SK(sk);
-
-               /* Reset backoff */
-               scp->nsp_rxtshift = 0;
-
-               /*
-                * We linearize everything except data segments here.
-                */
-               if (cb->nsp_flags & ~0x60) {
-                       if (unlikely(skb_linearize(skb)))
-                               goto free_out;
-               }
-
-               return sk_receive_skb(sk, skb, 0);
-       }
-
-       return dn_nsp_no_socket(skb, reason);
-
-free_out:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-int dn_nsp_rx(struct sk_buff *skb)
-{
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_IN,
-                      &init_net, NULL, skb, skb->dev, NULL,
-                      dn_nsp_rx_packet);
-}
-
-/*
- * This is the main receive routine for sockets. It is called
- * from the above when the socket is not busy, and also from
- * sock_release() when there is a backlog queued up.
- */
-int dn_nsp_backlog_rcv(struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-       if (cb->rt_flags & DN_RT_F_RTS) {
-               if (cb->nsp_flags == 0x18 || cb->nsp_flags == 0x68)
-                       dn_returned_conn_init(sk, skb);
-               else
-                       kfree_skb(skb);
-               return NET_RX_SUCCESS;
-       }
-
-       /*
-        * Control packet.
-        */
-       if ((cb->nsp_flags & 0x0c) == 0x08) {
-               switch (cb->nsp_flags & 0x70) {
-               case 0x10:
-               case 0x60:
-                       dn_nsp_conn_init(sk, skb);
-                       break;
-               case 0x20:
-                       dn_nsp_conn_conf(sk, skb);
-                       break;
-               case 0x30:
-                       dn_nsp_disc_init(sk, skb);
-                       break;
-               case 0x40:
-                       dn_nsp_disc_conf(sk, skb);
-                       break;
-               }
-
-       } else if (cb->nsp_flags == 0x24) {
-               /*
-                * Special for connacks, 'cos they don't have
-                * ack data or ack otherdata info.
-                */
-               dn_nsp_conn_ack(sk, skb);
-       } else {
-               int other = 1;
-
-               /* both data and ack frames can kick a CC socket into RUN */
-               if ((scp->state == DN_CC) && !sock_flag(sk, SOCK_DEAD)) {
-                       scp->state = DN_RUN;
-                       sk->sk_state = TCP_ESTABLISHED;
-                       sk->sk_state_change(sk);
-               }
-
-               if ((cb->nsp_flags & 0x1c) == 0)
-                       other = 0;
-               if (cb->nsp_flags == 0x04)
-                       other = 0;
-
-               /*
-                * Read out ack data here, this applies equally
-                * to data, other data, link service and both
-                * ack data and ack otherdata.
-                */
-               dn_process_ack(sk, skb, other);
-
-               /*
-                * If we've some sort of data here then call a
-                * suitable routine for dealing with it, otherwise
-                * the packet is an ack and can be discarded.
-                */
-               if ((cb->nsp_flags & 0x0c) == 0) {
-
-                       if (scp->state != DN_RUN)
-                               goto free_out;
-
-                       switch (cb->nsp_flags) {
-                       case 0x10: /* LS */
-                               dn_nsp_linkservice(sk, skb);
-                               break;
-                       case 0x30: /* OD */
-                               dn_nsp_otherdata(sk, skb);
-                               break;
-                       default:
-                               dn_nsp_data(sk, skb);
-                       }
-
-               } else { /* Ack, chuck it out here */
-free_out:
-                       kfree_skb(skb);
-               }
-       }
-
-       return NET_RX_SUCCESS;
-}
diff --git a/net/decnet/dn_nsp_out.c b/net/decnet/dn_nsp_out.c
deleted file mode 100644 (file)
index b05639b..0000000
+++ /dev/null
@@ -1,696 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Network Services Protocol (Output)
- *
- * Author:      Eduardo Marcelo Serrat <emserrat@geocities.com>
- *
- * Changes:
- *
- *    Steve Whitehouse:  Split into dn_nsp_in.c and dn_nsp_out.c from
- *                       original dn_nsp.c.
- *    Steve Whitehouse:  Updated to work with my new routing architecture.
- *    Steve Whitehouse:  Added changes from Eduardo Serrat's patches.
- *    Steve Whitehouse:  Now conninits have the "return" bit set.
- *    Steve Whitehouse:  Fixes to check alloc'd skbs are non NULL!
- *                       Moved output state machine into one function
- *    Steve Whitehouse:  New output state machine
- *         Paul Koning:  Connect Confirm message fix.
- *      Eduardo Serrat:  Fix to stop dn_nsp_do_disc() sending malformed packets.
- *    Steve Whitehouse:  dn_nsp_output() and friends needed a spring clean
- *    Steve Whitehouse:  Moved dn_nsp_send() in here from route.h
- */
-
-/******************************************************************************
-    (c) 1995-1998 E.M. Serrat          emserrat@geocities.com
-
-*******************************************************************************/
-
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/string.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/inet.h>
-#include <linux/route.h>
-#include <linux/slab.h>
-#include <net/sock.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/termios.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/if_packet.h>
-#include <linux/jiffies.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/dn.h>
-#include <net/dn_nsp.h>
-#include <net/dn_dev.h>
-#include <net/dn_route.h>
-
-
-static int nsp_backoff[NSP_MAXRXTSHIFT + 1] = { 1, 2, 4, 8, 16, 32, 64, 64, 64, 64, 64, 64, 64 };
-
-static void dn_nsp_send(struct sk_buff *skb)
-{
-       struct sock *sk = skb->sk;
-       struct dn_scp *scp = DN_SK(sk);
-       struct dst_entry *dst;
-       struct flowidn fld;
-
-       skb_reset_transport_header(skb);
-       scp->stamp = jiffies;
-
-       dst = sk_dst_check(sk, 0);
-       if (dst) {
-try_again:
-               skb_dst_set(skb, dst);
-               dst_output(&init_net, skb->sk, skb);
-               return;
-       }
-
-       memset(&fld, 0, sizeof(fld));
-       fld.flowidn_oif = sk->sk_bound_dev_if;
-       fld.saddr = dn_saddr2dn(&scp->addr);
-       fld.daddr = dn_saddr2dn(&scp->peer);
-       dn_sk_ports_copy(&fld, scp);
-       fld.flowidn_proto = DNPROTO_NSP;
-       if (dn_route_output_sock(&sk->sk_dst_cache, &fld, sk, 0) == 0) {
-               dst = sk_dst_get(sk);
-               sk->sk_route_caps = dst->dev->features;
-               goto try_again;
-       }
-
-       sk->sk_err = EHOSTUNREACH;
-       if (!sock_flag(sk, SOCK_DEAD))
-               sk->sk_state_change(sk);
-}
-
-
-/*
- * If sk == NULL, then we assume that we are supposed to be making
- * a routing layer skb. If sk != NULL, then we are supposed to be
- * creating an skb for the NSP layer.
- *
- * The eventual aim is for each socket to have a cached header size
- * for its outgoing packets, and to set hdr from this when sk != NULL.
- */
-struct sk_buff *dn_alloc_skb(struct sock *sk, int size, gfp_t pri)
-{
-       struct sk_buff *skb;
-       int hdr = 64;
-
-       if ((skb = alloc_skb(size + hdr, pri)) == NULL)
-               return NULL;
-
-       skb->protocol = htons(ETH_P_DNA_RT);
-       skb->pkt_type = PACKET_OUTGOING;
-
-       if (sk)
-               skb_set_owner_w(skb, sk);
-
-       skb_reserve(skb, hdr);
-
-       return skb;
-}
-
-/*
- * Calculate persist timer based upon the smoothed round
- * trip time and the variance. Backoff according to the
- * nsp_backoff[] array.
- */
-unsigned long dn_nsp_persist(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1;
-
-       t *= nsp_backoff[scp->nsp_rxtshift];
-
-       if (t < HZ) t = HZ;
-       if (t > (600*HZ)) t = (600*HZ);
-
-       if (scp->nsp_rxtshift < NSP_MAXRXTSHIFT)
-               scp->nsp_rxtshift++;
-
-       /* printk(KERN_DEBUG "rxtshift %lu, t=%lu\n", scp->nsp_rxtshift, t); */
-
-       return t;
-}
-
-/*
- * This is called each time we get an estimate for the rtt
- * on the link.
- */
-static void dn_nsp_rtt(struct sock *sk, long rtt)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       long srtt = (long)scp->nsp_srtt;
-       long rttvar = (long)scp->nsp_rttvar;
-       long delta;
-
-       /*
-        * If the jiffies clock flips over in the middle of timestamp
-        * gathering this value might turn out negative, so we make sure
-        * that is it always positive here.
-        */
-       if (rtt < 0)
-               rtt = -rtt;
-       /*
-        * Add new rtt to smoothed average
-        */
-       delta = ((rtt << 3) - srtt);
-       srtt += (delta >> 3);
-       if (srtt >= 1)
-               scp->nsp_srtt = (unsigned long)srtt;
-       else
-               scp->nsp_srtt = 1;
-
-       /*
-        * Add new rtt variance to smoothed varience
-        */
-       delta >>= 1;
-       rttvar += ((((delta>0)?(delta):(-delta)) - rttvar) >> 2);
-       if (rttvar >= 1)
-               scp->nsp_rttvar = (unsigned long)rttvar;
-       else
-               scp->nsp_rttvar = 1;
-
-       /* printk(KERN_DEBUG "srtt=%lu rttvar=%lu\n", scp->nsp_srtt, scp->nsp_rttvar); */
-}
-
-/**
- * dn_nsp_clone_and_send - Send a data packet by cloning it
- * @skb: The packet to clone and transmit
- * @gfp: memory allocation flag
- *
- * Clone a queued data or other data packet and transmit it.
- *
- * Returns: The number of times the packet has been sent previously
- */
-static inline unsigned int dn_nsp_clone_and_send(struct sk_buff *skb,
-                                            gfp_t gfp)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct sk_buff *skb2;
-       int ret = 0;
-
-       if ((skb2 = skb_clone(skb, gfp)) != NULL) {
-               ret = cb->xmit_count;
-               cb->xmit_count++;
-               cb->stamp = jiffies;
-               skb2->sk = skb->sk;
-               dn_nsp_send(skb2);
-       }
-
-       return ret;
-}
-
-/**
- * dn_nsp_output - Try and send something from socket queues
- * @sk: The socket whose queues are to be investigated
- *
- * Try and send the packet on the end of the data and other data queues.
- * Other data gets priority over data, and if we retransmit a packet we
- * reduce the window by dividing it in two.
- *
- */
-void dn_nsp_output(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct sk_buff *skb;
-       unsigned int reduce_win = 0;
-
-       /*
-        * First we check for otherdata/linkservice messages
-        */
-       if ((skb = skb_peek(&scp->other_xmit_queue)) != NULL)
-               reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC);
-
-       /*
-        * If we may not send any data, we don't.
-        * If we are still trying to get some other data down the
-        * channel, we don't try and send any data.
-        */
-       if (reduce_win || (scp->flowrem_sw != DN_SEND))
-               goto recalc_window;
-
-       if ((skb = skb_peek(&scp->data_xmit_queue)) != NULL)
-               reduce_win = dn_nsp_clone_and_send(skb, GFP_ATOMIC);
-
-       /*
-        * If we've sent any frame more than once, we cut the
-        * send window size in half. There is always a minimum
-        * window size of one available.
-        */
-recalc_window:
-       if (reduce_win) {
-               scp->snd_window >>= 1;
-               if (scp->snd_window < NSP_MIN_WINDOW)
-                       scp->snd_window = NSP_MIN_WINDOW;
-       }
-}
-
-int dn_nsp_xmit_timeout(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       dn_nsp_output(sk);
-
-       if (!skb_queue_empty(&scp->data_xmit_queue) ||
-           !skb_queue_empty(&scp->other_xmit_queue))
-               scp->persist = dn_nsp_persist(sk);
-
-       return 0;
-}
-
-static inline __le16 *dn_mk_common_header(struct dn_scp *scp, struct sk_buff *skb, unsigned char msgflag, int len)
-{
-       unsigned char *ptr = skb_push(skb, len);
-
-       BUG_ON(len < 5);
-
-       *ptr++ = msgflag;
-       *((__le16 *)ptr) = scp->addrrem;
-       ptr += 2;
-       *((__le16 *)ptr) = scp->addrloc;
-       ptr += 2;
-       return (__le16 __force *)ptr;
-}
-
-static __le16 *dn_mk_ack_header(struct sock *sk, struct sk_buff *skb, unsigned char msgflag, int hlen, int other)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       unsigned short acknum = scp->numdat_rcv & 0x0FFF;
-       unsigned short ackcrs = scp->numoth_rcv & 0x0FFF;
-       __le16 *ptr;
-
-       BUG_ON(hlen < 9);
-
-       scp->ackxmt_dat = acknum;
-       scp->ackxmt_oth = ackcrs;
-       acknum |= 0x8000;
-       ackcrs |= 0x8000;
-
-       /* If this is an "other data/ack" message, swap acknum and ackcrs */
-       if (other)
-               swap(acknum, ackcrs);
-
-       /* Set "cross subchannel" bit in ackcrs */
-       ackcrs |= 0x2000;
-
-       ptr = dn_mk_common_header(scp, skb, msgflag, hlen);
-
-       *ptr++ = cpu_to_le16(acknum);
-       *ptr++ = cpu_to_le16(ackcrs);
-
-       return ptr;
-}
-
-static __le16 *dn_nsp_mk_data_header(struct sock *sk, struct sk_buff *skb, int oth)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       __le16 *ptr = dn_mk_ack_header(sk, skb, cb->nsp_flags, 11, oth);
-
-       if (unlikely(oth)) {
-               cb->segnum = scp->numoth;
-               seq_add(&scp->numoth, 1);
-       } else {
-               cb->segnum = scp->numdat;
-               seq_add(&scp->numdat, 1);
-       }
-       *(ptr++) = cpu_to_le16(cb->segnum);
-
-       return ptr;
-}
-
-void dn_nsp_queue_xmit(struct sock *sk, struct sk_buff *skb,
-                       gfp_t gfp, int oth)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       unsigned long t = ((scp->nsp_srtt >> 2) + scp->nsp_rttvar) >> 1;
-
-       cb->xmit_count = 0;
-       dn_nsp_mk_data_header(sk, skb, oth);
-
-       /*
-        * Slow start: If we have been idle for more than
-        * one RTT, then reset window to min size.
-        */
-       if (time_is_before_jiffies(scp->stamp + t))
-               scp->snd_window = NSP_MIN_WINDOW;
-
-       if (oth)
-               skb_queue_tail(&scp->other_xmit_queue, skb);
-       else
-               skb_queue_tail(&scp->data_xmit_queue, skb);
-
-       if (scp->flowrem_sw != DN_SEND)
-               return;
-
-       dn_nsp_clone_and_send(skb, gfp);
-}
-
-
-int dn_nsp_check_xmit_queue(struct sock *sk, struct sk_buff *skb, struct sk_buff_head *q, unsigned short acknum)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct dn_scp *scp = DN_SK(sk);
-       struct sk_buff *skb2, *n, *ack = NULL;
-       int wakeup = 0;
-       int try_retrans = 0;
-       unsigned long reftime = cb->stamp;
-       unsigned long pkttime;
-       unsigned short xmit_count;
-       unsigned short segnum;
-
-       skb_queue_walk_safe(q, skb2, n) {
-               struct dn_skb_cb *cb2 = DN_SKB_CB(skb2);
-
-               if (dn_before_or_equal(cb2->segnum, acknum))
-                       ack = skb2;
-
-               /* printk(KERN_DEBUG "ack: %s %04x %04x\n", ack ? "ACK" : "SKIP", (int)cb2->segnum, (int)acknum); */
-
-               if (ack == NULL)
-                       continue;
-
-               /* printk(KERN_DEBUG "check_xmit_queue: %04x, %d\n", acknum, cb2->xmit_count); */
-
-               /* Does _last_ packet acked have xmit_count > 1 */
-               try_retrans = 0;
-               /* Remember to wake up the sending process */
-               wakeup = 1;
-               /* Keep various statistics */
-               pkttime = cb2->stamp;
-               xmit_count = cb2->xmit_count;
-               segnum = cb2->segnum;
-               /* Remove and drop ack'ed packet */
-               skb_unlink(ack, q);
-               kfree_skb(ack);
-               ack = NULL;
-
-               /*
-                * We don't expect to see acknowledgements for packets we
-                * haven't sent yet.
-                */
-               WARN_ON(xmit_count == 0);
-
-               /*
-                * If the packet has only been sent once, we can use it
-                * to calculate the RTT and also open the window a little
-                * further.
-                */
-               if (xmit_count == 1) {
-                       if (dn_equal(segnum, acknum))
-                               dn_nsp_rtt(sk, (long)(pkttime - reftime));
-
-                       if (scp->snd_window < scp->max_window)
-                               scp->snd_window++;
-               }
-
-               /*
-                * Packet has been sent more than once. If this is the last
-                * packet to be acknowledged then we want to send the next
-                * packet in the send queue again (assumes the remote host does
-                * go-back-N error control).
-                */
-               if (xmit_count > 1)
-                       try_retrans = 1;
-       }
-
-       if (try_retrans)
-               dn_nsp_output(sk);
-
-       return wakeup;
-}
-
-void dn_nsp_send_data_ack(struct sock *sk)
-{
-       struct sk_buff *skb = NULL;
-
-       if ((skb = dn_alloc_skb(sk, 9, GFP_ATOMIC)) == NULL)
-               return;
-
-       skb_reserve(skb, 9);
-       dn_mk_ack_header(sk, skb, 0x04, 9, 0);
-       dn_nsp_send(skb);
-}
-
-void dn_nsp_send_oth_ack(struct sock *sk)
-{
-       struct sk_buff *skb = NULL;
-
-       if ((skb = dn_alloc_skb(sk, 9, GFP_ATOMIC)) == NULL)
-               return;
-
-       skb_reserve(skb, 9);
-       dn_mk_ack_header(sk, skb, 0x14, 9, 1);
-       dn_nsp_send(skb);
-}
-
-
-void dn_send_conn_ack (struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct sk_buff *skb = NULL;
-       struct nsp_conn_ack_msg *msg;
-
-       if ((skb = dn_alloc_skb(sk, 3, sk->sk_allocation)) == NULL)
-               return;
-
-       msg = skb_put(skb, 3);
-       msg->msgflg = 0x24;
-       msg->dstaddr = scp->addrrem;
-
-       dn_nsp_send(skb);
-}
-
-static int dn_nsp_retrans_conn_conf(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (scp->state == DN_CC)
-               dn_send_conn_conf(sk, GFP_ATOMIC);
-
-       return 0;
-}
-
-void dn_send_conn_conf(struct sock *sk, gfp_t gfp)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct sk_buff *skb = NULL;
-       struct nsp_conn_init_msg *msg;
-       __u8 len = (__u8)le16_to_cpu(scp->conndata_out.opt_optl);
-
-       if ((skb = dn_alloc_skb(sk, 50 + len, gfp)) == NULL)
-               return;
-
-       msg = skb_put(skb, sizeof(*msg));
-       msg->msgflg = 0x28;
-       msg->dstaddr = scp->addrrem;
-       msg->srcaddr = scp->addrloc;
-       msg->services = scp->services_loc;
-       msg->info = scp->info_loc;
-       msg->segsize = cpu_to_le16(scp->segsize_loc);
-
-       skb_put_u8(skb, len);
-
-       if (len > 0)
-               skb_put_data(skb, scp->conndata_out.opt_data, len);
-
-
-       dn_nsp_send(skb);
-
-       scp->persist = dn_nsp_persist(sk);
-       scp->persist_fxn = dn_nsp_retrans_conn_conf;
-}
-
-
-static __inline__ void dn_nsp_do_disc(struct sock *sk, unsigned char msgflg,
-                       unsigned short reason, gfp_t gfp,
-                       struct dst_entry *dst,
-                       int ddl, unsigned char *dd, __le16 rem, __le16 loc)
-{
-       struct sk_buff *skb = NULL;
-       int size = 7 + ddl + ((msgflg == NSP_DISCINIT) ? 1 : 0);
-       unsigned char *msg;
-
-       if ((dst == NULL) || (rem == 0)) {
-               net_dbg_ratelimited("DECnet: dn_nsp_do_disc: BUG! Please report this to SteveW@ACM.org rem=%u dst=%p\n",
-                                   le16_to_cpu(rem), dst);
-               return;
-       }
-
-       if ((skb = dn_alloc_skb(sk, size, gfp)) == NULL)
-               return;
-
-       msg = skb_put(skb, size);
-       *msg++ = msgflg;
-       *(__le16 *)msg = rem;
-       msg += 2;
-       *(__le16 *)msg = loc;
-       msg += 2;
-       *(__le16 *)msg = cpu_to_le16(reason);
-       msg += 2;
-       if (msgflg == NSP_DISCINIT)
-               *msg++ = ddl;
-
-       if (ddl) {
-               memcpy(msg, dd, ddl);
-       }
-
-       /*
-        * This doesn't go via the dn_nsp_send() function since we need
-        * to be able to send disc packets out which have no socket
-        * associations.
-        */
-       skb_dst_set(skb, dst_clone(dst));
-       dst_output(&init_net, skb->sk, skb);
-}
-
-
-void dn_nsp_send_disc(struct sock *sk, unsigned char msgflg,
-                       unsigned short reason, gfp_t gfp)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       int ddl = 0;
-
-       if (msgflg == NSP_DISCINIT)
-               ddl = le16_to_cpu(scp->discdata_out.opt_optl);
-
-       if (reason == 0)
-               reason = le16_to_cpu(scp->discdata_out.opt_status);
-
-       dn_nsp_do_disc(sk, msgflg, reason, gfp, __sk_dst_get(sk), ddl,
-               scp->discdata_out.opt_data, scp->addrrem, scp->addrloc);
-}
-
-
-void dn_nsp_return_disc(struct sk_buff *skb, unsigned char msgflg,
-                       unsigned short reason)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       int ddl = 0;
-       gfp_t gfp = GFP_ATOMIC;
-
-       dn_nsp_do_disc(NULL, msgflg, reason, gfp, skb_dst(skb), ddl,
-                       NULL, cb->src_port, cb->dst_port);
-}
-
-
-void dn_nsp_send_link(struct sock *sk, unsigned char lsflags, char fcval)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct sk_buff *skb;
-       unsigned char *ptr;
-       gfp_t gfp = GFP_ATOMIC;
-
-       if ((skb = dn_alloc_skb(sk, DN_MAX_NSP_DATA_HEADER + 2, gfp)) == NULL)
-               return;
-
-       skb_reserve(skb, DN_MAX_NSP_DATA_HEADER);
-       ptr = skb_put(skb, 2);
-       DN_SKB_CB(skb)->nsp_flags = 0x10;
-       *ptr++ = lsflags;
-       *ptr = fcval;
-
-       dn_nsp_queue_xmit(sk, skb, gfp, 1);
-
-       scp->persist = dn_nsp_persist(sk);
-       scp->persist_fxn = dn_nsp_xmit_timeout;
-}
-
-static int dn_nsp_retrans_conninit(struct sock *sk)
-{
-       struct dn_scp *scp = DN_SK(sk);
-
-       if (scp->state == DN_CI)
-               dn_nsp_send_conninit(sk, NSP_RCI);
-
-       return 0;
-}
-
-void dn_nsp_send_conninit(struct sock *sk, unsigned char msgflg)
-{
-       struct dn_scp *scp = DN_SK(sk);
-       struct nsp_conn_init_msg *msg;
-       unsigned char aux;
-       unsigned char menuver;
-       struct dn_skb_cb *cb;
-       unsigned char type = 1;
-       gfp_t allocation = (msgflg == NSP_CI) ? sk->sk_allocation : GFP_ATOMIC;
-       struct sk_buff *skb = dn_alloc_skb(sk, 200, allocation);
-
-       if (!skb)
-               return;
-
-       cb  = DN_SKB_CB(skb);
-       msg = skb_put(skb, sizeof(*msg));
-
-       msg->msgflg     = msgflg;
-       msg->dstaddr    = 0x0000;               /* Remote Node will assign it*/
-
-       msg->srcaddr    = scp->addrloc;
-       msg->services   = scp->services_loc;    /* Requested flow control    */
-       msg->info       = scp->info_loc;        /* Version Number            */
-       msg->segsize    = cpu_to_le16(scp->segsize_loc);        /* Max segment size  */
-
-       if (scp->peer.sdn_objnum)
-               type = 0;
-
-       skb_put(skb, dn_sockaddr2username(&scp->peer,
-                                         skb_tail_pointer(skb), type));
-       skb_put(skb, dn_sockaddr2username(&scp->addr,
-                                         skb_tail_pointer(skb), 2));
-
-       menuver = DN_MENUVER_ACC | DN_MENUVER_USR;
-       if (scp->peer.sdn_flags & SDF_PROXY)
-               menuver |= DN_MENUVER_PRX;
-       if (scp->peer.sdn_flags & SDF_UICPROXY)
-               menuver |= DN_MENUVER_UIC;
-
-       skb_put_u8(skb, menuver);       /* Menu Version         */
-
-       aux = scp->accessdata.acc_userl;
-       skb_put_u8(skb, aux);
-       if (aux > 0)
-               skb_put_data(skb, scp->accessdata.acc_user, aux);
-
-       aux = scp->accessdata.acc_passl;
-       skb_put_u8(skb, aux);
-       if (aux > 0)
-               skb_put_data(skb, scp->accessdata.acc_pass, aux);
-
-       aux = scp->accessdata.acc_accl;
-       skb_put_u8(skb, aux);
-       if (aux > 0)
-               skb_put_data(skb, scp->accessdata.acc_acc, aux);
-
-       aux = (__u8)le16_to_cpu(scp->conndata_out.opt_optl);
-       skb_put_u8(skb, aux);
-       if (aux > 0)
-               skb_put_data(skb, scp->conndata_out.opt_data, aux);
-
-       scp->persist = dn_nsp_persist(sk);
-       scp->persist_fxn = dn_nsp_retrans_conninit;
-
-       cb->rt_flags = DN_RT_F_RQR;
-
-       dn_nsp_send(skb);
-}
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
deleted file mode 100644 (file)
index ac2ee16..0000000
+++ /dev/null
@@ -1,1922 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Routing Functions (Endnode and Router)
- *
- * Authors:     Steve Whitehouse <SteveW@ACM.org>
- *              Eduardo Marcelo Serrat <emserrat@geocities.com>
- *
- * Changes:
- *              Steve Whitehouse : Fixes to allow "intra-ethernet" and
- *                                 "return-to-sender" bits on outgoing
- *                                 packets.
- *             Steve Whitehouse : Timeouts for cached routes.
- *              Steve Whitehouse : Use dst cache for input routes too.
- *              Steve Whitehouse : Fixed error values in dn_send_skb.
- *              Steve Whitehouse : Rework routing functions to better fit
- *                                 DECnet routing design
- *              Alexey Kuznetsov : New SMP locking
- *              Steve Whitehouse : More SMP locking changes & dn_cache_dump()
- *              Steve Whitehouse : Prerouting NF hook, now really is prerouting.
- *                                Fixed possible skb leak in rtnetlink funcs.
- *              Steve Whitehouse : Dave Miller's dynamic hash table sizing and
- *                                 Alexey Kuznetsov's finer grained locking
- *                                 from ipv4/route.c.
- *              Steve Whitehouse : Routing is now starting to look like a
- *                                 sensible set of code now, mainly due to
- *                                 my copying the IPv4 routing code. The
- *                                 hooks here are modified and will continue
- *                                 to evolve for a while.
- *              Steve Whitehouse : Real SMP at last :-) Also new netfilter
- *                                 stuff. Look out raw sockets your days
- *                                 are numbered!
- *              Steve Whitehouse : Added return-to-sender functions. Added
- *                                 backlog congestion level return codes.
- *             Steve Whitehouse : Fixed bug where routes were set up with
- *                                 no ref count on net devices.
- *              Steve Whitehouse : RCU for the route cache
- *              Steve Whitehouse : Preparations for the flow cache
- *              Steve Whitehouse : Prepare for nonlinear skbs
- */
-
-/******************************************************************************
-    (c) 1995-1998 E.M. Serrat          emserrat@geocities.com
-
-*******************************************************************************/
-
-#include <linux/errno.h>
-#include <linux/types.h>
-#include <linux/socket.h>
-#include <linux/in.h>
-#include <linux/kernel.h>
-#include <linux/sockios.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/inet.h>
-#include <linux/route.h>
-#include <linux/in_route.h>
-#include <linux/slab.h>
-#include <net/sock.h>
-#include <linux/mm.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/rtnetlink.h>
-#include <linux/string.h>
-#include <linux/netfilter_decnet.h>
-#include <linux/rcupdate.h>
-#include <linux/times.h>
-#include <linux/export.h>
-#include <asm/errno.h>
-#include <net/net_namespace.h>
-#include <net/netlink.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/fib_rules.h>
-#include <net/dn.h>
-#include <net/dn_dev.h>
-#include <net/dn_nsp.h>
-#include <net/dn_route.h>
-#include <net/dn_neigh.h>
-#include <net/dn_fib.h>
-
-struct dn_rt_hash_bucket {
-       struct dn_route __rcu *chain;
-       spinlock_t lock;
-};
-
-extern struct neigh_table dn_neigh_table;
-
-
-static unsigned char dn_hiord_addr[6] = {0xAA, 0x00, 0x04, 0x00, 0x00, 0x00};
-
-static const int dn_rt_min_delay = 2 * HZ;
-static const int dn_rt_max_delay = 10 * HZ;
-static const int dn_rt_mtu_expires = 10 * 60 * HZ;
-
-static unsigned long dn_rt_deadline;
-
-static int dn_dst_gc(struct dst_ops *ops);
-static struct dst_entry *dn_dst_check(struct dst_entry *, __u32);
-static unsigned int dn_dst_default_advmss(const struct dst_entry *dst);
-static unsigned int dn_dst_mtu(const struct dst_entry *dst);
-static void dn_dst_destroy(struct dst_entry *);
-static void dn_dst_ifdown(struct dst_entry *, struct net_device *dev, int how);
-static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
-static void dn_dst_link_failure(struct sk_buff *);
-static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                              struct sk_buff *skb , u32 mtu,
-                              bool confirm_neigh);
-static void dn_dst_redirect(struct dst_entry *dst, struct sock *sk,
-                           struct sk_buff *skb);
-static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
-                                            struct sk_buff *skb,
-                                            const void *daddr);
-static int dn_route_input(struct sk_buff *);
-static void dn_run_flush(struct timer_list *unused);
-
-static struct dn_rt_hash_bucket *dn_rt_hash_table;
-static unsigned int dn_rt_hash_mask;
-
-static struct timer_list dn_route_timer;
-static DEFINE_TIMER(dn_rt_flush_timer, dn_run_flush);
-int decnet_dst_gc_interval = 2;
-
-static struct dst_ops dn_dst_ops = {
-       .family =               PF_DECnet,
-       .gc_thresh =            128,
-       .gc =                   dn_dst_gc,
-       .check =                dn_dst_check,
-       .default_advmss =       dn_dst_default_advmss,
-       .mtu =                  dn_dst_mtu,
-       .cow_metrics =          dst_cow_metrics_generic,
-       .destroy =              dn_dst_destroy,
-       .ifdown =               dn_dst_ifdown,
-       .negative_advice =      dn_dst_negative_advice,
-       .link_failure =         dn_dst_link_failure,
-       .update_pmtu =          dn_dst_update_pmtu,
-       .redirect =             dn_dst_redirect,
-       .neigh_lookup =         dn_dst_neigh_lookup,
-};
-
-static void dn_dst_destroy(struct dst_entry *dst)
-{
-       struct dn_route *rt = (struct dn_route *) dst;
-
-       if (rt->n)
-               neigh_release(rt->n);
-       dst_destroy_metrics_generic(dst);
-}
-
-static void dn_dst_ifdown(struct dst_entry *dst, struct net_device *dev, int how)
-{
-       if (how) {
-               struct dn_route *rt = (struct dn_route *) dst;
-               struct neighbour *n = rt->n;
-
-               if (n && n->dev == dev) {
-                       n->dev = blackhole_netdev;
-                       dev_hold(n->dev);
-                       dev_put(dev);
-               }
-       }
-}
-
-static __inline__ unsigned int dn_hash(__le16 src, __le16 dst)
-{
-       __u16 tmp = (__u16 __force)(src ^ dst);
-       tmp ^= (tmp >> 3);
-       tmp ^= (tmp >> 5);
-       tmp ^= (tmp >> 10);
-       return dn_rt_hash_mask & (unsigned int)tmp;
-}
-
-static void dn_dst_check_expire(struct timer_list *unused)
-{
-       int i;
-       struct dn_route *rt;
-       struct dn_route __rcu **rtp;
-       unsigned long now = jiffies;
-       unsigned long expire = 120 * HZ;
-
-       for (i = 0; i <= dn_rt_hash_mask; i++) {
-               rtp = &dn_rt_hash_table[i].chain;
-
-               spin_lock(&dn_rt_hash_table[i].lock);
-               while ((rt = rcu_dereference_protected(*rtp,
-                                               lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
-                       if (atomic_read(&rt->dst.__refcnt) > 1 ||
-                           (now - rt->dst.lastuse) < expire) {
-                               rtp = &rt->dn_next;
-                               continue;
-                       }
-                       *rtp = rt->dn_next;
-                       rt->dn_next = NULL;
-                       dst_dev_put(&rt->dst);
-                       dst_release(&rt->dst);
-               }
-               spin_unlock(&dn_rt_hash_table[i].lock);
-
-               if (jiffies != now)
-                       break;
-       }
-
-       mod_timer(&dn_route_timer, now + decnet_dst_gc_interval * HZ);
-}
-
-static int dn_dst_gc(struct dst_ops *ops)
-{
-       struct dn_route *rt;
-       struct dn_route __rcu **rtp;
-       int i;
-       unsigned long now = jiffies;
-       unsigned long expire = 10 * HZ;
-
-       for (i = 0; i <= dn_rt_hash_mask; i++) {
-
-               spin_lock_bh(&dn_rt_hash_table[i].lock);
-               rtp = &dn_rt_hash_table[i].chain;
-
-               while ((rt = rcu_dereference_protected(*rtp,
-                                               lockdep_is_held(&dn_rt_hash_table[i].lock))) != NULL) {
-                       if (atomic_read(&rt->dst.__refcnt) > 1 ||
-                           (now - rt->dst.lastuse) < expire) {
-                               rtp = &rt->dn_next;
-                               continue;
-                       }
-                       *rtp = rt->dn_next;
-                       rt->dn_next = NULL;
-                       dst_dev_put(&rt->dst);
-                       dst_release(&rt->dst);
-                       break;
-               }
-               spin_unlock_bh(&dn_rt_hash_table[i].lock);
-       }
-
-       return 0;
-}
-
-/*
- * The decnet standards don't impose a particular minimum mtu, what they
- * do insist on is that the routing layer accepts a datagram of at least
- * 230 bytes long. Here we have to subtract the routing header length from
- * 230 to get the minimum acceptable mtu. If there is no neighbour, then we
- * assume the worst and use a long header size.
- *
- * We update both the mtu and the advertised mss (i.e. the segment size we
- * advertise to the other end).
- */
-static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                              struct sk_buff *skb, u32 mtu,
-                              bool confirm_neigh)
-{
-       struct dn_route *rt = (struct dn_route *) dst;
-       struct neighbour *n = rt->n;
-       u32 min_mtu = 230;
-       struct dn_dev *dn;
-
-       dn = n ? rcu_dereference_raw(n->dev->dn_ptr) : NULL;
-
-       if (dn && dn->use_long == 0)
-               min_mtu -= 6;
-       else
-               min_mtu -= 21;
-
-       if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) {
-               if (!(dst_metric_locked(dst, RTAX_MTU))) {
-                       dst_metric_set(dst, RTAX_MTU, mtu);
-                       dst_set_expires(dst, dn_rt_mtu_expires);
-               }
-               if (!(dst_metric_locked(dst, RTAX_ADVMSS))) {
-                       u32 mss = mtu - DN_MAX_NSP_DATA_HEADER;
-                       u32 existing_mss = dst_metric_raw(dst, RTAX_ADVMSS);
-                       if (!existing_mss || existing_mss > mss)
-                               dst_metric_set(dst, RTAX_ADVMSS, mss);
-               }
-       }
-}
-
-static void dn_dst_redirect(struct dst_entry *dst, struct sock *sk,
-                           struct sk_buff *skb)
-{
-}
-
-/*
- * When a route has been marked obsolete. (e.g. routing cache flush)
- */
-static struct dst_entry *dn_dst_check(struct dst_entry *dst, __u32 cookie)
-{
-       return NULL;
-}
-
-static struct dst_entry *dn_dst_negative_advice(struct dst_entry *dst)
-{
-       dst_release(dst);
-       return NULL;
-}
-
-static void dn_dst_link_failure(struct sk_buff *skb)
-{
-}
-
-static inline int compare_keys(struct flowidn *fl1, struct flowidn *fl2)
-{
-       return ((fl1->daddr ^ fl2->daddr) |
-               (fl1->saddr ^ fl2->saddr) |
-               (fl1->flowidn_mark ^ fl2->flowidn_mark) |
-               (fl1->flowidn_scope ^ fl2->flowidn_scope) |
-               (fl1->flowidn_oif ^ fl2->flowidn_oif) |
-               (fl1->flowidn_iif ^ fl2->flowidn_iif)) == 0;
-}
-
-static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_route **rp)
-{
-       struct dn_route *rth;
-       struct dn_route __rcu **rthp;
-       unsigned long now = jiffies;
-
-       rthp = &dn_rt_hash_table[hash].chain;
-
-       spin_lock_bh(&dn_rt_hash_table[hash].lock);
-       while ((rth = rcu_dereference_protected(*rthp,
-                                               lockdep_is_held(&dn_rt_hash_table[hash].lock))) != NULL) {
-               if (compare_keys(&rth->fld, &rt->fld)) {
-                       /* Put it first */
-                       *rthp = rth->dn_next;
-                       rcu_assign_pointer(rth->dn_next,
-                                          dn_rt_hash_table[hash].chain);
-                       rcu_assign_pointer(dn_rt_hash_table[hash].chain, rth);
-
-                       dst_hold_and_use(&rth->dst, now);
-                       spin_unlock_bh(&dn_rt_hash_table[hash].lock);
-
-                       dst_release_immediate(&rt->dst);
-                       *rp = rth;
-                       return 0;
-               }
-               rthp = &rth->dn_next;
-       }
-
-       rcu_assign_pointer(rt->dn_next, dn_rt_hash_table[hash].chain);
-       rcu_assign_pointer(dn_rt_hash_table[hash].chain, rt);
-
-       dst_hold_and_use(&rt->dst, now);
-       spin_unlock_bh(&dn_rt_hash_table[hash].lock);
-       *rp = rt;
-       return 0;
-}
-
-static void dn_run_flush(struct timer_list *unused)
-{
-       int i;
-       struct dn_route *rt, *next;
-
-       for (i = 0; i < dn_rt_hash_mask; i++) {
-               spin_lock_bh(&dn_rt_hash_table[i].lock);
-
-               rt = xchg((struct dn_route **)&dn_rt_hash_table[i].chain, NULL);
-               if (!rt)
-                       goto nothing_to_declare;
-
-               for (; rt; rt = next) {
-                       next = rcu_dereference_raw(rt->dn_next);
-                       RCU_INIT_POINTER(rt->dn_next, NULL);
-                       dst_dev_put(&rt->dst);
-                       dst_release(&rt->dst);
-               }
-
-nothing_to_declare:
-               spin_unlock_bh(&dn_rt_hash_table[i].lock);
-       }
-}
-
-static DEFINE_SPINLOCK(dn_rt_flush_lock);
-
-void dn_rt_cache_flush(int delay)
-{
-       unsigned long now = jiffies;
-       int user_mode = !in_interrupt();
-
-       if (delay < 0)
-               delay = dn_rt_min_delay;
-
-       spin_lock_bh(&dn_rt_flush_lock);
-
-       if (del_timer(&dn_rt_flush_timer) && delay > 0 && dn_rt_deadline) {
-               long tmo = (long)(dn_rt_deadline - now);
-
-               if (user_mode && tmo < dn_rt_max_delay - dn_rt_min_delay)
-                       tmo = 0;
-
-               if (delay > tmo)
-                       delay = tmo;
-       }
-
-       if (delay <= 0) {
-               spin_unlock_bh(&dn_rt_flush_lock);
-               dn_run_flush(NULL);
-               return;
-       }
-
-       if (dn_rt_deadline == 0)
-               dn_rt_deadline = now + dn_rt_max_delay;
-
-       dn_rt_flush_timer.expires = now + delay;
-       add_timer(&dn_rt_flush_timer);
-       spin_unlock_bh(&dn_rt_flush_lock);
-}
-
-/**
- * dn_return_short - Return a short packet to its sender
- * @skb: The packet to return
- *
- */
-static int dn_return_short(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb;
-       unsigned char *ptr;
-       __le16 *src;
-       __le16 *dst;
-
-       /* Add back headers */
-       skb_push(skb, skb->data - skb_network_header(skb));
-
-       skb = skb_unshare(skb, GFP_ATOMIC);
-       if (!skb)
-               return NET_RX_DROP;
-
-       cb = DN_SKB_CB(skb);
-       /* Skip packet length and point to flags */
-       ptr = skb->data + 2;
-       *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
-
-       dst = (__le16 *)ptr;
-       ptr += 2;
-       src = (__le16 *)ptr;
-       ptr += 2;
-       *ptr = 0; /* Zero hop count */
-
-       swap(*src, *dst);
-
-       skb->pkt_type = PACKET_OUTGOING;
-       dn_rt_finish_output(skb, NULL, NULL);
-       return NET_RX_SUCCESS;
-}
-
-/**
- * dn_return_long - Return a long packet to its sender
- * @skb: The long format packet to return
- *
- */
-static int dn_return_long(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb;
-       unsigned char *ptr;
-       unsigned char *src_addr, *dst_addr;
-       unsigned char tmp[ETH_ALEN];
-
-       /* Add back all headers */
-       skb_push(skb, skb->data - skb_network_header(skb));
-
-       skb = skb_unshare(skb, GFP_ATOMIC);
-       if (!skb)
-               return NET_RX_DROP;
-
-       cb = DN_SKB_CB(skb);
-       /* Ignore packet length and point to flags */
-       ptr = skb->data + 2;
-
-       /* Skip padding */
-       if (*ptr & DN_RT_F_PF) {
-               char padlen = (*ptr & ~DN_RT_F_PF);
-               ptr += padlen;
-       }
-
-       *ptr++ = (cb->rt_flags & ~DN_RT_F_RQR) | DN_RT_F_RTS;
-       ptr += 2;
-       dst_addr = ptr;
-       ptr += 8;
-       src_addr = ptr;
-       ptr += 6;
-       *ptr = 0; /* Zero hop count */
-
-       /* Swap source and destination */
-       memcpy(tmp, src_addr, ETH_ALEN);
-       memcpy(src_addr, dst_addr, ETH_ALEN);
-       memcpy(dst_addr, tmp, ETH_ALEN);
-
-       skb->pkt_type = PACKET_OUTGOING;
-       dn_rt_finish_output(skb, dst_addr, src_addr);
-       return NET_RX_SUCCESS;
-}
-
-/**
- * dn_route_rx_packet - Try and find a route for an incoming packet
- * @net: The applicable net namespace
- * @sk: Socket packet transmitted on
- * @skb: The packet to find a route for
- *
- * Returns: result of input function if route is found, error code otherwise
- */
-static int dn_route_rx_packet(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb;
-       int err;
-
-       err = dn_route_input(skb);
-       if (err == 0)
-               return dst_input(skb);
-
-       cb = DN_SKB_CB(skb);
-       if (decnet_debug_level & 4) {
-               char *devname = skb->dev ? skb->dev->name : "???";
-
-               printk(KERN_DEBUG
-                       "DECnet: dn_route_rx_packet: rt_flags=0x%02x dev=%s len=%d src=0x%04hx dst=0x%04hx err=%d type=%d\n",
-                       (int)cb->rt_flags, devname, skb->len,
-                       le16_to_cpu(cb->src), le16_to_cpu(cb->dst),
-                       err, skb->pkt_type);
-       }
-
-       if ((skb->pkt_type == PACKET_HOST) && (cb->rt_flags & DN_RT_F_RQR)) {
-               switch (cb->rt_flags & DN_RT_PKT_MSK) {
-               case DN_RT_PKT_SHORT:
-                       return dn_return_short(skb);
-               case DN_RT_PKT_LONG:
-                       return dn_return_long(skb);
-               }
-       }
-
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-static int dn_route_rx_long(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       unsigned char *ptr = skb->data;
-
-       if (!pskb_may_pull(skb, 21)) /* 20 for long header, 1 for shortest nsp */
-               goto drop_it;
-
-       skb_pull(skb, 20);
-       skb_reset_transport_header(skb);
-
-       /* Destination info */
-       ptr += 2;
-       cb->dst = dn_eth2dn(ptr);
-       if (memcmp(ptr, dn_hiord_addr, 4) != 0)
-               goto drop_it;
-       ptr += 6;
-
-
-       /* Source info */
-       ptr += 2;
-       cb->src = dn_eth2dn(ptr);
-       if (memcmp(ptr, dn_hiord_addr, 4) != 0)
-               goto drop_it;
-       ptr += 6;
-       /* Other junk */
-       ptr++;
-       cb->hops = *ptr++; /* Visit Count */
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING,
-                      &init_net, NULL, skb, skb->dev, NULL,
-                      dn_route_rx_packet);
-
-drop_it:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-
-
-static int dn_route_rx_short(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       unsigned char *ptr = skb->data;
-
-       if (!pskb_may_pull(skb, 6)) /* 5 for short header + 1 for shortest nsp */
-               goto drop_it;
-
-       skb_pull(skb, 5);
-       skb_reset_transport_header(skb);
-
-       cb->dst = *(__le16 *)ptr;
-       ptr += 2;
-       cb->src = *(__le16 *)ptr;
-       ptr += 2;
-       cb->hops = *ptr & 0x3f;
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_PRE_ROUTING,
-                      &init_net, NULL, skb, skb->dev, NULL,
-                      dn_route_rx_packet);
-
-drop_it:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-static int dn_route_discard(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       /*
-        * I know we drop the packet here, but that's considered success in
-        * this case
-        */
-       kfree_skb(skb);
-       return NET_RX_SUCCESS;
-}
-
-static int dn_route_ptp_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       dn_dev_hello(skb);
-       dn_neigh_pointopoint_hello(skb);
-       return NET_RX_SUCCESS;
-}
-
-int dn_route_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
-{
-       struct dn_skb_cb *cb;
-       unsigned char flags = 0;
-       __u16 len = le16_to_cpu(*(__le16 *)skb->data);
-       struct dn_dev *dn = rcu_dereference(dev->dn_ptr);
-       unsigned char padlen = 0;
-
-       if (!net_eq(dev_net(dev), &init_net))
-               goto dump_it;
-
-       if (dn == NULL)
-               goto dump_it;
-
-       skb = skb_share_check(skb, GFP_ATOMIC);
-       if (!skb)
-               goto out;
-
-       if (!pskb_may_pull(skb, 3))
-               goto dump_it;
-
-       skb_pull(skb, 2);
-
-       if (len > skb->len)
-               goto dump_it;
-
-       skb_trim(skb, len);
-
-       flags = *skb->data;
-
-       cb = DN_SKB_CB(skb);
-       cb->stamp = jiffies;
-       cb->iif = dev->ifindex;
-
-       /*
-        * If we have padding, remove it.
-        */
-       if (flags & DN_RT_F_PF) {
-               padlen = flags & ~DN_RT_F_PF;
-               if (!pskb_may_pull(skb, padlen + 1))
-                       goto dump_it;
-               skb_pull(skb, padlen);
-               flags = *skb->data;
-       }
-
-       skb_reset_network_header(skb);
-
-       /*
-        * Weed out future version DECnet
-        */
-       if (flags & DN_RT_F_VER)
-               goto dump_it;
-
-       cb->rt_flags = flags;
-
-       if (decnet_debug_level & 1)
-               printk(KERN_DEBUG
-                       "dn_route_rcv: got 0x%02x from %s [%d %d %d]\n",
-                       (int)flags, dev->name, len, skb->len,
-                       padlen);
-
-       if (flags & DN_RT_PKT_CNTL) {
-               if (unlikely(skb_linearize(skb)))
-                       goto dump_it;
-
-               switch (flags & DN_RT_CNTL_MSK) {
-               case DN_RT_PKT_INIT:
-                       dn_dev_init_pkt(skb);
-                       break;
-               case DN_RT_PKT_VERI:
-                       dn_dev_veri_pkt(skb);
-                       break;
-               }
-
-               if (dn->parms.state != DN_DEV_S_RU)
-                       goto dump_it;
-
-               switch (flags & DN_RT_CNTL_MSK) {
-               case DN_RT_PKT_HELO:
-                       return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
-                                      &init_net, NULL, skb, skb->dev, NULL,
-                                      dn_route_ptp_hello);
-
-               case DN_RT_PKT_L1RT:
-               case DN_RT_PKT_L2RT:
-                       return NF_HOOK(NFPROTO_DECNET, NF_DN_ROUTE,
-                                      &init_net, NULL, skb, skb->dev, NULL,
-                                      dn_route_discard);
-               case DN_RT_PKT_ERTH:
-                       return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
-                                      &init_net, NULL, skb, skb->dev, NULL,
-                                      dn_neigh_router_hello);
-
-               case DN_RT_PKT_EEDH:
-                       return NF_HOOK(NFPROTO_DECNET, NF_DN_HELLO,
-                                      &init_net, NULL, skb, skb->dev, NULL,
-                                      dn_neigh_endnode_hello);
-               }
-       } else {
-               if (dn->parms.state != DN_DEV_S_RU)
-                       goto dump_it;
-
-               skb_pull(skb, 1); /* Pull flags */
-
-               switch (flags & DN_RT_PKT_MSK) {
-               case DN_RT_PKT_LONG:
-                       return dn_route_rx_long(skb);
-               case DN_RT_PKT_SHORT:
-                       return dn_route_rx_short(skb);
-               }
-       }
-
-dump_it:
-       kfree_skb(skb);
-out:
-       return NET_RX_DROP;
-}
-
-static int dn_output(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct dst_entry *dst = skb_dst(skb);
-       struct dn_route *rt = (struct dn_route *)dst;
-       struct net_device *dev = dst->dev;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-       int err = -EINVAL;
-
-       if (rt->n == NULL)
-               goto error;
-
-       skb->dev = dev;
-
-       cb->src = rt->rt_saddr;
-       cb->dst = rt->rt_daddr;
-
-       /*
-        * Always set the Intra-Ethernet bit on all outgoing packets
-        * originated on this node. Only valid flag from upper layers
-        * is return-to-sender-requested. Set hop count to 0 too.
-        */
-       cb->rt_flags &= ~DN_RT_F_RQR;
-       cb->rt_flags |= DN_RT_F_IE;
-       cb->hops = 0;
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_LOCAL_OUT,
-                      &init_net, sk, skb, NULL, dev,
-                      dn_to_neigh_output);
-
-error:
-       net_dbg_ratelimited("dn_output: This should not happen\n");
-
-       kfree_skb(skb);
-
-       return err;
-}
-
-static int dn_forward(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct dst_entry *dst = skb_dst(skb);
-       struct dn_dev *dn_db = rcu_dereference(dst->dev->dn_ptr);
-       struct dn_route *rt;
-       int header_len;
-       struct net_device *dev = skb->dev;
-
-       if (skb->pkt_type != PACKET_HOST)
-               goto drop;
-
-       /* Ensure that we have enough space for headers */
-       rt = (struct dn_route *)skb_dst(skb);
-       header_len = dn_db->use_long ? 21 : 6;
-       if (skb_cow(skb, LL_RESERVED_SPACE(rt->dst.dev)+header_len))
-               goto drop;
-
-       /*
-        * Hop count exceeded.
-        */
-       if (++cb->hops > 30)
-               goto drop;
-
-       skb->dev = rt->dst.dev;
-
-       /*
-        * If packet goes out same interface it came in on, then set
-        * the Intra-Ethernet bit. This has no effect for short
-        * packets, so we don't need to test for them here.
-        */
-       cb->rt_flags &= ~DN_RT_F_IE;
-       if (rt->rt_flags & RTCF_DOREDIRECT)
-               cb->rt_flags |= DN_RT_F_IE;
-
-       return NF_HOOK(NFPROTO_DECNET, NF_DN_FORWARD,
-                      &init_net, NULL, skb, dev, skb->dev,
-                      dn_to_neigh_output);
-
-drop:
-       kfree_skb(skb);
-       return NET_RX_DROP;
-}
-
-/*
- * Used to catch bugs. This should never normally get
- * called.
- */
-static int dn_rt_bug_out(struct net *net, struct sock *sk, struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-       net_dbg_ratelimited("dn_rt_bug: skb from:%04x to:%04x\n",
-                           le16_to_cpu(cb->src), le16_to_cpu(cb->dst));
-
-       kfree_skb(skb);
-
-       return NET_RX_DROP;
-}
-
-static int dn_rt_bug(struct sk_buff *skb)
-{
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-
-       net_dbg_ratelimited("dn_rt_bug: skb from:%04x to:%04x\n",
-                           le16_to_cpu(cb->src), le16_to_cpu(cb->dst));
-
-       kfree_skb(skb);
-
-       return NET_RX_DROP;
-}
-
-static unsigned int dn_dst_default_advmss(const struct dst_entry *dst)
-{
-       return dn_mss_from_pmtu(dst->dev, dst_mtu(dst));
-}
-
-static unsigned int dn_dst_mtu(const struct dst_entry *dst)
-{
-       unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
-
-       return mtu ? : dst->dev->mtu;
-}
-
-static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
-                                            struct sk_buff *skb,
-                                            const void *daddr)
-{
-       return __neigh_lookup_errno(&dn_neigh_table, daddr, dst->dev);
-}
-
-static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res)
-{
-       struct dn_fib_info *fi = res->fi;
-       struct net_device *dev = rt->dst.dev;
-       unsigned int mss_metric;
-       struct neighbour *n;
-
-       if (fi) {
-               if (DN_FIB_RES_GW(*res) &&
-                   DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK)
-                       rt->rt_gateway = DN_FIB_RES_GW(*res);
-               dst_init_metrics(&rt->dst, fi->fib_metrics, true);
-       }
-       rt->rt_type = res->type;
-
-       if (dev != NULL && rt->n == NULL) {
-               n = __neigh_lookup_errno(&dn_neigh_table, &rt->rt_gateway, dev);
-               if (IS_ERR(n))
-                       return PTR_ERR(n);
-               rt->n = n;
-       }
-
-       if (dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu)
-               dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu);
-       mss_metric = dst_metric_raw(&rt->dst, RTAX_ADVMSS);
-       if (mss_metric) {
-               unsigned int mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst));
-               if (mss_metric > mss)
-                       dst_metric_set(&rt->dst, RTAX_ADVMSS, mss);
-       }
-       return 0;
-}
-
-static inline int dn_match_addr(__le16 addr1, __le16 addr2)
-{
-       __u16 tmp = le16_to_cpu(addr1) ^ le16_to_cpu(addr2);
-       int match = 16;
-       while (tmp) {
-               tmp >>= 1;
-               match--;
-       }
-       return match;
-}
-
-static __le16 dnet_select_source(const struct net_device *dev, __le16 daddr, int scope)
-{
-       __le16 saddr = 0;
-       struct dn_dev *dn_db;
-       struct dn_ifaddr *ifa;
-       int best_match = 0;
-       int ret;
-
-       rcu_read_lock();
-       dn_db = rcu_dereference(dev->dn_ptr);
-       for (ifa = rcu_dereference(dn_db->ifa_list);
-            ifa != NULL;
-            ifa = rcu_dereference(ifa->ifa_next)) {
-               if (ifa->ifa_scope > scope)
-                       continue;
-               if (!daddr) {
-                       saddr = ifa->ifa_local;
-                       break;
-               }
-               ret = dn_match_addr(daddr, ifa->ifa_local);
-               if (ret > best_match)
-                       saddr = ifa->ifa_local;
-               if (best_match == 0)
-                       saddr = ifa->ifa_local;
-       }
-       rcu_read_unlock();
-
-       return saddr;
-}
-
-static inline __le16 __dn_fib_res_prefsrc(struct dn_fib_res *res)
-{
-       return dnet_select_source(DN_FIB_RES_DEV(*res), DN_FIB_RES_GW(*res), res->scope);
-}
-
-static inline __le16 dn_fib_rules_map_destination(__le16 daddr, struct dn_fib_res *res)
-{
-       __le16 mask = dnet_make_mask(res->prefixlen);
-       return (daddr&~mask)|res->fi->fib_nh->nh_gw;
-}
-
-static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *oldflp, int try_hard)
-{
-       struct flowidn fld = {
-               .daddr = oldflp->daddr,
-               .saddr = oldflp->saddr,
-               .flowidn_scope = RT_SCOPE_UNIVERSE,
-               .flowidn_mark = oldflp->flowidn_mark,
-               .flowidn_iif = LOOPBACK_IFINDEX,
-               .flowidn_oif = oldflp->flowidn_oif,
-       };
-       struct dn_route *rt = NULL;
-       struct net_device *dev_out = NULL, *dev;
-       struct neighbour *neigh = NULL;
-       unsigned int hash;
-       unsigned int flags = 0;
-       struct dn_fib_res res = { .fi = NULL, .type = RTN_UNICAST };
-       int err;
-       int free_res = 0;
-       __le16 gateway = 0;
-
-       if (decnet_debug_level & 16)
-               printk(KERN_DEBUG
-                      "dn_route_output_slow: dst=%04x src=%04x mark=%d"
-                      " iif=%d oif=%d\n", le16_to_cpu(oldflp->daddr),
-                      le16_to_cpu(oldflp->saddr),
-                      oldflp->flowidn_mark, LOOPBACK_IFINDEX,
-                      oldflp->flowidn_oif);
-
-       /* If we have an output interface, verify its a DECnet device */
-       if (oldflp->flowidn_oif) {
-               dev_out = dev_get_by_index(&init_net, oldflp->flowidn_oif);
-               err = -ENODEV;
-               if (dev_out && dev_out->dn_ptr == NULL) {
-                       dev_put(dev_out);
-                       dev_out = NULL;
-               }
-               if (dev_out == NULL)
-                       goto out;
-       }
-
-       /* If we have a source address, verify that its a local address */
-       if (oldflp->saddr) {
-               err = -EADDRNOTAVAIL;
-
-               if (dev_out) {
-                       if (dn_dev_islocal(dev_out, oldflp->saddr))
-                               goto source_ok;
-                       dev_put(dev_out);
-                       goto out;
-               }
-               rcu_read_lock();
-               for_each_netdev_rcu(&init_net, dev) {
-                       if (!dev->dn_ptr)
-                               continue;
-                       if (!dn_dev_islocal(dev, oldflp->saddr))
-                               continue;
-                       if ((dev->flags & IFF_LOOPBACK) &&
-                           oldflp->daddr &&
-                           !dn_dev_islocal(dev, oldflp->daddr))
-                               continue;
-
-                       dev_out = dev;
-                       break;
-               }
-               rcu_read_unlock();
-               if (dev_out == NULL)
-                       goto out;
-               dev_hold(dev_out);
-source_ok:
-               ;
-       }
-
-       /* No destination? Assume its local */
-       if (!fld.daddr) {
-               fld.daddr = fld.saddr;
-
-               dev_put(dev_out);
-               err = -EINVAL;
-               dev_out = init_net.loopback_dev;
-               if (!dev_out->dn_ptr)
-                       goto out;
-               err = -EADDRNOTAVAIL;
-               dev_hold(dev_out);
-               if (!fld.daddr) {
-                       fld.daddr =
-                       fld.saddr = dnet_select_source(dev_out, 0,
-                                                      RT_SCOPE_HOST);
-                       if (!fld.daddr)
-                               goto done;
-               }
-               fld.flowidn_oif = LOOPBACK_IFINDEX;
-               res.type = RTN_LOCAL;
-               goto make_route;
-       }
-
-       if (decnet_debug_level & 16)
-               printk(KERN_DEBUG
-                      "dn_route_output_slow: initial checks complete."
-                      " dst=%04x src=%04x oif=%d try_hard=%d\n",
-                      le16_to_cpu(fld.daddr), le16_to_cpu(fld.saddr),
-                      fld.flowidn_oif, try_hard);
-
-       /*
-        * N.B. If the kernel is compiled without router support then
-        * dn_fib_lookup() will evaluate to non-zero so this if () block
-        * will always be executed.
-        */
-       err = -ESRCH;
-       if (try_hard || (err = dn_fib_lookup(&fld, &res)) != 0) {
-               struct dn_dev *dn_db;
-               if (err != -ESRCH)
-                       goto out;
-               /*
-                * Here the fallback is basically the standard algorithm for
-                * routing in endnodes which is described in the DECnet routing
-                * docs
-                *
-                * If we are not trying hard, look in neighbour cache.
-                * The result is tested to ensure that if a specific output
-                * device/source address was requested, then we honour that
-                * here
-                */
-               if (!try_hard) {
-                       neigh = neigh_lookup_nodev(&dn_neigh_table, &init_net, &fld.daddr);
-                       if (neigh) {
-                               if ((oldflp->flowidn_oif &&
-                                   (neigh->dev->ifindex != oldflp->flowidn_oif)) ||
-                                   (oldflp->saddr &&
-                                   (!dn_dev_islocal(neigh->dev,
-                                                    oldflp->saddr)))) {
-                                       neigh_release(neigh);
-                                       neigh = NULL;
-                               } else {
-                                       dev_put(dev_out);
-                                       if (dn_dev_islocal(neigh->dev, fld.daddr)) {
-                                               dev_out = init_net.loopback_dev;
-                                               res.type = RTN_LOCAL;
-                                       } else {
-                                               dev_out = neigh->dev;
-                                       }
-                                       dev_hold(dev_out);
-                                       goto select_source;
-                               }
-                       }
-               }
-
-               /* Not there? Perhaps its a local address */
-               if (dev_out == NULL)
-                       dev_out = dn_dev_get_default();
-               err = -ENODEV;
-               if (dev_out == NULL)
-                       goto out;
-               dn_db = rcu_dereference_raw(dev_out->dn_ptr);
-               if (!dn_db)
-                       goto e_inval;
-               /* Possible improvement - check all devices for local addr */
-               if (dn_dev_islocal(dev_out, fld.daddr)) {
-                       dev_put(dev_out);
-                       dev_out = init_net.loopback_dev;
-                       dev_hold(dev_out);
-                       res.type = RTN_LOCAL;
-                       goto select_source;
-               }
-               /* Not local either.... try sending it to the default router */
-               neigh = neigh_clone(dn_db->router);
-               BUG_ON(neigh && neigh->dev != dev_out);
-
-               /* Ok then, we assume its directly connected and move on */
-select_source:
-               if (neigh)
-                       gateway = container_of(neigh, struct dn_neigh, n)->addr;
-               if (gateway == 0)
-                       gateway = fld.daddr;
-               if (fld.saddr == 0) {
-                       fld.saddr = dnet_select_source(dev_out, gateway,
-                                                      res.type == RTN_LOCAL ?
-                                                      RT_SCOPE_HOST :
-                                                      RT_SCOPE_LINK);
-                       if (fld.saddr == 0 && res.type != RTN_LOCAL)
-                               goto e_addr;
-               }
-               fld.flowidn_oif = dev_out->ifindex;
-               goto make_route;
-       }
-       free_res = 1;
-
-       if (res.type == RTN_NAT)
-               goto e_inval;
-
-       if (res.type == RTN_LOCAL) {
-               if (!fld.saddr)
-                       fld.saddr = fld.daddr;
-               dev_put(dev_out);
-               dev_out = init_net.loopback_dev;
-               dev_hold(dev_out);
-               if (!dev_out->dn_ptr)
-                       goto e_inval;
-               fld.flowidn_oif = dev_out->ifindex;
-               if (res.fi)
-                       dn_fib_info_put(res.fi);
-               res.fi = NULL;
-               goto make_route;
-       }
-
-       if (res.fi->fib_nhs > 1 && fld.flowidn_oif == 0)
-               dn_fib_select_multipath(&fld, &res);
-
-       /*
-        * We could add some logic to deal with default routes here and
-        * get rid of some of the special casing above.
-        */
-
-       if (!fld.saddr)
-               fld.saddr = DN_FIB_RES_PREFSRC(res);
-
-       dev_put(dev_out);
-       dev_out = DN_FIB_RES_DEV(res);
-       dev_hold(dev_out);
-       fld.flowidn_oif = dev_out->ifindex;
-       gateway = DN_FIB_RES_GW(res);
-
-make_route:
-       if (dev_out->flags & IFF_LOOPBACK)
-               flags |= RTCF_LOCAL;
-
-       rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, 0);
-       if (rt == NULL)
-               goto e_nobufs;
-
-       rt->dn_next = NULL;
-       memset(&rt->fld, 0, sizeof(rt->fld));
-       rt->fld.saddr        = oldflp->saddr;
-       rt->fld.daddr        = oldflp->daddr;
-       rt->fld.flowidn_oif  = oldflp->flowidn_oif;
-       rt->fld.flowidn_iif  = 0;
-       rt->fld.flowidn_mark = oldflp->flowidn_mark;
-
-       rt->rt_saddr      = fld.saddr;
-       rt->rt_daddr      = fld.daddr;
-       rt->rt_gateway    = gateway ? gateway : fld.daddr;
-       rt->rt_local_src  = fld.saddr;
-
-       rt->rt_dst_map    = fld.daddr;
-       rt->rt_src_map    = fld.saddr;
-
-       rt->n = neigh;
-       neigh = NULL;
-
-       rt->dst.lastuse = jiffies;
-       rt->dst.output  = dn_output;
-       rt->dst.input   = dn_rt_bug;
-       rt->rt_flags      = flags;
-       if (flags & RTCF_LOCAL)
-               rt->dst.input = dn_nsp_rx;
-
-       err = dn_rt_set_next_hop(rt, &res);
-       if (err)
-               goto e_neighbour;
-
-       hash = dn_hash(rt->fld.saddr, rt->fld.daddr);
-       /* dn_insert_route() increments dst->__refcnt */
-       dn_insert_route(rt, hash, (struct dn_route **)pprt);
-
-done:
-       if (neigh)
-               neigh_release(neigh);
-       if (free_res)
-               dn_fib_res_put(&res);
-       dev_put(dev_out);
-out:
-       return err;
-
-e_addr:
-       err = -EADDRNOTAVAIL;
-       goto done;
-e_inval:
-       err = -EINVAL;
-       goto done;
-e_nobufs:
-       err = -ENOBUFS;
-       goto done;
-e_neighbour:
-       dst_release_immediate(&rt->dst);
-       goto e_nobufs;
-}
-
-
-/*
- * N.B. The flags may be moved into the flowi at some future stage.
- */
-static int __dn_route_output_key(struct dst_entry **pprt, const struct flowidn *flp, int flags)
-{
-       unsigned int hash = dn_hash(flp->saddr, flp->daddr);
-       struct dn_route *rt = NULL;
-
-       if (!(flags & MSG_TRYHARD)) {
-               rcu_read_lock_bh();
-               for (rt = rcu_dereference_bh(dn_rt_hash_table[hash].chain); rt;
-                       rt = rcu_dereference_bh(rt->dn_next)) {
-                       if ((flp->daddr == rt->fld.daddr) &&
-                           (flp->saddr == rt->fld.saddr) &&
-                           (flp->flowidn_mark == rt->fld.flowidn_mark) &&
-                           dn_is_output_route(rt) &&
-                           (rt->fld.flowidn_oif == flp->flowidn_oif)) {
-                               dst_hold_and_use(&rt->dst, jiffies);
-                               rcu_read_unlock_bh();
-                               *pprt = &rt->dst;
-                               return 0;
-                       }
-               }
-               rcu_read_unlock_bh();
-       }
-
-       return dn_route_output_slow(pprt, flp, flags);
-}
-
-static int dn_route_output_key(struct dst_entry **pprt, struct flowidn *flp, int flags)
-{
-       int err;
-
-       err = __dn_route_output_key(pprt, flp, flags);
-       if (err == 0 && flp->flowidn_proto) {
-               *pprt = xfrm_lookup(&init_net, *pprt,
-                                   flowidn_to_flowi(flp), NULL, 0);
-               if (IS_ERR(*pprt)) {
-                       err = PTR_ERR(*pprt);
-                       *pprt = NULL;
-               }
-       }
-       return err;
-}
-
-int dn_route_output_sock(struct dst_entry __rcu **pprt, struct flowidn *fl, struct sock *sk, int flags)
-{
-       int err;
-
-       err = __dn_route_output_key(pprt, fl, flags & MSG_TRYHARD);
-       if (err == 0 && fl->flowidn_proto) {
-               *pprt = xfrm_lookup(&init_net, *pprt,
-                                   flowidn_to_flowi(fl), sk, 0);
-               if (IS_ERR(*pprt)) {
-                       err = PTR_ERR(*pprt);
-                       *pprt = NULL;
-               }
-       }
-       return err;
-}
-
-static int dn_route_input_slow(struct sk_buff *skb)
-{
-       struct dn_route *rt = NULL;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       struct net_device *in_dev = skb->dev;
-       struct net_device *out_dev = NULL;
-       struct dn_dev *dn_db;
-       struct neighbour *neigh = NULL;
-       unsigned int hash;
-       int flags = 0;
-       __le16 gateway = 0;
-       __le16 local_src = 0;
-       struct flowidn fld = {
-               .daddr = cb->dst,
-               .saddr = cb->src,
-               .flowidn_scope = RT_SCOPE_UNIVERSE,
-               .flowidn_mark = skb->mark,
-               .flowidn_iif = skb->dev->ifindex,
-       };
-       struct dn_fib_res res = { .fi = NULL, .type = RTN_UNREACHABLE };
-       int err = -EINVAL;
-       int free_res = 0;
-
-       dev_hold(in_dev);
-
-       dn_db = rcu_dereference(in_dev->dn_ptr);
-       if (!dn_db)
-               goto out;
-
-       /* Zero source addresses are not allowed */
-       if (fld.saddr == 0)
-               goto out;
-
-       /*
-        * In this case we've just received a packet from a source
-        * outside ourselves pretending to come from us. We don't
-        * allow it any further to prevent routing loops, spoofing and
-        * other nasties. Loopback packets already have the dst attached
-        * so this only affects packets which have originated elsewhere.
-        */
-       err  = -ENOTUNIQ;
-       if (dn_dev_islocal(in_dev, cb->src))
-               goto out;
-
-       err = dn_fib_lookup(&fld, &res);
-       if (err) {
-               if (err != -ESRCH)
-                       goto out;
-               /*
-                * Is the destination us ?
-                */
-               if (!dn_dev_islocal(in_dev, cb->dst))
-                       goto e_inval;
-
-               res.type = RTN_LOCAL;
-       } else {
-               __le16 src_map = fld.saddr;
-               free_res = 1;
-
-               out_dev = DN_FIB_RES_DEV(res);
-               if (out_dev == NULL) {
-                       net_crit_ratelimited("Bug in dn_route_input_slow() No output device\n");
-                       goto e_inval;
-               }
-               dev_hold(out_dev);
-
-               if (res.r)
-                       src_map = fld.saddr; /* no NAT support for now */
-
-               gateway = DN_FIB_RES_GW(res);
-               if (res.type == RTN_NAT) {
-                       fld.daddr = dn_fib_rules_map_destination(fld.daddr, &res);
-                       dn_fib_res_put(&res);
-                       free_res = 0;
-                       if (dn_fib_lookup(&fld, &res))
-                               goto e_inval;
-                       free_res = 1;
-                       if (res.type != RTN_UNICAST)
-                               goto e_inval;
-                       flags |= RTCF_DNAT;
-                       gateway = fld.daddr;
-               }
-               fld.saddr = src_map;
-       }
-
-       switch (res.type) {
-       case RTN_UNICAST:
-               /*
-                * Forwarding check here, we only check for forwarding
-                * being turned off, if you want to only forward intra
-                * area, its up to you to set the routing tables up
-                * correctly.
-                */
-               if (dn_db->parms.forwarding == 0)
-                       goto e_inval;
-
-               if (res.fi->fib_nhs > 1 && fld.flowidn_oif == 0)
-                       dn_fib_select_multipath(&fld, &res);
-
-               /*
-                * Check for out_dev == in_dev. We use the RTCF_DOREDIRECT
-                * flag as a hint to set the intra-ethernet bit when
-                * forwarding. If we've got NAT in operation, we don't do
-                * this optimisation.
-                */
-               if (out_dev == in_dev && !(flags & RTCF_NAT))
-                       flags |= RTCF_DOREDIRECT;
-
-               local_src = DN_FIB_RES_PREFSRC(res);
-               break;
-       case RTN_BLACKHOLE:
-       case RTN_UNREACHABLE:
-               break;
-       case RTN_LOCAL:
-               flags |= RTCF_LOCAL;
-               fld.saddr = cb->dst;
-               fld.daddr = cb->src;
-
-               /* Routing tables gave us a gateway */
-               if (gateway)
-                       goto make_route;
-
-               /* Packet was intra-ethernet, so we know its on-link */
-               if (cb->rt_flags & DN_RT_F_IE) {
-                       gateway = cb->src;
-                       goto make_route;
-               }
-
-               /* Use the default router if there is one */
-               neigh = neigh_clone(dn_db->router);
-               if (neigh) {
-                       gateway = container_of(neigh, struct dn_neigh, n)->addr;
-                       goto make_route;
-               }
-
-               /* Close eyes and pray */
-               gateway = cb->src;
-               goto make_route;
-       default:
-               goto e_inval;
-       }
-
-make_route:
-       rt = dst_alloc(&dn_dst_ops, out_dev, 1, DST_OBSOLETE_NONE, 0);
-       if (rt == NULL)
-               goto e_nobufs;
-
-       rt->dn_next = NULL;
-       memset(&rt->fld, 0, sizeof(rt->fld));
-       rt->rt_saddr      = fld.saddr;
-       rt->rt_daddr      = fld.daddr;
-       rt->rt_gateway    = fld.daddr;
-       if (gateway)
-               rt->rt_gateway = gateway;
-       rt->rt_local_src  = local_src ? local_src : rt->rt_saddr;
-
-       rt->rt_dst_map    = fld.daddr;
-       rt->rt_src_map    = fld.saddr;
-
-       rt->fld.saddr        = cb->src;
-       rt->fld.daddr        = cb->dst;
-       rt->fld.flowidn_oif  = 0;
-       rt->fld.flowidn_iif  = in_dev->ifindex;
-       rt->fld.flowidn_mark = fld.flowidn_mark;
-
-       rt->n = neigh;
-       rt->dst.lastuse = jiffies;
-       rt->dst.output = dn_rt_bug_out;
-       switch (res.type) {
-       case RTN_UNICAST:
-               rt->dst.input = dn_forward;
-               break;
-       case RTN_LOCAL:
-               rt->dst.output = dn_output;
-               rt->dst.input = dn_nsp_rx;
-               rt->dst.dev = in_dev;
-               flags |= RTCF_LOCAL;
-               break;
-       default:
-       case RTN_UNREACHABLE:
-       case RTN_BLACKHOLE:
-               rt->dst.input = dst_discard;
-       }
-       rt->rt_flags = flags;
-
-       err = dn_rt_set_next_hop(rt, &res);
-       if (err)
-               goto e_neighbour;
-
-       hash = dn_hash(rt->fld.saddr, rt->fld.daddr);
-       /* dn_insert_route() increments dst->__refcnt */
-       dn_insert_route(rt, hash, &rt);
-       skb_dst_set(skb, &rt->dst);
-
-done:
-       if (neigh)
-               neigh_release(neigh);
-       if (free_res)
-               dn_fib_res_put(&res);
-       dev_put(in_dev);
-       dev_put(out_dev);
-out:
-       return err;
-
-e_inval:
-       err = -EINVAL;
-       goto done;
-
-e_nobufs:
-       err = -ENOBUFS;
-       goto done;
-
-e_neighbour:
-       dst_release_immediate(&rt->dst);
-       goto done;
-}
-
-static int dn_route_input(struct sk_buff *skb)
-{
-       struct dn_route *rt;
-       struct dn_skb_cb *cb = DN_SKB_CB(skb);
-       unsigned int hash = dn_hash(cb->src, cb->dst);
-
-       if (skb_dst(skb))
-               return 0;
-
-       rcu_read_lock();
-       for (rt = rcu_dereference(dn_rt_hash_table[hash].chain); rt != NULL;
-           rt = rcu_dereference(rt->dn_next)) {
-               if ((rt->fld.saddr == cb->src) &&
-                   (rt->fld.daddr == cb->dst) &&
-                   (rt->fld.flowidn_oif == 0) &&
-                   (rt->fld.flowidn_mark == skb->mark) &&
-                   (rt->fld.flowidn_iif == cb->iif)) {
-                       dst_hold_and_use(&rt->dst, jiffies);
-                       rcu_read_unlock();
-                       skb_dst_set(skb, (struct dst_entry *)rt);
-                       return 0;
-               }
-       }
-       rcu_read_unlock();
-
-       return dn_route_input_slow(skb);
-}
-
-static int dn_rt_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
-                          int event, int nowait, unsigned int flags)
-{
-       struct dn_route *rt = (struct dn_route *)skb_dst(skb);
-       struct rtmsg *r;
-       struct nlmsghdr *nlh;
-       long expires;
-
-       nlh = nlmsg_put(skb, portid, seq, event, sizeof(*r), flags);
-       if (!nlh)
-               return -EMSGSIZE;
-
-       r = nlmsg_data(nlh);
-       r->rtm_family = AF_DECnet;
-       r->rtm_dst_len = 16;
-       r->rtm_src_len = 0;
-       r->rtm_tos = 0;
-       r->rtm_table = RT_TABLE_MAIN;
-       r->rtm_type = rt->rt_type;
-       r->rtm_flags = (rt->rt_flags & ~0xFFFF) | RTM_F_CLONED;
-       r->rtm_scope = RT_SCOPE_UNIVERSE;
-       r->rtm_protocol = RTPROT_UNSPEC;
-
-       if (rt->rt_flags & RTCF_NOTIFY)
-               r->rtm_flags |= RTM_F_NOTIFY;
-
-       if (nla_put_u32(skb, RTA_TABLE, RT_TABLE_MAIN) < 0 ||
-           nla_put_le16(skb, RTA_DST, rt->rt_daddr) < 0)
-               goto errout;
-
-       if (rt->fld.saddr) {
-               r->rtm_src_len = 16;
-               if (nla_put_le16(skb, RTA_SRC, rt->fld.saddr) < 0)
-                       goto errout;
-       }
-       if (rt->dst.dev &&
-           nla_put_u32(skb, RTA_OIF, rt->dst.dev->ifindex) < 0)
-               goto errout;
-
-       /*
-        * Note to self - change this if input routes reverse direction when
-        * they deal only with inputs and not with replies like they do
-        * currently.
-        */
-       if (nla_put_le16(skb, RTA_PREFSRC, rt->rt_local_src) < 0)
-               goto errout;
-
-       if (rt->rt_daddr != rt->rt_gateway &&
-           nla_put_le16(skb, RTA_GATEWAY, rt->rt_gateway) < 0)
-               goto errout;
-
-       if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0)
-               goto errout;
-
-       expires = rt->dst.expires ? rt->dst.expires - jiffies : 0;
-       if (rtnl_put_cacheinfo(skb, &rt->dst, 0, expires,
-                              rt->dst.error) < 0)
-               goto errout;
-
-       if (dn_is_input_route(rt) &&
-           nla_put_u32(skb, RTA_IIF, rt->fld.flowidn_iif) < 0)
-               goto errout;
-
-       nlmsg_end(skb, nlh);
-       return 0;
-
-errout:
-       nlmsg_cancel(skb, nlh);
-       return -EMSGSIZE;
-}
-
-const struct nla_policy rtm_dn_policy[RTA_MAX + 1] = {
-       [RTA_DST]               = { .type = NLA_U16 },
-       [RTA_SRC]               = { .type = NLA_U16 },
-       [RTA_IIF]               = { .type = NLA_U32 },
-       [RTA_OIF]               = { .type = NLA_U32 },
-       [RTA_GATEWAY]           = { .type = NLA_U16 },
-       [RTA_PRIORITY]          = { .type = NLA_U32 },
-       [RTA_PREFSRC]           = { .type = NLA_U16 },
-       [RTA_METRICS]           = { .type = NLA_NESTED },
-       [RTA_MULTIPATH]         = { .type = NLA_NESTED },
-       [RTA_TABLE]             = { .type = NLA_U32 },
-       [RTA_MARK]              = { .type = NLA_U32 },
-};
-
-/*
- * This is called by both endnodes and routers now.
- */
-static int dn_cache_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
-                            struct netlink_ext_ack *extack)
-{
-       struct net *net = sock_net(in_skb->sk);
-       struct rtmsg *rtm = nlmsg_data(nlh);
-       struct dn_route *rt = NULL;
-       struct dn_skb_cb *cb;
-       int err;
-       struct sk_buff *skb;
-       struct flowidn fld;
-       struct nlattr *tb[RTA_MAX+1];
-
-       if (!net_eq(net, &init_net))
-               return -EINVAL;
-
-       err = nlmsg_parse_deprecated(nlh, sizeof(*rtm), tb, RTA_MAX,
-                                    rtm_dn_policy, extack);
-       if (err < 0)
-               return err;
-
-       memset(&fld, 0, sizeof(fld));
-       fld.flowidn_proto = DNPROTO_NSP;
-
-       skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
-       if (skb == NULL)
-               return -ENOBUFS;
-       skb_reset_mac_header(skb);
-       cb = DN_SKB_CB(skb);
-
-       if (tb[RTA_SRC])
-               fld.saddr = nla_get_le16(tb[RTA_SRC]);
-
-       if (tb[RTA_DST])
-               fld.daddr = nla_get_le16(tb[RTA_DST]);
-
-       if (tb[RTA_IIF])
-               fld.flowidn_iif = nla_get_u32(tb[RTA_IIF]);
-
-       if (fld.flowidn_iif) {
-               struct net_device *dev;
-               dev = __dev_get_by_index(&init_net, fld.flowidn_iif);
-               if (!dev || !dev->dn_ptr) {
-                       kfree_skb(skb);
-                       return -ENODEV;
-               }
-               skb->protocol = htons(ETH_P_DNA_RT);
-               skb->dev = dev;
-               cb->src = fld.saddr;
-               cb->dst = fld.daddr;
-               local_bh_disable();
-               err = dn_route_input(skb);
-               local_bh_enable();
-               memset(cb, 0, sizeof(struct dn_skb_cb));
-               rt = (struct dn_route *)skb_dst(skb);
-               if (!err && -rt->dst.error)
-                       err = rt->dst.error;
-       } else {
-               if (tb[RTA_OIF])
-                       fld.flowidn_oif = nla_get_u32(tb[RTA_OIF]);
-
-               err = dn_route_output_key((struct dst_entry **)&rt, &fld, 0);
-       }
-
-       skb->dev = NULL;
-       if (err)
-               goto out_free;
-       skb_dst_set(skb, &rt->dst);
-       if (rtm->rtm_flags & RTM_F_NOTIFY)
-               rt->rt_flags |= RTCF_NOTIFY;
-
-       err = dn_rt_fill_info(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, RTM_NEWROUTE, 0, 0);
-       if (err < 0) {
-               err = -EMSGSIZE;
-               goto out_free;
-       }
-
-       return rtnl_unicast(skb, &init_net, NETLINK_CB(in_skb).portid);
-
-out_free:
-       kfree_skb(skb);
-       return err;
-}
-
-/*
- * For routers, this is called from dn_fib_dump, but for endnodes its
- * called directly from the rtnetlink dispatch table.
- */
-int dn_cache_dump(struct sk_buff *skb, struct netlink_callback *cb)
-{
-       struct net *net = sock_net(skb->sk);
-       struct dn_route *rt;
-       int h, s_h;
-       int idx, s_idx;
-       struct rtmsg *rtm;
-
-       if (!net_eq(net, &init_net))
-               return 0;
-
-       if (nlmsg_len(cb->nlh) < sizeof(struct rtmsg))
-               return -EINVAL;
-
-       rtm = nlmsg_data(cb->nlh);
-       if (!(rtm->rtm_flags & RTM_F_CLONED))
-               return 0;
-
-       s_h = cb->args[0];
-       s_idx = idx = cb->args[1];
-       for (h = 0; h <= dn_rt_hash_mask; h++) {
-               if (h < s_h)
-                       continue;
-               if (h > s_h)
-                       s_idx = 0;
-               rcu_read_lock_bh();
-               for (rt = rcu_dereference_bh(dn_rt_hash_table[h].chain), idx = 0;
-                       rt;
-                       rt = rcu_dereference_bh(rt->dn_next), idx++) {
-                       if (idx < s_idx)
-                               continue;
-                       skb_dst_set(skb, dst_clone(&rt->dst));
-                       if (dn_rt_fill_info(skb, NETLINK_CB(cb->skb).portid,
-                                       cb->nlh->nlmsg_seq, RTM_NEWROUTE,
-                                       1, NLM_F_MULTI) < 0) {
-                               skb_dst_drop(skb);
-                               rcu_read_unlock_bh();
-                               goto done;
-                       }
-                       skb_dst_drop(skb);
-               }
-               rcu_read_unlock_bh();
-       }
-
-done:
-       cb->args[0] = h;
-       cb->args[1] = idx;
-       return skb->len;
-}
-
-#ifdef CONFIG_PROC_FS
-struct dn_rt_cache_iter_state {
-       int bucket;
-};
-
-static struct dn_route *dn_rt_cache_get_first(struct seq_file *seq)
-{
-       struct dn_route *rt = NULL;
-       struct dn_rt_cache_iter_state *s = seq->private;
-
-       for (s->bucket = dn_rt_hash_mask; s->bucket >= 0; --s->bucket) {
-               rcu_read_lock_bh();
-               rt = rcu_dereference_bh(dn_rt_hash_table[s->bucket].chain);
-               if (rt)
-                       break;
-               rcu_read_unlock_bh();
-       }
-       return rt;
-}
-
-static struct dn_route *dn_rt_cache_get_next(struct seq_file *seq, struct dn_route *rt)
-{
-       struct dn_rt_cache_iter_state *s = seq->private;
-
-       rt = rcu_dereference_bh(rt->dn_next);
-       while (!rt) {
-               rcu_read_unlock_bh();
-               if (--s->bucket < 0)
-                       break;
-               rcu_read_lock_bh();
-               rt = rcu_dereference_bh(dn_rt_hash_table[s->bucket].chain);
-       }
-       return rt;
-}
-
-static void *dn_rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
-{
-       struct dn_route *rt = dn_rt_cache_get_first(seq);
-
-       if (rt) {
-               while (*pos && (rt = dn_rt_cache_get_next(seq, rt)))
-                       --*pos;
-       }
-       return *pos ? NULL : rt;
-}
-
-static void *dn_rt_cache_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-       struct dn_route *rt = dn_rt_cache_get_next(seq, v);
-       ++*pos;
-       return rt;
-}
-
-static void dn_rt_cache_seq_stop(struct seq_file *seq, void *v)
-{
-       if (v)
-               rcu_read_unlock_bh();
-}
-
-static int dn_rt_cache_seq_show(struct seq_file *seq, void *v)
-{
-       struct dn_route *rt = v;
-       char buf1[DN_ASCBUF_LEN], buf2[DN_ASCBUF_LEN];
-
-       seq_printf(seq, "%-8s %-7s %-7s %04d %04d %04d\n",
-                  rt->dst.dev ? rt->dst.dev->name : "*",
-                  dn_addr2asc(le16_to_cpu(rt->rt_daddr), buf1),
-                  dn_addr2asc(le16_to_cpu(rt->rt_saddr), buf2),
-                  atomic_read(&rt->dst.__refcnt),
-                  rt->dst.__use, 0);
-       return 0;
-}
-
-static const struct seq_operations dn_rt_cache_seq_ops = {
-       .start  = dn_rt_cache_seq_start,
-       .next   = dn_rt_cache_seq_next,
-       .stop   = dn_rt_cache_seq_stop,
-       .show   = dn_rt_cache_seq_show,
-};
-#endif /* CONFIG_PROC_FS */
-
-void __init dn_route_init(void)
-{
-       int i, goal, order;
-
-       dn_dst_ops.kmem_cachep =
-               kmem_cache_create("dn_dst_cache", sizeof(struct dn_route), 0,
-                                 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-       dst_entries_init(&dn_dst_ops);
-       timer_setup(&dn_route_timer, dn_dst_check_expire, 0);
-       dn_route_timer.expires = jiffies + decnet_dst_gc_interval * HZ;
-       add_timer(&dn_route_timer);
-
-       goal = totalram_pages() >> (26 - PAGE_SHIFT);
-
-       for (order = 0; (1UL << order) < goal; order++)
-               /* NOTHING */;
-
-       /*
-        * Only want 1024 entries max, since the table is very, very unlikely
-        * to be larger than that.
-        */
-       while (order && ((((1UL << order) * PAGE_SIZE) /
-                               sizeof(struct dn_rt_hash_bucket)) >= 2048))
-               order--;
-
-       do {
-               dn_rt_hash_mask = (1UL << order) * PAGE_SIZE /
-                       sizeof(struct dn_rt_hash_bucket);
-               while (dn_rt_hash_mask & (dn_rt_hash_mask - 1))
-                       dn_rt_hash_mask--;
-               dn_rt_hash_table = (struct dn_rt_hash_bucket *)
-                       __get_free_pages(GFP_ATOMIC, order);
-       } while (dn_rt_hash_table == NULL && --order > 0);
-
-       if (!dn_rt_hash_table)
-               panic("Failed to allocate DECnet route cache hash table\n");
-
-       printk(KERN_INFO
-               "DECnet: Routing cache hash table of %u buckets, %ldKbytes\n",
-               dn_rt_hash_mask,
-               (long)(dn_rt_hash_mask*sizeof(struct dn_rt_hash_bucket))/1024);
-
-       dn_rt_hash_mask--;
-       for (i = 0; i <= dn_rt_hash_mask; i++) {
-               spin_lock_init(&dn_rt_hash_table[i].lock);
-               dn_rt_hash_table[i].chain = NULL;
-       }
-
-       dn_dst_ops.gc_thresh = (dn_rt_hash_mask + 1);
-
-       proc_create_seq_private("decnet_cache", 0444, init_net.proc_net,
-                       &dn_rt_cache_seq_ops,
-                       sizeof(struct dn_rt_cache_iter_state), NULL);
-
-#ifdef CONFIG_DECNET_ROUTER
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_GETROUTE,
-                            dn_cache_getroute, dn_fib_dump, 0);
-#else
-       rtnl_register_module(THIS_MODULE, PF_DECnet, RTM_GETROUTE,
-                            dn_cache_getroute, dn_cache_dump, 0);
-#endif
-}
-
-void __exit dn_route_cleanup(void)
-{
-       del_timer(&dn_route_timer);
-       dn_run_flush(NULL);
-
-       remove_proc_entry("decnet_cache", init_net.proc_net);
-       dst_entries_destroy(&dn_dst_ops);
-}
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
deleted file mode 100644 (file)
index ee73057..0000000
+++ /dev/null
@@ -1,253 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Routing Forwarding Information Base (Rules)
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *              Mostly copied from Alexey Kuznetsov's ipv4/fib_rules.c
- *
- *
- * Changes:
- *              Steve Whitehouse <steve@chygwyn.com>
- *              Updated for Thomas Graf's generic rules
- *
- */
-#include <linux/net.h>
-#include <linux/init.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <linux/list.h>
-#include <linux/rcupdate.h>
-#include <linux/export.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/fib_rules.h>
-#include <net/dn.h>
-#include <net/dn_fib.h>
-#include <net/dn_neigh.h>
-#include <net/dn_dev.h>
-#include <net/dn_route.h>
-
-static struct fib_rules_ops *dn_fib_rules_ops;
-
-struct dn_fib_rule
-{
-       struct fib_rule         common;
-       unsigned char           dst_len;
-       unsigned char           src_len;
-       __le16                  src;
-       __le16                  srcmask;
-       __le16                  dst;
-       __le16                  dstmask;
-       __le16                  srcmap;
-       u8                      flags;
-};
-
-
-int dn_fib_lookup(struct flowidn *flp, struct dn_fib_res *res)
-{
-       struct fib_lookup_arg arg = {
-               .result = res,
-       };
-       int err;
-
-       err = fib_rules_lookup(dn_fib_rules_ops,
-                              flowidn_to_flowi(flp), 0, &arg);
-       res->r = arg.rule;
-
-       return err;
-}
-
-static int dn_fib_rule_action(struct fib_rule *rule, struct flowi *flp,
-                             int flags, struct fib_lookup_arg *arg)
-{
-       struct flowidn *fld = &flp->u.dn;
-       int err = -EAGAIN;
-       struct dn_fib_table *tbl;
-
-       switch(rule->action) {
-       case FR_ACT_TO_TBL:
-               break;
-
-       case FR_ACT_UNREACHABLE:
-               err = -ENETUNREACH;
-               goto errout;
-
-       case FR_ACT_PROHIBIT:
-               err = -EACCES;
-               goto errout;
-
-       case FR_ACT_BLACKHOLE:
-       default:
-               err = -EINVAL;
-               goto errout;
-       }
-
-       tbl = dn_fib_get_table(rule->table, 0);
-       if (tbl == NULL)
-               goto errout;
-
-       err = tbl->lookup(tbl, fld, (struct dn_fib_res *)arg->result);
-       if (err > 0)
-               err = -EAGAIN;
-errout:
-       return err;
-}
-
-static int dn_fib_rule_match(struct fib_rule *rule, struct flowi *fl, int flags)
-{
-       struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
-       struct flowidn *fld = &fl->u.dn;
-       __le16 daddr = fld->daddr;
-       __le16 saddr = fld->saddr;
-
-       if (((saddr ^ r->src) & r->srcmask) ||
-           ((daddr ^ r->dst) & r->dstmask))
-               return 0;
-
-       return 1;
-}
-
-static int dn_fib_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
-                                struct fib_rule_hdr *frh,
-                                struct nlattr **tb,
-                                struct netlink_ext_ack *extack)
-{
-       int err = -EINVAL;
-       struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
-
-       if (frh->tos) {
-               NL_SET_ERR_MSG(extack, "Invalid tos value");
-               goto  errout;
-       }
-
-       if (rule->table == RT_TABLE_UNSPEC) {
-               if (rule->action == FR_ACT_TO_TBL) {
-                       struct dn_fib_table *table;
-
-                       table = dn_fib_empty_table();
-                       if (table == NULL) {
-                               err = -ENOBUFS;
-                               goto errout;
-                       }
-
-                       rule->table = table->n;
-               }
-       }
-
-       if (frh->src_len)
-               r->src = nla_get_le16(tb[FRA_SRC]);
-
-       if (frh->dst_len)
-               r->dst = nla_get_le16(tb[FRA_DST]);
-
-       r->src_len = frh->src_len;
-       r->srcmask = dnet_make_mask(r->src_len);
-       r->dst_len = frh->dst_len;
-       r->dstmask = dnet_make_mask(r->dst_len);
-       err = 0;
-errout:
-       return err;
-}
-
-static int dn_fib_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
-                              struct nlattr **tb)
-{
-       struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
-
-       if (frh->src_len && (r->src_len != frh->src_len))
-               return 0;
-
-       if (frh->dst_len && (r->dst_len != frh->dst_len))
-               return 0;
-
-       if (frh->src_len && (r->src != nla_get_le16(tb[FRA_SRC])))
-               return 0;
-
-       if (frh->dst_len && (r->dst != nla_get_le16(tb[FRA_DST])))
-               return 0;
-
-       return 1;
-}
-
-unsigned int dnet_addr_type(__le16 addr)
-{
-       struct flowidn fld = { .daddr = addr };
-       struct dn_fib_res res;
-       unsigned int ret = RTN_UNICAST;
-       struct dn_fib_table *tb = dn_fib_get_table(RT_TABLE_LOCAL, 0);
-
-       res.r = NULL;
-
-       if (tb) {
-               if (!tb->lookup(tb, &fld, &res)) {
-                       ret = res.type;
-                       dn_fib_res_put(&res);
-               }
-       }
-       return ret;
-}
-
-static int dn_fib_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
-                           struct fib_rule_hdr *frh)
-{
-       struct dn_fib_rule *r = (struct dn_fib_rule *)rule;
-
-       frh->dst_len = r->dst_len;
-       frh->src_len = r->src_len;
-       frh->tos = 0;
-
-       if ((r->dst_len &&
-            nla_put_le16(skb, FRA_DST, r->dst)) ||
-           (r->src_len &&
-            nla_put_le16(skb, FRA_SRC, r->src)))
-               goto nla_put_failure;
-       return 0;
-
-nla_put_failure:
-       return -ENOBUFS;
-}
-
-static void dn_fib_rule_flush_cache(struct fib_rules_ops *ops)
-{
-       dn_rt_cache_flush(-1);
-}
-
-static const struct fib_rules_ops __net_initconst dn_fib_rules_ops_template = {
-       .family         = AF_DECnet,
-       .rule_size      = sizeof(struct dn_fib_rule),
-       .addr_size      = sizeof(u16),
-       .action         = dn_fib_rule_action,
-       .match          = dn_fib_rule_match,
-       .configure      = dn_fib_rule_configure,
-       .compare        = dn_fib_rule_compare,
-       .fill           = dn_fib_rule_fill,
-       .flush_cache    = dn_fib_rule_flush_cache,
-       .nlgroup        = RTNLGRP_DECnet_RULE,
-       .owner          = THIS_MODULE,
-       .fro_net        = &init_net,
-};
-
-void __init dn_fib_rules_init(void)
-{
-       dn_fib_rules_ops =
-               fib_rules_register(&dn_fib_rules_ops_template, &init_net);
-       BUG_ON(IS_ERR(dn_fib_rules_ops));
-       BUG_ON(fib_default_rule_add(dn_fib_rules_ops, 0x7fff,
-                                   RT_TABLE_MAIN, 0));
-}
-
-void __exit dn_fib_rules_cleanup(void)
-{
-       rtnl_lock();
-       fib_rules_unregister(dn_fib_rules_ops);
-       rtnl_unlock();
-       rcu_barrier();
-}
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
deleted file mode 100644 (file)
index 4086f9c..0000000
+++ /dev/null
@@ -1,929 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Routing Forwarding Information Base (Routing Tables)
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *              Mostly copied from the IPv4 routing code
- *
- *
- * Changes:
- *
- */
-#include <linux/string.h>
-#include <linux/net.h>
-#include <linux/socket.h>
-#include <linux/slab.h>
-#include <linux/sockios.h>
-#include <linux/init.h>
-#include <linux/skbuff.h>
-#include <linux/rtnetlink.h>
-#include <linux/proc_fs.h>
-#include <linux/netdevice.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <linux/atomic.h>
-#include <linux/uaccess.h>
-#include <linux/route.h> /* RTF_xxx */
-#include <net/neighbour.h>
-#include <net/netlink.h>
-#include <net/tcp.h>
-#include <net/dst.h>
-#include <net/flow.h>
-#include <net/fib_rules.h>
-#include <net/dn.h>
-#include <net/dn_route.h>
-#include <net/dn_fib.h>
-#include <net/dn_neigh.h>
-#include <net/dn_dev.h>
-
-struct dn_zone
-{
-       struct dn_zone          *dz_next;
-       struct dn_fib_node      **dz_hash;
-       int                     dz_nent;
-       int                     dz_divisor;
-       u32                     dz_hashmask;
-#define DZ_HASHMASK(dz)        ((dz)->dz_hashmask)
-       int                     dz_order;
-       __le16                  dz_mask;
-#define DZ_MASK(dz)    ((dz)->dz_mask)
-};
-
-struct dn_hash
-{
-       struct dn_zone  *dh_zones[17];
-       struct dn_zone  *dh_zone_list;
-};
-
-#define dz_key_0(key)          ((key).datum = 0)
-
-#define for_nexthops(fi) { int nhsel; const struct dn_fib_nh *nh;\
-       for(nhsel = 0, nh = (fi)->fib_nh; nhsel < (fi)->fib_nhs; nh++, nhsel++)
-
-#define endfor_nexthops(fi) }
-
-#define DN_MAX_DIVISOR 1024
-#define DN_S_ZOMBIE 1
-#define DN_S_ACCESSED 2
-
-#define DN_FIB_SCAN(f, fp) \
-for( ; ((f) = *(fp)) != NULL; (fp) = &(f)->fn_next)
-
-#define DN_FIB_SCAN_KEY(f, fp, key) \
-for( ; ((f) = *(fp)) != NULL && dn_key_eq((f)->fn_key, (key)); (fp) = &(f)->fn_next)
-
-#define RT_TABLE_MIN 1
-#define DN_FIB_TABLE_HASHSZ 256
-static struct hlist_head dn_fib_table_hash[DN_FIB_TABLE_HASHSZ];
-static DEFINE_RWLOCK(dn_fib_tables_lock);
-
-static struct kmem_cache *dn_hash_kmem __read_mostly;
-static int dn_fib_hash_zombies;
-
-static inline dn_fib_idx_t dn_hash(dn_fib_key_t key, struct dn_zone *dz)
-{
-       u16 h = le16_to_cpu(key.datum)>>(16 - dz->dz_order);
-       h ^= (h >> 10);
-       h ^= (h >> 6);
-       h &= DZ_HASHMASK(dz);
-       return *(dn_fib_idx_t *)&h;
-}
-
-static inline dn_fib_key_t dz_key(__le16 dst, struct dn_zone *dz)
-{
-       dn_fib_key_t k;
-       k.datum = dst & DZ_MASK(dz);
-       return k;
-}
-
-static inline struct dn_fib_node **dn_chain_p(dn_fib_key_t key, struct dn_zone *dz)
-{
-       return &dz->dz_hash[dn_hash(key, dz).datum];
-}
-
-static inline struct dn_fib_node *dz_chain(dn_fib_key_t key, struct dn_zone *dz)
-{
-       return dz->dz_hash[dn_hash(key, dz).datum];
-}
-
-static inline int dn_key_eq(dn_fib_key_t a, dn_fib_key_t b)
-{
-       return a.datum == b.datum;
-}
-
-static inline int dn_key_leq(dn_fib_key_t a, dn_fib_key_t b)
-{
-       return a.datum <= b.datum;
-}
-
-static inline void dn_rebuild_zone(struct dn_zone *dz,
-                                  struct dn_fib_node **old_ht,
-                                  int old_divisor)
-{
-       struct dn_fib_node *f, **fp, *next;
-       int i;
-
-       for(i = 0; i < old_divisor; i++) {
-               for(f = old_ht[i]; f; f = next) {
-                       next = f->fn_next;
-                       for(fp = dn_chain_p(f->fn_key, dz);
-                               *fp && dn_key_leq((*fp)->fn_key, f->fn_key);
-                               fp = &(*fp)->fn_next)
-                               /* NOTHING */;
-                       f->fn_next = *fp;
-                       *fp = f;
-               }
-       }
-}
-
-static void dn_rehash_zone(struct dn_zone *dz)
-{
-       struct dn_fib_node **ht, **old_ht;
-       int old_divisor, new_divisor;
-       u32 new_hashmask;
-
-       old_divisor = dz->dz_divisor;
-
-       switch (old_divisor) {
-       case 16:
-               new_divisor = 256;
-               new_hashmask = 0xFF;
-               break;
-       default:
-               printk(KERN_DEBUG "DECnet: dn_rehash_zone: BUG! %d\n",
-                      old_divisor);
-               fallthrough;
-       case 256:
-               new_divisor = 1024;
-               new_hashmask = 0x3FF;
-               break;
-       }
-
-       ht = kcalloc(new_divisor, sizeof(struct dn_fib_node*), GFP_KERNEL);
-       if (ht == NULL)
-               return;
-
-       write_lock_bh(&dn_fib_tables_lock);
-       old_ht = dz->dz_hash;
-       dz->dz_hash = ht;
-       dz->dz_hashmask = new_hashmask;
-       dz->dz_divisor = new_divisor;
-       dn_rebuild_zone(dz, old_ht, old_divisor);
-       write_unlock_bh(&dn_fib_tables_lock);
-       kfree(old_ht);
-}
-
-static void dn_free_node(struct dn_fib_node *f)
-{
-       dn_fib_release_info(DN_FIB_INFO(f));
-       kmem_cache_free(dn_hash_kmem, f);
-}
-
-
-static struct dn_zone *dn_new_zone(struct dn_hash *table, int z)
-{
-       int i;
-       struct dn_zone *dz = kzalloc(sizeof(struct dn_zone), GFP_KERNEL);
-       if (!dz)
-               return NULL;
-
-       if (z) {
-               dz->dz_divisor = 16;
-               dz->dz_hashmask = 0x0F;
-       } else {
-               dz->dz_divisor = 1;
-               dz->dz_hashmask = 0;
-       }
-
-       dz->dz_hash = kcalloc(dz->dz_divisor, sizeof(struct dn_fib_node *), GFP_KERNEL);
-       if (!dz->dz_hash) {
-               kfree(dz);
-               return NULL;
-       }
-
-       dz->dz_order = z;
-       dz->dz_mask = dnet_make_mask(z);
-
-       for(i = z + 1; i <= 16; i++)
-               if (table->dh_zones[i])
-                       break;
-
-       write_lock_bh(&dn_fib_tables_lock);
-       if (i>16) {
-               dz->dz_next = table->dh_zone_list;
-               table->dh_zone_list = dz;
-       } else {
-               dz->dz_next = table->dh_zones[i]->dz_next;
-               table->dh_zones[i]->dz_next = dz;
-       }
-       table->dh_zones[z] = dz;
-       write_unlock_bh(&dn_fib_tables_lock);
-       return dz;
-}
-
-
-static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct nlattr *attrs[], struct dn_fib_info *fi)
-{
-       struct rtnexthop *nhp;
-       int nhlen;
-
-       if (attrs[RTA_PRIORITY] &&
-           nla_get_u32(attrs[RTA_PRIORITY]) != fi->fib_priority)
-               return 1;
-
-       if (attrs[RTA_OIF] || attrs[RTA_GATEWAY]) {
-               if ((!attrs[RTA_OIF] || nla_get_u32(attrs[RTA_OIF]) == fi->fib_nh->nh_oif) &&
-                   (!attrs[RTA_GATEWAY]  || nla_get_le16(attrs[RTA_GATEWAY]) != fi->fib_nh->nh_gw))
-                       return 0;
-               return 1;
-       }
-
-       if (!attrs[RTA_MULTIPATH])
-               return 0;
-
-       nhp = nla_data(attrs[RTA_MULTIPATH]);
-       nhlen = nla_len(attrs[RTA_MULTIPATH]);
-
-       for_nexthops(fi) {
-               int attrlen = nhlen - sizeof(struct rtnexthop);
-               __le16 gw;
-
-               if (attrlen < 0 || (nhlen -= nhp->rtnh_len) < 0)
-                       return -EINVAL;
-               if (nhp->rtnh_ifindex && nhp->rtnh_ifindex != nh->nh_oif)
-                       return 1;
-               if (attrlen) {
-                       struct nlattr *gw_attr;
-
-                       gw_attr = nla_find((struct nlattr *) (nhp + 1), attrlen, RTA_GATEWAY);
-                       gw = gw_attr ? nla_get_le16(gw_attr) : 0;
-
-                       if (gw && gw != nh->nh_gw)
-                               return 1;
-               }
-               nhp = RTNH_NEXT(nhp);
-       } endfor_nexthops(fi);
-
-       return 0;
-}
-
-static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi)
-{
-       size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
-                        + nla_total_size(4) /* RTA_TABLE */
-                        + nla_total_size(2) /* RTA_DST */
-                        + nla_total_size(4) /* RTA_PRIORITY */
-                        + nla_total_size(TCP_CA_NAME_MAX); /* RTAX_CC_ALGO */
-
-       /* space for nested metrics */
-       payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
-
-       if (fi->fib_nhs) {
-               /* Also handles the special case fib_nhs == 1 */
-
-               /* each nexthop is packed in an attribute */
-               size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
-
-               /* may contain a gateway attribute */
-               nhsize += nla_total_size(4);
-
-               /* all nexthops are packed in a nested attribute */
-               payload += nla_total_size(fi->fib_nhs * nhsize);
-       }
-
-       return payload;
-}
-
-static int dn_fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
-                       u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
-                       struct dn_fib_info *fi, unsigned int flags)
-{
-       struct rtmsg *rtm;
-       struct nlmsghdr *nlh;
-
-       nlh = nlmsg_put(skb, portid, seq, event, sizeof(*rtm), flags);
-       if (!nlh)
-               return -EMSGSIZE;
-
-       rtm = nlmsg_data(nlh);
-       rtm->rtm_family = AF_DECnet;
-       rtm->rtm_dst_len = dst_len;
-       rtm->rtm_src_len = 0;
-       rtm->rtm_tos = 0;
-       rtm->rtm_table = tb_id;
-       rtm->rtm_flags = fi->fib_flags;
-       rtm->rtm_scope = scope;
-       rtm->rtm_type  = type;
-       rtm->rtm_protocol = fi->fib_protocol;
-
-       if (nla_put_u32(skb, RTA_TABLE, tb_id) < 0)
-               goto errout;
-
-       if (rtm->rtm_dst_len &&
-           nla_put(skb, RTA_DST, 2, dst) < 0)
-               goto errout;
-
-       if (fi->fib_priority &&
-           nla_put_u32(skb, RTA_PRIORITY, fi->fib_priority) < 0)
-               goto errout;
-
-       if (rtnetlink_put_metrics(skb, fi->fib_metrics) < 0)
-               goto errout;
-
-       if (fi->fib_nhs == 1) {
-               if (fi->fib_nh->nh_gw &&
-                   nla_put_le16(skb, RTA_GATEWAY, fi->fib_nh->nh_gw) < 0)
-                       goto errout;
-
-               if (fi->fib_nh->nh_oif &&
-                   nla_put_u32(skb, RTA_OIF, fi->fib_nh->nh_oif) < 0)
-                       goto errout;
-       }
-
-       if (fi->fib_nhs > 1) {
-               struct rtnexthop *nhp;
-               struct nlattr *mp_head;
-
-               mp_head = nla_nest_start_noflag(skb, RTA_MULTIPATH);
-               if (!mp_head)
-                       goto errout;
-
-               for_nexthops(fi) {
-                       if (!(nhp = nla_reserve_nohdr(skb, sizeof(*nhp))))
-                               goto errout;
-
-                       nhp->rtnh_flags = nh->nh_flags & 0xFF;
-                       nhp->rtnh_hops = nh->nh_weight - 1;
-                       nhp->rtnh_ifindex = nh->nh_oif;
-
-                       if (nh->nh_gw &&
-                           nla_put_le16(skb, RTA_GATEWAY, nh->nh_gw) < 0)
-                               goto errout;
-
-                       nhp->rtnh_len = skb_tail_pointer(skb) - (unsigned char *)nhp;
-               } endfor_nexthops(fi);
-
-               nla_nest_end(skb, mp_head);
-       }
-
-       nlmsg_end(skb, nlh);
-       return 0;
-
-errout:
-       nlmsg_cancel(skb, nlh);
-       return -EMSGSIZE;
-}
-
-
-static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
-                       struct nlmsghdr *nlh, struct netlink_skb_parms *req)
-{
-       struct sk_buff *skb;
-       u32 portid = req ? req->portid : 0;
-       int err = -ENOBUFS;
-
-       skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f)), GFP_KERNEL);
-       if (skb == NULL)
-               goto errout;
-
-       err = dn_fib_dump_info(skb, portid, nlh->nlmsg_seq, event, tb_id,
-                              f->fn_type, f->fn_scope, &f->fn_key, z,
-                              DN_FIB_INFO(f), 0);
-       if (err < 0) {
-               /* -EMSGSIZE implies BUG in dn_fib_nlmsg_size() */
-               WARN_ON(err == -EMSGSIZE);
-               kfree_skb(skb);
-               goto errout;
-       }
-       rtnl_notify(skb, &init_net, portid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
-       return;
-errout:
-       if (err < 0)
-               rtnl_set_sk_err(&init_net, RTNLGRP_DECnet_ROUTE, err);
-}
-
-static __inline__ int dn_hash_dump_bucket(struct sk_buff *skb,
-                               struct netlink_callback *cb,
-                               struct dn_fib_table *tb,
-                               struct dn_zone *dz,
-                               struct dn_fib_node *f)
-{
-       int i, s_i;
-
-       s_i = cb->args[4];
-       for(i = 0; f; i++, f = f->fn_next) {
-               if (i < s_i)
-                       continue;
-               if (f->fn_state & DN_S_ZOMBIE)
-                       continue;
-               if (dn_fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
-                               cb->nlh->nlmsg_seq,
-                               RTM_NEWROUTE,
-                               tb->n,
-                               (f->fn_state & DN_S_ZOMBIE) ? 0 : f->fn_type,
-                               f->fn_scope, &f->fn_key, dz->dz_order,
-                               f->fn_info, NLM_F_MULTI) < 0) {
-                       cb->args[4] = i;
-                       return -1;
-               }
-       }
-       cb->args[4] = i;
-       return skb->len;
-}
-
-static __inline__ int dn_hash_dump_zone(struct sk_buff *skb,
-                               struct netlink_callback *cb,
-                               struct dn_fib_table *tb,
-                               struct dn_zone *dz)
-{
-       int h, s_h;
-
-       s_h = cb->args[3];
-       for(h = 0; h < dz->dz_divisor; h++) {
-               if (h < s_h)
-                       continue;
-               if (h > s_h)
-                       memset(&cb->args[4], 0, sizeof(cb->args) - 4*sizeof(cb->args[0]));
-               if (dz->dz_hash == NULL || dz->dz_hash[h] == NULL)
-                       continue;
-               if (dn_hash_dump_bucket(skb, cb, tb, dz, dz->dz_hash[h]) < 0) {
-                       cb->args[3] = h;
-                       return -1;
-               }
-       }
-       cb->args[3] = h;
-       return skb->len;
-}
-
-static int dn_fib_table_dump(struct dn_fib_table *tb, struct sk_buff *skb,
-                               struct netlink_callback *cb)
-{
-       int m, s_m;
-       struct dn_zone *dz;
-       struct dn_hash *table = (struct dn_hash *)tb->data;
-
-       s_m = cb->args[2];
-       read_lock(&dn_fib_tables_lock);
-       for(dz = table->dh_zone_list, m = 0; dz; dz = dz->dz_next, m++) {
-               if (m < s_m)
-                       continue;
-               if (m > s_m)
-                       memset(&cb->args[3], 0, sizeof(cb->args) - 3*sizeof(cb->args[0]));
-
-               if (dn_hash_dump_zone(skb, cb, tb, dz) < 0) {
-                       cb->args[2] = m;
-                       read_unlock(&dn_fib_tables_lock);
-                       return -1;
-               }
-       }
-       read_unlock(&dn_fib_tables_lock);
-       cb->args[2] = m;
-
-       return skb->len;
-}
-
-int dn_fib_dump(struct sk_buff *skb, struct netlink_callback *cb)
-{
-       struct net *net = sock_net(skb->sk);
-       unsigned int h, s_h;
-       unsigned int e = 0, s_e;
-       struct dn_fib_table *tb;
-       int dumped = 0;
-
-       if (!net_eq(net, &init_net))
-               return 0;
-
-       if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
-               ((struct rtmsg *)nlmsg_data(cb->nlh))->rtm_flags&RTM_F_CLONED)
-                       return dn_cache_dump(skb, cb);
-
-       s_h = cb->args[0];
-       s_e = cb->args[1];
-
-       for (h = s_h; h < DN_FIB_TABLE_HASHSZ; h++, s_h = 0) {
-               e = 0;
-               hlist_for_each_entry(tb, &dn_fib_table_hash[h], hlist) {
-                       if (e < s_e)
-                               goto next;
-                       if (dumped)
-                               memset(&cb->args[2], 0, sizeof(cb->args) -
-                                                2 * sizeof(cb->args[0]));
-                       if (tb->dump(tb, skb, cb) < 0)
-                               goto out;
-                       dumped = 1;
-next:
-                       e++;
-               }
-       }
-out:
-       cb->args[1] = e;
-       cb->args[0] = h;
-
-       return skb->len;
-}
-
-static int dn_fib_table_insert(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
-                              struct nlmsghdr *n, struct netlink_skb_parms *req)
-{
-       struct dn_hash *table = (struct dn_hash *)tb->data;
-       struct dn_fib_node *new_f, *f, **fp, **del_fp;
-       struct dn_zone *dz;
-       struct dn_fib_info *fi;
-       int z = r->rtm_dst_len;
-       int type = r->rtm_type;
-       dn_fib_key_t key;
-       int err;
-
-       if (z > 16)
-               return -EINVAL;
-
-       dz = table->dh_zones[z];
-       if (!dz && !(dz = dn_new_zone(table, z)))
-               return -ENOBUFS;
-
-       dz_key_0(key);
-       if (attrs[RTA_DST]) {
-               __le16 dst = nla_get_le16(attrs[RTA_DST]);
-               if (dst & ~DZ_MASK(dz))
-                       return -EINVAL;
-               key = dz_key(dst, dz);
-       }
-
-       if ((fi = dn_fib_create_info(r, attrs, n, &err)) == NULL)
-               return err;
-
-       if (dz->dz_nent > (dz->dz_divisor << 2) &&
-                       dz->dz_divisor > DN_MAX_DIVISOR &&
-                       (z==16 || (1<<z) > dz->dz_divisor))
-               dn_rehash_zone(dz);
-
-       fp = dn_chain_p(key, dz);
-
-       DN_FIB_SCAN(f, fp) {
-               if (dn_key_leq(key, f->fn_key))
-                       break;
-       }
-
-       del_fp = NULL;
-
-       if (f && (f->fn_state & DN_S_ZOMBIE) &&
-                       dn_key_eq(f->fn_key, key)) {
-               del_fp = fp;
-               fp = &f->fn_next;
-               f = *fp;
-               goto create;
-       }
-
-       DN_FIB_SCAN_KEY(f, fp, key) {
-               if (fi->fib_priority <= DN_FIB_INFO(f)->fib_priority)
-                       break;
-       }
-
-       if (f && dn_key_eq(f->fn_key, key) &&
-                       fi->fib_priority == DN_FIB_INFO(f)->fib_priority) {
-               struct dn_fib_node **ins_fp;
-
-               err = -EEXIST;
-               if (n->nlmsg_flags & NLM_F_EXCL)
-                       goto out;
-
-               if (n->nlmsg_flags & NLM_F_REPLACE) {
-                       del_fp = fp;
-                       fp = &f->fn_next;
-                       f = *fp;
-                       goto replace;
-               }
-
-               ins_fp = fp;
-               err = -EEXIST;
-
-               DN_FIB_SCAN_KEY(f, fp, key) {
-                       if (fi->fib_priority != DN_FIB_INFO(f)->fib_priority)
-                               break;
-                       if (f->fn_type == type &&
-                           f->fn_scope == r->rtm_scope &&
-                           DN_FIB_INFO(f) == fi)
-                               goto out;
-               }
-
-               if (!(n->nlmsg_flags & NLM_F_APPEND)) {
-                       fp = ins_fp;
-                       f = *fp;
-               }
-       }
-
-create:
-       err = -ENOENT;
-       if (!(n->nlmsg_flags & NLM_F_CREATE))
-               goto out;
-
-replace:
-       err = -ENOBUFS;
-       new_f = kmem_cache_zalloc(dn_hash_kmem, GFP_KERNEL);
-       if (new_f == NULL)
-               goto out;
-
-       new_f->fn_key = key;
-       new_f->fn_type = type;
-       new_f->fn_scope = r->rtm_scope;
-       DN_FIB_INFO(new_f) = fi;
-
-       new_f->fn_next = f;
-       write_lock_bh(&dn_fib_tables_lock);
-       *fp = new_f;
-       write_unlock_bh(&dn_fib_tables_lock);
-       dz->dz_nent++;
-
-       if (del_fp) {
-               f = *del_fp;
-               write_lock_bh(&dn_fib_tables_lock);
-               *del_fp = f->fn_next;
-               write_unlock_bh(&dn_fib_tables_lock);
-
-               if (!(f->fn_state & DN_S_ZOMBIE))
-                       dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
-               if (f->fn_state & DN_S_ACCESSED)
-                       dn_rt_cache_flush(-1);
-               dn_free_node(f);
-               dz->dz_nent--;
-       } else {
-               dn_rt_cache_flush(-1);
-       }
-
-       dn_rtmsg_fib(RTM_NEWROUTE, new_f, z, tb->n, n, req);
-
-       return 0;
-out:
-       dn_fib_release_info(fi);
-       return err;
-}
-
-
-static int dn_fib_table_delete(struct dn_fib_table *tb, struct rtmsg *r, struct nlattr *attrs[],
-                              struct nlmsghdr *n, struct netlink_skb_parms *req)
-{
-       struct dn_hash *table = (struct dn_hash*)tb->data;
-       struct dn_fib_node **fp, **del_fp, *f;
-       int z = r->rtm_dst_len;
-       struct dn_zone *dz;
-       dn_fib_key_t key;
-       int matched;
-
-
-       if (z > 16)
-               return -EINVAL;
-
-       if ((dz = table->dh_zones[z]) == NULL)
-               return -ESRCH;
-
-       dz_key_0(key);
-       if (attrs[RTA_DST]) {
-               __le16 dst = nla_get_le16(attrs[RTA_DST]);
-               if (dst & ~DZ_MASK(dz))
-                       return -EINVAL;
-               key = dz_key(dst, dz);
-       }
-
-       fp = dn_chain_p(key, dz);
-
-       DN_FIB_SCAN(f, fp) {
-               if (dn_key_eq(f->fn_key, key))
-                       break;
-               if (dn_key_leq(key, f->fn_key))
-                       return -ESRCH;
-       }
-
-       matched = 0;
-       del_fp = NULL;
-       DN_FIB_SCAN_KEY(f, fp, key) {
-               struct dn_fib_info *fi = DN_FIB_INFO(f);
-
-               if (f->fn_state & DN_S_ZOMBIE)
-                       return -ESRCH;
-
-               matched++;
-
-               if (del_fp == NULL &&
-                               (!r->rtm_type || f->fn_type == r->rtm_type) &&
-                               (r->rtm_scope == RT_SCOPE_NOWHERE || f->fn_scope == r->rtm_scope) &&
-                               (!r->rtm_protocol ||
-                                       fi->fib_protocol == r->rtm_protocol) &&
-                               dn_fib_nh_match(r, n, attrs, fi) == 0)
-                       del_fp = fp;
-       }
-
-       if (del_fp) {
-               f = *del_fp;
-               dn_rtmsg_fib(RTM_DELROUTE, f, z, tb->n, n, req);
-
-               if (matched != 1) {
-                       write_lock_bh(&dn_fib_tables_lock);
-                       *del_fp = f->fn_next;
-                       write_unlock_bh(&dn_fib_tables_lock);
-
-                       if (f->fn_state & DN_S_ACCESSED)
-                               dn_rt_cache_flush(-1);
-                       dn_free_node(f);
-                       dz->dz_nent--;
-               } else {
-                       f->fn_state |= DN_S_ZOMBIE;
-                       if (f->fn_state & DN_S_ACCESSED) {
-                               f->fn_state &= ~DN_S_ACCESSED;
-                               dn_rt_cache_flush(-1);
-                       }
-                       if (++dn_fib_hash_zombies > 128)
-                               dn_fib_flush();
-               }
-
-               return 0;
-       }
-
-       return -ESRCH;
-}
-
-static inline int dn_flush_list(struct dn_fib_node **fp, int z, struct dn_hash *table)
-{
-       int found = 0;
-       struct dn_fib_node *f;
-
-       while((f = *fp) != NULL) {
-               struct dn_fib_info *fi = DN_FIB_INFO(f);
-
-               if (fi && ((f->fn_state & DN_S_ZOMBIE) || (fi->fib_flags & RTNH_F_DEAD))) {
-                       write_lock_bh(&dn_fib_tables_lock);
-                       *fp = f->fn_next;
-                       write_unlock_bh(&dn_fib_tables_lock);
-
-                       dn_free_node(f);
-                       found++;
-                       continue;
-               }
-               fp = &f->fn_next;
-       }
-
-       return found;
-}
-
-static int dn_fib_table_flush(struct dn_fib_table *tb)
-{
-       struct dn_hash *table = (struct dn_hash *)tb->data;
-       struct dn_zone *dz;
-       int found = 0;
-
-       dn_fib_hash_zombies = 0;
-       for(dz = table->dh_zone_list; dz; dz = dz->dz_next) {
-               int i;
-               int tmp = 0;
-               for(i = dz->dz_divisor-1; i >= 0; i--)
-                       tmp += dn_flush_list(&dz->dz_hash[i], dz->dz_order, table);
-               dz->dz_nent -= tmp;
-               found += tmp;
-       }
-
-       return found;
-}
-
-static int dn_fib_table_lookup(struct dn_fib_table *tb, const struct flowidn *flp, struct dn_fib_res *res)
-{
-       int err;
-       struct dn_zone *dz;
-       struct dn_hash *t = (struct dn_hash *)tb->data;
-
-       read_lock(&dn_fib_tables_lock);
-       for(dz = t->dh_zone_list; dz; dz = dz->dz_next) {
-               struct dn_fib_node *f;
-               dn_fib_key_t k = dz_key(flp->daddr, dz);
-
-               for(f = dz_chain(k, dz); f; f = f->fn_next) {
-                       if (!dn_key_eq(k, f->fn_key)) {
-                               if (dn_key_leq(k, f->fn_key))
-                                       break;
-                               else
-                                       continue;
-                       }
-
-                       f->fn_state |= DN_S_ACCESSED;
-
-                       if (f->fn_state&DN_S_ZOMBIE)
-                               continue;
-
-                       if (f->fn_scope < flp->flowidn_scope)
-                               continue;
-
-                       err = dn_fib_semantic_match(f->fn_type, DN_FIB_INFO(f), flp, res);
-
-                       if (err == 0) {
-                               res->type = f->fn_type;
-                               res->scope = f->fn_scope;
-                               res->prefixlen = dz->dz_order;
-                               goto out;
-                       }
-                       if (err < 0)
-                               goto out;
-               }
-       }
-       err = 1;
-out:
-       read_unlock(&dn_fib_tables_lock);
-       return err;
-}
-
-
-struct dn_fib_table *dn_fib_get_table(u32 n, int create)
-{
-       struct dn_fib_table *t;
-       unsigned int h;
-
-       if (n < RT_TABLE_MIN)
-               return NULL;
-
-       if (n > RT_TABLE_MAX)
-               return NULL;
-
-       h = n & (DN_FIB_TABLE_HASHSZ - 1);
-       rcu_read_lock();
-       hlist_for_each_entry_rcu(t, &dn_fib_table_hash[h], hlist) {
-               if (t->n == n) {
-                       rcu_read_unlock();
-                       return t;
-               }
-       }
-       rcu_read_unlock();
-
-       if (!create)
-               return NULL;
-
-       if (in_interrupt()) {
-               net_dbg_ratelimited("DECnet: BUG! Attempt to create routing table from interrupt\n");
-               return NULL;
-       }
-
-       t = kzalloc(sizeof(struct dn_fib_table) + sizeof(struct dn_hash),
-                   GFP_KERNEL);
-       if (t == NULL)
-               return NULL;
-
-       t->n = n;
-       t->insert = dn_fib_table_insert;
-       t->delete = dn_fib_table_delete;
-       t->lookup = dn_fib_table_lookup;
-       t->flush  = dn_fib_table_flush;
-       t->dump = dn_fib_table_dump;
-       hlist_add_head_rcu(&t->hlist, &dn_fib_table_hash[h]);
-
-       return t;
-}
-
-struct dn_fib_table *dn_fib_empty_table(void)
-{
-       u32 id;
-
-       for(id = RT_TABLE_MIN; id <= RT_TABLE_MAX; id++)
-               if (dn_fib_get_table(id, 0) == NULL)
-                       return dn_fib_get_table(id, 1);
-       return NULL;
-}
-
-void dn_fib_flush(void)
-{
-       int flushed = 0;
-       struct dn_fib_table *tb;
-       unsigned int h;
-
-       for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
-               hlist_for_each_entry(tb, &dn_fib_table_hash[h], hlist)
-                       flushed += tb->flush(tb);
-       }
-
-       if (flushed)
-               dn_rt_cache_flush(-1);
-}
-
-void __init dn_fib_table_init(void)
-{
-       dn_hash_kmem = kmem_cache_create("dn_fib_info_cache",
-                                       sizeof(struct dn_fib_info),
-                                       0, SLAB_HWCACHE_ALIGN,
-                                       NULL);
-}
-
-void __exit dn_fib_table_cleanup(void)
-{
-       struct dn_fib_table *t;
-       struct hlist_node *next;
-       unsigned int h;
-
-       write_lock(&dn_fib_tables_lock);
-       for (h = 0; h < DN_FIB_TABLE_HASHSZ; h++) {
-               hlist_for_each_entry_safe(t, next, &dn_fib_table_hash[h],
-                                         hlist) {
-                       hlist_del(&t->hlist);
-                       kfree(t);
-               }
-       }
-       write_unlock(&dn_fib_tables_lock);
-}
diff --git a/net/decnet/dn_timer.c b/net/decnet/dn_timer.c
deleted file mode 100644 (file)
index aa41558..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Socket Timer Functions
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *
- *
- * Changes:
- *       Steve Whitehouse      : Made keepalive timer part of the same
- *                               timer idea.
- *       Steve Whitehouse      : Added checks for sk->sock_readers
- *       David S. Miller       : New socket locking
- *       Steve Whitehouse      : Timer grabs socket ref.
- */
-#include <linux/net.h>
-#include <linux/socket.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/timer.h>
-#include <linux/spinlock.h>
-#include <net/sock.h>
-#include <linux/atomic.h>
-#include <linux/jiffies.h>
-#include <net/flow.h>
-#include <net/dn.h>
-
-/*
- * Slow timer is for everything else (n * 500mS)
- */
-
-#define SLOW_INTERVAL (HZ/2)
-
-static void dn_slow_timer(struct timer_list *t);
-
-void dn_start_slow_timer(struct sock *sk)
-{
-       timer_setup(&sk->sk_timer, dn_slow_timer, 0);
-       sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL);
-}
-
-void dn_stop_slow_timer(struct sock *sk)
-{
-       sk_stop_timer(sk, &sk->sk_timer);
-}
-
-static void dn_slow_timer(struct timer_list *t)
-{
-       struct sock *sk = from_timer(sk, t, sk_timer);
-       struct dn_scp *scp = DN_SK(sk);
-
-       bh_lock_sock(sk);
-
-       if (sock_owned_by_user(sk)) {
-               sk_reset_timer(sk, &sk->sk_timer, jiffies + HZ / 10);
-               goto out;
-       }
-
-       /*
-        * The persist timer is the standard slow timer used for retransmits
-        * in both connection establishment and disconnection as well as
-        * in the RUN state. The different states are catered for by changing
-        * the function pointer in the socket. Setting the timer to a value
-        * of zero turns it off. We allow the persist_fxn to turn the
-        * timer off in a permant way by returning non-zero, so that
-        * timer based routines may remove sockets. This is why we have a
-        * sock_hold()/sock_put() around the timer to prevent the socket
-        * going away in the middle.
-        */
-       if (scp->persist && scp->persist_fxn) {
-               if (scp->persist <= SLOW_INTERVAL) {
-                       scp->persist = 0;
-
-                       if (scp->persist_fxn(sk))
-                               goto out;
-               } else {
-                       scp->persist -= SLOW_INTERVAL;
-               }
-       }
-
-       /*
-        * Check for keepalive timeout. After the other timer 'cos if
-        * the previous timer caused a retransmit, we don't need to
-        * do this. scp->stamp is the last time that we sent a packet.
-        * The keepalive function sends a link service packet to the
-        * other end. If it remains unacknowledged, the standard
-        * socket timers will eventually shut the socket down. Each
-        * time we do this, scp->stamp will be updated, thus
-        * we won't try and send another until scp->keepalive has passed
-        * since the last successful transmission.
-        */
-       if (scp->keepalive && scp->keepalive_fxn && (scp->state == DN_RUN)) {
-               if (time_after_eq(jiffies, scp->stamp + scp->keepalive))
-                       scp->keepalive_fxn(sk);
-       }
-
-       sk_reset_timer(sk, &sk->sk_timer, jiffies + SLOW_INTERVAL);
-out:
-       bh_unlock_sock(sk);
-       sock_put(sk);
-}
diff --git a/net/decnet/netfilter/Kconfig b/net/decnet/netfilter/Kconfig
deleted file mode 100644 (file)
index 14ec4ef..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# DECnet netfilter configuration
-#
-
-menu "DECnet: Netfilter Configuration"
-       depends on DECNET && NETFILTER
-       depends on NETFILTER_ADVANCED
-
-config DECNET_NF_GRABULATOR
-       tristate "Routing message grabulator (for userland routing daemon)"
-       help
-         Enable this module if you want to use the userland DECnet routing
-         daemon. You will also need to enable routing support for DECnet
-         unless you just want to monitor routing messages from other nodes.
-
-endmenu
diff --git a/net/decnet/netfilter/Makefile b/net/decnet/netfilter/Makefile
deleted file mode 100644 (file)
index 429c842..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for DECnet netfilter modules
-#
-
-obj-$(CONFIG_DECNET_NF_GRABULATOR) += dn_rtmsg.o
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
deleted file mode 100644 (file)
index 26a9193..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet Routing Message Grabulator
- *
- *              (C) 2000 ChyGwyn Limited  -  https://www.chygwyn.com/
- *
- * Author:      Steven Whitehouse <steve@chygwyn.com>
- */
-#include <linux/module.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/netfilter.h>
-#include <linux/spinlock.h>
-#include <net/netlink.h>
-#include <linux/netfilter_decnet.h>
-
-#include <net/sock.h>
-#include <net/flow.h>
-#include <net/dn.h>
-#include <net/dn_route.h>
-
-static struct sock *dnrmg = NULL;
-
-
-static struct sk_buff *dnrmg_build_message(struct sk_buff *rt_skb, int *errp)
-{
-       struct sk_buff *skb = NULL;
-       size_t size;
-       sk_buff_data_t old_tail;
-       struct nlmsghdr *nlh;
-       unsigned char *ptr;
-       struct nf_dn_rtmsg *rtm;
-
-       size = NLMSG_ALIGN(rt_skb->len) +
-              NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg));
-       skb = nlmsg_new(size, GFP_ATOMIC);
-       if (!skb) {
-               *errp = -ENOMEM;
-               return NULL;
-       }
-       old_tail = skb->tail;
-       nlh = nlmsg_put(skb, 0, 0, 0, size, 0);
-       if (!nlh) {
-               kfree_skb(skb);
-               *errp = -ENOMEM;
-               return NULL;
-       }
-       rtm = (struct nf_dn_rtmsg *)nlmsg_data(nlh);
-       rtm->nfdn_ifindex = rt_skb->dev->ifindex;
-       ptr = NFDN_RTMSG(rtm);
-       skb_copy_from_linear_data(rt_skb, ptr, rt_skb->len);
-       nlh->nlmsg_len = skb->tail - old_tail;
-       return skb;
-}
-
-static void dnrmg_send_peer(struct sk_buff *skb)
-{
-       struct sk_buff *skb2;
-       int status = 0;
-       int group = 0;
-       unsigned char flags = *skb->data;
-
-       switch (flags & DN_RT_CNTL_MSK) {
-       case DN_RT_PKT_L1RT:
-               group = DNRNG_NLGRP_L1;
-               break;
-       case DN_RT_PKT_L2RT:
-               group = DNRNG_NLGRP_L2;
-               break;
-       default:
-               return;
-       }
-
-       skb2 = dnrmg_build_message(skb, &status);
-       if (skb2 == NULL)
-               return;
-       NETLINK_CB(skb2).dst_group = group;
-       netlink_broadcast(dnrmg, skb2, 0, group, GFP_ATOMIC);
-}
-
-
-static unsigned int dnrmg_hook(void *priv,
-                       struct sk_buff *skb,
-                       const struct nf_hook_state *state)
-{
-       dnrmg_send_peer(skb);
-       return NF_ACCEPT;
-}
-
-
-#define RCV_SKB_FAIL(err) do { netlink_ack(skb, nlh, (err), NULL); return; } while (0)
-
-static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
-{
-       struct nlmsghdr *nlh = nlmsg_hdr(skb);
-
-       if (skb->len < sizeof(*nlh) ||
-           nlh->nlmsg_len < sizeof(*nlh) ||
-           skb->len < nlh->nlmsg_len)
-               return;
-
-       if (!netlink_capable(skb, CAP_NET_ADMIN))
-               RCV_SKB_FAIL(-EPERM);
-
-       /* Eventually we might send routing messages too */
-
-       RCV_SKB_FAIL(-EINVAL);
-}
-
-static const struct nf_hook_ops dnrmg_ops = {
-       .hook           = dnrmg_hook,
-       .pf             = NFPROTO_DECNET,
-       .hooknum        = NF_DN_ROUTE,
-       .priority       = NF_DN_PRI_DNRTMSG,
-};
-
-static int __init dn_rtmsg_init(void)
-{
-       int rv = 0;
-       struct netlink_kernel_cfg cfg = {
-               .groups = DNRNG_NLGRP_MAX,
-               .input  = dnrmg_receive_user_skb,
-       };
-
-       dnrmg = netlink_kernel_create(&init_net, NETLINK_DNRTMSG, &cfg);
-       if (dnrmg == NULL) {
-               printk(KERN_ERR "dn_rtmsg: Cannot create netlink socket");
-               return -ENOMEM;
-       }
-
-       rv = nf_register_net_hook(&init_net, &dnrmg_ops);
-       if (rv) {
-               netlink_kernel_release(dnrmg);
-       }
-
-       return rv;
-}
-
-static void __exit dn_rtmsg_fini(void)
-{
-       nf_unregister_net_hook(&init_net, &dnrmg_ops);
-       netlink_kernel_release(dnrmg);
-}
-
-
-MODULE_DESCRIPTION("DECnet Routing Message Grabulator");
-MODULE_AUTHOR("Steven Whitehouse <steve@chygwyn.com>");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_DNRTMSG);
-
-module_init(dn_rtmsg_init);
-module_exit(dn_rtmsg_fini);
diff --git a/net/decnet/sysctl_net_decnet.c b/net/decnet/sysctl_net_decnet.c
deleted file mode 100644 (file)
index 67b5ab2..0000000
+++ /dev/null
@@ -1,362 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * DECnet       An implementation of the DECnet protocol suite for the LINUX
- *              operating system.  DECnet is implemented using the  BSD Socket
- *              interface as the means of communication with the user level.
- *
- *              DECnet sysctl support functions
- *
- * Author:      Steve Whitehouse <SteveW@ACM.org>
- *
- *
- * Changes:
- * Steve Whitehouse - C99 changes and default device handling
- * Steve Whitehouse - Memory buffer settings, like the tcp ones
- *
- */
-#include <linux/mm.h>
-#include <linux/sysctl.h>
-#include <linux/fs.h>
-#include <linux/netdevice.h>
-#include <linux/string.h>
-#include <net/neighbour.h>
-#include <net/dst.h>
-#include <net/flow.h>
-
-#include <linux/uaccess.h>
-
-#include <net/dn.h>
-#include <net/dn_dev.h>
-#include <net/dn_route.h>
-
-
-int decnet_debug_level;
-int decnet_time_wait = 30;
-int decnet_dn_count = 1;
-int decnet_di_count = 3;
-int decnet_dr_count = 3;
-int decnet_log_martians = 1;
-int decnet_no_fc_max_cwnd = NSP_MIN_WINDOW;
-
-/* Reasonable defaults, I hope, based on tcp's defaults */
-long sysctl_decnet_mem[3] = { 768 << 3, 1024 << 3, 1536 << 3 };
-int sysctl_decnet_wmem[3] = { 4 * 1024, 16 * 1024, 128 * 1024 };
-int sysctl_decnet_rmem[3] = { 4 * 1024, 87380, 87380 * 2 };
-
-#ifdef CONFIG_SYSCTL
-extern int decnet_dst_gc_interval;
-static int min_decnet_time_wait[] = { 5 };
-static int max_decnet_time_wait[] = { 600 };
-static int min_state_count[] = { 1 };
-static int max_state_count[] = { NSP_MAXRXTSHIFT };
-static int min_decnet_dst_gc_interval[] = { 1 };
-static int max_decnet_dst_gc_interval[] = { 60 };
-static int min_decnet_no_fc_max_cwnd[] = { NSP_MIN_WINDOW };
-static int max_decnet_no_fc_max_cwnd[] = { NSP_MAX_WINDOW };
-static char node_name[7] = "???";
-
-static struct ctl_table_header *dn_table_header = NULL;
-
-/*
- * ctype.h :-)
- */
-#define ISNUM(x) (((x) >= '0') && ((x) <= '9'))
-#define ISLOWER(x) (((x) >= 'a') && ((x) <= 'z'))
-#define ISUPPER(x) (((x) >= 'A') && ((x) <= 'Z'))
-#define ISALPHA(x) (ISLOWER(x) || ISUPPER(x))
-#define INVALID_END_CHAR(x) (ISNUM(x) || ISALPHA(x))
-
-static void strip_it(char *str)
-{
-       for(;;) {
-               switch (*str) {
-               case ' ':
-               case '\n':
-               case '\r':
-               case ':':
-                       *str = 0;
-                       fallthrough;
-               case 0:
-                       return;
-               }
-               str++;
-       }
-}
-
-/*
- * Simple routine to parse an ascii DECnet address
- * into a network order address.
- */
-static int parse_addr(__le16 *addr, char *str)
-{
-       __u16 area, node;
-
-       while(*str && !ISNUM(*str)) str++;
-
-       if (*str == 0)
-               return -1;
-
-       area = (*str++ - '0');
-       if (ISNUM(*str)) {
-               area *= 10;
-               area += (*str++ - '0');
-       }
-
-       if (*str++ != '.')
-               return -1;
-
-       if (!ISNUM(*str))
-               return -1;
-
-       node = *str++ - '0';
-       if (ISNUM(*str)) {
-               node *= 10;
-               node += (*str++ - '0');
-       }
-       if (ISNUM(*str)) {
-               node *= 10;
-               node += (*str++ - '0');
-       }
-       if (ISNUM(*str)) {
-               node *= 10;
-               node += (*str++ - '0');
-       }
-
-       if ((node > 1023) || (area > 63))
-               return -1;
-
-       if (INVALID_END_CHAR(*str))
-               return -1;
-
-       *addr = cpu_to_le16((area << 10) | node);
-
-       return 0;
-}
-
-static int dn_node_address_handler(struct ctl_table *table, int write,
-               void *buffer, size_t *lenp, loff_t *ppos)
-{
-       char addr[DN_ASCBUF_LEN];
-       size_t len;
-       __le16 dnaddr;
-
-       if (!*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-
-       if (write) {
-               len = (*lenp < DN_ASCBUF_LEN) ? *lenp : (DN_ASCBUF_LEN-1);
-               memcpy(addr, buffer, len);
-               addr[len] = 0;
-               strip_it(addr);
-
-               if (parse_addr(&dnaddr, addr))
-                       return -EINVAL;
-
-               dn_dev_devices_off();
-
-               decnet_address = dnaddr;
-
-               dn_dev_devices_on();
-
-               *ppos += len;
-
-               return 0;
-       }
-
-       dn_addr2asc(le16_to_cpu(decnet_address), addr);
-       len = strlen(addr);
-       addr[len++] = '\n';
-
-       if (len > *lenp)
-               len = *lenp;
-       memcpy(buffer, addr, len);
-       *lenp = len;
-       *ppos += len;
-
-       return 0;
-}
-
-static int dn_def_dev_handler(struct ctl_table *table, int write,
-               void *buffer, size_t *lenp, loff_t *ppos)
-{
-       size_t len;
-       struct net_device *dev;
-       char devname[17];
-
-       if (!*lenp || (*ppos && !write)) {
-               *lenp = 0;
-               return 0;
-       }
-
-       if (write) {
-               if (*lenp > 16)
-                       return -E2BIG;
-
-               memcpy(devname, buffer, *lenp);
-               devname[*lenp] = 0;
-               strip_it(devname);
-
-               dev = dev_get_by_name(&init_net, devname);
-               if (dev == NULL)
-                       return -ENODEV;
-
-               if (dev->dn_ptr == NULL) {
-                       dev_put(dev);
-                       return -ENODEV;
-               }
-
-               if (dn_dev_set_default(dev, 1)) {
-                       dev_put(dev);
-                       return -ENODEV;
-               }
-               *ppos += *lenp;
-
-               return 0;
-       }
-
-       dev = dn_dev_get_default();
-       if (dev == NULL) {
-               *lenp = 0;
-               return 0;
-       }
-
-       strcpy(devname, dev->name);
-       dev_put(dev);
-       len = strlen(devname);
-       devname[len++] = '\n';
-
-       if (len > *lenp) len = *lenp;
-
-       memcpy(buffer, devname, len);
-       *lenp = len;
-       *ppos += len;
-
-       return 0;
-}
-
-static struct ctl_table dn_table[] = {
-       {
-               .procname = "node_address",
-               .maxlen = 7,
-               .mode = 0644,
-               .proc_handler = dn_node_address_handler,
-       },
-       {
-               .procname = "node_name",
-               .data = node_name,
-               .maxlen = 7,
-               .mode = 0644,
-               .proc_handler = proc_dostring,
-       },
-       {
-               .procname = "default_device",
-               .maxlen = 16,
-               .mode = 0644,
-               .proc_handler = dn_def_dev_handler,
-       },
-       {
-               .procname = "time_wait",
-               .data = &decnet_time_wait,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_decnet_time_wait,
-               .extra2 = &max_decnet_time_wait
-       },
-       {
-               .procname = "dn_count",
-               .data = &decnet_dn_count,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_state_count,
-               .extra2 = &max_state_count
-       },
-       {
-               .procname = "di_count",
-               .data = &decnet_di_count,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_state_count,
-               .extra2 = &max_state_count
-       },
-       {
-               .procname = "dr_count",
-               .data = &decnet_dr_count,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_state_count,
-               .extra2 = &max_state_count
-       },
-       {
-               .procname = "dst_gc_interval",
-               .data = &decnet_dst_gc_interval,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_decnet_dst_gc_interval,
-               .extra2 = &max_decnet_dst_gc_interval
-       },
-       {
-               .procname = "no_fc_max_cwnd",
-               .data = &decnet_no_fc_max_cwnd,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec_minmax,
-               .extra1 = &min_decnet_no_fc_max_cwnd,
-               .extra2 = &max_decnet_no_fc_max_cwnd
-       },
-       {
-               .procname = "decnet_mem",
-               .data = &sysctl_decnet_mem,
-               .maxlen = sizeof(sysctl_decnet_mem),
-               .mode = 0644,
-               .proc_handler = proc_doulongvec_minmax
-       },
-       {
-               .procname = "decnet_rmem",
-               .data = &sysctl_decnet_rmem,
-               .maxlen = sizeof(sysctl_decnet_rmem),
-               .mode = 0644,
-               .proc_handler = proc_dointvec,
-       },
-       {
-               .procname = "decnet_wmem",
-               .data = &sysctl_decnet_wmem,
-               .maxlen = sizeof(sysctl_decnet_wmem),
-               .mode = 0644,
-               .proc_handler = proc_dointvec,
-       },
-       {
-               .procname = "debug",
-               .data = &decnet_debug_level,
-               .maxlen = sizeof(int),
-               .mode = 0644,
-               .proc_handler = proc_dointvec,
-       },
-       { }
-};
-
-void dn_register_sysctl(void)
-{
-       dn_table_header = register_net_sysctl(&init_net, "net/decnet", dn_table);
-}
-
-void dn_unregister_sysctl(void)
-{
-       unregister_net_sysctl_table(dn_table_header);
-}
-
-#else  /* CONFIG_SYSCTL */
-void dn_unregister_sysctl(void)
-{
-}
-void dn_register_sysctl(void)
-{
-}
-
-#endif
index cac48a7..ed56c7a 100644 (file)
@@ -469,10 +469,16 @@ static int dsa_port_setup(struct dsa_port *dp)
                dsa_port_disable(dp);
                break;
        case DSA_PORT_TYPE_CPU:
-               err = dsa_port_link_register_of(dp);
-               if (err)
-                       break;
-               dsa_port_link_registered = true;
+               if (dp->dn) {
+                       err = dsa_shared_port_link_register_of(dp);
+                       if (err)
+                               break;
+                       dsa_port_link_registered = true;
+               } else {
+                       dev_warn(ds->dev,
+                                "skipping link registration for CPU port %d\n",
+                                dp->index);
+               }
 
                err = dsa_port_enable(dp, NULL);
                if (err)
@@ -481,10 +487,16 @@ static int dsa_port_setup(struct dsa_port *dp)
 
                break;
        case DSA_PORT_TYPE_DSA:
-               err = dsa_port_link_register_of(dp);
-               if (err)
-                       break;
-               dsa_port_link_registered = true;
+               if (dp->dn) {
+                       err = dsa_shared_port_link_register_of(dp);
+                       if (err)
+                               break;
+                       dsa_port_link_registered = true;
+               } else {
+                       dev_warn(ds->dev,
+                                "skipping link registration for DSA port %d\n",
+                                dp->index);
+               }
 
                err = dsa_port_enable(dp, NULL);
                if (err)
@@ -505,7 +517,7 @@ static int dsa_port_setup(struct dsa_port *dp)
        if (err && dsa_port_enabled)
                dsa_port_disable(dp);
        if (err && dsa_port_link_registered)
-               dsa_port_link_unregister_of(dp);
+               dsa_shared_port_link_unregister_of(dp);
        if (err) {
                if (ds->ops->port_teardown)
                        ds->ops->port_teardown(ds, dp->index);
@@ -577,11 +589,13 @@ static void dsa_port_teardown(struct dsa_port *dp)
                break;
        case DSA_PORT_TYPE_CPU:
                dsa_port_disable(dp);
-               dsa_port_link_unregister_of(dp);
+               if (dp->dn)
+                       dsa_shared_port_link_unregister_of(dp);
                break;
        case DSA_PORT_TYPE_DSA:
                dsa_port_disable(dp);
-               dsa_port_link_unregister_of(dp);
+               if (dp->dn)
+                       dsa_shared_port_link_unregister_of(dp);
                break;
        case DSA_PORT_TYPE_USER:
                if (dp->slave) {
@@ -1046,26 +1060,24 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
 
 static int dsa_tree_setup_master(struct dsa_switch_tree *dst)
 {
-       struct dsa_port *dp;
+       struct dsa_port *cpu_dp;
        int err = 0;
 
        rtnl_lock();
 
-       list_for_each_entry(dp, &dst->ports, list) {
-               if (dsa_port_is_cpu(dp)) {
-                       struct net_device *master = dp->master;
-                       bool admin_up = (master->flags & IFF_UP) &&
-                                       !qdisc_tx_is_noop(master);
+       dsa_tree_for_each_cpu_port(cpu_dp, dst) {
+               struct net_device *master = cpu_dp->master;
+               bool admin_up = (master->flags & IFF_UP) &&
+                               !qdisc_tx_is_noop(master);
 
-                       err = dsa_master_setup(master, dp);
-                       if (err)
-                               break;
+               err = dsa_master_setup(master, cpu_dp);
+               if (err)
+                       break;
 
-                       /* Replay master state event */
-                       dsa_tree_master_admin_state_change(dst, master, admin_up);
-                       dsa_tree_master_oper_state_change(dst, master,
-                                                         netif_oper_up(master));
-               }
+               /* Replay master state event */
+               dsa_tree_master_admin_state_change(dst, master, admin_up);
+               dsa_tree_master_oper_state_change(dst, master,
+                                                 netif_oper_up(master));
        }
 
        rtnl_unlock();
@@ -1075,22 +1087,20 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst)
 
 static void dsa_tree_teardown_master(struct dsa_switch_tree *dst)
 {
-       struct dsa_port *dp;
+       struct dsa_port *cpu_dp;
 
        rtnl_lock();
 
-       list_for_each_entry(dp, &dst->ports, list) {
-               if (dsa_port_is_cpu(dp)) {
-                       struct net_device *master = dp->master;
+       dsa_tree_for_each_cpu_port(cpu_dp, dst) {
+               struct net_device *master = cpu_dp->master;
 
-                       /* Synthesizing an "admin down" state is sufficient for
-                        * the switches to get a notification if the master is
-                        * currently up and running.
-                        */
-                       dsa_tree_master_admin_state_change(dst, master, false);
+               /* Synthesizing an "admin down" state is sufficient for
+                * the switches to get a notification if the master is
+                * currently up and running.
+                */
+               dsa_tree_master_admin_state_change(dst, master, false);
 
-                       dsa_master_teardown(master);
-               }
+               dsa_master_teardown(master);
        }
 
        rtnl_unlock();
@@ -1238,7 +1248,6 @@ out_disconnect:
  * they would have formed disjoint trees (different "dsa,member" values).
  */
 int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
-                             struct net_device *master,
                              const struct dsa_device_ops *tag_ops,
                              const struct dsa_device_ops *old_tag_ops)
 {
@@ -1254,14 +1263,11 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
         * attempts to change the tagging protocol. If we ever lift the IFF_UP
         * restriction, there needs to be another mutex which serializes this.
         */
-       if (master->flags & IFF_UP)
-               goto out_unlock;
-
        list_for_each_entry(dp, &dst->ports, list) {
-               if (!dsa_port_is_user(dp))
-                       continue;
+               if (dsa_port_is_cpu(dp) && (dp->master->flags & IFF_UP))
+                       goto out_unlock;
 
-               if (dp->slave->flags & IFF_UP)
+               if (dsa_port_is_user(dp) && (dp->slave->flags & IFF_UP))
                        goto out_unlock;
        }
 
index d9722e4..614fbba 100644 (file)
@@ -285,8 +285,8 @@ int dsa_port_mrp_add_ring_role(const struct dsa_port *dp,
 int dsa_port_mrp_del_ring_role(const struct dsa_port *dp,
                               const struct switchdev_obj_ring_role_mrp *mrp);
 int dsa_port_phylink_create(struct dsa_port *dp);
-int dsa_port_link_register_of(struct dsa_port *dp);
-void dsa_port_link_unregister_of(struct dsa_port *dp);
+int dsa_shared_port_link_register_of(struct dsa_port *dp);
+void dsa_shared_port_link_unregister_of(struct dsa_port *dp);
 int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr);
 void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr);
 int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast);
@@ -545,7 +545,6 @@ struct dsa_lag *dsa_tree_lag_find(struct dsa_switch_tree *dst,
 int dsa_tree_notify(struct dsa_switch_tree *dst, unsigned long e, void *v);
 int dsa_broadcast(unsigned long e, void *v);
 int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
-                             struct net_device *master,
                              const struct dsa_device_ops *tag_ops,
                              const struct dsa_device_ops *old_tag_ops);
 void dsa_tree_master_admin_state_change(struct dsa_switch_tree *dst,
index 2851e44..fb810ed 100644 (file)
@@ -58,7 +58,7 @@ static void dsa_master_get_regs(struct net_device *dev,
        }
 
        cpu_info = (struct ethtool_drvinfo *)data;
-       strlcpy(cpu_info->driver, "dsa", sizeof(cpu_info->driver));
+       strscpy(cpu_info->driver, "dsa", sizeof(cpu_info->driver));
        data += sizeof(*cpu_info);
        cpu_regs = (struct ethtool_regs *)data;
        data += sizeof(*cpu_regs);
@@ -307,7 +307,7 @@ static ssize_t tagging_store(struct device *d, struct device_attribute *attr,
                 */
                goto out;
 
-       err = dsa_tree_change_tag_proto(cpu_dp->ds->dst, dev, new_tag_ops,
+       err = dsa_tree_change_tag_proto(cpu_dp->ds->dst, new_tag_ops,
                                        old_tag_ops);
        if (err) {
                /* On failure the old tagger is restored, so we don't need the
index a8895ee..7afc35d 100644 (file)
@@ -1555,7 +1555,7 @@ int dsa_port_phylink_create(struct dsa_port *dp)
        return 0;
 }
 
-static int dsa_port_setup_phy_of(struct dsa_port *dp, bool enable)
+static int dsa_shared_port_setup_phy_of(struct dsa_port *dp, bool enable)
 {
        struct dsa_switch *ds = dp->ds;
        struct phy_device *phydev;
@@ -1593,7 +1593,7 @@ err_put_dev:
        return err;
 }
 
-static int dsa_port_fixed_link_register_of(struct dsa_port *dp)
+static int dsa_shared_port_fixed_link_register_of(struct dsa_port *dp)
 {
        struct device_node *dn = dp->dn;
        struct dsa_switch *ds = dp->ds;
@@ -1627,7 +1627,7 @@ static int dsa_port_fixed_link_register_of(struct dsa_port *dp)
        return 0;
 }
 
-static int dsa_port_phylink_register(struct dsa_port *dp)
+static int dsa_shared_port_phylink_register(struct dsa_port *dp)
 {
        struct dsa_switch *ds = dp->ds;
        struct device_node *port_dn = dp->dn;
@@ -1653,22 +1653,184 @@ err_phy_connect:
        return err;
 }
 
-int dsa_port_link_register_of(struct dsa_port *dp)
+/* During the initial DSA driver migration to OF, port nodes were sometimes
+ * added to device trees with no indication of how they should operate from a
+ * link management perspective (phy-handle, fixed-link, etc). Additionally, the
+ * phy-mode may be absent. The interpretation of these port OF nodes depends on
+ * their type.
+ *
+ * User ports with no phy-handle or fixed-link are expected to connect to an
+ * internal PHY located on the ds->slave_mii_bus at an MDIO address equal to
+ * the port number. This description is still actively supported.
+ *
+ * Shared (CPU and DSA) ports with no phy-handle or fixed-link are expected to
+ * operate at the maximum speed that their phy-mode is capable of. If the
+ * phy-mode is absent, they are expected to operate using the phy-mode
+ * supported by the port that gives the highest link speed. It is unspecified
+ * if the port should use flow control or not, half duplex or full duplex, or
+ * if the phy-mode is a SERDES link, whether in-band autoneg is expected to be
+ * enabled or not.
+ *
+ * In the latter case of shared ports, omitting the link management description
+ * from the firmware node is deprecated and strongly discouraged. DSA uses
+ * phylink, which rejects the firmware nodes of these ports for lacking
+ * required properties.
+ *
+ * For switches in this table, DSA will skip enforcing validation and will
+ * later omit registering a phylink instance for the shared ports, if they lack
+ * a fixed-link, a phy-handle, or a managed = "in-band-status" property.
+ * It becomes the responsibility of the driver to ensure that these ports
+ * operate at the maximum speed (whatever this means) and will interoperate
+ * with the DSA master or other cascade port, since phylink methods will not be
+ * invoked for them.
+ *
+ * If you are considering expanding this table for newly introduced switches,
+ * think again. It is OK to remove switches from this table if there aren't DT
+ * blobs in circulation which rely on defaulting the shared ports.
+ */
+static const char * const dsa_switches_apply_workarounds[] = {
+#if IS_ENABLED(CONFIG_NET_DSA_XRS700X)
+       "arrow,xrs7003e",
+       "arrow,xrs7003f",
+       "arrow,xrs7004e",
+       "arrow,xrs7004f",
+#endif
+#if IS_ENABLED(CONFIG_B53)
+       "brcm,bcm5325",
+       "brcm,bcm53115",
+       "brcm,bcm53125",
+       "brcm,bcm53128",
+       "brcm,bcm5365",
+       "brcm,bcm5389",
+       "brcm,bcm5395",
+       "brcm,bcm5397",
+       "brcm,bcm5398",
+       "brcm,bcm53010-srab",
+       "brcm,bcm53011-srab",
+       "brcm,bcm53012-srab",
+       "brcm,bcm53018-srab",
+       "brcm,bcm53019-srab",
+       "brcm,bcm5301x-srab",
+       "brcm,bcm11360-srab",
+       "brcm,bcm58522-srab",
+       "brcm,bcm58525-srab",
+       "brcm,bcm58535-srab",
+       "brcm,bcm58622-srab",
+       "brcm,bcm58623-srab",
+       "brcm,bcm58625-srab",
+       "brcm,bcm88312-srab",
+       "brcm,cygnus-srab",
+       "brcm,nsp-srab",
+       "brcm,omega-srab",
+       "brcm,bcm3384-switch",
+       "brcm,bcm6328-switch",
+       "brcm,bcm6368-switch",
+       "brcm,bcm63xx-switch",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_BCM_SF2)
+       "brcm,bcm7445-switch-v4.0",
+       "brcm,bcm7278-switch-v4.0",
+       "brcm,bcm7278-switch-v4.8",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_LANTIQ_GSWIP)
+       "lantiq,xrx200-gswip",
+       "lantiq,xrx300-gswip",
+       "lantiq,xrx330-gswip",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6060)
+       "marvell,mv88e6060",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_MV88E6XXX)
+       "marvell,mv88e6085",
+       "marvell,mv88e6190",
+       "marvell,mv88e6250",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_MICROCHIP_KSZ_COMMON)
+       "microchip,ksz8765",
+       "microchip,ksz8794",
+       "microchip,ksz8795",
+       "microchip,ksz8863",
+       "microchip,ksz8873",
+       "microchip,ksz9477",
+       "microchip,ksz9897",
+       "microchip,ksz9893",
+       "microchip,ksz9563",
+       "microchip,ksz8563",
+       "microchip,ksz9567",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_SMSC_LAN9303_MDIO)
+       "smsc,lan9303-mdio",
+#endif
+#if IS_ENABLED(CONFIG_NET_DSA_SMSC_LAN9303_I2C)
+       "smsc,lan9303-i2c",
+#endif
+       NULL,
+};
+
+static void dsa_shared_port_validate_of(struct dsa_port *dp,
+                                       bool *missing_phy_mode,
+                                       bool *missing_link_description)
 {
+       struct device_node *dn = dp->dn, *phy_np;
        struct dsa_switch *ds = dp->ds;
-       struct device_node *phy_np;
+       phy_interface_t mode;
+
+       *missing_phy_mode = false;
+       *missing_link_description = false;
+
+       if (of_get_phy_mode(dn, &mode)) {
+               *missing_phy_mode = true;
+               dev_err(ds->dev,
+                       "OF node %pOF of %s port %d lacks the required \"phy-mode\" property\n",
+                       dn, dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index);
+       }
+
+       /* Note: of_phy_is_fixed_link() also returns true for
+        * managed = "in-band-status"
+        */
+       if (of_phy_is_fixed_link(dn))
+               return;
+
+       phy_np = of_parse_phandle(dn, "phy-handle", 0);
+       if (phy_np) {
+               of_node_put(phy_np);
+               return;
+       }
+
+       *missing_link_description = true;
+
+       dev_err(ds->dev,
+               "OF node %pOF of %s port %d lacks the required \"phy-handle\", \"fixed-link\" or \"managed\" properties\n",
+               dn, dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index);
+}
+
+int dsa_shared_port_link_register_of(struct dsa_port *dp)
+{
+       struct dsa_switch *ds = dp->ds;
+       bool missing_link_description;
+       bool missing_phy_mode;
        int port = dp->index;
 
+       dsa_shared_port_validate_of(dp, &missing_phy_mode,
+                                   &missing_link_description);
+
+       if ((missing_phy_mode || missing_link_description) &&
+           !of_device_compatible_match(ds->dev->of_node,
+                                       dsa_switches_apply_workarounds))
+               return -EINVAL;
+
        if (!ds->ops->adjust_link) {
-               phy_np = of_parse_phandle(dp->dn, "phy-handle", 0);
-               if (of_phy_is_fixed_link(dp->dn) || phy_np) {
+               if (missing_link_description) {
+                       dev_warn(ds->dev,
+                                "Skipping phylink registration for %s port %d\n",
+                                dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index);
+               } else {
                        if (ds->ops->phylink_mac_link_down)
                                ds->ops->phylink_mac_link_down(ds, port,
                                        MLO_AN_FIXED, PHY_INTERFACE_MODE_NA);
-                       of_node_put(phy_np);
-                       return dsa_port_phylink_register(dp);
+
+                       return dsa_shared_port_phylink_register(dp);
                }
-               of_node_put(phy_np);
                return 0;
        }
 
@@ -1676,12 +1838,12 @@ int dsa_port_link_register_of(struct dsa_port *dp)
                 "Using legacy PHYLIB callbacks. Please migrate to PHYLINK!\n");
 
        if (of_phy_is_fixed_link(dp->dn))
-               return dsa_port_fixed_link_register_of(dp);
+               return dsa_shared_port_fixed_link_register_of(dp);
        else
-               return dsa_port_setup_phy_of(dp, true);
+               return dsa_shared_port_setup_phy_of(dp, true);
 }
 
-void dsa_port_link_unregister_of(struct dsa_port *dp)
+void dsa_shared_port_link_unregister_of(struct dsa_port *dp)
 {
        struct dsa_switch *ds = dp->ds;
 
@@ -1697,7 +1859,7 @@ void dsa_port_link_unregister_of(struct dsa_port *dp)
        if (of_phy_is_fixed_link(dp->dn))
                of_phy_deregister_fixed_link(dp->dn);
        else
-               dsa_port_setup_phy_of(dp, false);
+               dsa_shared_port_setup_phy_of(dp, false);
 }
 
 int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr)
index 1291c24..345106b 100644 (file)
@@ -826,9 +826,9 @@ static netdev_tx_t dsa_slave_xmit(struct sk_buff *skb, struct net_device *dev)
 static void dsa_slave_get_drvinfo(struct net_device *dev,
                                  struct ethtool_drvinfo *drvinfo)
 {
-       strlcpy(drvinfo->driver, "dsa", sizeof(drvinfo->driver));
-       strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
-       strlcpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
+       strscpy(drvinfo->driver, "dsa", sizeof(drvinfo->driver));
+       strscpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
+       strscpy(drvinfo->bus_info, "platform", sizeof(drvinfo->bus_info));
 }
 
 static int dsa_slave_get_regs_len(struct net_device *dev)
@@ -2476,6 +2476,9 @@ static int dsa_slave_changeupper(struct net_device *dev,
        struct netlink_ext_ack *extack;
        int err = NOTIFY_DONE;
 
+       if (!dsa_slave_dev_check(dev))
+               return err;
+
        extack = netdev_notifier_info_to_extack(&info->info);
 
        if (netif_is_bridge_master(info->upper_dev)) {
@@ -2531,6 +2534,9 @@ static int dsa_slave_prechangeupper(struct net_device *dev,
 {
        struct dsa_port *dp = dsa_slave_to_port(dev);
 
+       if (!dsa_slave_dev_check(dev))
+               return NOTIFY_DONE;
+
        if (netif_is_bridge_master(info->upper_dev) && !info->linking)
                dsa_port_pre_bridge_leave(dp, info->upper_dev);
        else if (netif_is_lag_master(info->upper_dev) && !info->linking)
@@ -2551,6 +2557,9 @@ dsa_slave_lag_changeupper(struct net_device *dev,
        int err = NOTIFY_DONE;
        struct dsa_port *dp;
 
+       if (!netif_is_lag_master(dev))
+               return err;
+
        netdev_for_each_lower_dev(dev, lower, iter) {
                if (!dsa_slave_dev_check(lower))
                        continue;
@@ -2580,6 +2589,9 @@ dsa_slave_lag_prechangeupper(struct net_device *dev,
        int err = NOTIFY_DONE;
        struct dsa_port *dp;
 
+       if (!netif_is_lag_master(dev))
+               return err;
+
        netdev_for_each_lower_dev(dev, lower, iter) {
                if (!dsa_slave_dev_check(lower))
                        continue;
@@ -2687,6 +2699,75 @@ dsa_slave_prechangeupper_sanity_check(struct net_device *dev,
        return NOTIFY_DONE;
 }
 
+static int
+dsa_master_prechangeupper_sanity_check(struct net_device *master,
+                                      struct netdev_notifier_changeupper_info *info)
+{
+       struct netlink_ext_ack *extack;
+
+       if (!netdev_uses_dsa(master))
+               return NOTIFY_DONE;
+
+       if (!info->linking)
+               return NOTIFY_DONE;
+
+       /* Allow DSA switch uppers */
+       if (dsa_slave_dev_check(info->upper_dev))
+               return NOTIFY_DONE;
+
+       /* Allow bridge uppers of DSA masters, subject to further
+        * restrictions in dsa_bridge_prechangelower_sanity_check()
+        */
+       if (netif_is_bridge_master(info->upper_dev))
+               return NOTIFY_DONE;
+
+       extack = netdev_notifier_info_to_extack(&info->info);
+
+       NL_SET_ERR_MSG_MOD(extack,
+                          "DSA master cannot join unknown upper interfaces");
+       return notifier_from_errno(-EBUSY);
+}
+
+/* Don't allow bridging of DSA masters, since the bridge layer rx_handler
+ * prevents the DSA fake ethertype handler to be invoked, so we don't get the
+ * chance to strip off and parse the DSA switch tag protocol header (the bridge
+ * layer just returns RX_HANDLER_CONSUMED, stopping RX processing for these
+ * frames).
+ * The only case where that would not be an issue is when bridging can already
+ * be offloaded, such as when the DSA master is itself a DSA or plain switchdev
+ * port, and is bridged only with other ports from the same hardware device.
+ */
+static int
+dsa_bridge_prechangelower_sanity_check(struct net_device *new_lower,
+                                      struct netdev_notifier_changeupper_info *info)
+{
+       struct net_device *br = info->upper_dev;
+       struct netlink_ext_ack *extack;
+       struct net_device *lower;
+       struct list_head *iter;
+
+       if (!netif_is_bridge_master(br))
+               return NOTIFY_DONE;
+
+       if (!info->linking)
+               return NOTIFY_DONE;
+
+       extack = netdev_notifier_info_to_extack(&info->info);
+
+       netdev_for_each_lower_dev(br, lower, iter) {
+               if (!netdev_uses_dsa(new_lower) && !netdev_uses_dsa(lower))
+                       continue;
+
+               if (!netdev_port_same_parent_id(lower, new_lower)) {
+                       NL_SET_ERR_MSG(extack,
+                                      "Cannot do software bridging with a DSA master");
+                       return notifier_from_errno(-EINVAL);
+               }
+       }
+
+       return NOTIFY_DONE;
+}
+
 static int dsa_slave_netdevice_event(struct notifier_block *nb,
                                     unsigned long event, void *ptr)
 {
@@ -2698,25 +2779,40 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
                int err;
 
                err = dsa_slave_prechangeupper_sanity_check(dev, info);
-               if (err != NOTIFY_DONE)
+               if (notifier_to_errno(err))
+                       return err;
+
+               err = dsa_master_prechangeupper_sanity_check(dev, info);
+               if (notifier_to_errno(err))
                        return err;
 
-               if (dsa_slave_dev_check(dev))
-                       return dsa_slave_prechangeupper(dev, ptr);
+               err = dsa_bridge_prechangelower_sanity_check(dev, info);
+               if (notifier_to_errno(err))
+                       return err;
 
-               if (netif_is_lag_master(dev))
-                       return dsa_slave_lag_prechangeupper(dev, ptr);
+               err = dsa_slave_prechangeupper(dev, ptr);
+               if (notifier_to_errno(err))
+                       return err;
+
+               err = dsa_slave_lag_prechangeupper(dev, ptr);
+               if (notifier_to_errno(err))
+                       return err;
 
                break;
        }
-       case NETDEV_CHANGEUPPER:
-               if (dsa_slave_dev_check(dev))
-                       return dsa_slave_changeupper(dev, ptr);
+       case NETDEV_CHANGEUPPER: {
+               int err;
 
-               if (netif_is_lag_master(dev))
-                       return dsa_slave_lag_changeupper(dev, ptr);
+               err = dsa_slave_changeupper(dev, ptr);
+               if (notifier_to_errno(err))
+                       return err;
+
+               err = dsa_slave_lag_changeupper(dev, ptr);
+               if (notifier_to_errno(err))
+                       return err;
 
                break;
+       }
        case NETDEV_CHANGELOWERSTATE: {
                struct netdev_notifier_changelowerstate_info *info = ptr;
                struct dsa_port *dp;
@@ -2777,6 +2873,9 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
                        if (!dsa_port_is_user(dp))
                                continue;
 
+                       if (dp->cpu_dp != cpu_dp)
+                               continue;
+
                        list_add(&dp->slave->close_list, &close_list);
                }
 
index 01a4278..b5f80bc 100644 (file)
@@ -2,9 +2,7 @@
 /* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
  *
  * This module is not a complete tagger implementation. It only provides
- * primitives for taggers that rely on 802.1Q VLAN tags to use. The
- * dsa_8021q_netdev_ops is registered for API compliance and not used
- * directly by callers.
+ * primitives for taggers that rely on 802.1Q VLAN tags to use.
  */
 #include <linux/if_vlan.h>
 #include <linux/dsa/8021q.h>
index eb204ad..846588c 100644 (file)
@@ -45,7 +45,7 @@ static struct sk_buff *hellcreek_rcv(struct sk_buff *skb,
 
        skb->dev = dsa_master_find_slave(dev, 0, port);
        if (!skb->dev) {
-               netdev_warn(dev, "Failed to get source port: %d\n", port);
+               netdev_warn_once(dev, "Failed to get source port: %d\n", port);
                return NULL;
        }
 
index 62b89d6..e02daa7 100644 (file)
@@ -414,12 +414,9 @@ struct sk_buff *eth_gro_receive(struct list_head *head, struct sk_buff *skb)
 
        off_eth = skb_gro_offset(skb);
        hlen = off_eth + sizeof(*eh);
-       eh = skb_gro_header_fast(skb, off_eth);
-       if (skb_gro_header_hard(skb, hlen)) {
-               eh = skb_gro_header_slow(skb, hlen, off_eth);
-               if (unlikely(!eh))
-                       goto out;
-       }
+       eh = skb_gro_header(skb, hlen, off_eth);
+       if (unlikely(!eh))
+               goto out;
 
        flush = 0;
 
index 6a7308d..9298eb3 100644 (file)
@@ -714,16 +714,16 @@ ethtool_get_drvinfo(struct net_device *dev, struct ethtool_devlink_compat *rsp)
        const struct ethtool_ops *ops = dev->ethtool_ops;
 
        rsp->info.cmd = ETHTOOL_GDRVINFO;
-       strlcpy(rsp->info.version, UTS_RELEASE, sizeof(rsp->info.version));
+       strscpy(rsp->info.version, UTS_RELEASE, sizeof(rsp->info.version));
        if (ops->get_drvinfo) {
                ops->get_drvinfo(dev, &rsp->info);
        } else if (dev->dev.parent && dev->dev.parent->driver) {
-               strlcpy(rsp->info.bus_info, dev_name(dev->dev.parent),
+               strscpy(rsp->info.bus_info, dev_name(dev->dev.parent),
                        sizeof(rsp->info.bus_info));
-               strlcpy(rsp->info.driver, dev->dev.parent->driver->name,
+               strscpy(rsp->info.driver, dev->dev.parent->driver->name,
                        sizeof(rsp->info.driver));
        } else if (dev->rtnl_link_ops) {
-               strlcpy(rsp->info.driver, dev->rtnl_link_ops->kind,
+               strscpy(rsp->info.driver, dev->rtnl_link_ops->kind,
                        sizeof(rsp->info.driver));
        } else {
                return -EOPNOTSUPP;
index e26079e..f4e41a6 100644 (file)
@@ -361,6 +361,9 @@ static int ethnl_default_doit(struct sk_buff *skb, struct genl_info *info)
        ops = ethnl_default_requests[cmd];
        if (WARN_ONCE(!ops, "cmd %u has no ethnl_request_ops\n", cmd))
                return -EOPNOTSUPP;
+       if (GENL_REQ_ATTR_CHECK(info, ops->hdr_attr))
+               return -EINVAL;
+
        req_info = kzalloc(ops->req_info_size, GFP_KERNEL);
        if (!req_info)
                return -ENOMEM;
@@ -1033,6 +1036,7 @@ static struct genl_family ethtool_genl_family __ro_after_init = {
        .parallel_ops   = true,
        .ops            = ethtool_genl_ops,
        .n_ops          = ARRAY_SIZE(ethtool_genl_ops),
+       .resv_start_op  = ETHTOOL_MSG_MODULE_GET + 1,
        .mcgrps         = ethtool_nl_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(ethtool_nl_mcgrps),
 };
index 2d51b7a..3f7de54 100644 (file)
@@ -167,7 +167,7 @@ static int strset_get_id(const struct nlattr *nest, u32 *val,
                               get_stringset_policy, extack);
        if (ret < 0)
                return ret;
-       if (!tb[ETHTOOL_A_STRINGSET_ID])
+       if (NL_REQ_ATTR_CHECK(extack, nest, tb, ETHTOOL_A_STRINGSET_ID))
                return -EINVAL;
 
        *val = nla_get_u32(tb[ETHTOOL_A_STRINGSET_ID]);
index 1405c03..7174a90 100644 (file)
@@ -522,6 +522,7 @@ static struct genl_family hsr_genl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = hsr_ops,
        .n_small_ops = ARRAY_SIZE(hsr_ops),
+       .resv_start_op = HSR_C_SET_NODE_LIST + 1,
        .mcgrps = hsr_mcgrps,
        .n_mcgrps = ARRAY_SIZE(hsr_mcgrps),
 };
index b07abc3..7d2de4e 100644 (file)
@@ -132,6 +132,7 @@ struct genl_family nl802154_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = ieee802154_ops,
        .n_small_ops    = ARRAY_SIZE(ieee802154_ops),
+       .resv_start_op  = IEEE802154_LLSEC_DEL_SECLEVEL + 1,
        .mcgrps         = ieee802154_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(ieee802154_mcgrps),
 };
index e0b072a..38c4f3c 100644 (file)
@@ -2500,6 +2500,7 @@ static struct genl_family nl802154_fam __ro_after_init = {
        .module = THIS_MODULE,
        .ops = nl802154_ops,
        .n_ops = ARRAY_SIZE(nl802154_ops),
+       .resv_start_op = NL802154_CMD_DEL_SEC_LEVEL + 1,
        .mcgrps = nl802154_mcgrps,
        .n_mcgrps = ARRAY_SIZE(nl802154_mcgrps),
 };
index 3ca0cc4..d3ab1ae 100644 (file)
@@ -1219,6 +1219,7 @@ EXPORT_SYMBOL(inet_unregister_protosw);
 
 static int inet_sk_reselect_saddr(struct sock *sk)
 {
+       struct inet_bind_hashbucket *prev_addr_hashbucket;
        struct inet_sock *inet = inet_sk(sk);
        __be32 old_saddr = inet->inet_saddr;
        __be32 daddr = inet->inet_daddr;
@@ -1226,6 +1227,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
        struct rtable *rt;
        __be32 new_saddr;
        struct ip_options_rcu *inet_opt;
+       int err;
 
        inet_opt = rcu_dereference_protected(inet->inet_opt,
                                             lockdep_sock_is_held(sk));
@@ -1240,20 +1242,34 @@ static int inet_sk_reselect_saddr(struct sock *sk)
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
-       sk_setup_caps(sk, &rt->dst);
-
        new_saddr = fl4->saddr;
 
-       if (new_saddr == old_saddr)
+       if (new_saddr == old_saddr) {
+               sk_setup_caps(sk, &rt->dst);
                return 0;
+       }
+
+       prev_addr_hashbucket =
+               inet_bhashfn_portaddr(sk->sk_prot->h.hashinfo, sk,
+                                     sock_net(sk), inet->inet_num);
+
+       inet->inet_saddr = inet->inet_rcv_saddr = new_saddr;
+
+       err = inet_bhash2_update_saddr(prev_addr_hashbucket, sk);
+       if (err) {
+               inet->inet_saddr = old_saddr;
+               inet->inet_rcv_saddr = old_saddr;
+               ip_rt_put(rt);
+               return err;
+       }
+
+       sk_setup_caps(sk, &rt->dst);
 
        if (READ_ONCE(sock_net(sk)->ipv4.sysctl_ip_dynaddr) > 1) {
                pr_info("%s(): shifting inet->saddr from %pI4 to %pI4\n",
                        __func__, &old_saddr, &new_saddr);
        }
 
-       inet->inet_saddr = inet->inet_rcv_saddr = new_saddr;
-
        /*
         * XXX The only one ugly spot where we need to
         * XXX really change the sockets identity after
@@ -1448,12 +1464,9 @@ struct sk_buff *inet_gro_receive(struct list_head *head, struct sk_buff *skb)
 
        off = skb_gro_offset(skb);
        hlen = off + sizeof(*iph);
-       iph = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, hlen)) {
-               iph = skb_gro_header_slow(skb, hlen, off);
-               if (unlikely(!iph))
-                       goto out;
-       }
+       iph = skb_gro_header(skb, hlen, off);
+       if (unlikely(!iph))
+               goto out;
 
        proto = iph->protocol;
 
index 87c7e3f..4f72376 100644 (file)
@@ -1129,7 +1129,7 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev)
                        r->arp_flags = arp_state_to_flags(neigh);
                        read_unlock_bh(&neigh->lock);
                        r->arp_ha.sa_family = dev->type;
-                       strlcpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
+                       strscpy(r->arp_dev, dev->name, sizeof(r->arp_dev));
                        err = 0;
                }
                neigh_release(neigh);
index ffd5752..405a8c2 100644 (file)
@@ -42,6 +42,8 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
                        oif = inet->mc_index;
                if (!saddr)
                        saddr = inet->mc_addr;
+       } else if (!oif) {
+               oif = inet->uc_index;
        }
        fl4 = &inet->cork.fl.u.ip4;
        rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr, oif,
index f361d3d..943edf4 100644 (file)
@@ -389,7 +389,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
        dev_match = dev_match || (res.type == RTN_LOCAL &&
                                  dev == net->loopback_dev);
        if (dev_match) {
-               ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
+               ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_LINK;
                return ret;
        }
        if (no_addr)
@@ -401,7 +401,7 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst,
        ret = 0;
        if (fib_lookup(net, &fl4, &res, FIB_LOOKUP_IGNORE_LINKSTATE) == 0) {
                if (res.type == RTN_UNICAST)
-                       ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_HOST;
+                       ret = FIB_RES_NHC(res)->nhc_scope >= RT_SCOPE_LINK;
        }
        return ret;
 
index 025a33c..0c3c6d0 100644 (file)
@@ -323,12 +323,9 @@ static struct sk_buff *gue_gro_receive(struct sock *sk,
        off = skb_gro_offset(skb);
        len = off + sizeof(*guehdr);
 
-       guehdr = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, len)) {
-               guehdr = skb_gro_header_slow(skb, len, off);
-               if (unlikely(!guehdr))
-                       goto out;
-       }
+       guehdr = skb_gro_header(skb, len, off);
+       if (unlikely(!guehdr))
+               goto out;
 
        switch (guehdr->version) {
        case 0:
@@ -931,6 +928,7 @@ static struct genl_family fou_nl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = fou_nl_ops,
        .n_small_ops    = ARRAY_SIZE(fou_nl_ops),
+       .resv_start_op  = FOU_CMD_GET + 1,
 };
 
 size_t fou_encap_hlen(struct ip_tunnel_encap *e)
index 07073fa..2b9cb53 100644 (file)
@@ -137,12 +137,9 @@ static struct sk_buff *gre_gro_receive(struct list_head *head,
 
        off = skb_gro_offset(skb);
        hlen = off + sizeof(*greh);
-       greh = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, hlen)) {
-               greh = skb_gro_header_slow(skb, hlen, off);
-               if (unlikely(!greh))
-                       goto out;
-       }
+       greh = skb_gro_header(skb, hlen, off);
+       if (unlikely(!greh))
+               goto out;
 
        /* Only support version 0 and K (key), C (csum) flags. Note that
         * although the support for the S (seq#) flag can be added easily
index eb31c71..f003804 100644 (file)
@@ -130,14 +130,75 @@ void inet_get_local_port_range(struct net *net, int *low, int *high)
 }
 EXPORT_SYMBOL(inet_get_local_port_range);
 
+static bool inet_use_bhash2_on_bind(const struct sock *sk)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6) {
+               int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr);
+
+               return addr_type != IPV6_ADDR_ANY &&
+                       addr_type != IPV6_ADDR_MAPPED;
+       }
+#endif
+       return sk->sk_rcv_saddr != htonl(INADDR_ANY);
+}
+
+static bool inet_bind_conflict(const struct sock *sk, struct sock *sk2,
+                              kuid_t sk_uid, bool relax,
+                              bool reuseport_cb_ok, bool reuseport_ok)
+{
+       int bound_dev_if2;
+
+       if (sk == sk2)
+               return false;
+
+       bound_dev_if2 = READ_ONCE(sk2->sk_bound_dev_if);
+
+       if (!sk->sk_bound_dev_if || !bound_dev_if2 ||
+           sk->sk_bound_dev_if == bound_dev_if2) {
+               if (sk->sk_reuse && sk2->sk_reuse &&
+                   sk2->sk_state != TCP_LISTEN) {
+                       if (!relax || (!reuseport_ok && sk->sk_reuseport &&
+                                      sk2->sk_reuseport && reuseport_cb_ok &&
+                                      (sk2->sk_state == TCP_TIME_WAIT ||
+                                       uid_eq(sk_uid, sock_i_uid(sk2)))))
+                               return true;
+               } else if (!reuseport_ok || !sk->sk_reuseport ||
+                          !sk2->sk_reuseport || !reuseport_cb_ok ||
+                          (sk2->sk_state != TCP_TIME_WAIT &&
+                           !uid_eq(sk_uid, sock_i_uid(sk2)))) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+static bool inet_bhash2_conflict(const struct sock *sk,
+                                const struct inet_bind2_bucket *tb2,
+                                kuid_t sk_uid,
+                                bool relax, bool reuseport_cb_ok,
+                                bool reuseport_ok)
+{
+       struct sock *sk2;
+
+       sk_for_each_bound_bhash2(sk2, &tb2->owners) {
+               if (sk->sk_family == AF_INET && ipv6_only_sock(sk2))
+                       continue;
+
+               if (inet_bind_conflict(sk, sk2, sk_uid, relax,
+                                      reuseport_cb_ok, reuseport_ok))
+                       return true;
+       }
+       return false;
+}
+
+/* This should be called only when the tb and tb2 hashbuckets' locks are held */
 static int inet_csk_bind_conflict(const struct sock *sk,
                                  const struct inet_bind_bucket *tb,
+                                 const struct inet_bind2_bucket *tb2, /* may be null */
                                  bool relax, bool reuseport_ok)
 {
-       struct sock *sk2;
        bool reuseport_cb_ok;
-       bool reuse = sk->sk_reuse;
-       bool reuseport = !!sk->sk_reuseport;
        struct sock_reuseport *reuseport_cb;
        kuid_t uid = sock_i_uid((struct sock *)sk);
 
@@ -150,55 +211,87 @@ static int inet_csk_bind_conflict(const struct sock *sk,
        /*
         * Unlike other sk lookup places we do not check
         * for sk_net here, since _all_ the socks listed
-        * in tb->owners list belong to the same net - the
-        * one this bucket belongs to.
+        * in tb->owners and tb2->owners list belong
+        * to the same net - the one this bucket belongs to.
         */
 
-       sk_for_each_bound(sk2, &tb->owners) {
-               int bound_dev_if2;
+       if (!inet_use_bhash2_on_bind(sk)) {
+               struct sock *sk2;
 
-               if (sk == sk2)
-                       continue;
-               bound_dev_if2 = READ_ONCE(sk2->sk_bound_dev_if);
-               if ((!sk->sk_bound_dev_if ||
-                    !bound_dev_if2 ||
-                    sk->sk_bound_dev_if == bound_dev_if2)) {
-                       if (reuse && sk2->sk_reuse &&
-                           sk2->sk_state != TCP_LISTEN) {
-                               if ((!relax ||
-                                    (!reuseport_ok &&
-                                     reuseport && sk2->sk_reuseport &&
-                                     reuseport_cb_ok &&
-                                     (sk2->sk_state == TCP_TIME_WAIT ||
-                                      uid_eq(uid, sock_i_uid(sk2))))) &&
-                                   inet_rcv_saddr_equal(sk, sk2, true))
-                                       break;
-                       } else if (!reuseport_ok ||
-                                  !reuseport || !sk2->sk_reuseport ||
-                                  !reuseport_cb_ok ||
-                                  (sk2->sk_state != TCP_TIME_WAIT &&
-                                   !uid_eq(uid, sock_i_uid(sk2)))) {
-                               if (inet_rcv_saddr_equal(sk, sk2, true))
-                                       break;
-                       }
-               }
+               sk_for_each_bound(sk2, &tb->owners)
+                       if (inet_bind_conflict(sk, sk2, uid, relax,
+                                              reuseport_cb_ok, reuseport_ok) &&
+                           inet_rcv_saddr_equal(sk, sk2, true))
+                               return true;
+
+               return false;
+       }
+
+       /* Conflicts with an existing IPV6_ADDR_ANY (if ipv6) or INADDR_ANY (if
+        * ipv4) should have been checked already. We need to do these two
+        * checks separately because their spinlocks have to be acquired/released
+        * independently of each other, to prevent possible deadlocks
+        */
+       return tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok,
+                                          reuseport_ok);
+}
+
+/* Determine if there is a bind conflict with an existing IPV6_ADDR_ANY (if ipv6) or
+ * INADDR_ANY (if ipv4) socket.
+ *
+ * Caller must hold bhash hashbucket lock with local bh disabled, to protect
+ * against concurrent binds on the port for addr any
+ */
+static bool inet_bhash2_addr_any_conflict(const struct sock *sk, int port, int l3mdev,
+                                         bool relax, bool reuseport_ok)
+{
+       kuid_t uid = sock_i_uid((struct sock *)sk);
+       const struct net *net = sock_net(sk);
+       struct sock_reuseport *reuseport_cb;
+       struct inet_bind_hashbucket *head2;
+       struct inet_bind2_bucket *tb2;
+       bool reuseport_cb_ok;
+
+       rcu_read_lock();
+       reuseport_cb = rcu_dereference(sk->sk_reuseport_cb);
+       /* paired with WRITE_ONCE() in __reuseport_(add|detach)_closed_sock */
+       reuseport_cb_ok = !reuseport_cb || READ_ONCE(reuseport_cb->num_closed_socks);
+       rcu_read_unlock();
+
+       head2 = inet_bhash2_addr_any_hashbucket(sk, net, port);
+
+       spin_lock(&head2->lock);
+
+       inet_bind_bucket_for_each(tb2, &head2->chain)
+               if (inet_bind2_bucket_match_addr_any(tb2, net, port, l3mdev, sk))
+                       break;
+
+       if (tb2 && inet_bhash2_conflict(sk, tb2, uid, relax, reuseport_cb_ok,
+                                       reuseport_ok)) {
+               spin_unlock(&head2->lock);
+               return true;
        }
-       return sk2 != NULL;
+
+       spin_unlock(&head2->lock);
+       return false;
 }
 
 /*
  * Find an open port number for the socket.  Returns with the
- * inet_bind_hashbucket lock held.
+ * inet_bind_hashbucket locks held if successful.
  */
 static struct inet_bind_hashbucket *
-inet_csk_find_open_port(struct sock *sk, struct inet_bind_bucket **tb_ret, int *port_ret)
+inet_csk_find_open_port(const struct sock *sk, struct inet_bind_bucket **tb_ret,
+                       struct inet_bind2_bucket **tb2_ret,
+                       struct inet_bind_hashbucket **head2_ret, int *port_ret)
 {
        struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
        int port = 0;
-       struct inet_bind_hashbucket *head;
+       struct inet_bind_hashbucket *head, *head2;
        struct net *net = sock_net(sk);
        bool relax = false;
        int i, low, high, attempt_half;
+       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
        u32 remaining, offset;
        int l3mdev;
@@ -239,11 +332,20 @@ other_parity_scan:
                head = &hinfo->bhash[inet_bhashfn(net, port,
                                                  hinfo->bhash_size)];
                spin_lock_bh(&head->lock);
+               if (inet_use_bhash2_on_bind(sk)) {
+                       if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, relax, false))
+                               goto next_port;
+               }
+
+               head2 = inet_bhashfn_portaddr(hinfo, sk, net, port);
+               spin_lock(&head2->lock);
+               tb2 = inet_bind2_bucket_find(head2, net, port, l3mdev, sk);
                inet_bind_bucket_for_each(tb, &head->chain)
-                       if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
-                           tb->port == port) {
-                               if (!inet_csk_bind_conflict(sk, tb, relax, false))
+                       if (inet_bind_bucket_match(tb, net, port, l3mdev)) {
+                               if (!inet_csk_bind_conflict(sk, tb, tb2,
+                                                           relax, false))
                                        goto success;
+                               spin_unlock(&head2->lock);
                                goto next_port;
                        }
                tb = NULL;
@@ -272,6 +374,8 @@ next_port:
 success:
        *port_ret = port;
        *tb_ret = tb;
+       *tb2_ret = tb2;
+       *head2_ret = head2;
        return head;
 }
 
@@ -368,53 +472,95 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
        bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN;
        struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
        int ret = 1, port = snum;
-       struct inet_bind_hashbucket *head;
        struct net *net = sock_net(sk);
+       bool found_port = false, check_bind_conflict = true;
+       bool bhash_created = false, bhash2_created = false;
+       struct inet_bind_hashbucket *head, *head2;
+       struct inet_bind2_bucket *tb2 = NULL;
        struct inet_bind_bucket *tb = NULL;
+       bool head2_lock_acquired = false;
        int l3mdev;
 
        l3mdev = inet_sk_bound_l3mdev(sk);
 
        if (!port) {
-               head = inet_csk_find_open_port(sk, &tb, &port);
+               head = inet_csk_find_open_port(sk, &tb, &tb2, &head2, &port);
                if (!head)
                        return ret;
+
+               head2_lock_acquired = true;
+
+               if (tb && tb2)
+                       goto success;
+               found_port = true;
+       } else {
+               head = &hinfo->bhash[inet_bhashfn(net, port,
+                                                 hinfo->bhash_size)];
+               spin_lock_bh(&head->lock);
+               inet_bind_bucket_for_each(tb, &head->chain)
+                       if (inet_bind_bucket_match(tb, net, port, l3mdev))
+                               break;
+       }
+
+       if (!tb) {
+               tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, net,
+                                            head, port, l3mdev);
                if (!tb)
-                       goto tb_not_found;
-               goto success;
+                       goto fail_unlock;
+               bhash_created = true;
        }
-       head = &hinfo->bhash[inet_bhashfn(net, port,
-                                         hinfo->bhash_size)];
-       spin_lock_bh(&head->lock);
-       inet_bind_bucket_for_each(tb, &head->chain)
-               if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
-                   tb->port == port)
-                       goto tb_found;
-tb_not_found:
-       tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep,
-                                    net, head, port, l3mdev);
-       if (!tb)
-               goto fail_unlock;
-tb_found:
-       if (!hlist_empty(&tb->owners)) {
-               if (sk->sk_reuse == SK_FORCE_REUSE)
-                       goto success;
 
-               if ((tb->fastreuse > 0 && reuse) ||
-                   sk_reuseport_match(tb, sk))
-                       goto success;
-               if (inet_csk_bind_conflict(sk, tb, true, true))
+       if (!found_port) {
+               if (!hlist_empty(&tb->owners)) {
+                       if (sk->sk_reuse == SK_FORCE_REUSE ||
+                           (tb->fastreuse > 0 && reuse) ||
+                           sk_reuseport_match(tb, sk))
+                               check_bind_conflict = false;
+               }
+
+               if (check_bind_conflict && inet_use_bhash2_on_bind(sk)) {
+                       if (inet_bhash2_addr_any_conflict(sk, port, l3mdev, true, true))
+                               goto fail_unlock;
+               }
+
+               head2 = inet_bhashfn_portaddr(hinfo, sk, net, port);
+               spin_lock(&head2->lock);
+               head2_lock_acquired = true;
+               tb2 = inet_bind2_bucket_find(head2, net, port, l3mdev, sk);
+       }
+
+       if (!tb2) {
+               tb2 = inet_bind2_bucket_create(hinfo->bind2_bucket_cachep,
+                                              net, head2, port, l3mdev, sk);
+               if (!tb2)
                        goto fail_unlock;
+               bhash2_created = true;
        }
+
+       if (!found_port && check_bind_conflict) {
+               if (inet_csk_bind_conflict(sk, tb, tb2, true, true))
+                       goto fail_unlock;
+       }
+
 success:
        inet_csk_update_fastreuse(tb, sk);
 
        if (!inet_csk(sk)->icsk_bind_hash)
-               inet_bind_hash(sk, tb, port);
+               inet_bind_hash(sk, tb, tb2, port);
        WARN_ON(inet_csk(sk)->icsk_bind_hash != tb);
+       WARN_ON(inet_csk(sk)->icsk_bind2_hash != tb2);
        ret = 0;
 
 fail_unlock:
+       if (ret) {
+               if (bhash_created)
+                       inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
+               if (bhash2_created)
+                       inet_bind2_bucket_destroy(hinfo->bind2_bucket_cachep,
+                                                 tb2);
+       }
+       if (head2_lock_acquired)
+               spin_unlock(&head2->lock);
        spin_unlock_bh(&head->lock);
        return ret;
 }
@@ -962,6 +1108,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
 
                inet_sk_set_state(newsk, TCP_SYN_RECV);
                newicsk->icsk_bind_hash = NULL;
+               newicsk->icsk_bind2_hash = NULL;
 
                inet_sk(newsk)->inet_dport = inet_rsk(req)->ir_rmt_port;
                inet_sk(newsk)->inet_num = inet_rsk(req)->ir_num;
index b9d995b..60d77e2 100644 (file)
@@ -92,12 +92,75 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket
        }
 }
 
+bool inet_bind_bucket_match(const struct inet_bind_bucket *tb, const struct net *net,
+                           unsigned short port, int l3mdev)
+{
+       return net_eq(ib_net(tb), net) && tb->port == port &&
+               tb->l3mdev == l3mdev;
+}
+
+static void inet_bind2_bucket_init(struct inet_bind2_bucket *tb,
+                                  struct net *net,
+                                  struct inet_bind_hashbucket *head,
+                                  unsigned short port, int l3mdev,
+                                  const struct sock *sk)
+{
+       write_pnet(&tb->ib_net, net);
+       tb->l3mdev    = l3mdev;
+       tb->port      = port;
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               tb->v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+       else
+#endif
+               tb->rcv_saddr = sk->sk_rcv_saddr;
+       INIT_HLIST_HEAD(&tb->owners);
+       hlist_add_head(&tb->node, &head->chain);
+}
+
+struct inet_bind2_bucket *inet_bind2_bucket_create(struct kmem_cache *cachep,
+                                                  struct net *net,
+                                                  struct inet_bind_hashbucket *head,
+                                                  unsigned short port,
+                                                  int l3mdev,
+                                                  const struct sock *sk)
+{
+       struct inet_bind2_bucket *tb = kmem_cache_alloc(cachep, GFP_ATOMIC);
+
+       if (tb)
+               inet_bind2_bucket_init(tb, net, head, port, l3mdev, sk);
+
+       return tb;
+}
+
+/* Caller must hold hashbucket lock for this tb with local BH disabled */
+void inet_bind2_bucket_destroy(struct kmem_cache *cachep, struct inet_bind2_bucket *tb)
+{
+       if (hlist_empty(&tb->owners)) {
+               __hlist_del(&tb->node);
+               kmem_cache_free(cachep, tb);
+       }
+}
+
+static bool inet_bind2_bucket_addr_match(const struct inet_bind2_bucket *tb2,
+                                        const struct sock *sk)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               return ipv6_addr_equal(&tb2->v6_rcv_saddr,
+                                      &sk->sk_v6_rcv_saddr);
+#endif
+       return tb2->rcv_saddr == sk->sk_rcv_saddr;
+}
+
 void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
-                   const unsigned short snum)
+                   struct inet_bind2_bucket *tb2, unsigned short port)
 {
-       inet_sk(sk)->inet_num = snum;
+       inet_sk(sk)->inet_num = port;
        sk_add_bind_node(sk, &tb->owners);
        inet_csk(sk)->icsk_bind_hash = tb;
+       sk_add_bind2_node(sk, &tb2->owners);
+       inet_csk(sk)->icsk_bind2_hash = tb2;
 }
 
 /*
@@ -109,6 +172,9 @@ static void __inet_put_port(struct sock *sk)
        const int bhash = inet_bhashfn(sock_net(sk), inet_sk(sk)->inet_num,
                        hashinfo->bhash_size);
        struct inet_bind_hashbucket *head = &hashinfo->bhash[bhash];
+       struct inet_bind_hashbucket *head2 =
+               inet_bhashfn_portaddr(hashinfo, sk, sock_net(sk),
+                                     inet_sk(sk)->inet_num);
        struct inet_bind_bucket *tb;
 
        spin_lock(&head->lock);
@@ -117,6 +183,17 @@ static void __inet_put_port(struct sock *sk)
        inet_csk(sk)->icsk_bind_hash = NULL;
        inet_sk(sk)->inet_num = 0;
        inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
+
+       spin_lock(&head2->lock);
+       if (inet_csk(sk)->icsk_bind2_hash) {
+               struct inet_bind2_bucket *tb2 = inet_csk(sk)->icsk_bind2_hash;
+
+               __sk_del_bind2_node(sk);
+               inet_csk(sk)->icsk_bind2_hash = NULL;
+               inet_bind2_bucket_destroy(hashinfo->bind2_bucket_cachep, tb2);
+       }
+       spin_unlock(&head2->lock);
+
        spin_unlock(&head->lock);
 }
 
@@ -135,12 +212,21 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
        const int bhash = inet_bhashfn(sock_net(sk), port,
                        table->bhash_size);
        struct inet_bind_hashbucket *head = &table->bhash[bhash];
+       struct inet_bind_hashbucket *head2 =
+               inet_bhashfn_portaddr(table, child, sock_net(sk), port);
+       bool created_inet_bind_bucket = false;
+       bool update_fastreuse = false;
+       struct net *net = sock_net(sk);
+       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
        int l3mdev;
 
        spin_lock(&head->lock);
+       spin_lock(&head2->lock);
        tb = inet_csk(sk)->icsk_bind_hash;
-       if (unlikely(!tb)) {
+       tb2 = inet_csk(sk)->icsk_bind2_hash;
+       if (unlikely(!tb || !tb2)) {
+               spin_unlock(&head2->lock);
                spin_unlock(&head->lock);
                return -ENOENT;
        }
@@ -153,25 +239,49 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child)
                 * as that of the child socket. We have to look up or
                 * create a new bind bucket for the child here. */
                inet_bind_bucket_for_each(tb, &head->chain) {
-                       if (net_eq(ib_net(tb), sock_net(sk)) &&
-                           tb->l3mdev == l3mdev && tb->port == port)
+                       if (inet_bind_bucket_match(tb, net, port, l3mdev))
                                break;
                }
                if (!tb) {
                        tb = inet_bind_bucket_create(table->bind_bucket_cachep,
-                                                    sock_net(sk), head, port,
-                                                    l3mdev);
+                                                    net, head, port, l3mdev);
                        if (!tb) {
+                               spin_unlock(&head2->lock);
                                spin_unlock(&head->lock);
                                return -ENOMEM;
                        }
+                       created_inet_bind_bucket = true;
+               }
+               update_fastreuse = true;
+
+               goto bhash2_find;
+       } else if (!inet_bind2_bucket_addr_match(tb2, child)) {
+               l3mdev = inet_sk_bound_l3mdev(sk);
+
+bhash2_find:
+               tb2 = inet_bind2_bucket_find(head2, net, port, l3mdev, child);
+               if (!tb2) {
+                       tb2 = inet_bind2_bucket_create(table->bind2_bucket_cachep,
+                                                      net, head2, port,
+                                                      l3mdev, child);
+                       if (!tb2)
+                               goto error;
                }
-               inet_csk_update_fastreuse(tb, child);
        }
-       inet_bind_hash(child, tb, port);
+       if (update_fastreuse)
+               inet_csk_update_fastreuse(tb, child);
+       inet_bind_hash(child, tb, tb2, port);
+       spin_unlock(&head2->lock);
        spin_unlock(&head->lock);
 
        return 0;
+
+error:
+       if (created_inet_bind_bucket)
+               inet_bind_bucket_destroy(table->bind_bucket_cachep, tb);
+       spin_unlock(&head2->lock);
+       spin_unlock(&head->lock);
+       return -ENOMEM;
 }
 EXPORT_SYMBOL_GPL(__inet_inherit_port);
 
@@ -675,6 +785,112 @@ void inet_unhash(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(inet_unhash);
 
+static bool inet_bind2_bucket_match(const struct inet_bind2_bucket *tb,
+                                   const struct net *net, unsigned short port,
+                                   int l3mdev, const struct sock *sk)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       if (sk->sk_family == AF_INET6)
+               return net_eq(ib2_net(tb), net) && tb->port == port &&
+                       tb->l3mdev == l3mdev &&
+                       ipv6_addr_equal(&tb->v6_rcv_saddr, &sk->sk_v6_rcv_saddr);
+       else
+#endif
+               return net_eq(ib2_net(tb), net) && tb->port == port &&
+                       tb->l3mdev == l3mdev && tb->rcv_saddr == sk->sk_rcv_saddr;
+}
+
+bool inet_bind2_bucket_match_addr_any(const struct inet_bind2_bucket *tb, const struct net *net,
+                                     unsigned short port, int l3mdev, const struct sock *sk)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       struct in6_addr addr_any = {};
+
+       if (sk->sk_family == AF_INET6)
+               return net_eq(ib2_net(tb), net) && tb->port == port &&
+                       tb->l3mdev == l3mdev &&
+                       ipv6_addr_equal(&tb->v6_rcv_saddr, &addr_any);
+       else
+#endif
+               return net_eq(ib2_net(tb), net) && tb->port == port &&
+                       tb->l3mdev == l3mdev && tb->rcv_saddr == 0;
+}
+
+/* The socket's bhash2 hashbucket spinlock must be held when this is called */
+struct inet_bind2_bucket *
+inet_bind2_bucket_find(const struct inet_bind_hashbucket *head, const struct net *net,
+                      unsigned short port, int l3mdev, const struct sock *sk)
+{
+       struct inet_bind2_bucket *bhash2 = NULL;
+
+       inet_bind_bucket_for_each(bhash2, &head->chain)
+               if (inet_bind2_bucket_match(bhash2, net, port, l3mdev, sk))
+                       break;
+
+       return bhash2;
+}
+
+struct inet_bind_hashbucket *
+inet_bhash2_addr_any_hashbucket(const struct sock *sk, const struct net *net, int port)
+{
+       struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
+       u32 hash;
+#if IS_ENABLED(CONFIG_IPV6)
+       struct in6_addr addr_any = {};
+
+       if (sk->sk_family == AF_INET6)
+               hash = ipv6_portaddr_hash(net, &addr_any, port);
+       else
+#endif
+               hash = ipv4_portaddr_hash(net, 0, port);
+
+       return &hinfo->bhash2[hash & (hinfo->bhash_size - 1)];
+}
+
+int inet_bhash2_update_saddr(struct inet_bind_hashbucket *prev_saddr, struct sock *sk)
+{
+       struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo;
+       struct inet_bind2_bucket *tb2, *new_tb2;
+       int l3mdev = inet_sk_bound_l3mdev(sk);
+       struct inet_bind_hashbucket *head2;
+       int port = inet_sk(sk)->inet_num;
+       struct net *net = sock_net(sk);
+
+       /* Allocate a bind2 bucket ahead of time to avoid permanently putting
+        * the bhash2 table in an inconsistent state if a new tb2 bucket
+        * allocation fails.
+        */
+       new_tb2 = kmem_cache_alloc(hinfo->bind2_bucket_cachep, GFP_ATOMIC);
+       if (!new_tb2)
+               return -ENOMEM;
+
+       head2 = inet_bhashfn_portaddr(hinfo, sk, net, port);
+
+       if (prev_saddr) {
+               spin_lock_bh(&prev_saddr->lock);
+               __sk_del_bind2_node(sk);
+               inet_bind2_bucket_destroy(hinfo->bind2_bucket_cachep,
+                                         inet_csk(sk)->icsk_bind2_hash);
+               spin_unlock_bh(&prev_saddr->lock);
+       }
+
+       spin_lock_bh(&head2->lock);
+       tb2 = inet_bind2_bucket_find(head2, net, port, l3mdev, sk);
+       if (!tb2) {
+               tb2 = new_tb2;
+               inet_bind2_bucket_init(tb2, net, head2, port, l3mdev, sk);
+       }
+       sk_add_bind2_node(sk, &tb2->owners);
+       inet_csk(sk)->icsk_bind2_hash = tb2;
+       spin_unlock_bh(&head2->lock);
+
+       if (tb2 != new_tb2)
+               kmem_cache_free(hinfo->bind2_bucket_cachep, new_tb2);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(inet_bhash2_update_saddr);
+
 /* RFC 6056 3.3.4.  Algorithm 4: Double-Hash Port Selection Algorithm
  * Note that we use 32bit integers (vs RFC 'short integers')
  * because 2^16 is not a multiple of num_ephemeral and this
@@ -694,11 +910,13 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
                        struct sock *, __u16, struct inet_timewait_sock **))
 {
        struct inet_hashinfo *hinfo = death_row->hashinfo;
+       struct inet_bind_hashbucket *head, *head2;
        struct inet_timewait_sock *tw = NULL;
-       struct inet_bind_hashbucket *head;
        int port = inet_sk(sk)->inet_num;
        struct net *net = sock_net(sk);
+       struct inet_bind2_bucket *tb2;
        struct inet_bind_bucket *tb;
+       bool tb_created = false;
        u32 remaining, offset;
        int ret, i, low, high;
        int l3mdev;
@@ -755,8 +973,7 @@ other_parity_scan:
                 * the established check is already unique enough.
                 */
                inet_bind_bucket_for_each(tb, &head->chain) {
-                       if (net_eq(ib_net(tb), net) && tb->l3mdev == l3mdev &&
-                           tb->port == port) {
+                       if (inet_bind_bucket_match(tb, net, port, l3mdev)) {
                                if (tb->fastreuse >= 0 ||
                                    tb->fastreuseport >= 0)
                                        goto next_port;
@@ -774,6 +991,7 @@ other_parity_scan:
                        spin_unlock_bh(&head->lock);
                        return -ENOMEM;
                }
+               tb_created = true;
                tb->fastreuse = -1;
                tb->fastreuseport = -1;
                goto ok;
@@ -789,6 +1007,20 @@ next_port:
        return -EADDRNOTAVAIL;
 
 ok:
+       /* Find the corresponding tb2 bucket since we need to
+        * add the socket to the bhash2 table as well
+        */
+       head2 = inet_bhashfn_portaddr(hinfo, sk, net, port);
+       spin_lock(&head2->lock);
+
+       tb2 = inet_bind2_bucket_find(head2, net, port, l3mdev, sk);
+       if (!tb2) {
+               tb2 = inet_bind2_bucket_create(hinfo->bind2_bucket_cachep, net,
+                                              head2, port, l3mdev, sk);
+               if (!tb2)
+                       goto error;
+       }
+
        /* Here we want to add a little bit of randomness to the next source
         * port that will be chosen. We use a max() with a random here so that
         * on low contention the randomness is maximal and on high contention
@@ -798,7 +1030,10 @@ ok:
        WRITE_ONCE(table_perturb[index], READ_ONCE(table_perturb[index]) + i + 2);
 
        /* Head lock still held and bh's disabled */
-       inet_bind_hash(sk, tb, port);
+       inet_bind_hash(sk, tb, tb2, port);
+
+       spin_unlock(&head2->lock);
+
        if (sk_unhashed(sk)) {
                inet_sk(sk)->inet_sport = htons(port);
                inet_ehash_nolisten(sk, (struct sock *)tw, NULL);
@@ -810,6 +1045,13 @@ ok:
                inet_twsk_deschedule_put(tw);
        local_bh_enable();
        return 0;
+
+error:
+       spin_unlock(&head2->lock);
+       if (tb_created)
+               inet_bind_bucket_destroy(hinfo->bind_bucket_cachep, tb);
+       spin_unlock_bh(&head->lock);
+       return -ENOMEM;
 }
 
 /*
index 5c58e21..f866d62 100644 (file)
@@ -609,7 +609,7 @@ static int gre_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb)
        ip_tunnel_init_flow(&fl4, IPPROTO_GRE, key->u.ipv4.dst, key->u.ipv4.src,
                            tunnel_id_to_key32(key->tun_id),
                            key->tos & ~INET_ECN_MASK, dev_net(dev), 0,
-                           skb->mark, skb_get_hash(skb));
+                           skb->mark, skb_get_hash(skb), key->flow_flags);
        rt = ip_route_output_key(dev_net(dev), &fl4);
        if (IS_ERR(rt))
                return PTR_ERR(rt);
index 04e2034..8201cd4 100644 (file)
@@ -1109,10 +1109,7 @@ alloc_new_skb:
                                 (fraglen + alloc_extra < SKB_MAX_ALLOC ||
                                  !(rt->dst.dev->features & NETIF_F_SG)))
                                alloclen = fraglen;
-                       else if (!zc) {
-                               alloclen = min_t(int, fraglen, MAX_HEADER);
-                               pagedlen = fraglen - alloclen;
-                       } else {
+                       else {
                                alloclen = fragheaderlen + transhdrlen;
                                pagedlen = datalen - transhdrlen;
                        }
index e65e948..019f3b0 100644 (file)
@@ -295,7 +295,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
                ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
                                    iph->saddr, tunnel->parms.o_key,
                                    RT_TOS(iph->tos), dev_net(dev),
-                                   tunnel->parms.link, tunnel->fwmark, 0);
+                                   tunnel->parms.link, tunnel->fwmark, 0, 0);
                rt = ip_route_output_key(tunnel->net, &fl4);
 
                if (!IS_ERR(rt)) {
@@ -570,7 +570,8 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        }
        ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
                            tunnel_id_to_key32(key->tun_id), RT_TOS(tos),
-                           dev_net(dev), 0, skb->mark, skb_get_hash(skb));
+                           dev_net(dev), 0, skb->mark, skb_get_hash(skb),
+                           key->flow_flags);
        if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
                goto tx_error;
 
@@ -729,7 +730,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
                            tunnel->parms.o_key, RT_TOS(tos),
                            dev_net(dev), tunnel->parms.link,
-                           tunnel->fwmark, skb_get_hash(skb));
+                           tunnel->fwmark, skb_get_hash(skb), 0);
 
        if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
                goto tx_error;
index e5011c1..306b94d 100644 (file)
@@ -4433,12 +4433,16 @@ static void __tcp_alloc_md5sig_pool(void)
         * to memory. See smp_rmb() in tcp_get_md5sig_pool()
         */
        smp_wmb();
-       tcp_md5sig_pool_populated = true;
+       /* Paired with READ_ONCE() from tcp_alloc_md5sig_pool()
+        * and tcp_get_md5sig_pool().
+       */
+       WRITE_ONCE(tcp_md5sig_pool_populated, true);
 }
 
 bool tcp_alloc_md5sig_pool(void)
 {
-       if (unlikely(!tcp_md5sig_pool_populated)) {
+       /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */
+       if (unlikely(!READ_ONCE(tcp_md5sig_pool_populated))) {
                mutex_lock(&tcp_md5sig_mutex);
 
                if (!tcp_md5sig_pool_populated) {
@@ -4449,7 +4453,8 @@ bool tcp_alloc_md5sig_pool(void)
 
                mutex_unlock(&tcp_md5sig_mutex);
        }
-       return tcp_md5sig_pool_populated;
+       /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */
+       return READ_ONCE(tcp_md5sig_pool_populated);
 }
 EXPORT_SYMBOL(tcp_alloc_md5sig_pool);
 
@@ -4465,7 +4470,8 @@ struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
 {
        local_bh_disable();
 
-       if (tcp_md5sig_pool_populated) {
+       /* Paired with WRITE_ONCE() from __tcp_alloc_md5sig_pool() */
+       if (READ_ONCE(tcp_md5sig_pool_populated)) {
                /* coupled with smp_wmb() in __tcp_alloc_md5sig_pool() */
                smp_rmb();
                return this_cpu_ptr(&tcp_md5sig_pool);
@@ -4736,6 +4742,12 @@ void __init tcp_init(void)
                                  SLAB_HWCACHE_ALIGN | SLAB_PANIC |
                                  SLAB_ACCOUNT,
                                  NULL);
+       tcp_hashinfo.bind2_bucket_cachep =
+               kmem_cache_create("tcp_bind2_bucket",
+                                 sizeof(struct inet_bind2_bucket), 0,
+                                 SLAB_HWCACHE_ALIGN | SLAB_PANIC |
+                                 SLAB_ACCOUNT,
+                                 NULL);
 
        /* Size and allocate the main established and bind bucket
         * hash tables.
@@ -4759,7 +4771,7 @@ void __init tcp_init(void)
                panic("TCP: failed to alloc ehash_locks");
        tcp_hashinfo.bhash =
                alloc_large_system_hash("TCP bind",
-                                       sizeof(struct inet_bind_hashbucket),
+                                       2 * sizeof(struct inet_bind_hashbucket),
                                        tcp_hashinfo.ehash_mask + 1,
                                        17, /* one slot per 128 KB of memory */
                                        0,
@@ -4768,9 +4780,12 @@ void __init tcp_init(void)
                                        0,
                                        64 * 1024);
        tcp_hashinfo.bhash_size = 1U << tcp_hashinfo.bhash_size;
+       tcp_hashinfo.bhash2 = tcp_hashinfo.bhash + tcp_hashinfo.bhash_size;
        for (i = 0; i < tcp_hashinfo.bhash_size; i++) {
                spin_lock_init(&tcp_hashinfo.bhash[i].lock);
                INIT_HLIST_HEAD(&tcp_hashinfo.bhash[i].chain);
+               spin_lock_init(&tcp_hashinfo.bhash2[i].lock);
+               INIT_HLIST_HEAD(&tcp_hashinfo.bhash2[i].chain);
        }
 
 
index 825b216..45cc7f1 100644 (file)
@@ -272,8 +272,9 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
         * The request socket is not added to the ehash
         * because it's been added to the accept queue directly.
         */
+       req->timeout = tcp_timeout_init(child);
        inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS,
-                                 TCP_TIMEOUT_INIT, TCP_RTO_MAX);
+                                 req->timeout, TCP_RTO_MAX);
 
        refcount_set(&req->rsk_refcnt, 2);
 
index ab5f0ea..b85a9f7 100644 (file)
@@ -3614,12 +3614,9 @@ bool tcp_oow_rate_limited(struct net *net, const struct sk_buff *skb,
 /* RFC 5961 7 [ACK Throttling] */
 static void tcp_send_challenge_ack(struct sock *sk)
 {
-       /* unprotected vars, we dont care of overwrites */
-       static u32 challenge_timestamp;
-       static unsigned int challenge_count;
        struct tcp_sock *tp = tcp_sk(sk);
        struct net *net = sock_net(sk);
-       u32 count, now;
+       u32 count, now, ack_limit;
 
        /* First check our per-socket dupack rate limit. */
        if (__tcp_oow_rate_limited(net,
@@ -3627,18 +3624,22 @@ static void tcp_send_challenge_ack(struct sock *sk)
                                   &tp->last_oow_ack_time))
                return;
 
+       ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
+       if (ack_limit == INT_MAX)
+               goto send_ack;
+
        /* Then check host-wide RFC 5961 rate limit. */
        now = jiffies / HZ;
-       if (now != challenge_timestamp) {
-               u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
+       if (now != READ_ONCE(net->ipv4.tcp_challenge_timestamp)) {
                u32 half = (ack_limit + 1) >> 1;
 
-               challenge_timestamp = now;
-               WRITE_ONCE(challenge_count, half + prandom_u32_max(ack_limit));
+               WRITE_ONCE(net->ipv4.tcp_challenge_timestamp, now);
+               WRITE_ONCE(net->ipv4.tcp_challenge_count, half + prandom_u32_max(ack_limit));
        }
-       count = READ_ONCE(challenge_count);
+       count = READ_ONCE(net->ipv4.tcp_challenge_count);
        if (count > 0) {
-               WRITE_ONCE(challenge_count, count - 1);
+               WRITE_ONCE(net->ipv4.tcp_challenge_count, count - 1);
+send_ack:
                NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);
                tcp_send_ack(sk);
        }
index 0c83780..01b31f5 100644 (file)
@@ -199,11 +199,12 @@ static int tcp_v4_pre_connect(struct sock *sk, struct sockaddr *uaddr,
 /* This will initiate an outgoing connection. */
 int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
+       struct inet_bind_hashbucket *prev_addr_hashbucket = NULL;
        struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
+       __be32 daddr, nexthop, prev_sk_rcv_saddr;
        struct inet_sock *inet = inet_sk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        __be16 orig_sport, orig_dport;
-       __be32 daddr, nexthop;
        struct flowi4 *fl4;
        struct rtable *rt;
        int err;
@@ -246,10 +247,28 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (!inet_opt || !inet_opt->opt.srr)
                daddr = fl4->daddr;
 
-       if (!inet->inet_saddr)
+       if (!inet->inet_saddr) {
+               if (inet_csk(sk)->icsk_bind2_hash) {
+                       prev_addr_hashbucket = inet_bhashfn_portaddr(&tcp_hashinfo,
+                                                                    sk, sock_net(sk),
+                                                                    inet->inet_num);
+                       prev_sk_rcv_saddr = sk->sk_rcv_saddr;
+               }
                inet->inet_saddr = fl4->saddr;
+       }
+
        sk_rcv_saddr_set(sk, inet->inet_saddr);
 
+       if (prev_addr_hashbucket) {
+               err = inet_bhash2_update_saddr(prev_addr_hashbucket, sk);
+               if (err) {
+                       inet->inet_saddr = 0;
+                       sk_rcv_saddr_set(sk, prev_sk_rcv_saddr);
+                       ip_rt_put(rt);
+                       return err;
+               }
+       }
+
        if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) {
                /* Reset inherited state */
                tp->rx_opt.ts_recent       = 0;
@@ -3139,8 +3158,10 @@ static int __net_init tcp_sk_init(struct net *net)
        net->ipv4.sysctl_tcp_tso_win_divisor = 3;
        /* Default TSQ limit of 16 TSO segments */
        net->ipv4.sysctl_tcp_limit_output_bytes = 16 * 65536;
-       /* rfc5961 challenge ack rate limiting */
-       net->ipv4.sysctl_tcp_challenge_ack_limit = 1000;
+
+       /* rfc5961 challenge ack rate limiting, per net-ns, disabled by default. */
+       net->ipv4.sysctl_tcp_challenge_ack_limit = INT_MAX;
+
        net->ipv4.sysctl_tcp_min_tso_segs = 2;
        net->ipv4.sysctl_tcp_tso_rtt_log = 9;  /* 2^9 = 512 usec */
        net->ipv4.sysctl_tcp_min_rtt_wlen = 300;
index d58e672..82f4575 100644 (file)
@@ -969,6 +969,7 @@ static struct genl_family tcp_metrics_nl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = tcp_metrics_nl_ops,
        .n_small_ops    = ARRAY_SIZE(tcp_metrics_nl_ops),
+       .resv_start_op  = TCP_METRICS_CMD_DEL + 1,
 };
 
 static unsigned int tcpmhash_entries;
index 30abde8..a844a0d 100644 (file)
@@ -195,12 +195,9 @@ struct sk_buff *tcp_gro_receive(struct list_head *head, struct sk_buff *skb)
 
        off = skb_gro_offset(skb);
        hlen = off + sizeof(*th);
-       th = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, hlen)) {
-               th = skb_gro_header_slow(skb, hlen, off);
-               if (unlikely(!th))
-                       goto out;
-       }
+       th = skb_gro_header(skb, hlen, off);
+       if (unlikely(!th))
+               goto out;
 
        thlen = th->doff * 4;
        if (thlen < sizeof(*th))
index b4dfb82..cb79127 100644 (file)
@@ -428,7 +428,7 @@ static void tcp_fastopen_synack_timer(struct sock *sk, struct request_sock *req)
        if (!tp->retrans_stamp)
                tp->retrans_stamp = tcp_time_stamp(tp);
        inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS,
-                         TCP_TIMEOUT_INIT << req->num_timeout, TCP_RTO_MAX);
+                         req->timeout << req->num_timeout, TCP_RTO_MAX);
 }
 
 
index 36c58aa..3faf625 100644 (file)
@@ -55,6 +55,7 @@ struct genl_family ila_nl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .ops            = ila_nl_ops,
        .n_ops          = ARRAY_SIZE(ila_nl_ops),
+       .resv_start_op  = ILA_CMD_FLUSH + 1,
 };
 
 static __net_init int ila_init_net(struct net *net)
index 1098131..571f0e4 100644 (file)
@@ -619,6 +619,7 @@ static struct genl_family ioam6_genl_family __ro_after_init = {
        .parallel_ops   = true,
        .ops            = ioam6_genl_ops,
        .n_ops          = ARRAY_SIZE(ioam6_genl_ops),
+       .resv_start_op  = IOAM6_CMD_NS_SET_SCHEMA + 1,
        .module         = THIS_MODULE,
 };
 
index 80cb50d..48b4ff0 100644 (file)
@@ -360,7 +360,7 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net,
        if (parms->name[0]) {
                if (!dev_valid_name(parms->name))
                        return NULL;
-               strlcpy(name, parms->name, IFNAMSIZ);
+               strscpy(name, parms->name, IFNAMSIZ);
        } else {
                strcpy(name, "ip6gre%d");
        }
index d12dba2..d37a8c9 100644 (file)
@@ -219,12 +219,9 @@ INDIRECT_CALLABLE_SCOPE struct sk_buff *ipv6_gro_receive(struct list_head *head,
 
        off = skb_gro_offset(skb);
        hlen = off + sizeof(*iph);
-       iph = skb_gro_header_fast(skb, off);
-       if (skb_gro_header_hard(skb, hlen)) {
-               iph = skb_gro_header_slow(skb, hlen, off);
-               if (unlikely(!iph))
-                       goto out;
-       }
+       iph = skb_gro_header_slow(skb, hlen, off);
+       if (unlikely(!iph))
+               goto out;
 
        skb_set_network_header(skb, off);
        skb_gro_pull(skb, sizeof(*iph));
index f152e51..a60176e 100644 (file)
@@ -1648,10 +1648,7 @@ alloc_new_skb:
                                 (fraglen + alloc_extra < SKB_MAX_ALLOC ||
                                  !(rt->dst.dev->features & NETIF_F_SG)))
                                alloclen = fraglen;
-                       else if (!zc) {
-                               alloclen = min_t(int, fraglen, MAX_HEADER);
-                               pagedlen = fraglen - alloclen;
-                       } else {
+                       else {
                                alloclen = fragheaderlen + transhdrlen;
                                pagedlen = datalen - transhdrlen;
                        }
index 79c6a82..9e97f3b 100644 (file)
@@ -293,7 +293,7 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p)
        if (p->name[0]) {
                if (!dev_valid_name(p->name))
                        goto failed;
-               strlcpy(name, p->name, IFNAMSIZ);
+               strscpy(name, p->name, IFNAMSIZ);
        } else {
                sprintf(name, "ip6tnl%%d");
        }
index 8fe59a7..1ddd60d 100644 (file)
@@ -211,7 +211,7 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p
        if (p->name[0]) {
                if (!dev_valid_name(p->name))
                        goto failed;
-               strlcpy(name, p->name, IFNAMSIZ);
+               strscpy(name, p->name, IFNAMSIZ);
        } else {
                sprintf(name, "ip6_vti%%d");
        }
index 73aaabf..5421cc7 100644 (file)
@@ -499,6 +499,7 @@ static struct genl_family seg6_genl_family __ro_after_init = {
        .parallel_ops   = true,
        .ops            = seg6_genl_ops,
        .n_ops          = ARRAY_SIZE(seg6_genl_ops),
+       .resv_start_op  = SEG6_CMD_GET_TUNSRC + 1,
        .module         = THIS_MODULE,
 };
 
index 6b73b7a..98f1cf4 100644 (file)
@@ -254,7 +254,7 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net,
        if (parms->name[0]) {
                if (!dev_valid_name(parms->name))
                        goto failed;
-               strlcpy(name, parms->name, IFNAMSIZ);
+               strscpy(name, parms->name, IFNAMSIZ);
        } else {
                strcpy(name, "sit%d");
        }
index e54eee8..3501349 100644 (file)
@@ -287,8 +287,25 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        }
 
        if (!saddr) {
+               struct inet_bind_hashbucket *prev_addr_hashbucket = NULL;
+               struct in6_addr prev_v6_rcv_saddr;
+
+               if (icsk->icsk_bind2_hash) {
+                       prev_addr_hashbucket = inet_bhashfn_portaddr(&tcp_hashinfo,
+                                                                    sk, sock_net(sk),
+                                                                    inet->inet_num);
+                       prev_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
+               }
                saddr = &fl6.saddr;
                sk->sk_v6_rcv_saddr = *saddr;
+
+               if (prev_addr_hashbucket) {
+                       err = inet_bhash2_update_saddr(prev_addr_hashbucket, sk);
+                       if (err) {
+                               sk->sk_v6_rcv_saddr = prev_v6_rcv_saddr;
+                               goto failure;
+                       }
+               }
        }
 
        /* set the source address */
@@ -841,7 +858,7 @@ const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
 static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 seq,
                                 u32 ack, u32 win, u32 tsval, u32 tsecr,
                                 int oif, struct tcp_md5sig_key *key, int rst,
-                                u8 tclass, __be32 label, u32 priority)
+                                u8 tclass, __be32 label, u32 priority, u32 txhash)
 {
        const struct tcphdr *th = tcp_hdr(skb);
        struct tcphdr *t1;
@@ -932,16 +949,16 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
        }
 
        if (sk) {
-               if (sk->sk_state == TCP_TIME_WAIT) {
+               if (sk->sk_state == TCP_TIME_WAIT)
                        mark = inet_twsk(sk)->tw_mark;
-                       /* autoflowlabel relies on buff->hash */
-                       skb_set_hash(buff, inet_twsk(sk)->tw_txhash,
-                                    PKT_HASH_TYPE_L4);
-               } else {
+               else
                        mark = sk->sk_mark;
-               }
                skb_set_delivery_time(buff, tcp_transmit_time(sk), true);
        }
+       if (txhash) {
+               /* autoflowlabel/skb_get_hash_flowi6 rely on buff->hash */
+               skb_set_hash(buff, txhash, PKT_HASH_TYPE_L4);
+       }
        fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark;
        fl6.fl6_dport = t1->dest;
        fl6.fl6_sport = t1->source;
@@ -1068,7 +1085,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
        }
 
        tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1,
-                            ipv6_get_dsfield(ipv6h), label, priority);
+                            ipv6_get_dsfield(ipv6h), label, priority, 0);
 
 #ifdef CONFIG_TCP_MD5SIG
 out:
@@ -1079,10 +1096,10 @@ out:
 static void tcp_v6_send_ack(const struct sock *sk, struct sk_buff *skb, u32 seq,
                            u32 ack, u32 win, u32 tsval, u32 tsecr, int oif,
                            struct tcp_md5sig_key *key, u8 tclass,
-                           __be32 label, u32 priority)
+                           __be32 label, u32 priority, u32 txhash)
 {
        tcp_v6_send_response(sk, skb, seq, ack, win, tsval, tsecr, oif, key, 0,
-                            tclass, label, priority);
+                            tclass, label, priority, txhash);
 }
 
 static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
@@ -1094,7 +1111,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
                        tcp_time_stamp_raw() + tcptw->tw_ts_offset,
                        tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw),
-                       tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel), tw->tw_priority);
+                       tw->tw_tclass, cpu_to_be32(tw->tw_flowlabel), tw->tw_priority,
+                       tw->tw_txhash);
 
        inet_twsk_put(tw);
 }
@@ -1121,7 +1139,8 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
                        req->ts_recent, sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index),
-                       ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority);
+                       ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority,
+                       tcp_rsk(req)->txhash);
 }
 
 
index 71899e5..1215c86 100644 (file)
@@ -1412,12 +1412,6 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
        psock->sk = csk;
        psock->bpf_prog = prog;
 
-       err = strp_init(&psock->strp, csk, &cb);
-       if (err) {
-               kmem_cache_free(kcm_psockp, psock);
-               goto out;
-       }
-
        write_lock_bh(&csk->sk_callback_lock);
 
        /* Check if sk_user_data is already by KCM or someone else.
@@ -1425,13 +1419,18 @@ static int kcm_attach(struct socket *sock, struct socket *csock,
         */
        if (csk->sk_user_data) {
                write_unlock_bh(&csk->sk_callback_lock);
-               strp_stop(&psock->strp);
-               strp_done(&psock->strp);
                kmem_cache_free(kcm_psockp, psock);
                err = -EALREADY;
                goto out;
        }
 
+       err = strp_init(&psock->strp, csk, &cb);
+       if (err) {
+               write_unlock_bh(&csk->sk_callback_lock);
+               kmem_cache_free(kcm_psockp, psock);
+               goto out;
+       }
+
        psock->save_data_ready = csk->sk_data_ready;
        psock->save_write_space = csk->sk_write_space;
        psock->save_state_change = csk->sk_state_change;
index 6cd97c7..f2ae03c 100644 (file)
@@ -254,7 +254,7 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
        int rc;
 
        if (cfg->ifname) {
-               strlcpy(name, cfg->ifname, IFNAMSIZ);
+               strscpy(name, cfg->ifname, IFNAMSIZ);
                name_assign_type = NET_NAME_USER;
        } else {
                strcpy(name, L2TP_ETH_DEV_NAME);
@@ -314,7 +314,7 @@ static int l2tp_eth_create(struct net *net, struct l2tp_tunnel *tunnel,
                return rc;
        }
 
-       strlcpy(session->ifname, dev->name, IFNAMSIZ);
+       strscpy(session->ifname, dev->name, IFNAMSIZ);
        rcu_assign_pointer(spriv->dev, dev);
 
        rtnl_unlock();
index 96eb91b..a901fd1 100644 (file)
@@ -989,6 +989,7 @@ static struct genl_family l2tp_nl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = l2tp_nl_ops,
        .n_small_ops    = ARRAY_SIZE(l2tp_nl_ops),
+       .resv_start_op  = L2TP_CMD_SESSION_GET + 1,
        .mcgrps         = l2tp_multicast_group,
        .n_mcgrps       = ARRAY_SIZE(l2tp_multicast_group),
 };
index af1df3a..b8de44d 100644 (file)
@@ -16,6 +16,7 @@ mac80211-y := \
        s1g.o \
        ibss.o \
        iface.o \
+       link.o \
        rate.o \
        michael.o \
        tkip.o \
index a4f6971..687b4c8 100644 (file)
 #include "mesh.h"
 #include "wme.h"
 
+static struct ieee80211_link_data *
+ieee80211_link_or_deflink(struct ieee80211_sub_if_data *sdata, int link_id,
+                         bool require_valid)
+{
+       struct ieee80211_link_data *link;
+
+       if (link_id < 0) {
+               /*
+                * For keys, if sdata is not an MLD, we might not use
+                * the return value at all (if it's not a pairwise key),
+                * so in that case (require_valid==false) don't error.
+                */
+               if (require_valid && sdata->vif.valid_links)
+                       return ERR_PTR(-EINVAL);
+
+               return &sdata->deflink;
+       }
+
+       link = sdata_dereference(sdata->link[link_id], sdata);
+       if (!link)
+               return ERR_PTR(-ENOLINK);
+       return link;
+}
+
 static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
                                         struct vif_params *params)
 {
@@ -202,6 +226,10 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
                if (params->use_4addr == ifmgd->use_4addr)
                        return 0;
 
+               /* FIXME: no support for 4-addr MLO yet */
+               if (sdata->vif.valid_links)
+                       return -EOPNOTSUPP;
+
                sdata->u.mgd.use_4addr = params->use_4addr;
                if (!ifmgd->associated)
                        return 0;
@@ -434,10 +462,12 @@ static int ieee80211_set_tx(struct ieee80211_sub_if_data *sdata,
 }
 
 static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
-                            u8 key_idx, bool pairwise, const u8 *mac_addr,
-                            struct key_params *params)
+                            int link_id, u8 key_idx, bool pairwise,
+                            const u8 *mac_addr, struct key_params *params)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_link_data *link =
+               ieee80211_link_or_deflink(sdata, link_id, false);
        struct ieee80211_local *local = sdata->local;
        struct sta_info *sta = NULL;
        struct ieee80211_key *key;
@@ -446,6 +476,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        if (!ieee80211_sdata_running(sdata))
                return -ENETDOWN;
 
+       if (IS_ERR(link))
+               return PTR_ERR(link);
+
        if (pairwise && params->mode == NL80211_KEY_SET_TX)
                return ieee80211_set_tx(sdata, mac_addr, key_idx);
 
@@ -454,6 +487,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        case WLAN_CIPHER_SUITE_WEP40:
        case WLAN_CIPHER_SUITE_TKIP:
        case WLAN_CIPHER_SUITE_WEP104:
+               if (link_id >= 0)
+                       return -EINVAL;
                if (WARN_ON_ONCE(fips_enabled))
                        return -EINVAL;
                break;
@@ -466,6 +501,8 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        if (IS_ERR(key))
                return PTR_ERR(key);
 
+       key->conf.link_id = link_id;
+
        if (pairwise)
                key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
 
@@ -527,7 +564,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                break;
        }
 
-       err = ieee80211_key_link(key, sdata, sta);
+       err = ieee80211_key_link(key, link, sta);
 
  out_unlock:
        mutex_unlock(&local->sta_mtx);
@@ -536,18 +573,37 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static struct ieee80211_key *
-ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
+ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata, int link_id,
                     u8 key_idx, bool pairwise, const u8 *mac_addr)
 {
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_link_data *link = &sdata->deflink;
        struct ieee80211_key *key;
-       struct sta_info *sta;
+
+       if (link_id >= 0) {
+               link = rcu_dereference_check(sdata->link[link_id],
+                                            lockdep_is_held(&sdata->wdev.mtx));
+               if (!link)
+                       return NULL;
+       }
 
        if (mac_addr) {
+               struct sta_info *sta;
+               struct link_sta_info *link_sta;
+
                sta = sta_info_get_bss(sdata, mac_addr);
                if (!sta)
                        return NULL;
 
+               if (link_id >= 0) {
+                       link_sta = rcu_dereference_check(sta->link[link_id],
+                                                        lockdep_is_held(&local->sta_mtx));
+                       if (!link_sta)
+                               return NULL;
+               } else {
+                       link_sta = &sta->deflink;
+               }
+
                if (pairwise && key_idx < NUM_DEFAULT_KEYS)
                        return rcu_dereference_check_key_mtx(local,
                                                             sta->ptk[key_idx]);
@@ -557,7 +613,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
                              NUM_DEFAULT_MGMT_KEYS +
                              NUM_DEFAULT_BEACON_KEYS)
                        return rcu_dereference_check_key_mtx(local,
-                                                            sta->deflink.gtk[key_idx]);
+                                                            link_sta->gtk[key_idx]);
 
                return NULL;
        }
@@ -566,7 +622,7 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
                return rcu_dereference_check_key_mtx(local,
                                                     sdata->keys[key_idx]);
 
-       key = rcu_dereference_check_key_mtx(local, sdata->deflink.gtk[key_idx]);
+       key = rcu_dereference_check_key_mtx(local, link->gtk[key_idx]);
        if (key)
                return key;
 
@@ -578,7 +634,8 @@ ieee80211_lookup_key(struct ieee80211_sub_if_data *sdata,
 }
 
 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
-                            u8 key_idx, bool pairwise, const u8 *mac_addr)
+                            int link_id, u8 key_idx, bool pairwise,
+                            const u8 *mac_addr)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
@@ -588,7 +645,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
        mutex_lock(&local->sta_mtx);
        mutex_lock(&local->key_mtx);
 
-       key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
+       key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
        if (!key) {
                ret = -ENOENT;
                goto out_unlock;
@@ -605,8 +662,8 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 }
 
 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
-                            u8 key_idx, bool pairwise, const u8 *mac_addr,
-                            void *cookie,
+                            int link_id, u8 key_idx, bool pairwise,
+                            const u8 *mac_addr, void *cookie,
                             void (*callback)(void *cookie,
                                              struct key_params *params))
 {
@@ -624,7 +681,7 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
        rcu_read_lock();
 
-       key = ieee80211_lookup_key(sdata, key_idx, pairwise, mac_addr);
+       key = ieee80211_lookup_key(sdata, link_id, key_idx, pairwise, mac_addr);
        if (!key)
                goto out;
 
@@ -711,34 +768,49 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 
 static int ieee80211_config_default_key(struct wiphy *wiphy,
                                        struct net_device *dev,
-                                       u8 key_idx, bool uni,
+                                       int link_id, u8 key_idx, bool uni,
                                        bool multi)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_link_data *link =
+               ieee80211_link_or_deflink(sdata, link_id, false);
 
-       ieee80211_set_default_key(sdata, key_idx, uni, multi);
+       if (IS_ERR(link))
+               return PTR_ERR(link);
+
+       ieee80211_set_default_key(link, key_idx, uni, multi);
 
        return 0;
 }
 
 static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
                                             struct net_device *dev,
-                                            u8 key_idx)
+                                            int link_id, u8 key_idx)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_link_data *link =
+               ieee80211_link_or_deflink(sdata, link_id, true);
+
+       if (IS_ERR(link))
+               return PTR_ERR(link);
 
-       ieee80211_set_default_mgmt_key(sdata, key_idx);
+       ieee80211_set_default_mgmt_key(link, key_idx);
 
        return 0;
 }
 
 static int ieee80211_config_default_beacon_key(struct wiphy *wiphy,
                                               struct net_device *dev,
-                                              u8 key_idx)
+                                              int link_id, u8 key_idx)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_link_data *link =
+               ieee80211_link_or_deflink(sdata, link_id, true);
+
+       if (IS_ERR(link))
+               return PTR_ERR(link);
 
-       ieee80211_set_default_beacon_key(sdata, key_idx);
+       ieee80211_set_default_beacon_key(link, key_idx);
 
        return 0;
 }
@@ -1610,6 +1682,18 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
                rcu_dereference_protected(sta->link[link_id],
                                          lockdep_is_held(&local->sta_mtx));
 
+       /*
+        * If there are no changes, then accept a link that doesn't exist,
+        * unless it's a new link.
+        */
+       if (params->link_id < 0 && !new_link &&
+           !params->link_mac && !params->txpwr_set &&
+           !params->supported_rates_len &&
+           !params->ht_capa && !params->vht_capa &&
+           !params->he_capa && !params->eht_capa &&
+           !params->opmode_notif_used)
+               return 0;
+
        if (!link || !link_sta)
                return -EINVAL;
 
@@ -1625,6 +1709,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
                                             params->link_mac)) {
                        return -EINVAL;
                }
+       } else if (new_link) {
+               return -EINVAL;
        }
 
        if (params->txpwr_set) {
@@ -2554,7 +2640,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
 {
        struct ieee80211_local *local = wiphy_priv(wiphy);
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_link_data *link = &sdata->deflink;
+       struct ieee80211_link_data *link =
+               ieee80211_link_or_deflink(sdata, params->link_id, true);
        struct ieee80211_tx_queue_params p;
 
        if (!local->ops->conf_tx)
@@ -2563,6 +2650,9 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
        if (local->hw.queues < IEEE80211_NUM_ACS)
                return -EOPNOTSUPP;
 
+       if (IS_ERR(link))
+               return PTR_ERR(link);
+
        memset(&p, 0, sizeof(p));
        p.aifs = params->aifs;
        p.cw_max = params->cwmax;
@@ -3597,9 +3687,6 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
        case NL80211_IFTYPE_MESH_POINT: {
                struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
-               if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
-                       return -EINVAL;
-
                /* changes into another band are not supported */
                if (sdata->vif.bss_conf.chandef.chan->band !=
                    params->chandef.chan->band)
@@ -3732,7 +3819,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
 
        cfg80211_ch_switch_started_notify(sdata->dev,
-                                         &sdata->deflink.csa_chandef,
+                                         &sdata->deflink.csa_chandef, 0,
                                          params->count, params->block_tx);
 
        if (changed) {
@@ -4614,6 +4701,9 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
+       if (wdev->use_4addr)
+               return -EOPNOTSUPP;
+
        return ieee80211_vif_set_links(sdata, wdev->valid_links);
 }
 
index 31e20a3..18bc6b7 100644 (file)
@@ -30,7 +30,9 @@ ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
                return;
 
        mcs_nss_size = ieee80211_eht_mcs_nss_size(he_cap_ie_elem,
-                                                 &eht_cap_ie_elem->fixed);
+                                                 &eht_cap_ie_elem->fixed,
+                                                 sdata->vif.type ==
+                                                       NL80211_IFTYPE_STATION);
 
        eht_total_size += mcs_nss_size;
 
index c2b3837..a3830d9 100644 (file)
@@ -83,17 +83,17 @@ static void ieee80211_get_stats(struct net_device *dev,
 
 #define ADD_STA_STATS(sta)                                     \
        do {                                                    \
-               data[i++] += (sta)->rx_stats.packets;           \
-               data[i++] += (sta)->rx_stats.bytes;             \
+               data[i++] += sinfo.rx_packets;                  \
+               data[i++] += sinfo.rx_bytes;                    \
                data[i++] += (sta)->rx_stats.num_duplicates;    \
                data[i++] += (sta)->rx_stats.fragments;         \
-               data[i++] += (sta)->rx_stats.dropped;           \
+               data[i++] += sinfo.rx_dropped_misc;             \
                                                                \
                data[i++] += sinfo.tx_packets;                  \
                data[i++] += sinfo.tx_bytes;                    \
                data[i++] += (sta)->status_stats.filtered;      \
-               data[i++] += (sta)->status_stats.retry_failed;  \
-               data[i++] += (sta)->status_stats.retry_count;   \
+               data[i++] += sinfo.tx_failed;                   \
+               data[i++] += sinfo.tx_retries;                  \
        } while (0)
 
        /* For Managed stations, find the single station based on BSSID
index 9b283bb..9dffc30 100644 (file)
@@ -1350,10 +1350,10 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
                                  capability, 0, true);
 }
 
-static unsigned ibss_setup_channels(struct wiphy *wiphy,
-                                   struct ieee80211_channel **channels,
-                                   unsigned int channels_max,
-                                   u32 center_freq, u32 width)
+static unsigned int ibss_setup_channels(struct wiphy *wiphy,
+                                       struct ieee80211_channel **channels,
+                                       unsigned int channels_max,
+                                       u32 center_freq, u32 width)
 {
        struct ieee80211_channel *chan = NULL;
        unsigned int n_chan = 0;
index e192e1e..977aea4 100644 (file)
@@ -213,6 +213,7 @@ struct ieee80211_rx_data {
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_link_data *link;
        struct sta_info *sta;
+       struct link_sta_info *link_sta;
        struct ieee80211_key *key;
 
        unsigned int flags;
@@ -1810,6 +1811,7 @@ void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
                                   u8 reason, bool tx);
 void ieee80211_mgd_setup_link(struct ieee80211_link_data *link);
 void ieee80211_mgd_stop_link(struct ieee80211_link_data *link);
+void ieee80211_mgd_set_link_qos_params(struct ieee80211_link_data *link);
 
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -1929,9 +1931,6 @@ void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata);
 int ieee80211_add_virtual_monitor(struct ieee80211_local *local);
 void ieee80211_del_virtual_monitor(struct ieee80211_local *local);
 
-int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
-                           u16 new_links);
-
 bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata);
 void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata,
                              bool update_bss);
@@ -1942,6 +1941,17 @@ static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata)
        return test_bit(SDATA_STATE_RUNNING, &sdata->state);
 }
 
+/* link handling */
+void ieee80211_link_setup(struct ieee80211_link_data *link);
+void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
+                        int link_id,
+                        struct ieee80211_link_data *link,
+                        struct ieee80211_bss_conf *link_conf);
+void ieee80211_link_stop(struct ieee80211_link_data *link);
+int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
+                           u16 new_links);
+void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata);
+
 /* tx handling */
 void ieee80211_clear_tx_pending(struct ieee80211_local *local);
 void ieee80211_tx_pending(struct tasklet_struct *t);
@@ -2184,6 +2194,8 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata,
  *     for that non-transmitting BSS is returned
  * @link_id: the link ID to parse elements for, if a STA profile
  *     is present in the multi-link element, or -1 to ignore
+ * @from_ap: frame is received from an AP (currently used only
+ *     for EHT capabilities parsing)
  */
 struct ieee80211_elems_parse_params {
        const u8 *start;
@@ -2193,6 +2205,7 @@ struct ieee80211_elems_parse_params {
        u32 crc;
        struct cfg80211_bss *bss;
        int link_id;
+       bool from_ap;
 };
 
 struct ieee802_11_elems *
@@ -2382,6 +2395,7 @@ u8 *ieee80211_ie_build_he_cap(ieee80211_conn_flags_t disable_flags, u8 *pos,
                              const struct ieee80211_sta_he_cap *he_cap,
                              u8 *end);
 void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
+                                   enum ieee80211_smps_mode smps_mode,
                                    struct sk_buff *skb);
 u8 *ieee80211_ie_build_he_oper(u8 *pos, struct cfg80211_chan_def *chandef);
 int ieee80211_parse_bitrates(enum nl80211_chan_width width,
@@ -2407,8 +2421,7 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
                                const struct ieee80211_vht_operation *oper,
                                const struct ieee80211_ht_operation *htop,
                                struct cfg80211_chan_def *chandef);
-void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
-                               const struct ieee80211_eht_operation *eht_oper,
+void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
                                bool support_160, bool support_320,
                                struct cfg80211_chan_def *chandef);
 bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
@@ -2513,7 +2526,8 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype);
 u8 *ieee80211_ie_build_eht_cap(u8 *pos,
                               const struct ieee80211_sta_he_cap *he_cap,
                               const struct ieee80211_sta_eht_cap *eht_cap,
-                              u8 *end);
+                              u8 *end,
+                              bool for_ap);
 
 void
 ieee80211_eht_cap_ie_to_sta_eht_cap(struct ieee80211_sub_if_data *sdata,
index 95b58c5..f99685e 100644 (file)
@@ -200,15 +200,73 @@ static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr,
        return ret;
 }
 
+static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdata)
+{
+       struct ieee80211_roc_work *roc;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_sub_if_data *scan_sdata;
+       int ret = 0;
+
+       /* To be the most flexible here we want to only limit changing the
+        * address if the specific interface is doing offchannel work or
+        * scanning.
+        */
+       if (netif_carrier_ok(sdata->dev))
+               return -EBUSY;
+
+       mutex_lock(&local->mtx);
+
+       /* First check no ROC work is happening on this iface */
+       list_for_each_entry(roc, &local->roc_list, list) {
+               if (roc->sdata != sdata)
+                       continue;
+
+               if (roc->started) {
+                       ret = -EBUSY;
+                       goto unlock;
+               }
+       }
+
+       /* And if this iface is scanning */
+       if (local->scanning) {
+               scan_sdata = rcu_dereference_protected(local->scan_sdata,
+                                                      lockdep_is_held(&local->mtx));
+               if (sdata == scan_sdata)
+                       ret = -EBUSY;
+       }
+
+       switch (sdata->vif.type) {
+       case NL80211_IFTYPE_STATION:
+       case NL80211_IFTYPE_P2P_CLIENT:
+               /* More interface types could be added here but changing the
+                * address while powered makes the most sense in client modes.
+                */
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+unlock:
+       mutex_unlock(&local->mtx);
+       return ret;
+}
+
 static int ieee80211_change_mac(struct net_device *dev, void *addr)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
        struct sockaddr *sa = addr;
        bool check_dup = true;
+       bool live = false;
        int ret;
 
-       if (ieee80211_sdata_running(sdata))
-               return -EBUSY;
+       if (ieee80211_sdata_running(sdata)) {
+               ret = ieee80211_can_powered_addr_change(sdata);
+               if (ret)
+                       return ret;
+
+               live = true;
+       }
 
        if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
            !(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
@@ -218,6 +276,8 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
        if (ret)
                return ret;
 
+       if (live)
+               drv_remove_interface(local, sdata);
        ret = eth_mac_addr(dev, sa);
 
        if (ret == 0) {
@@ -225,6 +285,12 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
                ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
        }
 
+       /* Regardless of eth_mac_addr() return we still want to add the
+        * interface back. This should not fail...
+        */
+       if (live)
+               WARN_ON(drv_add_interface(local, sdata));
+
        return ret;
 }
 
@@ -296,6 +362,11 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
                                                        nsdata->vif.type))
                                return -ENOTUNIQ;
 
+                       /* No support for VLAN with MLO yet */
+                       if (iftype == NL80211_IFTYPE_AP_VLAN &&
+                           nsdata->wdev.use_4addr)
+                               return -EOPNOTSUPP;
+
                        /*
                         * can only add VLANs to enabled APs
                         */
@@ -368,246 +439,6 @@ static int ieee80211_open(struct net_device *dev)
        return err;
 }
 
-static void ieee80211_link_setup(struct ieee80211_link_data *link)
-{
-       if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
-               ieee80211_mgd_setup_link(link);
-}
-
-static void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
-                               int link_id,
-                               struct ieee80211_link_data *link,
-                               struct ieee80211_bss_conf *link_conf)
-{
-       bool deflink = link_id < 0;
-
-       if (link_id < 0)
-               link_id = 0;
-
-       rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf);
-       rcu_assign_pointer(sdata->link[link_id], link);
-
-       link->sdata = sdata;
-       link->link_id = link_id;
-       link->conf = link_conf;
-       link_conf->link_id = link_id;
-
-       INIT_WORK(&link->csa_finalize_work,
-                 ieee80211_csa_finalize_work);
-       INIT_WORK(&link->color_change_finalize_work,
-                 ieee80211_color_change_finalize_work);
-       INIT_LIST_HEAD(&link->assigned_chanctx_list);
-       INIT_LIST_HEAD(&link->reserved_chanctx_list);
-       INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
-                         ieee80211_dfs_cac_timer_work);
-
-       if (!deflink) {
-               switch (sdata->vif.type) {
-               case NL80211_IFTYPE_AP:
-                       ether_addr_copy(link_conf->addr,
-                                       sdata->wdev.links[link_id].addr);
-                       WARN_ON(!(sdata->wdev.valid_links & BIT(link_id)));
-                       break;
-               case NL80211_IFTYPE_STATION:
-                       break;
-               default:
-                       WARN_ON(1);
-               }
-       }
-}
-
-static void ieee80211_link_stop(struct ieee80211_link_data *link)
-{
-       if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
-               ieee80211_mgd_stop_link(link);
-
-       ieee80211_link_release_channel(link);
-}
-
-struct link_container {
-       struct ieee80211_link_data data;
-       struct ieee80211_bss_conf conf;
-};
-
-static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
-                                struct link_container **links)
-{
-       unsigned int link_id;
-
-       synchronize_rcu();
-
-       for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
-               if (!links[link_id])
-                       continue;
-               ieee80211_link_stop(&links[link_id]->data);
-               kfree(links[link_id]);
-       }
-}
-
-static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
-{
-       unsigned int i, j;
-
-       for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
-               struct ieee80211_link_data *link1;
-
-               link1 = sdata_dereference(sdata->link[i], sdata);
-               if (!link1)
-                       continue;
-               for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) {
-                       struct ieee80211_link_data *link2;
-
-                       link2 = sdata_dereference(sdata->link[j], sdata);
-                       if (!link2)
-                               continue;
-
-                       if (ether_addr_equal(link1->conf->addr,
-                                            link2->conf->addr))
-                               return -EALREADY;
-               }
-       }
-
-       return 0;
-}
-
-static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
-                                     struct link_container **to_free,
-                                     u16 new_links)
-{
-       u16 old_links = sdata->vif.valid_links;
-       unsigned long add = new_links & ~old_links;
-       unsigned long rem = old_links & ~new_links;
-       unsigned int link_id;
-       int ret;
-       struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *link;
-       struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS];
-       struct ieee80211_link_data *old_data[IEEE80211_MLD_MAX_NUM_LINKS];
-       bool use_deflink = old_links == 0; /* set for error case */
-
-       sdata_assert_lock(sdata);
-
-       memset(to_free, 0, sizeof(links));
-
-       if (old_links == new_links)
-               return 0;
-
-       /* if there were no old links, need to clear the pointers to deflink */
-       if (!old_links)
-               rem |= BIT(0);
-
-       /* allocate new link structures first */
-       for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
-               link = kzalloc(sizeof(*link), GFP_KERNEL);
-               if (!link) {
-                       ret = -ENOMEM;
-                       goto free;
-               }
-               links[link_id] = link;
-       }
-
-       /* keep track of the old pointers for the driver */
-       BUILD_BUG_ON(sizeof(old) != sizeof(sdata->vif.link_conf));
-       memcpy(old, sdata->vif.link_conf, sizeof(old));
-       /* and for us in error cases */
-       BUILD_BUG_ON(sizeof(old_data) != sizeof(sdata->link));
-       memcpy(old_data, sdata->link, sizeof(old_data));
-
-       /* grab old links to free later */
-       for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
-               if (rcu_access_pointer(sdata->link[link_id]) != &sdata->deflink) {
-                       /*
-                        * we must have allocated the data through this path so
-                        * we know we can free both at the same time
-                        */
-                       to_free[link_id] = container_of(rcu_access_pointer(sdata->link[link_id]),
-                                                       typeof(*links[link_id]),
-                                                       data);
-               }
-
-               RCU_INIT_POINTER(sdata->link[link_id], NULL);
-               RCU_INIT_POINTER(sdata->vif.link_conf[link_id], NULL);
-       }
-
-       /* link them into data structures */
-       for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
-               WARN_ON(!use_deflink &&
-                       rcu_access_pointer(sdata->link[link_id]) == &sdata->deflink);
-
-               link = links[link_id];
-               ieee80211_link_init(sdata, link_id, &link->data, &link->conf);
-               ieee80211_link_setup(&link->data);
-       }
-
-       if (new_links == 0)
-               ieee80211_link_init(sdata, -1, &sdata->deflink,
-                                   &sdata->vif.bss_conf);
-
-       sdata->vif.valid_links = new_links;
-
-       ret = ieee80211_check_dup_link_addrs(sdata);
-       if (!ret) {
-               /* tell the driver */
-               ret = drv_change_vif_links(sdata->local, sdata,
-                                          old_links, new_links,
-                                          old);
-       }
-
-       if (ret) {
-               /* restore config */
-               memcpy(sdata->link, old_data, sizeof(old_data));
-               memcpy(sdata->vif.link_conf, old, sizeof(old));
-               sdata->vif.valid_links = old_links;
-               /* and free (only) the newly allocated links */
-               memset(to_free, 0, sizeof(links));
-               goto free;
-       }
-
-       /* use deflink/bss_conf again if and only if there are no more links */
-       use_deflink = new_links == 0;
-
-       goto deinit;
-free:
-       /* if we failed during allocation, only free all */
-       for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
-               kfree(links[link_id]);
-               links[link_id] = NULL;
-       }
-deinit:
-       if (use_deflink)
-               ieee80211_link_init(sdata, -1, &sdata->deflink,
-                                   &sdata->vif.bss_conf);
-       return ret;
-}
-
-int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
-                           u16 new_links)
-{
-       struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
-       int ret;
-
-       ret = ieee80211_vif_update_links(sdata, links, new_links);
-       ieee80211_free_links(sdata, links);
-
-       return ret;
-}
-
-static void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata)
-{
-       struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
-
-       /*
-        * The locking here is different because when we free links
-        * in the station case we need to be able to cancel_work_sync()
-        * something that also takes the lock.
-        */
-
-       sdata_lock(sdata);
-       ieee80211_vif_update_links(sdata, links, 0);
-       sdata_unlock(sdata);
-
-       ieee80211_free_links(sdata, links);
-}
-
 static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
 {
        struct ieee80211_local *local = sdata->local;
@@ -2267,7 +2098,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                wdev = &sdata->wdev;
 
                sdata->dev = NULL;
-               strlcpy(sdata->name, name, IFNAMSIZ);
+               strscpy(sdata->name, name, IFNAMSIZ);
                ieee80211_assign_perm_addr(local, wdev->address, type);
                memcpy(sdata->vif.addr, wdev->address, ETH_ALEN);
                ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
@@ -2396,6 +2227,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
                        sdata->u.mgd.use_4addr = params->use_4addr;
 
                ndev->features |= local->hw.netdev_features;
+               ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
                ndev->hw_features |= ndev->features &
                                        MAC80211_SUPPORTED_FEATURES_TX;
 
index 6befb57..d89ec93 100644 (file)
@@ -344,9 +344,10 @@ static void ieee80211_pairwise_rekey(struct ieee80211_key *old,
        }
 }
 
-static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
+static void __ieee80211_set_default_key(struct ieee80211_link_data *link,
                                        int idx, bool uni, bool multi)
 {
+       struct ieee80211_sub_if_data *sdata = link->sdata;
        struct ieee80211_key *key = NULL;
 
        assert_key_lock(sdata->local);
@@ -354,7 +355,7 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
        if (idx >= 0 && idx < NUM_DEFAULT_KEYS) {
                key = key_mtx_dereference(sdata->local, sdata->keys[idx]);
                if (!key)
-                       key = key_mtx_dereference(sdata->local, sdata->deflink.gtk[idx]);
+                       key = key_mtx_dereference(sdata->local, link->gtk[idx]);
        }
 
        if (uni) {
@@ -365,47 +366,48 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
        }
 
        if (multi)
-               rcu_assign_pointer(sdata->deflink.default_multicast_key, key);
+               rcu_assign_pointer(link->default_multicast_key, key);
 
        ieee80211_debugfs_key_update_default(sdata);
 }
 
-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
+void ieee80211_set_default_key(struct ieee80211_link_data *link, int idx,
                               bool uni, bool multi)
 {
-       mutex_lock(&sdata->local->key_mtx);
-       __ieee80211_set_default_key(sdata, idx, uni, multi);
-       mutex_unlock(&sdata->local->key_mtx);
+       mutex_lock(&link->sdata->local->key_mtx);
+       __ieee80211_set_default_key(link, idx, uni, multi);
+       mutex_unlock(&link->sdata->local->key_mtx);
 }
 
 static void
-__ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
+__ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link, int idx)
 {
+       struct ieee80211_sub_if_data *sdata = link->sdata;
        struct ieee80211_key *key = NULL;
 
        assert_key_lock(sdata->local);
 
        if (idx >= NUM_DEFAULT_KEYS &&
            idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
-               key = key_mtx_dereference(sdata->local,
-                                         sdata->deflink.gtk[idx]);
+               key = key_mtx_dereference(sdata->local, link->gtk[idx]);
 
-       rcu_assign_pointer(sdata->deflink.default_mgmt_key, key);
+       rcu_assign_pointer(link->default_mgmt_key, key);
 
        ieee80211_debugfs_key_update_default(sdata);
 }
 
-void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
+void ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link,
                                    int idx)
 {
-       mutex_lock(&sdata->local->key_mtx);
-       __ieee80211_set_default_mgmt_key(sdata, idx);
-       mutex_unlock(&sdata->local->key_mtx);
+       mutex_lock(&link->sdata->local->key_mtx);
+       __ieee80211_set_default_mgmt_key(link, idx);
+       mutex_unlock(&link->sdata->local->key_mtx);
 }
 
 static void
-__ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
+__ieee80211_set_default_beacon_key(struct ieee80211_link_data *link, int idx)
 {
+       struct ieee80211_sub_if_data *sdata = link->sdata;
        struct ieee80211_key *key = NULL;
 
        assert_key_lock(sdata->local);
@@ -413,28 +415,30 @@ __ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata, int idx)
        if (idx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS &&
            idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS +
            NUM_DEFAULT_BEACON_KEYS)
-               key = key_mtx_dereference(sdata->local,
-                                         sdata->deflink.gtk[idx]);
+               key = key_mtx_dereference(sdata->local, link->gtk[idx]);
 
-       rcu_assign_pointer(sdata->deflink.default_beacon_key, key);
+       rcu_assign_pointer(link->default_beacon_key, key);
 
        ieee80211_debugfs_key_update_default(sdata);
 }
 
-void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
+void ieee80211_set_default_beacon_key(struct ieee80211_link_data *link,
                                      int idx)
 {
-       mutex_lock(&sdata->local->key_mtx);
-       __ieee80211_set_default_beacon_key(sdata, idx);
-       mutex_unlock(&sdata->local->key_mtx);
+       mutex_lock(&link->sdata->local->key_mtx);
+       __ieee80211_set_default_beacon_key(link, idx);
+       mutex_unlock(&link->sdata->local->key_mtx);
 }
 
 static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
-                                 struct sta_info *sta,
-                                 bool pairwise,
-                                 struct ieee80211_key *old,
-                                 struct ieee80211_key *new)
+                                struct ieee80211_link_data *link,
+                                struct sta_info *sta,
+                                bool pairwise,
+                                struct ieee80211_key *old,
+                                struct ieee80211_key *new)
 {
+       struct link_sta_info *link_sta = sta ? &sta->deflink : NULL;
+       int link_id;
        int idx;
        int ret = 0;
        bool defunikey, defmultikey, defmgmtkey, defbeaconkey;
@@ -446,13 +450,36 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
 
        if (new) {
                idx = new->conf.keyidx;
-               list_add_tail_rcu(&new->list, &sdata->key_list);
                is_wep = new->conf.cipher == WLAN_CIPHER_SUITE_WEP40 ||
                         new->conf.cipher == WLAN_CIPHER_SUITE_WEP104;
+               link_id = new->conf.link_id;
        } else {
                idx = old->conf.keyidx;
                is_wep = old->conf.cipher == WLAN_CIPHER_SUITE_WEP40 ||
                         old->conf.cipher == WLAN_CIPHER_SUITE_WEP104;
+               link_id = old->conf.link_id;
+       }
+
+       if (WARN(old && old->conf.link_id != link_id,
+                "old link ID %d doesn't match new link ID %d\n",
+                old->conf.link_id, link_id))
+               return -EINVAL;
+
+       if (link_id >= 0) {
+               if (!link) {
+                       link = sdata_dereference(sdata->link[link_id], sdata);
+                       if (!link)
+                               return -ENOLINK;
+               }
+
+               if (sta) {
+                       link_sta = rcu_dereference_protected(sta->link[link_id],
+                                                            lockdep_is_held(&sta->local->sta_mtx));
+                       if (!link_sta)
+                               return -ENOLINK;
+               }
+       } else {
+               link = &sdata->deflink;
        }
 
        if ((is_wep || pairwise) && idx >= NUM_DEFAULT_KEYS)
@@ -482,6 +509,9 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
        if (ret)
                return ret;
 
+       if (new)
+               list_add_tail_rcu(&new->list, &sdata->key_list);
+
        if (sta) {
                if (pairwise) {
                        rcu_assign_pointer(sta->ptk[idx], new);
@@ -489,7 +519,7 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                            !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX))
                                _ieee80211_set_tx_key(new, true);
                } else {
-                       rcu_assign_pointer(sta->deflink.gtk[idx], new);
+                       rcu_assign_pointer(link_sta->gtk[idx], new);
                }
                /* Only needed for transition from no key -> key.
                 * Still triggers unnecessary when using Extended Key ID
@@ -503,39 +533,39 @@ static int ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
                                                sdata->default_unicast_key);
                defmultikey = old &&
                        old == key_mtx_dereference(sdata->local,
-                                               sdata->deflink.default_multicast_key);
+                                                  link->default_multicast_key);
                defmgmtkey = old &&
                        old == key_mtx_dereference(sdata->local,
-                                               sdata->deflink.default_mgmt_key);
+                                                  link->default_mgmt_key);
                defbeaconkey = old &&
                        old == key_mtx_dereference(sdata->local,
-                                                  sdata->deflink.default_beacon_key);
+                                                  link->default_beacon_key);
 
                if (defunikey && !new)
-                       __ieee80211_set_default_key(sdata, -1, true, false);
+                       __ieee80211_set_default_key(link, -1, true, false);
                if (defmultikey && !new)
-                       __ieee80211_set_default_key(sdata, -1, false, true);
+                       __ieee80211_set_default_key(link, -1, false, true);
                if (defmgmtkey && !new)
-                       __ieee80211_set_default_mgmt_key(sdata, -1);
+                       __ieee80211_set_default_mgmt_key(link, -1);
                if (defbeaconkey && !new)
-                       __ieee80211_set_default_beacon_key(sdata, -1);
+                       __ieee80211_set_default_beacon_key(link, -1);
 
                if (is_wep || pairwise)
                        rcu_assign_pointer(sdata->keys[idx], new);
                else
-                       rcu_assign_pointer(sdata->deflink.gtk[idx], new);
+                       rcu_assign_pointer(link->gtk[idx], new);
 
                if (defunikey && new)
-                       __ieee80211_set_default_key(sdata, new->conf.keyidx,
+                       __ieee80211_set_default_key(link, new->conf.keyidx,
                                                    true, false);
                if (defmultikey && new)
-                       __ieee80211_set_default_key(sdata, new->conf.keyidx,
+                       __ieee80211_set_default_key(link, new->conf.keyidx,
                                                    false, true);
                if (defmgmtkey && new)
-                       __ieee80211_set_default_mgmt_key(sdata,
+                       __ieee80211_set_default_mgmt_key(link,
                                                         new->conf.keyidx);
                if (defbeaconkey && new)
-                       __ieee80211_set_default_beacon_key(sdata,
+                       __ieee80211_set_default_beacon_key(link,
                                                           new->conf.keyidx);
        }
 
@@ -569,6 +599,7 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
        key->conf.flags = 0;
        key->flags = 0;
 
+       key->conf.link_id = -1;
        key->conf.cipher = cipher;
        key->conf.keyidx = idx;
        key->conf.keylen = key_len;
@@ -797,9 +828,10 @@ static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
 }
 
 int ieee80211_key_link(struct ieee80211_key *key,
-                      struct ieee80211_sub_if_data *sdata,
+                      struct ieee80211_link_data *link,
                       struct sta_info *sta)
 {
+       struct ieee80211_sub_if_data *sdata = link->sdata;
        static atomic_t key_color = ATOMIC_INIT(0);
        struct ieee80211_key *old_key = NULL;
        int idx = key->conf.keyidx;
@@ -827,15 +859,26 @@ int ieee80211_key_link(struct ieee80211_key *key,
                    (old_key && old_key->conf.cipher != key->conf.cipher))
                        goto out;
        } else if (sta) {
-               old_key = key_mtx_dereference(sdata->local,
-                                             sta->deflink.gtk[idx]);
+               struct link_sta_info *link_sta = &sta->deflink;
+               int link_id = key->conf.link_id;
+
+               if (link_id >= 0) {
+                       link_sta = rcu_dereference_protected(sta->link[link_id],
+                                                            lockdep_is_held(&sta->local->sta_mtx));
+                       if (!link_sta) {
+                               ret = -ENOLINK;
+                               goto out;
+                       }
+               }
+
+               old_key = key_mtx_dereference(sdata->local, link_sta->gtk[idx]);
        } else {
                if (idx < NUM_DEFAULT_KEYS)
                        old_key = key_mtx_dereference(sdata->local,
                                                      sdata->keys[idx]);
                if (!old_key)
                        old_key = key_mtx_dereference(sdata->local,
-                                                     sdata->deflink.gtk[idx]);
+                                                     link->gtk[idx]);
        }
 
        /* Non-pairwise keys must also not switch the cipher on rekey */
@@ -866,7 +909,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
 
        increment_tailroom_need_count(sdata);
 
-       ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
+       ret = ieee80211_key_replace(sdata, link, sta, pairwise, old_key, key);
 
        if (!ret) {
                ieee80211_debugfs_key_add(key);
@@ -890,9 +933,9 @@ void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom)
         * Replace key with nothingness if it was ever used.
         */
        if (key->sdata)
-               ieee80211_key_replace(key->sdata, key->sta,
-                               key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
-                               key, NULL);
+               ieee80211_key_replace(key->sdata, NULL, key->sta,
+                                     key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+                                     key, NULL);
        ieee80211_key_destroy(key, delay_tailroom);
 }
 
@@ -1019,15 +1062,45 @@ static void ieee80211_free_keys_iface(struct ieee80211_sub_if_data *sdata,
        ieee80211_debugfs_key_remove_beacon_default(sdata);
 
        list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
-               ieee80211_key_replace(key->sdata, key->sta,
-                               key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
-                               key, NULL);
+               ieee80211_key_replace(key->sdata, NULL, key->sta,
+                                     key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+                                     key, NULL);
                list_add_tail(&key->list, keys);
        }
 
        ieee80211_debugfs_key_update_default(sdata);
 }
 
+void ieee80211_remove_link_keys(struct ieee80211_link_data *link,
+                               struct list_head *keys)
+{
+       struct ieee80211_sub_if_data *sdata = link->sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_key *key, *tmp;
+
+       mutex_lock(&local->key_mtx);
+       list_for_each_entry_safe(key, tmp, &sdata->key_list, list) {
+               if (key->conf.link_id != link->link_id)
+                       continue;
+               ieee80211_key_replace(key->sdata, link, key->sta,
+                                     key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+                                     key, NULL);
+               list_add_tail(&key->list, keys);
+       }
+       mutex_unlock(&local->key_mtx);
+}
+
+void ieee80211_free_key_list(struct ieee80211_local *local,
+                            struct list_head *keys)
+{
+       struct ieee80211_key *key, *tmp;
+
+       mutex_lock(&local->key_mtx);
+       list_for_each_entry_safe(key, tmp, keys, list)
+               __ieee80211_key_destroy(key, false);
+       mutex_unlock(&local->key_mtx);
+}
+
 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
                         bool force_synchronize)
 {
@@ -1087,9 +1160,9 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                key = key_mtx_dereference(local, sta->deflink.gtk[i]);
                if (!key)
                        continue;
-               ieee80211_key_replace(key->sdata, key->sta,
-                               key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
-                               key, NULL);
+               ieee80211_key_replace(key->sdata, NULL, key->sta,
+                                     key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+                                     key, NULL);
                __ieee80211_key_destroy(key, key->sdata->vif.type ==
                                        NL80211_IFTYPE_STATION);
        }
@@ -1098,9 +1171,9 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
                key = key_mtx_dereference(local, sta->ptk[i]);
                if (!key)
                        continue;
-               ieee80211_key_replace(key->sdata, key->sta,
-                               key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
-                               key, NULL);
+               ieee80211_key_replace(key->sdata, NULL, key->sta,
+                                     key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
+                                     key, NULL);
                __ieee80211_key_destroy(key, key->sdata->vif.type ==
                                        NL80211_IFTYPE_STATION);
        }
@@ -1307,7 +1380,8 @@ ieee80211_gtk_rekey_add(struct ieee80211_vif *vif,
        if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
                key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
 
-       err = ieee80211_key_link(key, sdata, NULL);
+       /* FIXME: this function needs to get a link ID */
+       err = ieee80211_key_link(key, &sdata->deflink, NULL);
        if (err)
                return ERR_PTR(err);
 
index e994dce..518af24 100644 (file)
@@ -22,6 +22,7 @@
 
 struct ieee80211_local;
 struct ieee80211_sub_if_data;
+struct ieee80211_link_data;
 struct sta_info;
 
 /**
@@ -144,17 +145,21 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len,
  * to make it used, free old key. On failure, also free the new key.
  */
 int ieee80211_key_link(struct ieee80211_key *key,
-                      struct ieee80211_sub_if_data *sdata,
+                      struct ieee80211_link_data *link,
                       struct sta_info *sta);
 int ieee80211_set_tx_key(struct ieee80211_key *key);
 void ieee80211_key_free(struct ieee80211_key *key, bool delay_tailroom);
 void ieee80211_key_free_unused(struct ieee80211_key *key);
-void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx,
+void ieee80211_set_default_key(struct ieee80211_link_data *link, int idx,
                               bool uni, bool multi);
-void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
+void ieee80211_set_default_mgmt_key(struct ieee80211_link_data *link,
                                    int idx);
-void ieee80211_set_default_beacon_key(struct ieee80211_sub_if_data *sdata,
+void ieee80211_set_default_beacon_key(struct ieee80211_link_data *link,
                                      int idx);
+void ieee80211_remove_link_keys(struct ieee80211_link_data *link,
+                               struct list_head *keys);
+void ieee80211_free_key_list(struct ieee80211_local *local,
+                            struct list_head *keys);
 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata,
                         bool force_synchronize);
 void ieee80211_free_sta_keys(struct ieee80211_local *local,
diff --git a/net/mac80211/link.c b/net/mac80211/link.c
new file mode 100644 (file)
index 0000000..096f313
--- /dev/null
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * MLO link handling
+ *
+ * Copyright (C) 2022 Intel Corporation
+ */
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <net/mac80211.h>
+#include "ieee80211_i.h"
+#include "driver-ops.h"
+
+void ieee80211_link_setup(struct ieee80211_link_data *link)
+{
+       if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
+               ieee80211_mgd_setup_link(link);
+}
+
+void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
+                        int link_id,
+                        struct ieee80211_link_data *link,
+                        struct ieee80211_bss_conf *link_conf)
+{
+       bool deflink = link_id < 0;
+
+       if (link_id < 0)
+               link_id = 0;
+
+       rcu_assign_pointer(sdata->vif.link_conf[link_id], link_conf);
+       rcu_assign_pointer(sdata->link[link_id], link);
+
+       link->sdata = sdata;
+       link->link_id = link_id;
+       link->conf = link_conf;
+       link_conf->link_id = link_id;
+
+       INIT_WORK(&link->csa_finalize_work,
+                 ieee80211_csa_finalize_work);
+       INIT_WORK(&link->color_change_finalize_work,
+                 ieee80211_color_change_finalize_work);
+       INIT_LIST_HEAD(&link->assigned_chanctx_list);
+       INIT_LIST_HEAD(&link->reserved_chanctx_list);
+       INIT_DELAYED_WORK(&link->dfs_cac_timer_work,
+                         ieee80211_dfs_cac_timer_work);
+
+       if (!deflink) {
+               switch (sdata->vif.type) {
+               case NL80211_IFTYPE_AP:
+                       ether_addr_copy(link_conf->addr,
+                                       sdata->wdev.links[link_id].addr);
+                       link_conf->bssid = link_conf->addr;
+                       WARN_ON(!(sdata->wdev.valid_links & BIT(link_id)));
+                       break;
+               case NL80211_IFTYPE_STATION:
+                       /* station sets the bssid in ieee80211_mgd_setup_link */
+                       break;
+               default:
+                       WARN_ON(1);
+               }
+       }
+}
+
+void ieee80211_link_stop(struct ieee80211_link_data *link)
+{
+       if (link->sdata->vif.type == NL80211_IFTYPE_STATION)
+               ieee80211_mgd_stop_link(link);
+
+       ieee80211_link_release_channel(link);
+}
+
+struct link_container {
+       struct ieee80211_link_data data;
+       struct ieee80211_bss_conf conf;
+};
+
+static void ieee80211_free_links(struct ieee80211_sub_if_data *sdata,
+                                struct link_container **links)
+{
+       LIST_HEAD(keys);
+       unsigned int link_id;
+
+       for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+               if (!links[link_id])
+                       continue;
+               ieee80211_remove_link_keys(&links[link_id]->data, &keys);
+       }
+
+       synchronize_rcu();
+
+       ieee80211_free_key_list(sdata->local, &keys);
+
+       for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+               if (!links[link_id])
+                       continue;
+               ieee80211_link_stop(&links[link_id]->data);
+               kfree(links[link_id]);
+       }
+}
+
+static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
+{
+       unsigned int i, j;
+
+       for (i = 0; i < IEEE80211_MLD_MAX_NUM_LINKS; i++) {
+               struct ieee80211_link_data *link1;
+
+               link1 = sdata_dereference(sdata->link[i], sdata);
+               if (!link1)
+                       continue;
+               for (j = i + 1; j < IEEE80211_MLD_MAX_NUM_LINKS; j++) {
+                       struct ieee80211_link_data *link2;
+
+                       link2 = sdata_dereference(sdata->link[j], sdata);
+                       if (!link2)
+                               continue;
+
+                       if (ether_addr_equal(link1->conf->addr,
+                                            link2->conf->addr))
+                               return -EALREADY;
+               }
+       }
+
+       return 0;
+}
+
+static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
+                                     struct link_container **to_free,
+                                     u16 new_links)
+{
+       u16 old_links = sdata->vif.valid_links;
+       unsigned long add = new_links & ~old_links;
+       unsigned long rem = old_links & ~new_links;
+       unsigned int link_id;
+       int ret;
+       struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS] = {}, *link;
+       struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS];
+       struct ieee80211_link_data *old_data[IEEE80211_MLD_MAX_NUM_LINKS];
+       bool use_deflink = old_links == 0; /* set for error case */
+
+       sdata_assert_lock(sdata);
+
+       memset(to_free, 0, sizeof(links));
+
+       if (old_links == new_links)
+               return 0;
+
+       /* if there were no old links, need to clear the pointers to deflink */
+       if (!old_links)
+               rem |= BIT(0);
+
+       /* allocate new link structures first */
+       for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
+               link = kzalloc(sizeof(*link), GFP_KERNEL);
+               if (!link) {
+                       ret = -ENOMEM;
+                       goto free;
+               }
+               links[link_id] = link;
+       }
+
+       /* keep track of the old pointers for the driver */
+       BUILD_BUG_ON(sizeof(old) != sizeof(sdata->vif.link_conf));
+       memcpy(old, sdata->vif.link_conf, sizeof(old));
+       /* and for us in error cases */
+       BUILD_BUG_ON(sizeof(old_data) != sizeof(sdata->link));
+       memcpy(old_data, sdata->link, sizeof(old_data));
+
+       /* grab old links to free later */
+       for_each_set_bit(link_id, &rem, IEEE80211_MLD_MAX_NUM_LINKS) {
+               if (rcu_access_pointer(sdata->link[link_id]) != &sdata->deflink) {
+                       /*
+                        * we must have allocated the data through this path so
+                        * we know we can free both at the same time
+                        */
+                       to_free[link_id] = container_of(rcu_access_pointer(sdata->link[link_id]),
+                                                       typeof(*links[link_id]),
+                                                       data);
+               }
+
+               RCU_INIT_POINTER(sdata->link[link_id], NULL);
+               RCU_INIT_POINTER(sdata->vif.link_conf[link_id], NULL);
+       }
+
+       /* link them into data structures */
+       for_each_set_bit(link_id, &add, IEEE80211_MLD_MAX_NUM_LINKS) {
+               WARN_ON(!use_deflink &&
+                       rcu_access_pointer(sdata->link[link_id]) == &sdata->deflink);
+
+               link = links[link_id];
+               ieee80211_link_init(sdata, link_id, &link->data, &link->conf);
+               ieee80211_link_setup(&link->data);
+       }
+
+       if (new_links == 0)
+               ieee80211_link_init(sdata, -1, &sdata->deflink,
+                                   &sdata->vif.bss_conf);
+
+       sdata->vif.valid_links = new_links;
+
+       ret = ieee80211_check_dup_link_addrs(sdata);
+       if (!ret) {
+               /* tell the driver */
+               ret = drv_change_vif_links(sdata->local, sdata,
+                                          old_links, new_links,
+                                          old);
+       }
+
+       if (ret) {
+               /* restore config */
+               memcpy(sdata->link, old_data, sizeof(old_data));
+               memcpy(sdata->vif.link_conf, old, sizeof(old));
+               sdata->vif.valid_links = old_links;
+               /* and free (only) the newly allocated links */
+               memset(to_free, 0, sizeof(links));
+               goto free;
+       }
+
+       /* use deflink/bss_conf again if and only if there are no more links */
+       use_deflink = new_links == 0;
+
+       goto deinit;
+free:
+       /* if we failed during allocation, only free all */
+       for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+               kfree(links[link_id]);
+               links[link_id] = NULL;
+       }
+deinit:
+       if (use_deflink)
+               ieee80211_link_init(sdata, -1, &sdata->deflink,
+                                   &sdata->vif.bss_conf);
+       return ret;
+}
+
+int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
+                           u16 new_links)
+{
+       struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
+       int ret;
+
+       ret = ieee80211_vif_update_links(sdata, links, new_links);
+       ieee80211_free_links(sdata, links);
+
+       return ret;
+}
+
+void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata)
+{
+       struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
+
+       /*
+        * The locking here is different because when we free links
+        * in the station case we need to be able to cancel_work_sync()
+        * something that also takes the lock.
+        */
+
+       sdata_lock(sdata);
+       ieee80211_vif_update_links(sdata, links, 0);
+       sdata_unlock(sdata);
+
+       ieee80211_free_links(sdata, links);
+}
index 5b1c47e..46f3edd 100644 (file)
@@ -699,6 +699,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
                              NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS);
        wiphy_ext_feature_set(wiphy,
                              NL80211_EXT_FEATURE_SCAN_FREQ_KHZ);
+       wiphy_ext_feature_set(wiphy,
+                             NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE);
 
        if (!ops->hw_scan) {
                wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN |
index 6991c4c..5a99b8f 100644 (file)
@@ -634,7 +634,7 @@ int mesh_add_he_6ghz_cap_ie(struct ieee80211_sub_if_data *sdata,
        if (!iftd)
                return 0;
 
-       ieee80211_ie_build_he_6ghz_cap(sdata, skb);
+       ieee80211_ie_build_he_6ghz_cap(sdata, sdata->deflink.smps_mode, skb);
        return 0;
 }
 
index 5265d2b..699e409 100644 (file)
@@ -314,7 +314,7 @@ ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
        if (eht_oper && (eht_oper->params & IEEE80211_EHT_OPER_INFO_PRESENT)) {
                struct cfg80211_chan_def eht_chandef = *chandef;
 
-               ieee80211_chandef_eht_oper(sdata, eht_oper,
+               ieee80211_chandef_eht_oper(eht_oper,
                                           eht_chandef.width ==
                                           NL80211_CHAN_WIDTH_160,
                                           false, &eht_chandef);
@@ -695,6 +695,7 @@ static bool ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
 static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
                                struct sk_buff *skb,
                                struct ieee80211_supported_band *sband,
+                               enum ieee80211_smps_mode smps_mode,
                                ieee80211_conn_flags_t conn_flags)
 {
        u8 *pos, *pre_he_pos;
@@ -719,7 +720,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
        /* trim excess if any */
        skb_trim(skb, skb->len - (pre_he_pos + he_cap_size - pos));
 
-       ieee80211_ie_build_he_6ghz_cap(sdata, skb);
+       ieee80211_ie_build_he_6ghz_cap(sdata, smps_mode, skb);
 }
 
 static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata,
@@ -746,11 +747,13 @@ static void ieee80211_add_eht_ie(struct ieee80211_sub_if_data *sdata,
        eht_cap_size =
                2 + 1 + sizeof(eht_cap->eht_cap_elem) +
                ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
-                                          &eht_cap->eht_cap_elem) +
+                                          &eht_cap->eht_cap_elem,
+                                          false) +
                ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
                                       eht_cap->eht_cap_elem.phy_cap_info);
        pos = skb_put(skb, eht_cap_size);
-       ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size);
+       ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, pos + eht_cap_size,
+                                  false);
 }
 
 static void ieee80211_assoc_add_rates(struct sk_buff *skb,
@@ -1098,7 +1101,7 @@ static size_t ieee80211_assoc_link_elems(struct ieee80211_sub_if_data *sdata,
                                               offset);
 
        if (!(assoc_data->link[link_id].conn_flags & IEEE80211_CONN_DISABLE_HE)) {
-               ieee80211_add_he_ie(sdata, skb, sband,
+               ieee80211_add_he_ie(sdata, skb, sband, smps_mode,
                                    assoc_data->link[link_id].conn_flags);
                ADD_PRESENT_EXT_ELEM(WLAN_EID_EXT_HE_CAPABILITY);
        }
@@ -1220,14 +1223,21 @@ static void ieee80211_assoc_add_ml_elem(struct ieee80211_sub_if_data *sdata,
        ml_elem = skb_put(skb, sizeof(*ml_elem));
        ml_elem->control =
                cpu_to_le16(IEEE80211_ML_CONTROL_TYPE_BASIC |
-                           IEEE80211_MLC_BASIC_PRES_EML_CAPA |
                            IEEE80211_MLC_BASIC_PRES_MLD_CAPA_OP);
        common = skb_put(skb, sizeof(*common));
        common->len = sizeof(*common) +
-                     2 + /* EML capabilities */
                      2;  /* MLD capa/ops */
        memcpy(common->mld_mac_addr, sdata->vif.addr, ETH_ALEN);
-       skb_put_data(skb, &eml_capa, sizeof(eml_capa));
+
+       /* add EML_CAPA only if needed, see Draft P802.11be_D2.1, 35.3.17 */
+       if (eml_capa &
+           cpu_to_le16((IEEE80211_EML_CAP_EMLSR_SUPP |
+                        IEEE80211_EML_CAP_EMLMR_SUPPORT))) {
+               common->len += 2; /* EML capabilities */
+               ml_elem->control |=
+                       cpu_to_le16(IEEE80211_MLC_BASIC_PRES_EML_CAPA);
+               skb_put_data(skb, &eml_capa, sizeof(eml_capa));
+       }
        /* need indication from userspace to support this */
        mld_capa_ops &= ~cpu_to_le16(IEEE80211_MLD_CAP_OP_TID_TO_LINK_MAP_NEG_SUPP);
        skb_put_data(skb, &mld_capa_ops, sizeof(mld_capa_ops));
@@ -1902,7 +1912,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
                                          IEEE80211_QUEUE_STOP_REASON_CSA);
        mutex_unlock(&local->mtx);
 
-       cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
+       cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef, 0,
                                          csa_ie.count, csa_ie.mode);
 
        if (local->ops->channel_switch) {
@@ -2435,6 +2445,29 @@ static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
        ieee80211_sta_handle_tspec_ac_params(sdata);
 }
 
+void ieee80211_mgd_set_link_qos_params(struct ieee80211_link_data *link)
+{
+       struct ieee80211_sub_if_data *sdata = link->sdata;
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_tx_queue_params *params = link->tx_conf;
+       u8 ac;
+
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               mlme_dbg(sdata,
+                        "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
+                        ac, params[ac].acm,
+                        params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
+                        params[ac].txop, params[ac].uapsd,
+                        ifmgd->tx_tspec[ac].downgraded);
+               if (!ifmgd->tx_tspec[ac].downgraded &&
+                   drv_conf_tx(local, link, ac, &params[ac]))
+                       link_err(link,
+                                "failed to set TX queue parameters for AC %d\n",
+                                ac);
+       }
+}
+
 /* MLME */
 static bool
 ieee80211_sta_wmm_params(struct ieee80211_local *local,
@@ -2566,20 +2599,10 @@ ieee80211_sta_wmm_params(struct ieee80211_local *local,
                }
        }
 
-       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-               mlme_dbg(sdata,
-                        "WMM AC=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
-                        ac, params[ac].acm,
-                        params[ac].aifs, params[ac].cw_min, params[ac].cw_max,
-                        params[ac].txop, params[ac].uapsd,
-                        ifmgd->tx_tspec[ac].downgraded);
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
                link->tx_conf[ac] = params[ac];
-               if (!ifmgd->tx_tspec[ac].downgraded &&
-                   drv_conf_tx(local, link, ac, &params[ac]))
-                       link_err(link,
-                                "failed to set TX queue parameters for AC %d\n",
-                                ac);
-       }
+
+       ieee80211_mgd_set_link_qos_params(link);
 
        /* enable WMM or activate new settings */
        link->conf->qos = true;
@@ -3904,6 +3927,7 @@ static bool ieee80211_assoc_config_link(struct ieee80211_link_data *link,
                .len = elem_len,
                .bss = cbss,
                .link_id = link == &sdata->deflink ? -1 : link->link_id,
+               .from_ap = true,
        };
        bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
        bool is_s1g = cbss->channel->band == NL80211_BAND_S1GHZ;
@@ -4572,6 +4596,11 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        bool is_6ghz = cbss->channel->band == NL80211_BAND_6GHZ;
        bool is_5ghz = cbss->channel->band == NL80211_BAND_5GHZ;
        struct ieee80211_bss *bss = (void *)cbss->priv;
+       struct ieee80211_elems_parse_params parse_params = {
+               .bss = cbss,
+               .link_id = -1,
+               .from_ap = true,
+       };
        struct ieee802_11_elems *elems;
        const struct cfg80211_bss_ies *ies;
        int ret;
@@ -4581,7 +4610,9 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata,
        rcu_read_lock();
 
        ies = rcu_dereference(cbss->ies);
-       elems = ieee802_11_parse_elems(ies->data, ies->len, false, cbss);
+       parse_params.start = ies->data;
+       parse_params.len = ies->len;
+       elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems) {
                rcu_read_unlock();
                return -ENOMEM;
@@ -4936,6 +4967,11 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
        u16 capab_info, status_code, aid;
+       struct ieee80211_elems_parse_params parse_params = {
+               .bss = NULL,
+               .link_id = -1,
+               .from_ap = true,
+       };
        struct ieee802_11_elems *elems;
        int ac;
        const u8 *elem_start;
@@ -4990,7 +5026,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                return;
 
        elem_len = len - (elem_start - (u8 *)mgmt);
-       elems = ieee802_11_parse_elems(elem_start, elem_len, false, NULL);
+       parse_params.start = elem_start;
+       parse_params.len = elem_len;
+       elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                goto notify_driver;
 
@@ -5123,7 +5161,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
        resp.req_ies = ifmgd->assoc_req_ies;
        resp.req_ies_len = ifmgd->assoc_req_ies_len;
        if (sdata->vif.valid_links)
-               resp.ap_mld_addr = assoc_data->ap_addr;
+               resp.ap_mld_addr = sdata->vif.cfg.ap_addr;
        cfg80211_rx_assoc_resp(sdata->dev, &resp);
 notify_driver:
        drv_mgd_complete_tx(sdata->local, sdata, &info);
@@ -5355,6 +5393,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
        u32 ncrc = 0;
        u8 *bssid, *variable = mgmt->u.beacon.variable;
        u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
+       struct ieee80211_elems_parse_params parse_params = {
+               .link_id = -1,
+               .from_ap = true,
+       };
 
        sdata_assert_lock(sdata);
 
@@ -5373,6 +5415,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
        if (baselen > len)
                return;
 
+       parse_params.start = variable;
+       parse_params.len = len - baselen;
+
        rcu_read_lock();
        chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
        if (!chanctx_conf) {
@@ -5391,8 +5436,8 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
        if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon &&
            !WARN_ON(sdata->vif.valid_links) &&
            ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->link[0].bss)) {
-               elems = ieee802_11_parse_elems(variable, len - baselen, false,
-                                              ifmgd->assoc_data->link[0].bss);
+               parse_params.bss = ifmgd->assoc_data->link[0].bss;
+               elems = ieee802_11_parse_elems_full(&parse_params);
                if (!elems)
                        return;
 
@@ -5458,9 +5503,10 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
         */
        if (!ieee80211_is_s1g_beacon(hdr->frame_control))
                ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4);
-       elems = ieee802_11_parse_elems_crc(variable, len - baselen,
-                                          false, care_about_ies, ncrc,
-                                          link->u.mgd.bss);
+       parse_params.bss = link->u.mgd.bss;
+       parse_params.filter = care_about_ies;
+       parse_params.crc = ncrc;
+       elems = ieee802_11_parse_elems_full(&parse_params);
        if (!elems)
                return;
        ncrc = elems->crc;
@@ -5670,6 +5716,13 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 
        sdata_lock(sdata);
 
+       if (rx_status->link_valid) {
+               link = sdata_dereference(sdata->link[rx_status->link_id],
+                                        sdata);
+               if (!link)
+                       goto out;
+       }
+
        switch (fc & IEEE80211_FCTL_STYPE) {
        case IEEE80211_STYPE_BEACON:
                ieee80211_rx_mgmt_beacon(link, (void *)mgmt,
@@ -5746,6 +5799,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                }
                break;
        }
+out:
        sdata_unlock(sdata);
 }
 
@@ -6281,6 +6335,8 @@ void ieee80211_mgd_setup_link(struct ieee80211_link_data *link)
        if (sdata->u.mgd.assoc_data)
                ether_addr_copy(link->conf->addr,
                                sdata->u.mgd.assoc_data->link[link_id].addr);
+       else if (!is_valid_ether_addr(link->conf->addr))
+               eth_random_addr(link->conf->addr);
 }
 
 /* scan finished notification */
@@ -6368,9 +6424,6 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
                goto out_err;
        }
 
-       if (mlo && !is_valid_ether_addr(link->conf->addr))
-               eth_random_addr(link->conf->addr);
-
        if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) {
                err = -EINVAL;
                goto out_err;
@@ -6853,6 +6906,10 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                }
        }
 
+       /* FIXME: no support for 4-addr MLO yet */
+       if (sdata->u.mgd.use_4addr && req->link_id >= 0)
+               return -EOPNOTSUPP;
+
        assoc_data = kzalloc(size, GFP_KERNEL);
        if (!assoc_data)
                return -ENOMEM;
index 45d7e71..511c809 100644 (file)
@@ -215,9 +215,19 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
 }
 
 static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
+                                          int link_id,
                                           struct sta_info *sta,
                                           struct sk_buff *skb)
 {
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+
+       if (link_id >= 0) {
+               status->link_valid = 1;
+               status->link_id = link_id;
+       } else {
+               status->link_valid = 0;
+       }
+
        skb_queue_tail(&sdata->skb_queue, skb);
        ieee80211_queue_work(&sdata->local->hw, &sdata->work);
        if (sta)
@@ -225,11 +235,12 @@ static void __ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
 }
 
 static void ieee80211_queue_skb_to_iface(struct ieee80211_sub_if_data *sdata,
+                                        int link_id,
                                         struct sta_info *sta,
                                         struct sk_buff *skb)
 {
        skb->protocol = 0;
-       __ieee80211_queue_skb_to_iface(sdata, sta, skb);
+       __ieee80211_queue_skb_to_iface(sdata, link_id, sta, skb);
 }
 
 static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
@@ -272,7 +283,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
        if (!skb)
                return;
 
-       ieee80211_queue_skb_to_iface(sdata, NULL, skb);
+       ieee80211_queue_skb_to_iface(sdata, -1, NULL, skb);
 }
 
 /*
@@ -1394,7 +1405,7 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        /* if this mpdu is fragmented - terminate rx aggregation session */
        sc = le16_to_cpu(hdr->seq_ctrl);
        if (sc & IEEE80211_SCTL_FRAG) {
-               ieee80211_queue_skb_to_iface(rx->sdata, NULL, skb);
+               ieee80211_queue_skb_to_iface(rx->sdata, rx->link_id, NULL, skb);
                return;
        }
 
@@ -1854,7 +1865,6 @@ static struct ieee80211_key *
 ieee80211_rx_get_bigtk(struct ieee80211_rx_data *rx, int idx)
 {
        struct ieee80211_key *key = NULL;
-       struct ieee80211_sub_if_data *sdata = rx->sdata;
        int idx2;
 
        /* Make sure key gets set if either BIGTK key index is set so that
@@ -1873,14 +1883,14 @@ ieee80211_rx_get_bigtk(struct ieee80211_rx_data *rx, int idx)
                        idx2 = idx - 1;
        }
 
-       if (rx->sta)
-               key = rcu_dereference(rx->sta->deflink.gtk[idx]);
+       if (rx->link_sta)
+               key = rcu_dereference(rx->link_sta->gtk[idx]);
        if (!key)
-               key = rcu_dereference(sdata->deflink.gtk[idx]);
-       if (!key && rx->sta)
-               key = rcu_dereference(rx->sta->deflink.gtk[idx2]);
+               key = rcu_dereference(rx->link->gtk[idx]);
+       if (!key && rx->link_sta)
+               key = rcu_dereference(rx->link_sta->gtk[idx2]);
        if (!key)
-               key = rcu_dereference(sdata->deflink.gtk[idx2]);
+               key = rcu_dereference(rx->link->gtk[idx2]);
 
        return key;
 }
@@ -1986,15 +1996,15 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                if (mmie_keyidx < NUM_DEFAULT_KEYS ||
                    mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
                        return RX_DROP_MONITOR; /* unexpected BIP keyidx */
-               if (rx->sta) {
+               if (rx->link_sta) {
                        if (ieee80211_is_group_privacy_action(skb) &&
                            test_sta_flag(rx->sta, WLAN_STA_MFP))
                                return RX_DROP_MONITOR;
 
-                       rx->key = rcu_dereference(rx->sta->deflink.gtk[mmie_keyidx]);
+                       rx->key = rcu_dereference(rx->link_sta->gtk[mmie_keyidx]);
                }
                if (!rx->key)
-                       rx->key = rcu_dereference(rx->sdata->deflink.gtk[mmie_keyidx]);
+                       rx->key = rcu_dereference(rx->link->gtk[mmie_keyidx]);
        } else if (!ieee80211_has_protected(fc)) {
                /*
                 * The frame was not protected, so skip decryption. However, we
@@ -2003,25 +2013,24 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                 * have been expected.
                 */
                struct ieee80211_key *key = NULL;
-               struct ieee80211_sub_if_data *sdata = rx->sdata;
                int i;
 
                if (ieee80211_is_beacon(fc)) {
                        key = ieee80211_rx_get_bigtk(rx, -1);
                } else if (ieee80211_is_mgmt(fc) &&
                           is_multicast_ether_addr(hdr->addr1)) {
-                       key = rcu_dereference(rx->sdata->deflink.default_mgmt_key);
+                       key = rcu_dereference(rx->link->default_mgmt_key);
                } else {
-                       if (rx->sta) {
+                       if (rx->link_sta) {
                                for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                                       key = rcu_dereference(rx->sta->deflink.gtk[i]);
+                                       key = rcu_dereference(rx->link_sta->gtk[i]);
                                        if (key)
                                                break;
                                }
                        }
                        if (!key) {
                                for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                                       key = rcu_dereference(sdata->deflink.gtk[i]);
+                                       key = rcu_dereference(rx->link->gtk[i]);
                                        if (key)
                                                break;
                                }
@@ -2050,13 +2059,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                        return RX_DROP_UNUSABLE;
 
                /* check per-station GTK first, if multicast packet */
-               if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
-                       rx->key = rcu_dereference(rx->sta->deflink.gtk[keyidx]);
+               if (is_multicast_ether_addr(hdr->addr1) && rx->link_sta)
+                       rx->key = rcu_dereference(rx->link_sta->gtk[keyidx]);
 
                /* if not found, try default key */
                if (!rx->key) {
                        if (is_multicast_ether_addr(hdr->addr1))
-                               rx->key = rcu_dereference(rx->sdata->deflink.gtk[keyidx]);
+                               rx->key = rcu_dereference(rx->link->gtk[keyidx]);
                        if (!rx->key)
                                rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
 
@@ -3046,7 +3055,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
                    (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ||
                     tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) {
                        rx->skb->protocol = cpu_to_be16(ETH_P_TDLS);
-                       __ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+                       __ieee80211_queue_skb_to_iface(sdata, rx->link_id,
+                                                      rx->sta, rx->skb);
                        return RX_QUEUED;
                }
        }
@@ -3636,7 +3646,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 
  queue:
-       ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+       ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb);
        return RX_QUEUED;
 }
 
@@ -3794,7 +3804,7 @@ ieee80211_rx_h_ext(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
 
        /* for now only beacons are ext, so queue them */
-       ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+       ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb);
 
        return RX_QUEUED;
 }
@@ -3851,7 +3861,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
        }
 
-       ieee80211_queue_skb_to_iface(sdata, rx->sta, rx->skb);
+       ieee80211_queue_skb_to_iface(sdata, rx->link_id, rx->sta, rx->skb);
 
        return RX_QUEUED;
 }
@@ -4512,6 +4522,15 @@ void ieee80211_check_fast_rx_iface(struct ieee80211_sub_if_data *sdata)
        mutex_unlock(&local->sta_mtx);
 }
 
+static bool
+ieee80211_rx_is_valid_sta_link_id(struct ieee80211_sta *sta, u8 link_id)
+{
+       if (!sta->mlo)
+               return false;
+
+       return !!(sta->valid_links & BIT(link_id));
+}
+
 static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
                              struct ieee80211_fast_rx *fast_rx,
                              int orig_len)
@@ -4519,19 +4538,30 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
        struct ieee80211_sta_rx_stats *stats;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
        struct sta_info *sta = rx->sta;
+       struct link_sta_info *link_sta;
        struct sk_buff *skb = rx->skb;
        void *sa = skb->data + ETH_ALEN;
        void *da = skb->data;
 
-       stats = &sta->deflink.rx_stats;
+       if (rx->link_id >= 0) {
+               link_sta = rcu_dereference(sta->link[rx->link_id]);
+               if (WARN_ON_ONCE(!link_sta)) {
+                       dev_kfree_skb(rx->skb);
+                       return;
+               }
+       } else {
+               link_sta = &sta->deflink;
+       }
+
+       stats = &link_sta->rx_stats;
        if (fast_rx->uses_rss)
-               stats = this_cpu_ptr(sta->deflink.pcpu_rx_stats);
+               stats = this_cpu_ptr(link_sta->pcpu_rx_stats);
 
        /* statistics part of ieee80211_rx_h_sta_process() */
        if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
                stats->last_signal = status->signal;
                if (!fast_rx->uses_rss)
-                       ewma_signal_add(&sta->deflink.rx_stats_avg.signal,
+                       ewma_signal_add(&link_sta->rx_stats_avg.signal,
                                        -status->signal);
        }
 
@@ -4547,7 +4577,7 @@ static void ieee80211_rx_8023(struct ieee80211_rx_data *rx,
 
                        stats->chain_signal_last[i] = signal;
                        if (!fast_rx->uses_rss)
-                               ewma_signal_add(&sta->deflink.rx_stats_avg.chain_signal[i],
+                               ewma_signal_add(&link_sta->rx_stats_avg.chain_signal[i],
                                                -signal);
                }
        }
@@ -4623,7 +4653,8 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
                u8 da[ETH_ALEN];
                u8 sa[ETH_ALEN];
        } addrs __aligned(2);
-       struct ieee80211_sta_rx_stats *stats = &sta->deflink.rx_stats;
+       struct link_sta_info *link_sta;
+       struct ieee80211_sta_rx_stats *stats;
 
        /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
         * to a common data structure; drivers can implement that per queue
@@ -4724,8 +4755,19 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
        return true;
  drop:
        dev_kfree_skb(skb);
+
+       if (rx->link_id >= 0) {
+               link_sta = rcu_dereference(sta->link[rx->link_id]);
+               if (!link_sta)
+                       return true;
+       } else {
+               link_sta = &sta->deflink;
+       }
+
        if (fast_rx->uses_rss)
-               stats = this_cpu_ptr(sta->deflink.pcpu_rx_stats);
+               stats = this_cpu_ptr(link_sta->pcpu_rx_stats);
+       else
+               stats = &link_sta->rx_stats;
 
        stats->dropped++;
        return true;
@@ -4773,7 +4815,17 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
                if (!link)
                        return true;
                rx->link = link;
+
+               if (rx->sta) {
+                       rx->link_sta =
+                               rcu_dereference(rx->sta->link[rx->link_id]);
+                       if (!rx->link_sta)
+                               return true;
+               }
        } else {
+               if (rx->sta)
+                       rx->link_sta = &rx->sta->deflink;
+
                rx->link = &sdata->deflink;
        }
 
@@ -4831,6 +4883,7 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
                                       struct list_head *list)
 {
        struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_fast_rx *fast_rx;
        struct ieee80211_rx_data rx;
 
@@ -4851,7 +4904,31 @@ static void __ieee80211_rx_handle_8023(struct ieee80211_hw *hw,
 
        rx.sta = container_of(pubsta, struct sta_info, sta);
        rx.sdata = rx.sta->sdata;
-       rx.link = &rx.sdata->deflink;
+
+       if (status->link_valid &&
+           !ieee80211_rx_is_valid_sta_link_id(pubsta, status->link_id))
+               goto drop;
+
+       /*
+        * TODO: Should the frame be dropped if the right link_id is not
+        * available? Or may be it is fine in the current form to proceed with
+        * the frame processing because with frame being in 802.3 format,
+        * link_id is used only for stats purpose and updating the stats on
+        * the deflink is fine?
+        */
+       if (status->link_valid)
+               rx.link_id = status->link_id;
+
+       if (rx.link_id >= 0) {
+               struct ieee80211_link_data *link;
+
+               link =  rcu_dereference(rx.sdata->link[rx.link_id]);
+               if (!link)
+                       goto drop;
+               rx.link = link;
+       } else {
+               rx.link = &rx.sdata->deflink;
+       }
 
        fast_rx = rcu_dereference(rx.sta->fast_rx);
        if (!fast_rx)
@@ -4881,7 +4958,19 @@ static bool ieee80211_rx_for_interface(struct ieee80211_rx_data *rx,
                rx->sta = link_sta->sta;
                rx->link_id = link_sta->link_id;
        } else {
+               struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+
                rx->sta = sta_info_get_bss(rx->sdata, hdr->addr2);
+               if (rx->sta) {
+                       if (status->link_valid &&
+                           !ieee80211_rx_is_valid_sta_link_id(&rx->sta->sta,
+                                                              status->link_id))
+                               return false;
+
+                       rx->link_id = status->link_valid ? status->link_id : -1;
+               } else {
+                       rx->link_id = -1;
+               }
        }
 
        return ieee80211_prepare_and_rx_handle(rx, skb, consume);
@@ -4897,6 +4986,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                         struct list_head *list)
 {
        struct ieee80211_local *local = hw_to_local(hw);
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_hdr *hdr;
        __le16 fc;
@@ -4941,10 +5031,39 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
 
        if (ieee80211_is_data(fc)) {
                struct sta_info *sta, *prev_sta;
+               u8 link_id = status->link_id;
 
                if (pubsta) {
                        rx.sta = container_of(pubsta, struct sta_info, sta);
                        rx.sdata = rx.sta->sdata;
+
+                       if (status->link_valid &&
+                           !ieee80211_rx_is_valid_sta_link_id(pubsta, link_id))
+                               goto out;
+
+                       if (status->link_valid)
+                               rx.link_id = status->link_id;
+
+                       /*
+                        * In MLO connection, fetch the link_id using addr2
+                        * when the driver does not pass link_id in status.
+                        * When the address translation is already performed by
+                        * driver/hw, the valid link_id must be passed in
+                        * status.
+                        */
+
+                       if (!status->link_valid && pubsta->mlo) {
+                               struct ieee80211_hdr *hdr = (void *)skb->data;
+                               struct link_sta_info *link_sta;
+
+                               link_sta = link_sta_info_get_bss(rx.sdata,
+                                                                hdr->addr2);
+                               if (!link_sta)
+                                       goto out;
+
+                               rx.link_id = link_sta->link_id;
+                       }
+
                        if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
                                return;
                        goto out;
@@ -4958,6 +5077,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                continue;
                        }
 
+                       if ((status->link_valid &&
+                            !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
+                                                               link_id)) ||
+                           (!status->link_valid && prev_sta->sta.mlo))
+                               continue;
+
+                       rx.link_id = status->link_valid ? link_id : -1;
                        rx.sta = prev_sta;
                        rx.sdata = prev_sta->sdata;
                        ieee80211_prepare_and_rx_handle(&rx, skb, false);
@@ -4966,6 +5092,13 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                }
 
                if (prev_sta) {
+                       if ((status->link_valid &&
+                            !ieee80211_rx_is_valid_sta_link_id(&prev_sta->sta,
+                                                               link_id)) ||
+                           (!status->link_valid && prev_sta->sta.mlo))
+                               goto out;
+
+                       rx.link_id = status->link_valid ? link_id : -1;
                        rx.sta = prev_sta;
                        rx.sdata = prev_sta->sdata;
 
@@ -5108,6 +5241,9 @@ void ieee80211_rx_list(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta,
                }
        }
 
+       if (WARN_ON_ONCE(status->link_id >= IEEE80211_LINK_UNSPECIFIED))
+               goto drop;
+
        status->rx_flags = 0;
 
        kcov_remote_start_common(skb_get_kcov_handle(skb));
index c4f2aeb..0e8c4f4 100644 (file)
@@ -485,7 +485,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
        /* Set power back to normal operating levels. */
        ieee80211_hw_config(local, 0);
 
-       if (!hw_scan) {
+       if (!hw_scan && was_scanning) {
                ieee80211_configure_filter(local);
                drv_sw_scan_complete(local, scan_sdata);
                ieee80211_offchannel_return(local);
index 330dab4..fe8702d 100644 (file)
@@ -472,6 +472,7 @@ static void sta_info_add_link(struct sta_info *sta,
        link_info->sta = sta;
        link_info->link_id = link_id;
        link_info->pub = link_sta;
+       link_sta->link_id = link_id;
        rcu_assign_pointer(sta->link[link_id], link_info);
        rcu_assign_pointer(sta->sta.link[link_id], link_sta);
 }
@@ -2316,9 +2317,9 @@ static inline u64 sta_get_tidstats_msdu(struct ieee80211_sta_rx_stats *rxstats,
        u64 value;
 
        do {
-               start = u64_stats_fetch_begin(&rxstats->syncp);
+               start = u64_stats_fetch_begin_irq(&rxstats->syncp);
                value = rxstats->msdu[tid];
-       } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
 
        return value;
 }
@@ -2384,9 +2385,9 @@ static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
        u64 value;
 
        do {
-               start = u64_stats_fetch_begin(&rxstats->syncp);
+               start = u64_stats_fetch_begin_irq(&rxstats->syncp);
                value = rxstats->bytes;
-       } while (u64_stats_fetch_retry(&rxstats->syncp, start));
+       } while (u64_stats_fetch_retry_irq(&rxstats->syncp, start));
 
        return value;
 }
@@ -2777,10 +2778,8 @@ int ieee80211_sta_activate_link(struct sta_info *sta, unsigned int link_id)
 
        sta->sta.valid_links = new_links;
 
-       if (!test_sta_flag(sta, WLAN_STA_INSERTED)) {
-               ret = 0;
+       if (!test_sta_flag(sta, WLAN_STA_INSERTED))
                goto hash;
-       }
 
        ret = drv_change_sta_links(sdata->local, sdata, &sta->sta,
                                   old_links, new_links);
@@ -2799,6 +2798,7 @@ hash:
 void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
+       u16 old_links = sta->sta.valid_links;
 
        lockdep_assert_held(&sdata->local->sta_mtx);
 
@@ -2806,8 +2806,7 @@ void ieee80211_sta_remove_link(struct sta_info *sta, unsigned int link_id)
 
        if (test_sta_flag(sta, WLAN_STA_INSERTED))
                drv_change_sta_links(sdata->local, sdata, &sta->sta,
-                                    sta->sta.valid_links,
-                                    sta->sta.valid_links & ~BIT(link_id));
+                                    old_links, sta->sta.valid_links);
 
        sta_remove_link(sta, link_id, true);
 }
index bf7fe6c..1be8c9d 100644 (file)
@@ -576,6 +576,51 @@ ieee80211_tx_h_check_control_port_protocol(struct ieee80211_tx_data *tx)
        return TX_CONTINUE;
 }
 
+static struct ieee80211_key *
+ieee80211_select_link_key(struct ieee80211_tx_data *tx)
+{
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       enum {
+               USE_NONE,
+               USE_MGMT_KEY,
+               USE_MCAST_KEY,
+       } which_key = USE_NONE;
+       struct ieee80211_link_data *link;
+       unsigned int link_id;
+
+       if (ieee80211_is_group_privacy_action(tx->skb))
+               which_key = USE_MCAST_KEY;
+       else if (ieee80211_is_mgmt(hdr->frame_control) &&
+                is_multicast_ether_addr(hdr->addr1) &&
+                ieee80211_is_robust_mgmt_frame(tx->skb))
+               which_key = USE_MGMT_KEY;
+       else if (is_multicast_ether_addr(hdr->addr1))
+               which_key = USE_MCAST_KEY;
+       else
+               return NULL;
+
+       link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
+       if (link_id == IEEE80211_LINK_UNSPECIFIED) {
+               link = &tx->sdata->deflink;
+       } else {
+               link = rcu_dereference(tx->sdata->link[link_id]);
+               if (!link)
+                       return NULL;
+       }
+
+       switch (which_key) {
+       case USE_NONE:
+               break;
+       case USE_MGMT_KEY:
+               return rcu_dereference(link->default_mgmt_key);
+       case USE_MCAST_KEY:
+               return rcu_dereference(link->default_multicast_key);
+       }
+
+       return NULL;
+}
+
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
 {
@@ -591,16 +636,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx)
        if (tx->sta &&
            (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
                tx->key = key;
-       else if (ieee80211_is_group_privacy_action(tx->skb) &&
-               (key = rcu_dereference(tx->sdata->deflink.default_multicast_key)))
-               tx->key = key;
-       else if (ieee80211_is_mgmt(hdr->frame_control) &&
-                is_multicast_ether_addr(hdr->addr1) &&
-                ieee80211_is_robust_mgmt_frame(tx->skb) &&
-                (key = rcu_dereference(tx->sdata->deflink.default_mgmt_key)))
-               tx->key = key;
-       else if (is_multicast_ether_addr(hdr->addr1) &&
-                (key = rcu_dereference(tx->sdata->deflink.default_multicast_key)))
+       else if ((key = ieee80211_select_link_key(tx)))
                tx->key = key;
        else if (!is_multicast_ether_addr(hdr->addr1) &&
                 (key = rcu_dereference(tx->sdata->default_unicast_key)))
@@ -2640,7 +2676,8 @@ static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
                                goto free;
                        }
                        memcpy(hdr.addr2, link->conf->addr, ETH_ALEN);
-               } else if (link_id == IEEE80211_LINK_UNSPECIFIED) {
+               } else if (link_id == IEEE80211_LINK_UNSPECIFIED ||
+                          (sta && sta->sta.mlo)) {
                        memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
                } else {
                        struct ieee80211_bss_conf *conf;
@@ -3735,8 +3772,8 @@ begin:
                             !test_sta_flag(tx.sta, WLAN_STA_AUTHORIZED) &&
                             (!(info->control.flags &
                                IEEE80211_TX_CTRL_PORT_CTRL_PROTO) ||
-                             !ether_addr_equal(tx.sdata->vif.addr,
-                                               hdr->addr2)))) {
+                             !ieee80211_is_our_addr(tx.sdata, hdr->addr2,
+                                                    NULL)))) {
                        I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
                        ieee80211_free_txskb(&local->hw, skb);
                        goto begin;
@@ -5061,6 +5098,8 @@ ieee80211_beacon_get_finish(struct ieee80211_hw *hw,
        rate_control_get_rate(sdata, NULL, &txrc);
 
        info->control.vif = vif;
+       info->control.flags |= u32_encode_bits(link->link_id,
+                                              IEEE80211_TX_CTRL_MLO_LINK);
        info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
                       IEEE80211_TX_CTL_ASSIGN_SEQ |
                       IEEE80211_TX_CTL_FIRST_FRAGMENT;
index 53826c6..3359ab3 100644 (file)
@@ -954,9 +954,11 @@ void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
 }
 EXPORT_SYMBOL(ieee80211_queue_delayed_work);
 
-static void ieee80211_parse_extension_element(u32 *crc,
-                                             const struct element *elem,
-                                             struct ieee802_11_elems *elems)
+static void
+ieee80211_parse_extension_element(u32 *crc,
+                                 const struct element *elem,
+                                 struct ieee802_11_elems *elems,
+                                 struct ieee80211_elems_parse_params *params)
 {
        const void *data = elem->data + 1;
        u8 len;
@@ -1013,7 +1015,8 @@ static void ieee80211_parse_extension_element(u32 *crc,
                break;
        case WLAN_EID_EXT_EHT_CAPABILITY:
                if (ieee80211_eht_capa_size_ok(elems->he_cap,
-                                              data, len)) {
+                                              data, len,
+                                              params->from_ap)) {
                        elems->eht_cap = data;
                        elems->eht_cap_len = len;
                }
@@ -1385,7 +1388,7 @@ _ieee802_11_parse_elems_full(struct ieee80211_elems_parse_params *params,
                case WLAN_EID_EXTENSION:
                        ieee80211_parse_extension_element(calc_crc ?
                                                                &crc : NULL,
-                                                         elem, elems);
+                                                         elem, elems, params);
                        break;
                case WLAN_EID_S1G_CAPABILITIES:
                        if (elen >= sizeof(*elems->s1g_capab))
@@ -2025,7 +2028,8 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_sub_if_data *sdata,
            cfg80211_any_usable_channels(local->hw.wiphy, BIT(sband->band),
                                         IEEE80211_CHAN_NO_HE |
                                         IEEE80211_CHAN_NO_EHT)) {
-               pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end);
+               pos = ieee80211_ie_build_eht_cap(pos, he_cap, eht_cap, end,
+                                                sdata->vif.type == NL80211_IFTYPE_AP);
                if (!pos)
                        goto out_err;
        }
@@ -2526,7 +2530,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        if (link)
                                ieee80211_assign_chanctx(local, sdata, link);
                }
-               sdata_unlock(sdata);
 
                switch (sdata->vif.type) {
                case NL80211_IFTYPE_AP_VLAN:
@@ -2545,6 +2548,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                                            &sdata->deflink.tx_conf[i]);
                        break;
                }
+               sdata_unlock(sdata);
 
                /* common change flags for all interface types */
                changed = BSS_CHANGED_ERP_CTS_PROT |
@@ -2653,23 +2657,21 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        }
 
        /* APs are now beaconing, add back stations */
-       mutex_lock(&local->sta_mtx);
-       list_for_each_entry(sta, &local->sta_list, list) {
-               enum ieee80211_sta_state state;
-
-               if (!sta->uploaded)
-                       continue;
-
-               if (sta->sdata->vif.type != NL80211_IFTYPE_AP &&
-                   sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               if (!ieee80211_sdata_running(sdata))
                        continue;
 
-               for (state = IEEE80211_STA_NOTEXIST;
-                    state < sta->sta_state; state++)
-                       WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
-                                             state + 1));
+               sdata_lock(sdata);
+               switch (sdata->vif.type) {
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_AP:
+                       ieee80211_reconfig_stations(sdata);
+                       break;
+               default:
+                       break;
+               }
+               sdata_unlock(sdata);
        }
-       mutex_unlock(&local->sta_mtx);
 
        /* add back keys */
        list_for_each_entry(sdata, &local->interfaces, list)
@@ -3080,6 +3082,7 @@ end:
 }
 
 void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
+                                   enum ieee80211_smps_mode smps_mode,
                                    struct sk_buff *skb)
 {
        struct ieee80211_supported_band *sband;
@@ -3106,7 +3109,7 @@ void ieee80211_ie_build_he_6ghz_cap(struct ieee80211_sub_if_data *sdata,
        cap = le16_to_cpu(iftd->he_6ghz_capa.capa);
        cap &= ~IEEE80211_HE_6GHZ_CAP_SM_PS;
 
-       switch (sdata->deflink.smps_mode) {
+       switch (smps_mode) {
        case IEEE80211_SMPS_AUTOMATIC:
        case IEEE80211_SMPS_NUM_MODES:
                WARN_ON(1);
@@ -3507,8 +3510,7 @@ bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw, u32 vht_cap_info,
        return true;
 }
 
-void ieee80211_chandef_eht_oper(struct ieee80211_sub_if_data *sdata,
-                               const struct ieee80211_eht_operation *eht_oper,
+void ieee80211_chandef_eht_oper(const struct ieee80211_eht_operation *eht_oper,
                                bool support_160, bool support_320,
                                struct cfg80211_chan_def *chandef)
 {
@@ -3684,7 +3686,7 @@ bool ieee80211_chandef_he_6ghz_oper(struct ieee80211_sub_if_data *sdata,
                support_320 =
                        eht_phy_cap & IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ;
 
-               ieee80211_chandef_eht_oper(sdata, eht_oper, support_160,
+               ieee80211_chandef_eht_oper(eht_oper, support_160,
                                           support_320, &he_chandef);
        }
 
@@ -4770,6 +4772,7 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
        const struct ieee80211_sta_he_cap *he_cap;
        const struct ieee80211_sta_eht_cap *eht_cap;
        struct ieee80211_supported_band *sband;
+       bool is_ap;
        u8 n;
 
        sband = ieee80211_get_sband(sdata);
@@ -4781,8 +4784,12 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
        if (!he_cap || !eht_cap)
                return 0;
 
+       is_ap = iftype == NL80211_IFTYPE_AP ||
+               iftype == NL80211_IFTYPE_P2P_GO;
+
        n = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
-                                      &eht_cap->eht_cap_elem);
+                                      &eht_cap->eht_cap_elem,
+                                      is_ap);
        return 2 + 1 +
               sizeof(he_cap->he_cap_elem) + n +
               ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
@@ -4793,7 +4800,8 @@ u8 ieee80211_ie_len_eht_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
 u8 *ieee80211_ie_build_eht_cap(u8 *pos,
                               const struct ieee80211_sta_he_cap *he_cap,
                               const struct ieee80211_sta_eht_cap *eht_cap,
-                              u8 *end)
+                              u8 *end,
+                              bool for_ap)
 {
        u8 mcs_nss_len, ppet_len;
        u8 ie_len;
@@ -4804,7 +4812,8 @@ u8 *ieee80211_ie_build_eht_cap(u8 *pos,
                return orig_pos;
 
        mcs_nss_len = ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
-                                                &eht_cap->eht_cap_elem);
+                                                &eht_cap->eht_cap_elem,
+                                                for_ap);
        ppet_len = ieee80211_eht_ppe_size(eht_cap->eht_ppe_thres[0],
                                          eht_cap->eht_cap_elem.phy_cap_info);
 
index b8ce846..c439125 100644 (file)
@@ -44,7 +44,7 @@ ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
 
        switch (mac_cb(skb)->dest.mode) {
        case IEEE802154_ADDR_NONE:
-               if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
+               if (hdr->source.mode != IEEE802154_ADDR_NONE)
                        /* FIXME: check if we are PAN coordinator */
                        skb->pkt_type = PACKET_OTHERHOST;
                else
index 35b5f80..b52afe3 100644 (file)
@@ -1079,9 +1079,9 @@ static void mpls_get_stats(struct mpls_dev *mdev,
 
                p = per_cpu_ptr(mdev->stats, i);
                do {
-                       start = u64_stats_fetch_begin(&p->syncp);
+                       start = u64_stats_fetch_begin_irq(&p->syncp);
                        local = p->stats;
-               } while (u64_stats_fetch_retry(&p->syncp, start));
+               } while (u64_stats_fetch_retry_irq(&p->syncp, start));
 
                stats->rx_packets       += local.rx_packets;
                stats->rx_bytes         += local.rx_bytes;
index 291b5da..a3e4ee7 100644 (file)
@@ -2280,6 +2280,7 @@ static struct genl_family mptcp_genl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = mptcp_pm_ops,
        .n_small_ops    = ARRAY_SIZE(mptcp_pm_ops),
+       .resv_start_op  = MPTCP_PM_CMD_SUBFLOW_DESTROY + 1,
        .mcgrps         = mptcp_pm_mcgrps,
        .n_mcgrps       = ARRAY_SIZE(mptcp_pm_mcgrps),
 };
index c189b4c..d27f4ec 100644 (file)
@@ -768,6 +768,7 @@ static struct genl_family ncsi_genl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = ncsi_ops,
        .n_small_ops = ARRAY_SIZE(ncsi_ops),
+       .resv_start_op = NCSI_CMD_SET_CHANNEL_MASK + 1,
 };
 
 static int __init ncsi_init_netlink(void)
index dcf752b..5a6705a 100644 (file)
@@ -300,12 +300,6 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum,
                if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= hooknum))
                        return NULL;
                return net->nf.hooks_ipv6 + hooknum;
-#if IS_ENABLED(CONFIG_DECNET)
-       case NFPROTO_DECNET:
-               if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= hooknum))
-                       return NULL;
-               return net->nf.hooks_decnet + hooknum;
-#endif
        default:
                WARN_ON_ONCE(1);
                return NULL;
@@ -750,10 +744,6 @@ static int __net_init netfilter_net_init(struct net *net)
 #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE
        __netfilter_net_init(net->nf.hooks_bridge, ARRAY_SIZE(net->nf.hooks_bridge));
 #endif
-#if IS_ENABLED(CONFIG_DECNET)
-       __netfilter_net_init(net->nf.hooks_decnet, ARRAY_SIZE(net->nf.hooks_decnet));
-#endif
-
 #ifdef CONFIG_PROC_FS
        net->nf.proc_netfilter = proc_net_mkdir(net, "netfilter",
                                                net->proc_net);
index efab2b0..818b0b0 100644 (file)
@@ -4005,6 +4005,7 @@ static struct genl_family ip_vs_genl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = ip_vs_genl_ops,
        .n_small_ops    = ARRAY_SIZE(ip_vs_genl_ops),
+       .resv_start_op  = IPVS_CMD_FLUSH + 1,
 };
 
 static int __init ip_vs_genl_register(void)
index 71c2f4f..da65c6e 100644 (file)
@@ -2807,10 +2807,6 @@ err_expect:
        return ret;
 }
 
-#if (IS_BUILTIN(CONFIG_NF_CONNTRACK) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF)) || \
-    (IS_MODULE(CONFIG_NF_CONNTRACK) && IS_ENABLED(CONFIG_DEBUG_INFO_BTF_MODULES) || \
-    IS_ENABLED(CONFIG_NF_CT_NETLINK))
-
 /* ctnetlink code shared by both ctnetlink and nf_conntrack_bpf */
 
 int __nf_ct_change_timeout(struct nf_conn *ct, u64 timeout)
@@ -2866,5 +2862,3 @@ int nf_ct_change_status_common(struct nf_conn *ct, unsigned int status)
        return 0;
 }
 EXPORT_SYMBOL_GPL(nf_ct_change_status_common);
-
-#endif
index 71e29ad..8120aad 100644 (file)
@@ -215,13 +215,6 @@ nfnl_hook_entries_head(u8 pf, unsigned int hook, struct net *net, const char *de
                hook_head = rcu_dereference(net->nf.hooks_bridge[hook]);
 #endif
                break;
-#if IS_ENABLED(CONFIG_DECNET)
-       case NFPROTO_DECNET:
-               if (hook >= ARRAY_SIZE(net->nf.hooks_decnet))
-                       return ERR_PTR(-EINVAL);
-               hook_head = rcu_dereference(net->nf.hooks_decnet[hook]);
-               break;
-#endif
 #if defined(CONFIG_NETFILTER_INGRESS) || defined(CONFIG_NETFILTER_EGRESS)
        case NFPROTO_NETDEV:
                if (hook >= NF_NETDEV_NUMHOOKS)
index 91a19c3..f1d5b84 100644 (file)
@@ -344,6 +344,7 @@ static struct genl_family netlbl_calipso_gnl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = netlbl_calipso_ops,
        .n_small_ops = ARRAY_SIZE(netlbl_calipso_ops),
+       .resv_start_op = NLBL_CALIPSO_C_LISTALL + 1,
 };
 
 /* NetLabel Generic NETLINK Protocol Functions
index 894e6b8..fa08ee7 100644 (file)
@@ -767,6 +767,7 @@ static struct genl_family netlbl_cipsov4_gnl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = netlbl_cipsov4_ops,
        .n_small_ops = ARRAY_SIZE(netlbl_cipsov4_ops),
+       .resv_start_op = NLBL_CIPSOV4_C_LISTALL + 1,
 };
 
 /*
index 032b7d7..689eaa2 100644 (file)
@@ -826,6 +826,7 @@ static struct genl_family netlbl_mgmt_gnl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = netlbl_mgmt_genl_ops,
        .n_small_ops = ARRAY_SIZE(netlbl_mgmt_genl_ops),
+       .resv_start_op = NLBL_MGMT_C_VERSION + 1,
 };
 
 /*
index 0555dff..9996883 100644 (file)
@@ -1374,6 +1374,7 @@ static struct genl_family netlbl_unlabel_gnl_family __ro_after_init = {
        .module = THIS_MODULE,
        .small_ops = netlbl_unlabel_genl_ops,
        .n_small_ops = ARRAY_SIZE(netlbl_unlabel_genl_ops),
+       .resv_start_op = NLBL_UNLABEL_C_STATICLISTDEF + 1,
 };
 
 /*
index 0cd91f8..f89ba30 100644 (file)
@@ -2400,6 +2400,69 @@ error_free:
 }
 EXPORT_SYMBOL(__netlink_dump_start);
 
+static size_t
+netlink_ack_tlv_len(struct netlink_sock *nlk, int err,
+                   const struct netlink_ext_ack *extack)
+{
+       size_t tlvlen;
+
+       if (!extack || !(nlk->flags & NETLINK_F_EXT_ACK))
+               return 0;
+
+       tlvlen = 0;
+       if (extack->_msg)
+               tlvlen += nla_total_size(strlen(extack->_msg) + 1);
+       if (extack->cookie_len)
+               tlvlen += nla_total_size(extack->cookie_len);
+
+       /* Following attributes are only reported as error (not warning) */
+       if (!err)
+               return tlvlen;
+
+       if (extack->bad_attr)
+               tlvlen += nla_total_size(sizeof(u32));
+       if (extack->policy)
+               tlvlen += netlink_policy_dump_attr_size_estimate(extack->policy);
+       if (extack->miss_type)
+               tlvlen += nla_total_size(sizeof(u32));
+       if (extack->miss_nest)
+               tlvlen += nla_total_size(sizeof(u32));
+
+       return tlvlen;
+}
+
+static void
+netlink_ack_tlv_fill(struct sk_buff *in_skb, struct sk_buff *skb,
+                    struct nlmsghdr *nlh, int err,
+                    const struct netlink_ext_ack *extack)
+{
+       if (extack->_msg)
+               WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, extack->_msg));
+       if (extack->cookie_len)
+               WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
+                               extack->cookie_len, extack->cookie));
+
+       if (!err)
+               return;
+
+       if (extack->bad_attr &&
+           !WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
+                    (u8 *)extack->bad_attr >= in_skb->data + in_skb->len))
+               WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
+                                   (u8 *)extack->bad_attr - (u8 *)nlh));
+       if (extack->policy)
+               netlink_policy_dump_write_attr(skb, extack->policy,
+                                              NLMSGERR_ATTR_POLICY);
+       if (extack->miss_type)
+               WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_TYPE,
+                                   extack->miss_type));
+       if (extack->miss_nest &&
+           !WARN_ON((u8 *)extack->miss_nest < in_skb->data ||
+                    (u8 *)extack->miss_nest > in_skb->data + in_skb->len))
+               WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_MISS_NEST,
+                                   (u8 *)extack->miss_nest - (u8 *)nlh));
+}
+
 void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
                 const struct netlink_ext_ack *extack)
 {
@@ -2407,29 +2470,20 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
        struct nlmsghdr *rep;
        struct nlmsgerr *errmsg;
        size_t payload = sizeof(*errmsg);
-       size_t tlvlen = 0;
        struct netlink_sock *nlk = nlk_sk(NETLINK_CB(in_skb).sk);
        unsigned int flags = 0;
-       bool nlk_has_extack = nlk->flags & NETLINK_F_EXT_ACK;
+       size_t tlvlen;
 
        /* Error messages get the original request appened, unless the user
         * requests to cap the error message, and get extra error data if
         * requested.
         */
-       if (nlk_has_extack && extack && extack->_msg)
-               tlvlen += nla_total_size(strlen(extack->_msg) + 1);
-
        if (err && !(nlk->flags & NETLINK_F_CAP_ACK))
                payload += nlmsg_len(nlh);
        else
                flags |= NLM_F_CAPPED;
-       if (err && nlk_has_extack && extack && extack->bad_attr)
-               tlvlen += nla_total_size(sizeof(u32));
-       if (nlk_has_extack && extack && extack->cookie_len)
-               tlvlen += nla_total_size(extack->cookie_len);
-       if (err && nlk_has_extack && extack && extack->policy)
-               tlvlen += netlink_policy_dump_attr_size_estimate(extack->policy);
 
+       tlvlen = netlink_ack_tlv_len(nlk, err, extack);
        if (tlvlen)
                flags |= NLM_F_ACK_TLVS;
 
@@ -2446,25 +2500,8 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err,
        errmsg->error = err;
        memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh));
 
-       if (nlk_has_extack && extack) {
-               if (extack->_msg) {
-                       WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG,
-                                              extack->_msg));
-               }
-               if (err && extack->bad_attr &&
-                   !WARN_ON((u8 *)extack->bad_attr < in_skb->data ||
-                            (u8 *)extack->bad_attr >= in_skb->data +
-                                                      in_skb->len))
-                       WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS,
-                                           (u8 *)extack->bad_attr -
-                                           (u8 *)nlh));
-               if (extack->cookie_len)
-                       WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE,
-                                       extack->cookie_len, extack->cookie));
-               if (extack->policy)
-                       netlink_policy_dump_write_attr(skb, extack->policy,
-                                                      NLMSGERR_ATTR_POLICY);
-       }
+       if (tlvlen)
+               netlink_ack_tlv_fill(in_skb, skb, nlh, err, extack);
 
        nlmsg_end(skb, rep);
 
index 5701092..7c136de 100644 (file)
@@ -757,6 +757,9 @@ static int genl_family_rcv_msg(const struct genl_family *family,
        if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
                return -EINVAL;
 
+       if (hdr->cmd >= family->resv_start_op && hdr->reserved)
+               return -EINVAL;
+
        if (genl_get_cmd(hdr->cmd, family, &op))
                return -EOPNOTSUPP;
 
@@ -1348,6 +1351,7 @@ static struct genl_family genl_ctrl __ro_after_init = {
        .module = THIS_MODULE,
        .ops = genl_ctrl_ops,
        .n_ops = ARRAY_SIZE(genl_ctrl_ops),
+       .resv_start_op = CTRL_CMD_GETPOLICY + 1,
        .mcgrps = genl_ctrl_groups,
        .n_mcgrps = ARRAY_SIZE(genl_ctrl_groups),
        .id = GENL_ID_CTRL,
@@ -1362,7 +1366,7 @@ static int genl_bind(struct net *net, int group)
        unsigned int id;
        int ret = 0;
 
-       genl_lock_all();
+       down_read(&cb_lock);
 
        idr_for_each_entry(&genl_fam_idr, family, id) {
                const struct genl_multicast_group *grp;
@@ -1383,7 +1387,7 @@ static int genl_bind(struct net *net, int group)
                break;
        }
 
-       genl_unlock_all();
+       up_read(&cb_lock);
        return ret;
 }
 
index 7c62417..9d91087 100644 (file)
@@ -1783,6 +1783,7 @@ static struct genl_family nfc_genl_family __ro_after_init = {
        .module = THIS_MODULE,
        .ops = nfc_genl_ops,
        .n_ops = ARRAY_SIZE(nfc_genl_ops),
+       .resv_start_op = NFC_CMD_DEACTIVATE_TARGET + 1,
        .mcgrps = nfc_genl_mcgrps,
        .n_mcgrps = ARRAY_SIZE(nfc_genl_mcgrps),
 };
index 4e70df9..48e8f5c 100644 (file)
@@ -2283,6 +2283,7 @@ struct genl_family dp_ct_limit_genl_family __ro_after_init = {
        .parallel_ops = true,
        .small_ops = ct_limit_genl_ops,
        .n_small_ops = ARRAY_SIZE(ct_limit_genl_ops),
+       .resv_start_op = OVS_CT_LIMIT_CMD_GET + 1,
        .mcgrps = &ovs_ct_limit_multicast_group,
        .n_mcgrps = 1,
        .module = THIS_MODULE,
index 7e8a39a..c8a9075 100644 (file)
@@ -252,10 +252,17 @@ void ovs_dp_process_packet(struct sk_buff *skb, struct sw_flow_key *key)
 
                upcall.mru = OVS_CB(skb)->mru;
                error = ovs_dp_upcall(dp, skb, key, &upcall, 0);
-               if (unlikely(error))
-                       kfree_skb(skb);
-               else
+               switch (error) {
+               case 0:
+               case -EAGAIN:
+               case -ERESTARTSYS:
+               case -EINTR:
                        consume_skb(skb);
+                       break;
+               default:
+                       kfree_skb(skb);
+                       break;
+               }
                stats_counter = &stats->n_missed;
                goto out;
        }
@@ -551,8 +558,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 out:
        if (err)
                skb_tx_error(skb);
-       kfree_skb(user_skb);
-       kfree_skb(nskb);
+       consume_skb(user_skb);
+       consume_skb(nskb);
+
        return err;
 }
 
@@ -684,6 +692,7 @@ static struct genl_family dp_packet_genl_family __ro_after_init = {
        .parallel_ops = true,
        .small_ops = dp_packet_genl_ops,
        .n_small_ops = ARRAY_SIZE(dp_packet_genl_ops),
+       .resv_start_op = OVS_PACKET_CMD_EXECUTE + 1,
        .module = THIS_MODULE,
 };
 
@@ -1501,6 +1510,7 @@ static struct genl_family dp_flow_genl_family __ro_after_init = {
        .parallel_ops = true,
        .small_ops = dp_flow_genl_ops,
        .n_small_ops = ARRAY_SIZE(dp_flow_genl_ops),
+       .resv_start_op = OVS_FLOW_CMD_SET + 1,
        .mcgrps = &ovs_dp_flow_multicast_group,
        .n_mcgrps = 1,
        .module = THIS_MODULE,
@@ -1515,6 +1525,7 @@ static size_t ovs_dp_cmd_msg_size(void)
        msgsize += nla_total_size_64bit(sizeof(struct ovs_dp_megaflow_stats));
        msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_USER_FEATURES */
        msgsize += nla_total_size(sizeof(u32)); /* OVS_DP_ATTR_MASKS_CACHE_SIZE */
+       msgsize += nla_total_size(sizeof(u32) * nr_cpu_ids); /* OVS_DP_ATTR_PER_CPU_PIDS */
 
        return msgsize;
 }
@@ -1526,7 +1537,8 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
        struct ovs_header *ovs_header;
        struct ovs_dp_stats dp_stats;
        struct ovs_dp_megaflow_stats dp_megaflow_stats;
-       int err;
+       struct dp_nlsk_pids *pids = ovsl_dereference(dp->upcall_portids);
+       int err, pids_len;
 
        ovs_header = genlmsg_put(skb, portid, seq, &dp_datapath_genl_family,
                                 flags, cmd);
@@ -1556,6 +1568,12 @@ static int ovs_dp_cmd_fill_info(struct datapath *dp, struct sk_buff *skb,
                        ovs_flow_tbl_masks_cache_size(&dp->table)))
                goto nla_put_failure;
 
+       if (dp->user_features & OVS_DP_F_DISPATCH_UPCALL_PER_CPU && pids) {
+               pids_len = min(pids->n_pids, nr_cpu_ids) * sizeof(u32);
+               if (nla_put(skb, OVS_DP_ATTR_PER_CPU_PIDS, pids_len, &pids->pids))
+                       goto nla_put_failure;
+       }
+
        genlmsg_end(skb, ovs_header);
        return 0;
 
@@ -1779,6 +1797,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        parms.dp = dp;
        parms.port_no = OVSP_LOCAL;
        parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID];
+       parms.desired_ifindex = a[OVS_DP_ATTR_IFINDEX]
+               ? nla_get_u32(a[OVS_DP_ATTR_IFINDEX]) : 0;
 
        /* So far only local changes have been made, now need the lock. */
        ovs_lock();
@@ -1802,7 +1822,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
                                ovs_dp_reset_user_features(skb, info);
                }
 
-               goto err_unlock_and_destroy_meters;
+               goto err_destroy_portids;
        }
 
        err = ovs_dp_cmd_fill_info(dp, reply, info->snd_portid,
@@ -1817,6 +1837,8 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
        ovs_notify(&dp_datapath_genl_family, reply, info);
        return 0;
 
+err_destroy_portids:
+       kfree(rcu_dereference_raw(dp->upcall_portids));
 err_unlock_and_destroy_meters:
        ovs_unlock();
        ovs_meters_exit(dp);
@@ -1996,6 +2018,7 @@ static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = {
        [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 },
        [OVS_DP_ATTR_MASKS_CACHE_SIZE] =  NLA_POLICY_RANGE(NLA_U32, 0,
                PCPU_MIN_UNIT_SIZE / sizeof(struct mask_cache_entry)),
+       [OVS_DP_ATTR_IFINDEX] = {.type = NLA_U32 },
 };
 
 static const struct genl_small_ops dp_datapath_genl_ops[] = {
@@ -2032,6 +2055,7 @@ static struct genl_family dp_datapath_genl_family __ro_after_init = {
        .parallel_ops = true,
        .small_ops = dp_datapath_genl_ops,
        .n_small_ops = ARRAY_SIZE(dp_datapath_genl_ops),
+       .resv_start_op = OVS_DP_CMD_SET + 1,
        .mcgrps = &ovs_dp_datapath_multicast_group,
        .n_mcgrps = 1,
        .module = THIS_MODULE,
@@ -2199,7 +2223,10 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
        if (!a[OVS_VPORT_ATTR_NAME] || !a[OVS_VPORT_ATTR_TYPE] ||
            !a[OVS_VPORT_ATTR_UPCALL_PID])
                return -EINVAL;
-       if (a[OVS_VPORT_ATTR_IFINDEX])
+
+       parms.type = nla_get_u32(a[OVS_VPORT_ATTR_TYPE]);
+
+       if (a[OVS_VPORT_ATTR_IFINDEX] && parms.type != OVS_VPORT_TYPE_INTERNAL)
                return -EOPNOTSUPP;
 
        port_no = a[OVS_VPORT_ATTR_PORT_NO]
@@ -2236,11 +2263,12 @@ restart:
        }
 
        parms.name = nla_data(a[OVS_VPORT_ATTR_NAME]);
-       parms.type = nla_get_u32(a[OVS_VPORT_ATTR_TYPE]);
        parms.options = a[OVS_VPORT_ATTR_OPTIONS];
        parms.dp = dp;
        parms.port_no = port_no;
        parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID];
+       parms.desired_ifindex = a[OVS_VPORT_ATTR_IFINDEX]
+               ? nla_get_u32(a[OVS_VPORT_ATTR_IFINDEX]) : 0;
 
        vport = new_vport(&parms);
        err = PTR_ERR(vport);
index 04a060a..51111a9 100644 (file)
@@ -720,6 +720,7 @@ struct genl_family dp_meter_genl_family __ro_after_init = {
        .parallel_ops = true,
        .small_ops = dp_meter_genl_ops,
        .n_small_ops = ARRAY_SIZE(dp_meter_genl_ops),
+       .resv_start_op = OVS_METER_CMD_GET + 1,
        .mcgrps = &ovs_meter_multicast_group,
        .n_mcgrps = 1,
        .module = THIS_MODULE,
index 5b2ee9c..35f42c9 100644 (file)
@@ -65,7 +65,7 @@ static int internal_dev_stop(struct net_device *netdev)
 static void internal_dev_getinfo(struct net_device *netdev,
                                 struct ethtool_drvinfo *info)
 {
-       strlcpy(info->driver, "openvswitch", sizeof(info->driver));
+       strscpy(info->driver, "openvswitch", sizeof(info->driver));
 }
 
 static const struct ethtool_ops internal_dev_ethtool_ops = {
@@ -147,6 +147,7 @@ static struct vport *internal_dev_create(const struct vport_parms *parms)
        }
 
        dev_net_set(vport->dev, ovs_dp_get_net(vport->dp));
+       dev->ifindex = parms->desired_ifindex;
        internal_dev = internal_dev_priv(vport->dev);
        internal_dev->vport = vport;
 
index 9de5030..7d276f6 100644 (file)
@@ -90,12 +90,14 @@ struct vport {
  * @type: New vport's type.
  * @options: %OVS_VPORT_ATTR_OPTIONS attribute from Netlink message, %NULL if
  * none was supplied.
+ * @desired_ifindex: New vport's ifindex.
  * @dp: New vport's datapath.
  * @port_no: New vport's port number.
  */
 struct vport_parms {
        const char *name;
        enum ovs_vport_type type;
+       int desired_ifindex;
        struct nlattr *options;
 
        /* For ovs_vport_alloc(). */
index 5cbe071..7de46d8 100644 (file)
@@ -1905,7 +1905,7 @@ static int packet_rcv_spkt(struct sk_buff *skb, struct net_device *dev,
         */
 
        spkt->spkt_family = dev->type;
-       strlcpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
+       strscpy(spkt->spkt_device, dev->name, sizeof(spkt->spkt_device));
        spkt->spkt_protocol = skb->protocol;
 
        /*
@@ -3565,7 +3565,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr,
        rcu_read_lock();
        dev = dev_get_by_index_rcu(sock_net(sk), READ_ONCE(pkt_sk(sk)->ifindex));
        if (dev)
-               strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
+               strscpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data));
        rcu_read_unlock();
 
        return sizeof(*uaddr);
index 118d5d2..81a794e 100644 (file)
@@ -115,6 +115,7 @@ static struct genl_family psample_nl_family __ro_after_init = {
        .mcgrps         = psample_nl_mcgrps,
        .small_ops      = psample_nl_ops,
        .n_small_ops    = ARRAY_SIZE(psample_nl_ops),
+       .resv_start_op  = PSAMPLE_CMD_GET_GROUP + 1,
        .n_mcgrps       = ARRAY_SIZE(psample_nl_mcgrps),
 };
 
index d74be4e..44dbc61 100644 (file)
@@ -354,7 +354,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 
        for (i = 0; i < rm->data.op_nents; ++i) {
                sg_set_page(&rm->data.op_sg[i],
-                               virt_to_page(page_addrs[i]),
+                               virt_to_page((void *)page_addrs[i]),
                                PAGE_SIZE, 0);
        }
 
index 790d680..5d0d57d 100644 (file)
@@ -1977,9 +1977,6 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
        bool rtnl_held = false;
        u32 flags;
 
-       if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
 replay:
        tp_created = 0;
 
@@ -2208,9 +2205,6 @@ static int tc_del_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
        int err;
        bool rtnl_held = false;
 
-       if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
        err = nlmsg_parse_deprecated(n, sizeof(*t), tca, TCA_MAX,
                                     rtm_tca_policy, extack);
        if (err < 0)
@@ -2826,10 +2820,6 @@ static int tc_ctl_chain(struct sk_buff *skb, struct nlmsghdr *n,
        unsigned long cl;
        int err;
 
-       if (n->nlmsg_type != RTM_GETCHAIN &&
-           !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
 replay:
        q = NULL;
        err = nlmsg_parse_deprecated(n, sizeof(*t), tca, TCA_MAX,
@@ -3639,9 +3629,6 @@ int tcf_qevent_init(struct tcf_qevent *qe, struct Qdisc *sch,
        if (err)
                return err;
 
-       if (!block_index)
-               return 0;
-
        qe->info.binder_type = binder_type;
        qe->info.chain_head_change = tcf_chain_head_change_dflt;
        qe->info.chain_head_change_priv = &qe->filter_chain;
index 48712bc..29adac7 100644 (file)
@@ -488,7 +488,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
        }
 
        if (opt == NULL)
-               return handle ? -EINVAL : 0;
+               return -EINVAL;
 
        err = nla_parse_nested_deprecated(tb, TCA_ROUTE4_MAX, opt,
                                          route4_policy, NULL);
@@ -496,7 +496,7 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
                return err;
 
        fold = *arg;
-       if (fold && handle && fold->handle != handle)
+       if (fold && fold->handle != handle)
                        return -EINVAL;
 
        err = -ENOBUFS;
index bf87b50..db1569f 100644 (file)
@@ -171,7 +171,7 @@ out_einval:
 }
 EXPORT_SYMBOL(register_qdisc);
 
-int unregister_qdisc(struct Qdisc_ops *qops)
+void unregister_qdisc(struct Qdisc_ops *qops)
 {
        struct Qdisc_ops *q, **qp;
        int err = -ENOENT;
@@ -186,7 +186,8 @@ int unregister_qdisc(struct Qdisc_ops *qops)
                err = 0;
        }
        write_unlock(&qdisc_mod_lock);
-       return err;
+
+       WARN(err, "unregister qdisc(%s) failed\n", qops->id);
 }
 EXPORT_SYMBOL(unregister_qdisc);
 
@@ -194,7 +195,7 @@ EXPORT_SYMBOL(unregister_qdisc);
 void qdisc_get_default(char *name, size_t len)
 {
        read_lock(&qdisc_mod_lock);
-       strlcpy(name, default_qdisc_ops->id, len);
+       strscpy(name, default_qdisc_ops->id, len);
        read_unlock(&qdisc_mod_lock);
 }
 
@@ -1163,7 +1164,7 @@ static int qdisc_block_indexes_set(struct Qdisc *sch, struct nlattr **tca,
 
 static struct Qdisc *qdisc_create(struct net_device *dev,
                                  struct netdev_queue *dev_queue,
-                                 struct Qdisc *p, u32 parent, u32 handle,
+                                 u32 parent, u32 handle,
                                  struct nlattr **tca, int *errp,
                                  struct netlink_ext_ack *extack)
 {
@@ -1424,10 +1425,6 @@ static int tc_get_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
        struct Qdisc *p = NULL;
        int err;
 
-       if ((n->nlmsg_type != RTM_GETQDISC) &&
-           !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
        err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
                                     rtm_tca_policy, extack);
        if (err < 0)
@@ -1508,9 +1505,6 @@ static int tc_modify_qdisc(struct sk_buff *skb, struct nlmsghdr *n,
        struct Qdisc *q, *p;
        int err;
 
-       if (!netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
 replay:
        /* Reinit, just in case something touches this. */
        err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
@@ -1640,7 +1634,7 @@ create_n_graft:
        }
        if (clid == TC_H_INGRESS) {
                if (dev_ingress_queue(dev)) {
-                       q = qdisc_create(dev, dev_ingress_queue(dev), p,
+                       q = qdisc_create(dev, dev_ingress_queue(dev),
                                         tcm->tcm_parent, tcm->tcm_parent,
                                         tca, &err, extack);
                } else {
@@ -1657,7 +1651,7 @@ create_n_graft:
                else
                        dev_queue = netdev_get_tx_queue(dev, 0);
 
-               q = qdisc_create(dev, dev_queue, p,
+               q = qdisc_create(dev, dev_queue,
                                 tcm->tcm_parent, tcm->tcm_handle,
                                 tca, &err, extack);
        }
@@ -1992,10 +1986,6 @@ static int tc_ctl_tclass(struct sk_buff *skb, struct nlmsghdr *n,
        u32 qid;
        int err;
 
-       if ((n->nlmsg_type != RTM_GETTCLASS) &&
-           !netlink_ns_capable(skb, net->user_ns, CAP_NET_ADMIN))
-               return -EPERM;
-
        err = nlmsg_parse_deprecated(n, sizeof(*tcm), tca, TCA_MAX,
                                     rtm_tca_policy, extack);
        if (err < 0)
index 4c8e994..816fd0d 100644 (file)
@@ -577,7 +577,6 @@ static void atm_tc_reset(struct Qdisc *sch)
        pr_debug("atm_tc_reset(sch %p,[qdisc %p])\n", sch, p);
        list_for_each_entry(flow, &p->flows, list)
                qdisc_reset(flow->q);
-       sch->q.qlen = 0;
 }
 
 static void atm_tc_destroy(struct Qdisc *sch)
index a43a58a..36acc95 100644 (file)
@@ -2569,9 +2569,6 @@ static int cake_change(struct Qdisc *sch, struct nlattr *opt,
        struct nlattr *tb[TCA_CAKE_MAX + 1];
        int err;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_CAKE_MAX, opt, cake_policy,
                                          extack);
        if (err < 0)
index 91a0dc4..ba99ce0 100644 (file)
@@ -975,7 +975,6 @@ cbq_reset(struct Qdisc *sch)
                        cl->cpriority = cl->priority;
                }
        }
-       sch->q.qlen = 0;
 }
 
 
index 2adbd94..3ac3e5c 100644 (file)
@@ -60,7 +60,6 @@ struct choke_sched_data {
                u32     forced_drop;    /* Forced drops, qavg > max_thresh */
                u32     forced_mark;    /* Forced marks, qavg > max_thresh */
                u32     pdrop;          /* Drops due to queue limits */
-               u32     other;          /* Drops due to drop() calls */
                u32     matched;        /* Drops to flow match */
        } stats;
 
@@ -315,8 +314,6 @@ static void choke_reset(struct Qdisc *sch)
                rtnl_qdisc_drop(skb, sch);
        }
 
-       sch->q.qlen = 0;
-       sch->qstats.backlog = 0;
        if (q->tab)
                memset(q->tab, 0, (q->tab_mask + 1) * sizeof(struct sk_buff *));
        q->head = q->tail = 0;
@@ -466,7 +463,6 @@ static int choke_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
                .early  = q->stats.prob_drop + q->stats.forced_drop,
                .marked = q->stats.prob_mark + q->stats.forced_mark,
                .pdrop  = q->stats.pdrop,
-               .other  = q->stats.other,
                .matched = q->stats.matched,
        };
 
index 30169b3..d7a4874 100644 (file)
@@ -138,9 +138,6 @@ static int codel_change(struct Qdisc *sch, struct nlattr *opt,
        unsigned int qlen, dropped = 0;
        int err;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_CODEL_MAX, opt,
                                          codel_policy, NULL);
        if (err < 0)
index 18e4f7a..4e5b1cf 100644 (file)
@@ -441,8 +441,6 @@ static void drr_reset_qdisc(struct Qdisc *sch)
                        qdisc_reset(cl->qdisc);
                }
        }
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void drr_destroy_qdisc(struct Qdisc *sch)
index 4c100d1..7da6dc3 100644 (file)
@@ -409,8 +409,6 @@ static void dsmark_reset(struct Qdisc *sch)
        pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
        if (p->q)
                qdisc_reset(p->q);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void dsmark_destroy(struct Qdisc *sch)
index c48f910..61d1f0e 100644 (file)
@@ -323,9 +323,6 @@ static int etf_enable_offload(struct net_device *dev, struct etf_sched_data *q,
        struct tc_etf_qopt_offload etf = { };
        int err;
 
-       if (q->offload)
-               return 0;
-
        if (!ops->ndo_setup_tc) {
                NL_SET_ERR_MSG(extack, "Specified device does not support ETF offload");
                return -EOPNOTSUPP;
@@ -445,9 +442,6 @@ static void etf_reset(struct Qdisc *sch)
        timesortedlist_clear(sch);
        __qdisc_reset_queue(&sch->q);
 
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
-
        q->last = 0;
 }
 
index d733934..a3aea22 100644 (file)
@@ -594,11 +594,6 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
        unsigned int i;
        int err;
 
-       if (!opt) {
-               NL_SET_ERR_MSG(extack, "ETS options are required for this operation");
-               return -EINVAL;
-       }
-
        err = nla_parse_nested(tb, TCA_ETS_MAX, opt, ets_policy, extack);
        if (err < 0)
                return err;
@@ -727,8 +722,6 @@ static void ets_qdisc_reset(struct Qdisc *sch)
        }
        for (band = 0; band < q->nbands; band++)
                qdisc_reset(q->classes[band].qdisc);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void ets_qdisc_destroy(struct Qdisc *sch)
index 2fb76fc..48d14fb 100644 (file)
@@ -808,9 +808,6 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
        unsigned drop_len = 0;
        u32 fq_log;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_FQ_MAX, opt, fq_policy,
                                          NULL);
        if (err < 0)
index 839e123..eeea8c6 100644 (file)
@@ -347,8 +347,6 @@ static void fq_codel_reset(struct Qdisc *sch)
                codel_vars_init(&flow->cvars);
        }
        memset(q->backlogs, 0, q->flows_cnt * sizeof(u32));
-       sch->q.qlen = 0;
-       sch->qstats.backlog = 0;
        q->memory_usage = 0;
 }
 
@@ -374,9 +372,6 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt,
        u32 quantum = 0;
        int err;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_FQ_CODEL_MAX, opt,
                                          fq_codel_policy, NULL);
        if (err < 0)
@@ -483,26 +478,24 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
        if (opt) {
                err = fq_codel_change(sch, opt, extack);
                if (err)
-                       goto init_failure;
+                       return err;
        }
 
        err = tcf_block_get(&q->block, &q->filter_list, sch, extack);
        if (err)
-               goto init_failure;
+               return err;
 
        if (!q->flows) {
                q->flows = kvcalloc(q->flows_cnt,
                                    sizeof(struct fq_codel_flow),
                                    GFP_KERNEL);
-               if (!q->flows) {
-                       err = -ENOMEM;
-                       goto init_failure;
-               }
+               if (!q->flows)
+                       return -ENOMEM;
+
                q->backlogs = kvcalloc(q->flows_cnt, sizeof(u32), GFP_KERNEL);
-               if (!q->backlogs) {
-                       err = -ENOMEM;
-                       goto alloc_failure;
-               }
+               if (!q->backlogs)
+                       return -ENOMEM;
+
                for (i = 0; i < q->flows_cnt; i++) {
                        struct fq_codel_flow *flow = q->flows + i;
 
@@ -515,13 +508,6 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt,
        else
                sch->flags &= ~TCQ_F_CAN_BYPASS;
        return 0;
-
-alloc_failure:
-       kvfree(q->flows);
-       q->flows = NULL;
-init_failure:
-       q->flows_cnt = 0;
-       return err;
 }
 
 static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb)
index d6aba6e..6980796 100644 (file)
@@ -283,9 +283,6 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
        unsigned int num_dropped = 0;
        int err;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested(tb, TCA_FQ_PIE_MAX, opt, fq_pie_policy, extack);
        if (err < 0)
                return err;
@@ -521,9 +518,6 @@ static void fq_pie_reset(struct Qdisc *sch)
                INIT_LIST_HEAD(&flow->flowchain);
                pie_vars_init(&flow->vars);
        }
-
-       sch->q.qlen = 0;
-       sch->qstats.backlog = 0;
 }
 
 static void fq_pie_destroy(struct Qdisc *sch)
index 99b697a..a9aadc4 100644 (file)
@@ -941,7 +941,6 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue,
                goto errout;
        __skb_queue_head_init(&sch->gso_skb);
        __skb_queue_head_init(&sch->skb_bad_txq);
-       qdisc_skb_head_init(&sch->q);
        gnet_stats_basic_sync_init(&sch->bstats);
        spin_lock_init(&sch->q.lock);
 
@@ -1122,6 +1121,21 @@ struct Qdisc *dev_graft_qdisc(struct netdev_queue *dev_queue,
 }
 EXPORT_SYMBOL(dev_graft_qdisc);
 
+static void shutdown_scheduler_queue(struct net_device *dev,
+                                    struct netdev_queue *dev_queue,
+                                    void *_qdisc_default)
+{
+       struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
+       struct Qdisc *qdisc_default = _qdisc_default;
+
+       if (qdisc) {
+               rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
+               dev_queue->qdisc_sleeping = qdisc_default;
+
+               qdisc_put(qdisc);
+       }
+}
+
 static void attach_one_default_qdisc(struct net_device *dev,
                                     struct netdev_queue *dev_queue,
                                     void *_unused)
@@ -1169,6 +1183,7 @@ static void attach_default_qdiscs(struct net_device *dev)
        if (qdisc == &noop_qdisc) {
                netdev_warn(dev, "default qdisc (%s) fail, fallback to %s\n",
                            default_qdisc_ops->id, noqueue_qdisc_ops.id);
+               netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
                dev->priv_flags |= IFF_NO_QUEUE;
                netdev_for_each_tx_queue(dev, attach_one_default_qdisc, NULL);
                qdisc = txq->qdisc_sleeping;
@@ -1447,21 +1462,6 @@ void dev_init_scheduler(struct net_device *dev)
        timer_setup(&dev->watchdog_timer, dev_watchdog, 0);
 }
 
-static void shutdown_scheduler_queue(struct net_device *dev,
-                                    struct netdev_queue *dev_queue,
-                                    void *_qdisc_default)
-{
-       struct Qdisc *qdisc = dev_queue->qdisc_sleeping;
-       struct Qdisc *qdisc_default = _qdisc_default;
-
-       if (qdisc) {
-               rcu_assign_pointer(dev_queue->qdisc, qdisc_default);
-               dev_queue->qdisc_sleeping = qdisc_default;
-
-               qdisc_put(qdisc);
-       }
-}
-
 void dev_shutdown(struct net_device *dev)
 {
        netdev_for_each_tx_queue(dev, shutdown_scheduler_queue, &noop_qdisc);
index 1073c76..a661b06 100644 (file)
@@ -648,9 +648,6 @@ static int gred_change(struct Qdisc *sch, struct nlattr *opt,
        u32 max_P;
        struct gred_sched_data *prealloc;
 
-       if (opt == NULL)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_GRED_MAX, opt, gred_policy,
                                          extack);
        if (err < 0)
@@ -829,7 +826,6 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
                opt.Wlog        = q->parms.Wlog;
                opt.Plog        = q->parms.Plog;
                opt.Scell_log   = q->parms.Scell_log;
-               opt.other       = q->stats.other;
                opt.early       = q->stats.prob_drop;
                opt.forced      = q->stats.forced_drop;
                opt.pdrop       = q->stats.pdrop;
@@ -895,8 +891,6 @@ append_opt:
                        goto nla_put_failure;
                if (nla_put_u32(skb, TCA_GRED_VQ_STAT_PDROP, q->stats.pdrop))
                        goto nla_put_failure;
-               if (nla_put_u32(skb, TCA_GRED_VQ_STAT_OTHER, q->stats.other))
-                       goto nla_put_failure;
 
                nla_nest_end(skb, vq);
        }
@@ -914,10 +908,9 @@ static void gred_destroy(struct Qdisc *sch)
        struct gred_sched *table = qdisc_priv(sch);
        int i;
 
-       for (i = 0; i < table->DPs; i++) {
-               if (table->tab[i])
-                       gred_destroy_vq(table->tab[i]);
-       }
+       for (i = 0; i < table->DPs; i++)
+               gred_destroy_vq(table->tab[i]);
+
        gred_offload(sch, TC_GRED_DESTROY);
        kfree(table->opt);
 }
index d3979a6..c8bef92 100644 (file)
@@ -1430,7 +1430,7 @@ hfsc_change_qdisc(struct Qdisc *sch, struct nlattr *opt,
        struct hfsc_sched *q = qdisc_priv(sch);
        struct tc_hfsc_qopt *qopt;
 
-       if (opt == NULL || nla_len(opt) < sizeof(*qopt))
+       if (nla_len(opt) < sizeof(*qopt))
                return -EINVAL;
        qopt = nla_data(opt);
 
@@ -1484,8 +1484,6 @@ hfsc_reset_qdisc(struct Qdisc *sch)
        }
        q->eligible = RB_ROOT;
        qdisc_watchdog_cancel(&q->watchdog);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void
index 420ede8..d26cd43 100644 (file)
@@ -516,9 +516,6 @@ static int hhf_change(struct Qdisc *sch, struct nlattr *opt,
        u32 new_quantum = q->quantum;
        u32 new_hhf_non_hh_weight = q->hhf_non_hh_weight;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_HHF_MAX, opt, hhf_policy,
                                          NULL);
        if (err < 0)
index 23a9d62..78d0c75 100644 (file)
@@ -1008,8 +1008,6 @@ static void htb_reset(struct Qdisc *sch)
        }
        qdisc_watchdog_cancel(&q->watchdog);
        __qdisc_reset_queue(&q->direct_queue);
-       sch->q.qlen = 0;
-       sch->qstats.backlog = 0;
        memset(q->hlevel, 0, sizeof(q->hlevel));
        memset(q->row_mask, 0, sizeof(q->row_mask));
 }
@@ -1104,9 +1102,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
 
        err = qdisc_class_hash_init(&q->clhash);
        if (err < 0)
-               goto err_free_direct_qdiscs;
-
-       qdisc_skb_head_init(&q->direct_queue);
+               return err;
 
        if (tb[TCA_HTB_DIRECT_QLEN])
                q->direct_qlen = nla_get_u32(tb[TCA_HTB_DIRECT_QLEN]);
@@ -1127,8 +1123,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
                qdisc = qdisc_create_dflt(dev_queue, &pfifo_qdisc_ops,
                                          TC_H_MAKE(sch->handle, 0), extack);
                if (!qdisc) {
-                       err = -ENOMEM;
-                       goto err_free_qdiscs;
+                       return -ENOMEM;
                }
 
                htb_set_lockdep_class_child(qdisc);
@@ -1146,7 +1141,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
        };
        err = htb_offload(dev, &offload_opt);
        if (err)
-               goto err_free_qdiscs;
+               return err;
 
        /* Defer this assignment, so that htb_destroy skips offload-related
         * parts (especially calling ndo_setup_tc) on errors.
@@ -1154,22 +1149,6 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,
        q->offload = true;
 
        return 0;
-
-err_free_qdiscs:
-       for (ntx = 0; ntx < q->num_direct_qdiscs && q->direct_qdiscs[ntx];
-            ntx++)
-               qdisc_put(q->direct_qdiscs[ntx]);
-
-       qdisc_class_hash_destroy(&q->clhash);
-       /* Prevent use-after-free and double-free when htb_destroy gets called.
-        */
-       q->clhash.hash = NULL;
-       q->clhash.hashsize = 0;
-
-err_free_direct_qdiscs:
-       kfree(q->direct_qdiscs);
-       q->direct_qdiscs = NULL;
-       return err;
 }
 
 static void htb_attach_offload(struct Qdisc *sch)
@@ -1692,13 +1671,12 @@ static void htb_destroy(struct Qdisc *sch)
        qdisc_class_hash_destroy(&q->clhash);
        __qdisc_reset_queue(&q->direct_queue);
 
-       if (!q->offload)
-               return;
-
-       offload_opt = (struct tc_htb_qopt_offload) {
-               .command = TC_HTB_DESTROY,
-       };
-       htb_offload(dev, &offload_opt);
+       if (q->offload) {
+               offload_opt = (struct tc_htb_qopt_offload) {
+                       .command = TC_HTB_DESTROY,
+               };
+               htb_offload(dev, &offload_opt);
+       }
 
        if (!q->direct_qdiscs)
                return;
index cd8ab90..f28050c 100644 (file)
@@ -152,7 +152,6 @@ multiq_reset(struct Qdisc *sch)
 
        for (band = 0; band < q->bands; band++)
                qdisc_reset(q->queues[band]);
-       sch->q.qlen = 0;
        q->curband = 0;
 }
 
index 5449ed1..b70ac04 100644 (file)
@@ -961,9 +961,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt,
        int old_loss_model = CLG_RANDOM;
        int ret;
 
-       if (opt == NULL)
-               return -EINVAL;
-
        qopt = nla_data(opt);
        ret = parse_attr(tb, TCA_NETEM_MAX, opt, netem_policy, sizeof(*qopt));
        if (ret < 0)
index 5a457ff..974038b 100644 (file)
@@ -143,9 +143,6 @@ static int pie_change(struct Qdisc *sch, struct nlattr *opt,
        unsigned int qlen, dropped = 0;
        int err;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_PIE_MAX, opt, pie_policy,
                                          NULL);
        if (err < 0)
index cbc2ebc..ea8c4a7 100644 (file)
@@ -161,9 +161,6 @@ static int plug_change(struct Qdisc *sch, struct nlattr *opt,
        struct plug_sched_data *q = qdisc_priv(sch);
        struct tc_plug_qopt *msg;
 
-       if (opt == NULL)
-               return -EINVAL;
-
        msg = nla_data(opt);
        if (nla_len(opt) < sizeof(*msg))
                return -EINVAL;
index 3b8d719..298794c 100644 (file)
@@ -135,8 +135,6 @@ prio_reset(struct Qdisc *sch)
 
        for (prio = 0; prio < q->bands; prio++)
                qdisc_reset(q->queues[prio]);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static int prio_offload(struct Qdisc *sch, struct tc_prio_qopt *qopt)
@@ -187,7 +185,7 @@ static int prio_tune(struct Qdisc *sch, struct nlattr *opt,
                return -EINVAL;
        qopt = nla_data(opt);
 
-       if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < 2)
+       if (qopt->bands > TCQ_PRIO_BANDS || qopt->bands < TCQ_MIN_PRIO_BANDS)
                return -EINVAL;
 
        for (i = 0; i <= TC_PRIO_MAX; i++) {
index d4ce58c..13246a9 100644 (file)
@@ -1458,8 +1458,6 @@ static void qfq_reset_qdisc(struct Qdisc *sch)
                        qdisc_reset(cl->qdisc);
                }
        }
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void qfq_destroy_qdisc(struct Qdisc *sch)
index 40adf1f..4952406 100644 (file)
@@ -176,8 +176,6 @@ static void red_reset(struct Qdisc *sch)
        struct red_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
        red_restart(&q->vars);
 }
 
@@ -370,9 +368,6 @@ static int red_change(struct Qdisc *sch, struct nlattr *opt,
        struct nlattr *tb[TCA_RED_MAX + 1];
        int err;
 
-       if (!opt)
-               return -EINVAL;
-
        err = nla_parse_nested_deprecated(tb, TCA_RED_MAX, opt, red_policy,
                                          extack);
        if (err < 0)
@@ -463,7 +458,6 @@ static int red_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
        }
        st.early = q->stats.prob_drop + q->stats.forced_drop;
        st.pdrop = q->stats.pdrop;
-       st.other = q->stats.other;
        st.marked = q->stats.prob_mark + q->stats.forced_mark;
 
        return gnet_stats_copy_app(d, &st, sizeof(st));
index 3d061a1..31717fa 100644 (file)
@@ -453,8 +453,6 @@ static void sfb_reset(struct Qdisc *sch)
        struct sfb_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
        q->slot = 0;
        q->double_buffering = false;
        sfb_zero_all_buckets(q);
index 7a5e4c4..df72fb8 100644 (file)
@@ -213,9 +213,6 @@ static void skbprio_reset(struct Qdisc *sch)
        struct skbprio_sched_data *q = qdisc_priv(sch);
        int prio;
 
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
-
        for (prio = 0; prio < SKBPRIO_MAX_PRIORITY; prio++)
                __skb_queue_purge(&q->qdiscs[prio]);
 
index 0b941dd..db88a69 100644 (file)
@@ -1636,8 +1636,6 @@ static void taprio_reset(struct Qdisc *sch)
                        if (q->qdiscs[i])
                                qdisc_reset(q->qdiscs[i]);
        }
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
 }
 
 static void taprio_destroy(struct Qdisc *sch)
index 7210227..e031c1a 100644 (file)
@@ -330,8 +330,6 @@ static void tbf_reset(struct Qdisc *sch)
        struct tbf_sched_data *q = qdisc_priv(sch);
 
        qdisc_reset(q->qdisc);
-       sch->qstats.backlog = 0;
-       sch->q.qlen = 0;
        q->t_c = ktime_get_ns();
        q->tokens = q->buffer;
        q->ptokens = q->mtu;
@@ -356,6 +354,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
        struct nlattr *tb[TCA_TBF_MAX + 1];
        struct tc_tbf_qopt *qopt;
        struct Qdisc *child = NULL;
+       struct Qdisc *old = NULL;
        struct psched_ratecfg rate;
        struct psched_ratecfg peak;
        u64 max_size;
@@ -447,7 +446,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
        sch_tree_lock(sch);
        if (child) {
                qdisc_tree_flush_backlog(q->qdisc);
-               qdisc_put(q->qdisc);
+               old = q->qdisc;
                q->qdisc = child;
        }
        q->limit = qopt->limit;
@@ -467,6 +466,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt,
        memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg));
 
        sch_tree_unlock(sch);
+       qdisc_put(old);
        err = 0;
 
        tbf_offload_change(sch);
index 6af6b95..16f9238 100644 (file)
@@ -124,7 +124,6 @@ teql_reset(struct Qdisc *sch)
        struct teql_sched_data *dat = qdisc_priv(sch);
 
        skb_queue_purge(&dat->q);
-       sch->q.qlen = 0;
 }
 
 static void
@@ -492,7 +491,7 @@ static int __init teql_init(void)
 
                master = netdev_priv(dev);
 
-               strlcpy(master->qops.id, dev->name, IFNAMSIZ);
+               strscpy(master->qops.id, dev->name, IFNAMSIZ);
                err = register_qdisc(&master->qops);
 
                if (err) {
index 79c1318..0939cc3 100644 (file)
@@ -1855,7 +1855,6 @@ static void smc_listen_out_connected(struct smc_sock *new_smc)
 {
        struct sock *newsmcsk = &new_smc->sk;
 
-       sk_refcnt_debug_inc(newsmcsk);
        if (newsmcsk->sk_state == SMC_INIT)
                newsmcsk->sk_state = SMC_ACTIVE;
 
index c5a62f6..621c46c 100644 (file)
@@ -142,7 +142,8 @@ struct genl_family smc_gen_nl_family __ro_after_init = {
        .netnsok =      true,
        .module =       THIS_MODULE,
        .ops =          smc_gen_nl_ops,
-       .n_ops =        ARRAY_SIZE(smc_gen_nl_ops)
+       .n_ops =        ARRAY_SIZE(smc_gen_nl_ops),
+       .resv_start_op = SMC_NETLINK_DISABLE_HS_LIMITATION + 1,
 };
 
 int __init smc_nl_init(void)
index 4c3bf6d..25fb2fd 100644 (file)
@@ -715,7 +715,8 @@ static struct genl_family smc_pnet_nl_family __ro_after_init = {
        .netnsok = true,
        .module = THIS_MODULE,
        .ops = smc_pnet_ops,
-       .n_ops =  ARRAY_SIZE(smc_pnet_ops)
+       .n_ops =  ARRAY_SIZE(smc_pnet_ops),
+       .resv_start_op = SMC_PNETID_FLUSH + 1,
 };
 
 bool smc_pnet_is_ndev_pnetid(struct net *net, u8 *pnetid)
index c447cb5..e8fd257 100644 (file)
@@ -294,6 +294,7 @@ struct genl_family tipc_genl_family __ro_after_init = {
        .module         = THIS_MODULE,
        .ops            = tipc_genl_v2_ops,
        .n_ops          = ARRAY_SIZE(tipc_genl_v2_ops),
+       .resv_start_op  = TIPC_NL_ADDR_LEGACY_GET + 1,
 };
 
 int __init tipc_netlink_start(void)
index 0749df8..fc68733 100644 (file)
@@ -1357,6 +1357,7 @@ static struct genl_family tipc_genl_compat_family __ro_after_init = {
        .module         = THIS_MODULE,
        .small_ops      = tipc_genl_compat_ops,
        .n_small_ops    = ARRAY_SIZE(tipc_genl_compat_ops),
+       .resv_start_op  = TIPC_GENL_CMD + 1,
 };
 
 int __init tipc_netlink_compat_start(void)
index bf338b7..dea2972 100644 (file)
@@ -785,15 +785,45 @@ static int unix_set_peek_off(struct sock *sk, int val)
 }
 
 #ifdef CONFIG_PROC_FS
+static int unix_count_nr_fds(struct sock *sk)
+{
+       struct sk_buff *skb;
+       struct unix_sock *u;
+       int nr_fds = 0;
+
+       spin_lock(&sk->sk_receive_queue.lock);
+       skb = skb_peek(&sk->sk_receive_queue);
+       while (skb) {
+               u = unix_sk(skb->sk);
+               nr_fds += atomic_read(&u->scm_stat.nr_fds);
+               skb = skb_peek_next(skb, &sk->sk_receive_queue);
+       }
+       spin_unlock(&sk->sk_receive_queue.lock);
+
+       return nr_fds;
+}
+
 static void unix_show_fdinfo(struct seq_file *m, struct socket *sock)
 {
        struct sock *sk = sock->sk;
        struct unix_sock *u;
+       int nr_fds;
 
        if (sk) {
-               u = unix_sk(sock->sk);
-               seq_printf(m, "scm_fds: %u\n",
-                          atomic_read(&u->scm_stat.nr_fds));
+               u = unix_sk(sk);
+               if (sock->type == SOCK_DGRAM) {
+                       nr_fds = atomic_read(&u->scm_stat.nr_fds);
+                       goto out_print;
+               }
+
+               unix_state_lock(sk);
+               if (sk->sk_state != TCP_LISTEN)
+                       nr_fds = atomic_read(&u->scm_stat.nr_fds);
+               else
+                       nr_fds = unix_count_nr_fds(sk);
+               unix_state_unlock(sk);
+out_print:
+               seq_printf(m, "scm_fds: %u\n", nr_fds);
        }
 }
 #else
index b4ee163..ee41870 100644 (file)
@@ -882,6 +882,16 @@ s64 vsock_stream_has_space(struct vsock_sock *vsk)
 }
 EXPORT_SYMBOL_GPL(vsock_stream_has_space);
 
+void vsock_data_ready(struct sock *sk)
+{
+       struct vsock_sock *vsk = vsock_sk(sk);
+
+       if (vsock_stream_has_data(vsk) >= sk->sk_rcvlowat ||
+           sock_flag(sk, SOCK_DONE))
+               sk->sk_data_ready(sk);
+}
+EXPORT_SYMBOL_GPL(vsock_data_ready);
+
 static int vsock_release(struct socket *sock)
 {
        __vsock_release(sock->sk, 0);
@@ -1066,8 +1076,9 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
                if (transport && transport->stream_is_active(vsk) &&
                    !(sk->sk_shutdown & RCV_SHUTDOWN)) {
                        bool data_ready_now = false;
+                       int target = sock_rcvlowat(sk, 0, INT_MAX);
                        int ret = transport->notify_poll_in(
-                                       vsk, 1, &data_ready_now);
+                                       vsk, target, &data_ready_now);
                        if (ret < 0) {
                                mask |= EPOLLERR;
                        } else {
@@ -2137,6 +2148,25 @@ out:
        return err;
 }
 
+static int vsock_set_rcvlowat(struct sock *sk, int val)
+{
+       const struct vsock_transport *transport;
+       struct vsock_sock *vsk;
+
+       vsk = vsock_sk(sk);
+
+       if (val > vsk->buffer_size)
+               return -EINVAL;
+
+       transport = vsk->transport;
+
+       if (transport && transport->set_rcvlowat)
+               return transport->set_rcvlowat(vsk, val);
+
+       WRITE_ONCE(sk->sk_rcvlowat, val ? : 1);
+       return 0;
+}
+
 static const struct proto_ops vsock_stream_ops = {
        .family = PF_VSOCK,
        .owner = THIS_MODULE,
@@ -2156,6 +2186,7 @@ static const struct proto_ops vsock_stream_ops = {
        .recvmsg = vsock_connectible_recvmsg,
        .mmap = sock_no_mmap,
        .sendpage = sock_no_sendpage,
+       .set_rcvlowat = vsock_set_rcvlowat,
 };
 
 static const struct proto_ops vsock_seqpacket_ops = {
index fd98229..59c3e26 100644 (file)
@@ -815,6 +815,12 @@ int hvs_notify_send_post_enqueue(struct vsock_sock *vsk, ssize_t written,
        return 0;
 }
 
+static
+int hvs_set_rcvlowat(struct vsock_sock *vsk, int val)
+{
+       return -EOPNOTSUPP;
+}
+
 static struct vsock_transport hvs_transport = {
        .module                   = THIS_MODULE,
 
@@ -850,6 +856,7 @@ static struct vsock_transport hvs_transport = {
        .notify_send_pre_enqueue  = hvs_notify_send_pre_enqueue,
        .notify_send_post_enqueue = hvs_notify_send_post_enqueue,
 
+       .set_rcvlowat             = hvs_set_rcvlowat
 };
 
 static bool hvs_check_transport(struct vsock_sock *vsk)
index ec2c2af..3586313 100644 (file)
@@ -634,10 +634,7 @@ virtio_transport_notify_poll_in(struct vsock_sock *vsk,
                                size_t target,
                                bool *data_ready_now)
 {
-       if (vsock_stream_has_data(vsk))
-               *data_ready_now = true;
-       else
-               *data_ready_now = false;
+       *data_ready_now = vsock_stream_has_data(vsk) >= target;
 
        return 0;
 }
@@ -1084,7 +1081,7 @@ virtio_transport_recv_connected(struct sock *sk,
        switch (le16_to_cpu(pkt->hdr.op)) {
        case VIRTIO_VSOCK_OP_RW:
                virtio_transport_recv_enqueue(vsk, pkt);
-               sk->sk_data_ready(sk);
+               vsock_data_ready(sk);
                return err;
        case VIRTIO_VSOCK_OP_CREDIT_REQUEST:
                virtio_transport_send_credit_update(vsk);
index d69fc4b..7c3a7db 100644 (file)
@@ -307,7 +307,7 @@ vmci_transport_handle_wrote(struct sock *sk,
        struct vsock_sock *vsk = vsock_sk(sk);
        PKT_FIELD(vsk, sent_waiting_read) = false;
 #endif
-       sk->sk_data_ready(sk);
+       vsock_data_ready(sk);
 }
 
 static void vmci_transport_notify_pkt_socket_init(struct sock *sk)
@@ -340,12 +340,12 @@ vmci_transport_notify_pkt_poll_in(struct sock *sk,
 {
        struct vsock_sock *vsk = vsock_sk(sk);
 
-       if (vsock_stream_has_data(vsk)) {
+       if (vsock_stream_has_data(vsk) >= target) {
                *data_ready_now = true;
        } else {
-               /* We can't read right now because there is nothing in the
-                * queue. Ask for notifications when there is something to
-                * read.
+               /* We can't read right now because there is not enough data
+                * in the queue. Ask for notifications when there is something
+                * to read.
                 */
                if (sk->sk_state == TCP_ESTABLISHED) {
                        if (!send_waiting_read(sk, 1))
index 0f36d7c..e96a88d 100644 (file)
@@ -84,7 +84,7 @@ vmci_transport_handle_wrote(struct sock *sk,
                            bool bottom_half,
                            struct sockaddr_vm *dst, struct sockaddr_vm *src)
 {
-       sk->sk_data_ready(sk);
+       vsock_data_ready(sk);
 }
 
 static void vsock_block_update_write_window(struct sock *sk)
@@ -161,12 +161,12 @@ vmci_transport_notify_pkt_poll_in(struct sock *sk,
 {
        struct vsock_sock *vsk = vsock_sk(sk);
 
-       if (vsock_stream_has_data(vsk)) {
+       if (vsock_stream_has_data(vsk) >= target) {
                *data_ready_now = true;
        } else {
-               /* We can't read right now because there is nothing in the
-                * queue. Ask for notifications when there is something to
-                * read.
+               /* We can't read right now because there is not enough data
+                * in the queue. Ask for notifications when there is something
+                * to read.
                 */
                if (sk->sk_state == TCP_ESTABLISHED)
                        vsock_block_update_write_window(sk);
@@ -282,7 +282,7 @@ vmci_transport_notify_pkt_recv_post_dequeue(
                /* See the comment in
                 * vmci_transport_notify_pkt_send_post_enqueue().
                 */
-               sk->sk_data_ready(sk);
+               vsock_data_ready(sk);
        }
 
        return err;
index eefd6d8..5b0c4d5 100644 (file)
@@ -860,6 +860,9 @@ int wiphy_register(struct wiphy *wiphy)
 
                for (i = 0; i < sband->n_iftype_data; i++) {
                        const struct ieee80211_sband_iftype_data *iftd;
+                       bool has_ap, has_non_ap;
+                       u32 ap_bits = BIT(NL80211_IFTYPE_AP) |
+                                     BIT(NL80211_IFTYPE_P2P_GO);
 
                        iftd = &sband->iftype_data[i];
 
@@ -879,6 +882,19 @@ int wiphy_register(struct wiphy *wiphy)
                        else
                                have_he = have_he &&
                                          iftd->he_cap.has_he;
+
+                       has_ap = iftd->types_mask & ap_bits;
+                       has_non_ap = iftd->types_mask & ~ap_bits;
+
+                       /*
+                        * For EHT 20 MHz STA, the capabilities format differs
+                        * but to simplify, don't check 20 MHz but rather check
+                        * only if AP and non-AP were mentioned at the same time,
+                        * reject if so.
+                        */
+                       if (WARN_ON(iftd->eht_cap.has_eht &&
+                                   has_ap && has_non_ap))
+                               return -EINVAL;
                }
 
                if (WARN_ON(!have_he && band == NL80211_BAND_6GHZ))
index 4935f94..edd062f 100644 (file)
@@ -171,7 +171,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext)
         */
        if (rdev->ops->del_key)
                for (i = 0; i < 6; i++)
-                       rdev_del_key(rdev, dev, i, false, NULL);
+                       rdev_del_key(rdev, dev, -1, i, false, NULL);
 
        if (wdev->u.ibss.current_bss) {
                cfg80211_unhold_bss(wdev->u.ibss.current_bss);
index 2705e3e..8ff8b1c 100644 (file)
@@ -1545,7 +1545,6 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
                return -ENOLINK;
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_P2P_CLIENT:
-               /* for MLO, require driver validation of the link ID */
                if (wdev->connected)
                        return 0;
                return -ENOLINK;
@@ -1821,10 +1820,15 @@ nl80211_send_iftype_data(struct sk_buff *msg,
        if (eht_cap->has_eht && he_cap->has_he) {
                u8 mcs_nss_size, ppe_thresh_size;
                u16 ppe_thres_hdr;
+               bool is_ap;
+
+               is_ap = iftdata->types_mask & BIT(NL80211_IFTYPE_AP) ||
+                       iftdata->types_mask & BIT(NL80211_IFTYPE_P2P_GO);
 
                mcs_nss_size =
                        ieee80211_eht_mcs_nss_size(&he_cap->he_cap_elem,
-                                                  &eht_cap->eht_cap_elem);
+                                                  &eht_cap->eht_cap_elem,
+                                                  is_ap);
 
                ppe_thres_hdr = get_unaligned_le16(&eht_cap->eht_ppe_thres[0]);
                ppe_thresh_size =
@@ -3476,8 +3480,21 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
                        if (result)
                                goto out;
 
-                       result = rdev_set_txq_params(rdev, netdev,
-                                                    &txq_params);
+                       txq_params.link_id =
+                               nl80211_link_id_or_invalid(info->attrs);
+
+                       wdev_lock(netdev->ieee80211_ptr);
+                       if (txq_params.link_id >= 0 &&
+                           !(netdev->ieee80211_ptr->valid_links &
+                             BIT(txq_params.link_id)))
+                               result = -ENOLINK;
+                       else if (txq_params.link_id >= 0 &&
+                                !netdev->ieee80211_ptr->valid_links)
+                               result = -EINVAL;
+                       else
+                               result = rdev_set_txq_params(rdev, netdev,
+                                                            &txq_params);
+                       wdev_unlock(netdev->ieee80211_ptr);
                        if (result)
                                goto out;
                }
@@ -3848,12 +3865,19 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
 
                for_each_valid_link(wdev, link_id) {
                        struct nlattr *link = nla_nest_start(msg, link_id + 1);
+                       struct cfg80211_chan_def chandef = {};
+                       int ret;
 
                        if (nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
                                goto nla_put_failure;
                        if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
                                    wdev->links[link_id].addr))
                                goto nla_put_failure;
+
+                       ret = rdev_get_channel(rdev, wdev, link_id, &chandef);
+                       if (ret == 0 && nl80211_send_chandef(msg, &chandef))
+                               goto nla_put_failure;
+
                        nla_nest_end(msg, link);
                }
 
@@ -4320,6 +4344,38 @@ static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
        return rdev_set_noack_map(rdev, dev, noack_map);
 }
 
+static int nl80211_validate_key_link_id(struct genl_info *info,
+                                       struct wireless_dev *wdev,
+                                       int link_id, bool pairwise)
+{
+       if (pairwise) {
+               if (link_id != -1) {
+                       GENL_SET_ERR_MSG(info,
+                                        "link ID not allowed for pairwise key");
+                       return -EINVAL;
+               }
+
+               return 0;
+       }
+
+       if (wdev->valid_links) {
+               if (link_id == -1) {
+                       GENL_SET_ERR_MSG(info,
+                                        "link ID must for MLO group key");
+                       return -EINVAL;
+               }
+               if (!(wdev->valid_links & BIT(link_id))) {
+                       GENL_SET_ERR_MSG(info, "invalid link ID for MLO group key");
+                       return -EINVAL;
+               }
+       } else if (link_id != -1) {
+               GENL_SET_ERR_MSG(info, "link ID not allowed for non-MLO group key");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 struct get_key_cookie {
        struct sk_buff *msg;
        int error;
@@ -4381,13 +4437,15 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
        void *hdr;
        struct sk_buff *msg;
        bool bigtk_support = false;
+       int link_id = nl80211_link_id_or_invalid(info->attrs);
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
 
        if (wiphy_ext_feature_isset(&rdev->wiphy,
                                    NL80211_EXT_FEATURE_BEACON_PROTECTION))
                bigtk_support = true;
 
-       if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
-            dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
+       if ((wdev->iftype == NL80211_IFTYPE_STATION ||
+            wdev->iftype == NL80211_IFTYPE_P2P_CLIENT) &&
            wiphy_ext_feature_isset(&rdev->wiphy,
                                    NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
                bigtk_support = true;
@@ -4439,8 +4497,12 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
            nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr))
                goto nla_put_failure;
 
-       err = rdev_get_key(rdev, dev, key_idx, pairwise, mac_addr, &cookie,
-                          get_key_callback);
+       err = nl80211_validate_key_link_id(info, wdev, link_id, pairwise);
+       if (err)
+               goto free_msg;
+
+       err = rdev_get_key(rdev, dev, link_id, key_idx, pairwise, mac_addr,
+                          &cookie, get_key_callback);
 
        if (err)
                goto free_msg;
@@ -4464,6 +4526,8 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
        struct key_parse key;
        int err;
        struct net_device *dev = info->user_ptr[1];
+       int link_id = nl80211_link_id_or_invalid(info->attrs);
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
 
        err = nl80211_parse_key(info, &key);
        if (err)
@@ -4479,7 +4543,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
            !(key.p.mode == NL80211_KEY_SET_TX))
                return -EINVAL;
 
-       wdev_lock(dev->ieee80211_ptr);
+       wdev_lock(wdev);
 
        if (key.def) {
                if (!rdev->ops->set_default_key) {
@@ -4487,18 +4551,22 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
                        goto out;
                }
 
-               err = nl80211_key_allowed(dev->ieee80211_ptr);
+               err = nl80211_key_allowed(wdev);
                if (err)
                        goto out;
 
-               err = rdev_set_default_key(rdev, dev, key.idx,
-                                                key.def_uni, key.def_multi);
+               err = nl80211_validate_key_link_id(info, wdev, link_id, false);
+               if (err)
+                       goto out;
+
+               err = rdev_set_default_key(rdev, dev, link_id, key.idx,
+                                          key.def_uni, key.def_multi);
 
                if (err)
                        goto out;
 
 #ifdef CONFIG_CFG80211_WEXT
-               dev->ieee80211_ptr->wext.default_key = key.idx;
+               wdev->wext.default_key = key.idx;
 #endif
        } else if (key.defmgmt) {
                if (key.def_uni || !key.def_multi) {
@@ -4511,16 +4579,20 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
                        goto out;
                }
 
-               err = nl80211_key_allowed(dev->ieee80211_ptr);
+               err = nl80211_key_allowed(wdev);
                if (err)
                        goto out;
 
-               err = rdev_set_default_mgmt_key(rdev, dev, key.idx);
+               err = nl80211_validate_key_link_id(info, wdev, link_id, false);
+               if (err)
+                       goto out;
+
+               err = rdev_set_default_mgmt_key(rdev, dev, link_id, key.idx);
                if (err)
                        goto out;
 
 #ifdef CONFIG_CFG80211_WEXT
-               dev->ieee80211_ptr->wext.default_mgmt_key = key.idx;
+               wdev->wext.default_mgmt_key = key.idx;
 #endif
        } else if (key.defbeacon) {
                if (key.def_uni || !key.def_multi) {
@@ -4533,11 +4605,15 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
                        goto out;
                }
 
-               err = nl80211_key_allowed(dev->ieee80211_ptr);
+               err = nl80211_key_allowed(wdev);
+               if (err)
+                       goto out;
+
+               err = nl80211_validate_key_link_id(info, wdev, link_id, false);
                if (err)
                        goto out;
 
-               err = rdev_set_default_beacon_key(rdev, dev, key.idx);
+               err = rdev_set_default_beacon_key(rdev, dev, link_id, key.idx);
                if (err)
                        goto out;
        } else if (key.p.mode == NL80211_KEY_SET_TX &&
@@ -4553,14 +4629,18 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
                        goto out;
                }
 
-               err = rdev_add_key(rdev, dev, key.idx,
+               err = nl80211_validate_key_link_id(info, wdev, link_id, true);
+               if (err)
+                       goto out;
+
+               err = rdev_add_key(rdev, dev, link_id, key.idx,
                                   NL80211_KEYTYPE_PAIRWISE,
                                   mac_addr, &key.p);
        } else {
                err = -EINVAL;
        }
  out:
-       wdev_unlock(dev->ieee80211_ptr);
+       wdev_unlock(wdev);
 
        return err;
 }
@@ -4572,6 +4652,8 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
        struct net_device *dev = info->user_ptr[1];
        struct key_parse key;
        const u8 *mac_addr = NULL;
+       int link_id = nl80211_link_id_or_invalid(info->attrs);
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
 
        err = nl80211_parse_key(info, &key);
        if (err)
@@ -4613,18 +4695,23 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
                return -EINVAL;
        }
 
-       wdev_lock(dev->ieee80211_ptr);
-       err = nl80211_key_allowed(dev->ieee80211_ptr);
+       wdev_lock(wdev);
+       err = nl80211_key_allowed(wdev);
        if (err)
                GENL_SET_ERR_MSG(info, "key not allowed");
+
+       if (!err)
+               err = nl80211_validate_key_link_id(info, wdev, link_id,
+                               key.type == NL80211_KEYTYPE_PAIRWISE);
+
        if (!err) {
-               err = rdev_add_key(rdev, dev, key.idx,
+               err = rdev_add_key(rdev, dev, link_id, key.idx,
                                   key.type == NL80211_KEYTYPE_PAIRWISE,
                                    mac_addr, &key.p);
                if (err)
                        GENL_SET_ERR_MSG(info, "key addition failed");
        }
-       wdev_unlock(dev->ieee80211_ptr);
+       wdev_unlock(wdev);
 
        return err;
 }
@@ -4636,6 +4723,8 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
        struct net_device *dev = info->user_ptr[1];
        u8 *mac_addr = NULL;
        struct key_parse key;
+       int link_id = nl80211_link_id_or_invalid(info->attrs);
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
 
        err = nl80211_parse_key(info, &key);
        if (err)
@@ -4663,27 +4752,31 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->del_key)
                return -EOPNOTSUPP;
 
-       wdev_lock(dev->ieee80211_ptr);
-       err = nl80211_key_allowed(dev->ieee80211_ptr);
+       wdev_lock(wdev);
+       err = nl80211_key_allowed(wdev);
 
        if (key.type == NL80211_KEYTYPE_GROUP && mac_addr &&
            !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
                err = -ENOENT;
 
        if (!err)
-               err = rdev_del_key(rdev, dev, key.idx,
+               err = nl80211_validate_key_link_id(info, wdev, link_id,
+                               key.type == NL80211_KEYTYPE_PAIRWISE);
+
+       if (!err)
+               err = rdev_del_key(rdev, dev, link_id, key.idx,
                                   key.type == NL80211_KEYTYPE_PAIRWISE,
                                   mac_addr);
 
 #ifdef CONFIG_CFG80211_WEXT
        if (!err) {
-               if (key.idx == dev->ieee80211_ptr->wext.default_key)
-                       dev->ieee80211_ptr->wext.default_key = -1;
-               else if (key.idx == dev->ieee80211_ptr->wext.default_mgmt_key)
-                       dev->ieee80211_ptr->wext.default_mgmt_key = -1;
+               if (key.idx == wdev->wext.default_key)
+                       wdev->wext.default_key = -1;
+               else if (key.idx == wdev->wext.default_mgmt_key)
+                       wdev->wext.default_mgmt_key = -1;
        }
 #endif
-       wdev_unlock(dev->ieee80211_ptr);
+       wdev_unlock(wdev);
 
        return err;
 }
@@ -5587,7 +5680,7 @@ static int nl80211_calculate_ap_params(struct cfg80211_ap_settings *params)
                params->eht_cap = (void *)(cap->data + 1);
                if (!ieee80211_eht_capa_size_ok((const u8 *)params->he_cap,
                                                (const u8 *)params->eht_cap,
-                                               cap->datalen - 1))
+                                               cap->datalen - 1, true))
                        return -EINVAL;
        }
        cap = cfg80211_find_ext_elem(WLAN_EID_EXT_EHT_OPERATION, ies, ies_len);
@@ -6816,7 +6909,8 @@ static int nl80211_set_station_tdls(struct genl_info *info,
 
                        if (!ieee80211_eht_capa_size_ok((const u8 *)params->link_sta_params.he_capa,
                                                        (const u8 *)params->link_sta_params.eht_capa,
-                                                       params->link_sta_params.eht_capa_len))
+                                                       params->link_sta_params.eht_capa_len,
+                                                       false))
                                return -EINVAL;
                }
        }
@@ -7127,7 +7221,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 
                        if (!ieee80211_eht_capa_size_ok((const u8 *)params.link_sta_params.he_capa,
                                                        (const u8 *)params.link_sta_params.eht_capa,
-                                                       params.link_sta_params.eht_capa_len))
+                                                       params.link_sta_params.eht_capa_len,
+                                                       false))
                                return -EINVAL;
                }
        }
@@ -10087,8 +10182,10 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
                            (nla_put_u32(msg, NL80211_BSS_STATUS,
                                         NL80211_BSS_STATUS_ASSOCIATED) ||
                             (wdev->valid_links &&
-                             nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
-                                        link_id))))
+                             (nla_put_u8(msg, NL80211_BSS_MLO_LINK_ID,
+                                         link_id) ||
+                              nla_put(msg, NL80211_BSS_MLD_ADDR, ETH_ALEN,
+                                      wdev->u.client.connected_addr)))))
                                goto nla_put_failure;
                }
                break;
@@ -11184,7 +11281,6 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
        struct net_device *dev = info->user_ptr[1];
        int mcast_rate[NUM_NL80211_BANDS];
        u32 nla_rate;
-       int err;
 
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC &&
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
@@ -11203,9 +11299,7 @@ static int nl80211_set_mcast_rate(struct sk_buff *skb, struct genl_info *info)
        if (!nl80211_parse_mcast_rate(rdev, mcast_rate, nla_rate))
                return -EINVAL;
 
-       err = rdev_set_mcast_rate(rdev, dev, mcast_rate);
-
-       return err;
+       return rdev_set_mcast_rate(rdev, dev, mcast_rate);
 }
 
 static struct sk_buff *
@@ -15887,7 +15981,8 @@ nl80211_add_mod_link_station(struct sk_buff *skb, struct genl_info *info,
 
                        if (!ieee80211_eht_capa_size_ok((const u8 *)params.he_capa,
                                                        (const u8 *)params.eht_capa,
-                                                       params.eht_capa_len))
+                                                       params.eht_capa_len,
+                                                       false))
                                return -EINVAL;
                }
        }
@@ -17141,6 +17236,7 @@ static struct genl_family nl80211_fam __ro_after_init = {
        .n_ops = ARRAY_SIZE(nl80211_ops),
        .small_ops = nl80211_small_ops,
        .n_small_ops = ARRAY_SIZE(nl80211_small_ops),
+       .resv_start_op = NL80211_CMD_REMOVE_LINK_STA + 1,
        .mcgrps = nl80211_mcgrps,
        .n_mcgrps = ARRAY_SIZE(nl80211_mcgrps),
        .parallel_ops = true,
@@ -18836,11 +18932,13 @@ EXPORT_SYMBOL(cfg80211_pmksa_candidate_notify);
 
 static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
                                     struct net_device *netdev,
+                                    unsigned int link_id,
                                     struct cfg80211_chan_def *chandef,
                                     gfp_t gfp,
                                     enum nl80211_commands notif,
                                     u8 count, bool quiet)
 {
+       struct wireless_dev *wdev = netdev->ieee80211_ptr;
        struct sk_buff *msg;
        void *hdr;
 
@@ -18857,6 +18955,10 @@ static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
        if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex))
                goto nla_put_failure;
 
+       if (wdev->valid_links &&
+           nla_put_u8(msg, NL80211_ATTR_MLO_LINK_ID, link_id))
+               goto nla_put_failure;
+
        if (nl80211_send_chandef(msg, chandef))
                goto nla_put_failure;
 
@@ -18916,22 +19018,26 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
 
        cfg80211_sched_dfs_chan_update(rdev);
 
-       nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
+       nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
                                 NL80211_CMD_CH_SWITCH_NOTIFY, 0, false);
 }
 EXPORT_SYMBOL(cfg80211_ch_switch_notify);
 
 void cfg80211_ch_switch_started_notify(struct net_device *dev,
                                       struct cfg80211_chan_def *chandef,
-                                      u8 count, bool quiet)
+                                      unsigned int link_id, u8 count,
+                                      bool quiet)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
 
-       trace_cfg80211_ch_switch_started_notify(dev, chandef);
+       ASSERT_WDEV_LOCK(wdev);
+       WARN_INVALID_LINK_ID(wdev, link_id);
+
+       trace_cfg80211_ch_switch_started_notify(dev, chandef, link_id);
 
-       nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
+       nl80211_ch_switch_notify(rdev, dev, link_id, chandef, GFP_KERNEL,
                                 NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
                                 count, quiet);
 }
index 40915a8..13b209a 100644 (file)
@@ -77,65 +77,69 @@ rdev_change_virtual_intf(struct cfg80211_registered_device *rdev,
 }
 
 static inline int rdev_add_key(struct cfg80211_registered_device *rdev,
-                              struct net_device *netdev, u8 key_index,
-                              bool pairwise, const u8 *mac_addr,
+                              struct net_device *netdev, int link_id,
+                              u8 key_index, bool pairwise, const u8 *mac_addr,
                               struct key_params *params)
 {
        int ret;
-       trace_rdev_add_key(&rdev->wiphy, netdev, key_index, pairwise,
+       trace_rdev_add_key(&rdev->wiphy, netdev, link_id, key_index, pairwise,
                           mac_addr, params->mode);
-       ret = rdev->ops->add_key(&rdev->wiphy, netdev, key_index, pairwise,
-                                 mac_addr, params);
+       ret = rdev->ops->add_key(&rdev->wiphy, netdev, link_id, key_index,
+                                 pairwise, mac_addr, params);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
 }
 
 static inline int
 rdev_get_key(struct cfg80211_registered_device *rdev, struct net_device *netdev,
-            u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie,
+            int link_id, u8 key_index, bool pairwise, const u8 *mac_addr,
+            void *cookie,
             void (*callback)(void *cookie, struct key_params*))
 {
        int ret;
-       trace_rdev_get_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
-       ret = rdev->ops->get_key(&rdev->wiphy, netdev, key_index, pairwise,
-                                 mac_addr, cookie, callback);
+       trace_rdev_get_key(&rdev->wiphy, netdev, link_id, key_index, pairwise,
+                          mac_addr);
+       ret = rdev->ops->get_key(&rdev->wiphy, netdev, link_id, key_index,
+                                 pairwise, mac_addr, cookie, callback);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
 }
 
 static inline int rdev_del_key(struct cfg80211_registered_device *rdev,
-                              struct net_device *netdev, u8 key_index,
-                              bool pairwise, const u8 *mac_addr)
+                              struct net_device *netdev, int link_id,
+                              u8 key_index, bool pairwise, const u8 *mac_addr)
 {
        int ret;
-       trace_rdev_del_key(&rdev->wiphy, netdev, key_index, pairwise, mac_addr);
-       ret = rdev->ops->del_key(&rdev->wiphy, netdev, key_index, pairwise,
-                                 mac_addr);
+       trace_rdev_del_key(&rdev->wiphy, netdev, link_id, key_index, pairwise,
+                          mac_addr);
+       ret = rdev->ops->del_key(&rdev->wiphy, netdev, link_id, key_index,
+                                 pairwise, mac_addr);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
 }
 
 static inline int
 rdev_set_default_key(struct cfg80211_registered_device *rdev,
-                    struct net_device *netdev, u8 key_index, bool unicast,
-                    bool multicast)
+                    struct net_device *netdev, int link_id, u8 key_index,
+                    bool unicast, bool multicast)
 {
        int ret;
-       trace_rdev_set_default_key(&rdev->wiphy, netdev, key_index,
+       trace_rdev_set_default_key(&rdev->wiphy, netdev, link_id, key_index,
                                   unicast, multicast);
-       ret = rdev->ops->set_default_key(&rdev->wiphy, netdev, key_index,
-                                         unicast, multicast);
+       ret = rdev->ops->set_default_key(&rdev->wiphy, netdev, link_id,
+                                         key_index, unicast, multicast);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
 }
 
 static inline int
 rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev,
-                         struct net_device *netdev, u8 key_index)
+                         struct net_device *netdev, int link_id, u8 key_index)
 {
        int ret;
-       trace_rdev_set_default_mgmt_key(&rdev->wiphy, netdev, key_index);
-       ret = rdev->ops->set_default_mgmt_key(&rdev->wiphy, netdev,
+       trace_rdev_set_default_mgmt_key(&rdev->wiphy, netdev, link_id,
+                                       key_index);
+       ret = rdev->ops->set_default_mgmt_key(&rdev->wiphy, netdev, link_id,
                                               key_index);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
@@ -143,13 +147,15 @@ rdev_set_default_mgmt_key(struct cfg80211_registered_device *rdev,
 
 static inline int
 rdev_set_default_beacon_key(struct cfg80211_registered_device *rdev,
-                           struct net_device *netdev, u8 key_index)
+                           struct net_device *netdev, int link_id,
+                           u8 key_index)
 {
        int ret;
 
-       trace_rdev_set_default_beacon_key(&rdev->wiphy, netdev, key_index);
-       ret = rdev->ops->set_default_beacon_key(&rdev->wiphy, netdev,
-                                               key_index);
+       trace_rdev_set_default_beacon_key(&rdev->wiphy, netdev, link_id,
+                                         key_index);
+       ret = rdev->ops->set_default_beacon_key(&rdev->wiphy, netdev, link_id,
+                                                key_index);
        trace_rdev_return_int(&rdev->wiphy, ret);
        return ret;
 }
index c7383ed..d5c7a5a 100644 (file)
@@ -2389,6 +2389,10 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
                switch (iftype) {
                case NL80211_IFTYPE_AP:
                case NL80211_IFTYPE_P2P_GO:
+                       if (!wdev->links[link].ap.beacon_interval)
+                               continue;
+                       chandef = wdev->links[link].ap.chandef;
+                       break;
                case NL80211_IFTYPE_MESH_POINT:
                        if (!wdev->u.mesh.beacon_interval)
                                continue;
index 0134e5d..5382fc2 100644 (file)
@@ -540,7 +540,7 @@ static int cfg80211_parse_ap_info(struct cfg80211_colocated_ap *entry,
        memcpy(entry->bssid, pos, ETH_ALEN);
        pos += ETH_ALEN;
 
-       if (length == IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM) {
+       if (length >= IEEE80211_TBTT_INFO_OFFSET_BSSID_SSSID_BSS_PARAM) {
                memcpy(&entry->short_ssid, pos,
                       sizeof(entry->short_ssid));
                entry->short_ssid_valid = true;
index 27fb2a0..d513536 100644 (file)
@@ -747,6 +747,9 @@ void __cfg80211_connect_result(struct net_device *dev,
                        if (WARN_ON(!cr->links[link].addr))
                                goto out;
                }
+
+               if (WARN_ON(wdev->connect_keys))
+                       goto out;
        }
 
        wdev->unprot_beacon_reported = 0;
@@ -1325,7 +1328,7 @@ void __cfg80211_disconnected(struct net_device *dev, const u8 *ie,
                            NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))
                        max_key_idx = 7;
                for (i = 0; i <= max_key_idx; i++)
-                       rdev_del_key(rdev, dev, i, false, NULL);
+                       rdev_del_key(rdev, dev, -1, i, false, NULL);
        }
 
        rdev_set_qos_map(rdev, dev, NULL);
index 10b2fd9..a405c3e 100644 (file)
@@ -434,13 +434,14 @@ TRACE_EVENT(rdev_change_virtual_intf,
 );
 
 DECLARE_EVENT_CLASS(key_handle,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                bool pairwise, const u8 *mac_addr),
-       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr),
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index, bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
                MAC_ENTRY(mac_addr)
+               __field(int, link_id)
                __field(u8, key_index)
                __field(bool, pairwise)
        ),
@@ -448,34 +449,38 @@ DECLARE_EVENT_CLASS(key_handle,
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
                MAC_ASSIGN(mac_addr, mac_addr);
+               __entry->link_id = link_id;
                __entry->key_index = key_index;
                __entry->pairwise = pairwise;
        ),
-       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
-                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
-                 BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
+                 "key_index: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id,
+                 __entry->key_index, BOOL_TO_STR(__entry->pairwise),
+                 MAC_PR_ARG(mac_addr))
 );
 
 DEFINE_EVENT(key_handle, rdev_get_key,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                bool pairwise, const u8 *mac_addr),
-       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index, bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr)
 );
 
 DEFINE_EVENT(key_handle, rdev_del_key,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                bool pairwise, const u8 *mac_addr),
-       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr)
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index, bool pairwise, const u8 *mac_addr),
+       TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr)
 );
 
 TRACE_EVENT(rdev_add_key,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                bool pairwise, const u8 *mac_addr, u8 mode),
-       TP_ARGS(wiphy, netdev, key_index, pairwise, mac_addr, mode),
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index, bool pairwise, const u8 *mac_addr, u8 mode),
+       TP_ARGS(wiphy, netdev, link_id, key_index, pairwise, mac_addr, mode),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
                MAC_ENTRY(mac_addr)
+               __field(int, link_id)
                __field(u8, key_index)
                __field(bool, pairwise)
                __field(u8, mode)
@@ -484,24 +489,27 @@ TRACE_EVENT(rdev_add_key,
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
                MAC_ASSIGN(mac_addr, mac_addr);
+               __entry->link_id = link_id;
                __entry->key_index = key_index;
                __entry->pairwise = pairwise;
                __entry->mode = mode;
        ),
-       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key_index: %u, "
-                 "mode: %u, pairwise: %s, mac addr: " MAC_PR_FMT,
-                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
-                 __entry->mode, BOOL_TO_STR(__entry->pairwise),
-                 MAC_PR_ARG(mac_addr))
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
+                 "key_index: %u, mode: %u, pairwise: %s, "
+                 "mac addr: " MAC_PR_FMT,
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id,
+                 __entry->key_index, __entry->mode,
+                 BOOL_TO_STR(__entry->pairwise), MAC_PR_ARG(mac_addr))
 );
 
 TRACE_EVENT(rdev_set_default_key,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index,
-                bool unicast, bool multicast),
-       TP_ARGS(wiphy, netdev, key_index, unicast, multicast),
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index, bool unicast, bool multicast),
+       TP_ARGS(wiphy, netdev, link_id, key_index, unicast, multicast),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
+               __field(int, link_id)
                __field(u8, key_index)
                __field(bool, unicast)
                __field(bool, multicast)
@@ -509,48 +517,58 @@ TRACE_EVENT(rdev_set_default_key,
        TP_fast_assign(
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
+               __entry->link_id = link_id;
                __entry->key_index = key_index;
                __entry->unicast = unicast;
                __entry->multicast = multicast;
        ),
-       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u, unicast: %s, multicast: %s",
-                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index,
-                 BOOL_TO_STR(__entry->unicast),
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
+                 "key index: %u, unicast: %s, multicast: %s",
+                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->link_id,
+                 __entry->key_index, BOOL_TO_STR(__entry->unicast),
                  BOOL_TO_STR(__entry->multicast))
 );
 
 TRACE_EVENT(rdev_set_default_mgmt_key,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index),
-       TP_ARGS(wiphy, netdev, key_index),
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index),
+       TP_ARGS(wiphy, netdev, link_id, key_index),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
+               __field(int, link_id)
                __field(u8, key_index)
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
+               __entry->link_id = link_id;
                __entry->key_index = key_index;
        ),
-       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u",
-                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
+                 "key index: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
+                 __entry->link_id, __entry->key_index)
 );
 
 TRACE_EVENT(rdev_set_default_beacon_key,
-       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 key_index),
-       TP_ARGS(wiphy, netdev, key_index),
+       TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int link_id,
+                u8 key_index),
+       TP_ARGS(wiphy, netdev, link_id, key_index),
        TP_STRUCT__entry(
                WIPHY_ENTRY
                NETDEV_ENTRY
+               __field(int, link_id)
                __field(u8, key_index)
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
                NETDEV_ASSIGN;
+               __entry->link_id = link_id;
                __entry->key_index = key_index;
        ),
-       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", key index: %u",
-                 WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->key_index)
+       TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", link_id: %d, "
+                 "key index: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
+                 __entry->link_id, __entry->key_index)
 );
 
 TRACE_EVENT(rdev_start_ap,
@@ -3245,18 +3263,21 @@ TRACE_EVENT(cfg80211_ch_switch_notify,
 
 TRACE_EVENT(cfg80211_ch_switch_started_notify,
        TP_PROTO(struct net_device *netdev,
-                struct cfg80211_chan_def *chandef),
-       TP_ARGS(netdev, chandef),
+                struct cfg80211_chan_def *chandef,
+                unsigned int link_id),
+       TP_ARGS(netdev, chandef, link_id),
        TP_STRUCT__entry(
                NETDEV_ENTRY
                CHAN_DEF_ENTRY
+               __field(unsigned int, link_id)
        ),
        TP_fast_assign(
                NETDEV_ASSIGN;
                CHAN_DEF_ASSIGN(chandef);
+               __entry->link_id = link_id;
        ),
-       TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
-                 NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
+       TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT ", link:%d",
+                 NETDEV_PR_ARG, CHAN_DEF_PR_ARG, __entry->link_id)
 );
 
 TRACE_EVENT(cfg80211_radar_event,
index 2c12795..0b28d00 100644 (file)
@@ -935,13 +935,13 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev)
        for (i = 0; i < CFG80211_MAX_WEP_KEYS; i++) {
                if (!wdev->connect_keys->params[i].cipher)
                        continue;
-               if (rdev_add_key(rdev, dev, i, false, NULL,
+               if (rdev_add_key(rdev, dev, -1, i, false, NULL,
                                 &wdev->connect_keys->params[i])) {
                        netdev_err(dev, "failed to set key %d\n", i);
                        continue;
                }
                if (wdev->connect_keys->def == i &&
-                   rdev_set_default_key(rdev, dev, i, true, true)) {
+                   rdev_set_default_key(rdev, dev, -1, i, true, true)) {
                        netdev_err(dev, "failed to set defkey %d\n", i);
                        continue;
                }
index a9767bf..ddf340b 100644 (file)
@@ -470,7 +470,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
                            !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))
                                err = -ENOENT;
                        else
-                               err = rdev_del_key(rdev, dev, idx, pairwise,
+                               err = rdev_del_key(rdev, dev, -1, idx, pairwise,
                                                   addr);
                }
                wdev->wext.connect.privacy = false;
@@ -509,7 +509,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
        if (wdev->connected ||
            (wdev->iftype == NL80211_IFTYPE_ADHOC &&
             wdev->u.ibss.current_bss))
-               err = rdev_add_key(rdev, dev, idx, pairwise, addr, params);
+               err = rdev_add_key(rdev, dev, -1, idx, pairwise, addr, params);
        else if (params->cipher != WLAN_CIPHER_SUITE_WEP40 &&
                 params->cipher != WLAN_CIPHER_SUITE_WEP104)
                return -EINVAL;
@@ -546,7 +546,8 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
                                __cfg80211_leave_ibss(rdev, wdev->netdev, true);
                                rejoin = true;
                        }
-                       err = rdev_set_default_key(rdev, dev, idx, true, true);
+                       err = rdev_set_default_key(rdev, dev, -1, idx, true,
+                                                  true);
                }
                if (!err) {
                        wdev->wext.default_key = idx;
@@ -561,7 +562,7 @@ static int __cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
                if (wdev->connected ||
                    (wdev->iftype == NL80211_IFTYPE_ADHOC &&
                     wdev->u.ibss.current_bss))
-                       err = rdev_set_default_mgmt_key(rdev, dev, idx);
+                       err = rdev_set_default_mgmt_key(rdev, dev, -1, idx);
                if (!err)
                        wdev->wext.default_mgmt_key = idx;
                return err;
@@ -632,7 +633,7 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
                if (wdev->connected ||
                    (wdev->iftype == NL80211_IFTYPE_ADHOC &&
                     wdev->u.ibss.current_bss))
-                       err = rdev_set_default_key(rdev, dev, idx, true,
+                       err = rdev_set_default_key(rdev, dev, -1, idx, true,
                                                   true);
                if (!err)
                        wdev->wext.default_key = idx;
@@ -685,6 +686,13 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
            !rdev->ops->set_default_key)
                return -EOPNOTSUPP;
 
+       wdev_lock(wdev);
+       if (wdev->valid_links) {
+               wdev_unlock(wdev);
+               return -EOPNOTSUPP;
+       }
+       wdev_unlock(wdev);
+
        switch (ext->alg) {
        case IW_ENCODE_ALG_NONE:
                remove = true;
index f701121..a71a8c6 100644 (file)
@@ -379,6 +379,16 @@ static void xp_check_dma_contiguity(struct xsk_dma_map *dma_map)
 
 static int xp_init_dma_info(struct xsk_buff_pool *pool, struct xsk_dma_map *dma_map)
 {
+       if (!pool->unaligned) {
+               u32 i;
+
+               for (i = 0; i < pool->heads_cnt; i++) {
+                       struct xdp_buff_xsk *xskb = &pool->heads[i];
+
+                       xp_init_xskb_dma(xskb, pool, dma_map->dma_pages, xskb->orig_addr);
+               }
+       }
+
        pool->dma_pages = kvcalloc(dma_map->dma_pages_cnt, sizeof(*pool->dma_pages), GFP_KERNEL);
        if (!pool->dma_pages)
                return -ENOMEM;
@@ -428,12 +438,6 @@ int xp_dma_map(struct xsk_buff_pool *pool, struct device *dev,
 
        if (pool->unaligned)
                xp_check_dma_contiguity(dma_map);
-       else
-               for (i = 0; i < pool->heads_cnt; i++) {
-                       struct xdp_buff_xsk *xskb = &pool->heads[i];
-
-                       xp_init_xskb_dma(xskb, pool, dma_map->dma_pages, xskb->orig_addr);
-               }
 
        err = xp_init_dma_info(pool, dma_map);
        if (err) {
index 14d30fe..4b95de2 100644 (file)
@@ -2660,4 +2660,8 @@ int security_uring_sqpoll(void)
 {
        return call_int_hook(uring_sqpoll, 0);
 }
+int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       return call_int_hook(uring_cmd, 0, ioucmd);
+}
 #endif /* CONFIG_IO_URING */
index 7957350..03bca97 100644 (file)
@@ -91,6 +91,7 @@
 #include <uapi/linux/mount.h>
 #include <linux/fsnotify.h>
 #include <linux/fanotify.h>
+#include <linux/io_uring.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -6987,6 +6988,28 @@ static int selinux_uring_sqpoll(void)
        return avc_has_perm(&selinux_state, sid, sid,
                            SECCLASS_IO_URING, IO_URING__SQPOLL, NULL);
 }
+
+/**
+ * selinux_uring_cmd - check if IORING_OP_URING_CMD is allowed
+ * @ioucmd: the io_uring command structure
+ *
+ * Check to see if the current domain is allowed to execute an
+ * IORING_OP_URING_CMD against the device/file specified in @ioucmd.
+ *
+ */
+static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       struct file *file = ioucmd->file;
+       struct inode *inode = file_inode(file);
+       struct inode_security_struct *isec = selinux_inode(inode);
+       struct common_audit_data ad;
+
+       ad.type = LSM_AUDIT_DATA_FILE;
+       ad.u.file = file;
+
+       return avc_has_perm(&selinux_state, current_sid(), isec->sid,
+                           SECCLASS_IO_URING, IO_URING__CMD, &ad);
+}
 #endif /* CONFIG_IO_URING */
 
 /*
@@ -7231,6 +7254,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 #ifdef CONFIG_IO_URING
        LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds),
        LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll),
+       LSM_HOOK_INIT(uring_cmd, selinux_uring_cmd),
 #endif
 
        /*
index ff757ae..1c2f41f 100644 (file)
@@ -253,7 +253,7 @@ const struct security_class_mapping secclass_map[] = {
        { "anon_inode",
          { COMMON_FILE_PERMS, NULL } },
        { "io_uring",
-         { "override_creds", "sqpoll", NULL } },
+         { "override_creds", "sqpoll", "cmd", NULL } },
        { NULL }
   };
 
index 0018314..bffccdc 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/fs_context.h>
 #include <linux/fs_parser.h>
 #include <linux/watch_queue.h>
+#include <linux/io_uring.h>
 #include "smack.h"
 
 #define TRANS_TRUE     "TRUE"
@@ -4732,6 +4733,36 @@ static int smack_uring_sqpoll(void)
        return -EPERM;
 }
 
+/**
+ * smack_uring_cmd - check on file operations for io_uring
+ * @ioucmd: the command in question
+ *
+ * Make a best guess about whether a io_uring "command" should
+ * be allowed. Use the same logic used for determining if the
+ * file could be opened for read in the absence of better criteria.
+ */
+static int smack_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       struct file *file = ioucmd->file;
+       struct smk_audit_info ad;
+       struct task_smack *tsp;
+       struct inode *inode;
+       int rc;
+
+       if (!file)
+               return -EINVAL;
+
+       tsp = smack_cred(file->f_cred);
+       inode = file_inode(file);
+
+       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+       smk_ad_setfield_u_fs_path(&ad, file->f_path);
+       rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
+       rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc);
+
+       return rc;
+}
+
 #endif /* CONFIG_IO_URING */
 
 struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
@@ -4889,6 +4920,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
 #ifdef CONFIG_IO_URING
        LSM_HOOK_INIT(uring_override_creds, smack_uring_override_creds),
        LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll),
+       LSM_HOOK_INIT(uring_cmd, smack_uring_cmd),
 #endif
 };
 
index f3e8937..a727192 100644 (file)
@@ -385,14 +385,14 @@ static bool elem_id_matches(const struct snd_kcontrol *kctl,
 #define MULTIPLIER     37
 static unsigned long get_ctl_id_hash(const struct snd_ctl_elem_id *id)
 {
+       int i;
        unsigned long h;
-       const unsigned char *p;
 
        h = id->iface;
        h = MULTIPLIER * h + id->device;
        h = MULTIPLIER * h + id->subdevice;
-       for (p = id->name; *p; p++)
-               h = MULTIPLIER * h + *p;
+       for (i = 0; i < SNDRV_CTL_ELEM_ID_NAME_MAXLEN && id->name[i]; i++)
+               h = MULTIPLIER * h + id->name[i];
        h = MULTIPLIER * h + id->index;
        h &= LONG_MAX;
        return h;
index d3885cb..b665ac6 100644 (file)
 
 static const struct snd_malloc_ops *snd_dma_get_ops(struct snd_dma_buffer *dmab);
 
+#ifdef CONFIG_SND_DMA_SGBUF
+static void *do_alloc_fallback_pages(struct device *dev, size_t size,
+                                    dma_addr_t *addr, bool wc);
+static void do_free_fallback_pages(void *p, size_t size, bool wc);
+static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
+#endif
+
 /* a cast to gfp flag from the dev pointer; for CONTINUOUS and VMALLOC types */
 static inline gfp_t snd_mem_get_gfp_flags(const struct snd_dma_buffer *dmab,
                                          gfp_t default_gfp)
@@ -277,16 +284,21 @@ EXPORT_SYMBOL(snd_sgbuf_get_chunk_size);
 /*
  * Continuous pages allocator
  */
-static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+static void *do_alloc_pages(size_t size, dma_addr_t *addr, gfp_t gfp)
 {
-       gfp_t gfp = snd_mem_get_gfp_flags(dmab, GFP_KERNEL);
        void *p = alloc_pages_exact(size, gfp);
 
        if (p)
-               dmab->addr = page_to_phys(virt_to_page(p));
+               *addr = page_to_phys(virt_to_page(p));
        return p;
 }
 
+static void *snd_dma_continuous_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+       return do_alloc_pages(size, &dmab->addr,
+                             snd_mem_get_gfp_flags(dmab, GFP_KERNEL));
+}
+
 static void snd_dma_continuous_free(struct snd_dma_buffer *dmab)
 {
        free_pages_exact(dmab->area, dmab->bytes);
@@ -463,6 +475,25 @@ static const struct snd_malloc_ops snd_dma_dev_ops = {
 /*
  * Write-combined pages
  */
+/* x86-specific allocations */
+#ifdef CONFIG_SND_DMA_SGBUF
+static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
+{
+       return do_alloc_fallback_pages(dmab->dev.dev, size, &dmab->addr, true);
+}
+
+static void snd_dma_wc_free(struct snd_dma_buffer *dmab)
+{
+       do_free_fallback_pages(dmab->area, dmab->bytes, true);
+}
+
+static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
+                          struct vm_area_struct *area)
+{
+       area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+       return snd_dma_continuous_mmap(dmab, area);
+}
+#else
 static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
 {
        return dma_alloc_wc(dmab->dev.dev, size, &dmab->addr, DEFAULT_GFP);
@@ -479,6 +510,7 @@ static int snd_dma_wc_mmap(struct snd_dma_buffer *dmab,
        return dma_mmap_wc(dmab->dev.dev, area,
                           dmab->area, dmab->addr, dmab->bytes);
 }
+#endif /* CONFIG_SND_DMA_SGBUF */
 
 static const struct snd_malloc_ops snd_dma_wc_ops = {
        .alloc = snd_dma_wc_alloc,
@@ -486,10 +518,6 @@ static const struct snd_malloc_ops snd_dma_wc_ops = {
        .mmap = snd_dma_wc_mmap,
 };
 
-#ifdef CONFIG_SND_DMA_SGBUF
-static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size);
-#endif
-
 /*
  * Non-contiguous pages allocator
  */
@@ -669,6 +697,37 @@ static const struct snd_malloc_ops snd_dma_sg_wc_ops = {
        .get_chunk_size = snd_dma_noncontig_get_chunk_size,
 };
 
+/* manual page allocations with wc setup */
+static void *do_alloc_fallback_pages(struct device *dev, size_t size,
+                                    dma_addr_t *addr, bool wc)
+{
+       gfp_t gfp = GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN;
+       void *p;
+
+ again:
+       p = do_alloc_pages(size, addr, gfp);
+       if (!p || (*addr + size - 1) & ~dev->coherent_dma_mask) {
+               if (IS_ENABLED(CONFIG_ZONE_DMA32) && !(gfp & GFP_DMA32)) {
+                       gfp |= GFP_DMA32;
+                       goto again;
+               }
+               if (IS_ENABLED(CONFIG_ZONE_DMA) && !(gfp & GFP_DMA)) {
+                       gfp = (gfp & ~GFP_DMA32) | GFP_DMA;
+                       goto again;
+               }
+       }
+       if (p && wc)
+               set_memory_wc((unsigned long)(p), size >> PAGE_SHIFT);
+       return p;
+}
+
+static void do_free_fallback_pages(void *p, size_t size, bool wc)
+{
+       if (wc)
+               set_memory_wb((unsigned long)(p), size >> PAGE_SHIFT);
+       free_pages_exact(p, size);
+}
+
 /* Fallback SG-buffer allocations for x86 */
 struct snd_dma_sg_fallback {
        size_t count;
@@ -679,14 +738,11 @@ struct snd_dma_sg_fallback {
 static void __snd_dma_sg_fallback_free(struct snd_dma_buffer *dmab,
                                       struct snd_dma_sg_fallback *sgbuf)
 {
+       bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
        size_t i;
 
-       if (sgbuf->count && dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
-               set_pages_array_wb(sgbuf->pages, sgbuf->count);
        for (i = 0; i < sgbuf->count && sgbuf->pages[i]; i++)
-               dma_free_coherent(dmab->dev.dev, PAGE_SIZE,
-                                 page_address(sgbuf->pages[i]),
-                                 sgbuf->addrs[i]);
+               do_free_fallback_pages(page_address(sgbuf->pages[i]), PAGE_SIZE, wc);
        kvfree(sgbuf->pages);
        kvfree(sgbuf->addrs);
        kfree(sgbuf);
@@ -698,6 +754,7 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
        struct page **pages;
        size_t i, count;
        void *p;
+       bool wc = dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK;
 
        sgbuf = kzalloc(sizeof(*sgbuf), GFP_KERNEL);
        if (!sgbuf)
@@ -712,15 +769,13 @@ static void *snd_dma_sg_fallback_alloc(struct snd_dma_buffer *dmab, size_t size)
                goto error;
 
        for (i = 0; i < count; sgbuf->count++, i++) {
-               p = dma_alloc_coherent(dmab->dev.dev, PAGE_SIZE,
-                                      &sgbuf->addrs[i], DEFAULT_GFP);
+               p = do_alloc_fallback_pages(dmab->dev.dev, PAGE_SIZE,
+                                           &sgbuf->addrs[i], wc);
                if (!p)
                        goto error;
                sgbuf->pages[i] = virt_to_page(p);
        }
 
-       if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK)
-               set_pages_array_wc(pages, count);
        p = vmap(pages, count, VM_MAP, PAGE_KERNEL);
        if (!p)
                goto error;
index 1e3bf08..07efb38 100644 (file)
@@ -270,7 +270,9 @@ snd_seq_oss_midi_clear_all(void)
 void
 snd_seq_oss_midi_setup(struct seq_oss_devinfo *dp)
 {
+       spin_lock_irq(&register_lock);
        dp->max_mididev = max_midi_devs;
+       spin_unlock_irq(&register_lock);
 }
 
 /*
index 2e9d695..2d707af 100644 (file)
@@ -121,13 +121,13 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
        spin_unlock_irqrestore(&clients_lock, flags);
 #ifdef CONFIG_MODULES
        if (!in_interrupt()) {
-               static char client_requested[SNDRV_SEQ_GLOBAL_CLIENTS];
-               static char card_requested[SNDRV_CARDS];
+               static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);
+               static DECLARE_BITMAP(card_requested, SNDRV_CARDS);
+
                if (clientid < SNDRV_SEQ_GLOBAL_CLIENTS) {
                        int idx;
                        
-                       if (!client_requested[clientid]) {
-                               client_requested[clientid] = 1;
+                       if (!test_and_set_bit(clientid, client_requested)) {
                                for (idx = 0; idx < 15; idx++) {
                                        if (seq_client_load[idx] < 0)
                                                break;
@@ -142,10 +142,8 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
                        int card = (clientid - SNDRV_SEQ_GLOBAL_CLIENTS) /
                                SNDRV_SEQ_CLIENTS_PER_CARD;
                        if (card < snd_ecards_limit) {
-                               if (! card_requested[card]) {
-                                       card_requested[card] = 1;
+                               if (!test_and_set_bit(card, card_requested))
                                        snd_request_card(card);
-                               }
                                snd_seq_device_load_drivers();
                        }
                }
index 9db5ccd..13bb0cc 100644 (file)
@@ -55,16 +55,22 @@ int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt)
 
                /* find max number of channels based on format_configuration */
                if (fmt_configs->fmt_count) {
+                       struct nhlt_fmt_cfg *fmt_cfg = fmt_configs->fmt_config;
+
                        dev_dbg(dev, "found %d format definitions\n",
                                fmt_configs->fmt_count);
 
                        for (i = 0; i < fmt_configs->fmt_count; i++) {
                                struct wav_fmt_ext *fmt_ext;
 
-                               fmt_ext = &fmt_configs->fmt_config[i].fmt_ext;
+                               fmt_ext = &fmt_cfg->fmt_ext;
 
                                if (fmt_ext->fmt.channels > max_ch)
                                        max_ch = fmt_ext->fmt.channels;
+
+                               /* Move to the next nhlt_fmt_cfg */
+                               fmt_cfg = (struct nhlt_fmt_cfg *)(fmt_cfg->config.caps +
+                                                                 fmt_cfg->config.size);
                        }
                        dev_dbg(dev, "max channels found %d\n", max_ch);
                } else {
index 47e72cf..38930cf 100644 (file)
@@ -4700,6 +4700,48 @@ static void alc236_fixup_hp_mute_led_micmute_vref(struct hda_codec *codec,
        alc236_fixup_hp_micmute_led_vref(codec, fix, action);
 }
 
+static inline void alc298_samsung_write_coef_pack(struct hda_codec *codec,
+                                                 const unsigned short coefs[2])
+{
+       alc_write_coef_idx(codec, 0x23, coefs[0]);
+       alc_write_coef_idx(codec, 0x25, coefs[1]);
+       alc_write_coef_idx(codec, 0x26, 0xb011);
+}
+
+struct alc298_samsung_amp_desc {
+       unsigned char nid;
+       unsigned short init_seq[2][2];
+};
+
+static void alc298_fixup_samsung_amp(struct hda_codec *codec,
+                                    const struct hda_fixup *fix, int action)
+{
+       int i, j;
+       static const unsigned short init_seq[][2] = {
+               { 0x19, 0x00 }, { 0x20, 0xc0 }, { 0x22, 0x44 }, { 0x23, 0x08 },
+               { 0x24, 0x85 }, { 0x25, 0x41 }, { 0x35, 0x40 }, { 0x36, 0x01 },
+               { 0x38, 0x81 }, { 0x3a, 0x03 }, { 0x3b, 0x81 }, { 0x40, 0x3e },
+               { 0x41, 0x07 }, { 0x400, 0x1 }
+       };
+       static const struct alc298_samsung_amp_desc amps[] = {
+               { 0x3a, { { 0x18, 0x1 }, { 0x26, 0x0 } } },
+               { 0x39, { { 0x18, 0x2 }, { 0x26, 0x1 } } }
+       };
+
+       if (action != HDA_FIXUP_ACT_INIT)
+               return;
+
+       for (i = 0; i < ARRAY_SIZE(amps); i++) {
+               alc_write_coef_idx(codec, 0x22, amps[i].nid);
+
+               for (j = 0; j < ARRAY_SIZE(amps[i].init_seq); j++)
+                       alc298_samsung_write_coef_pack(codec, amps[i].init_seq[j]);
+
+               for (j = 0; j < ARRAY_SIZE(init_seq); j++)
+                       alc298_samsung_write_coef_pack(codec, init_seq[j]);
+       }
+}
+
 #if IS_REACHABLE(CONFIG_INPUT)
 static void gpio2_mic_hotkey_event(struct hda_codec *codec,
                                   struct hda_jack_callback *event)
@@ -7030,6 +7072,7 @@ enum {
        ALC236_FIXUP_HP_GPIO_LED,
        ALC236_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+       ALC298_FIXUP_SAMSUNG_AMP,
        ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
        ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET,
        ALC295_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -8396,6 +8439,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc236_fixup_hp_mute_led_micmute_vref,
        },
+       [ALC298_FIXUP_SAMSUNG_AMP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc298_fixup_samsung_amp,
+               .chained = true,
+               .chain_id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET
+       },
        [ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -9342,13 +9391,13 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x10ec, 0x1254, "Intel Reference board", ALC295_FIXUP_CHROME_BOOK),
        SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-SZ6", ALC269_FIXUP_HEADSET_MODE),
        SND_PCI_QUIRK(0x144d, 0xc109, "Samsung Ativ book 9 (NP900X3G)", ALC269_FIXUP_INV_DMIC),
-       SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+       SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc189, "Samsung Galaxy Flex Book (NT950QCG-X716)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc18a, "Samsung Galaxy Book Ion (NP930XCJ-K01US)", ALC298_FIXUP_SAMSUNG_AMP),
        SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
-       SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
-       SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
+       SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_AMP),
+       SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
        SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
@@ -9716,7 +9765,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC299_FIXUP_PREDATOR_SPK, .name = "predator-spk"},
        {.id = ALC298_FIXUP_HUAWEI_MBX_STEREO, .name = "huawei-mbx-stereo"},
        {.id = ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE, .name = "alc256-medion-headset"},
-       {.id = ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc298-samsung-headphone"},
+       {.id = ALC298_FIXUP_SAMSUNG_AMP, .name = "alc298-samsung-amp"},
        {.id = ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET, .name = "alc256-samsung-headphone"},
        {.id = ALC255_FIXUP_XIAOMI_HEADSET_MIC, .name = "alc255-xiaomi-headset"},
        {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
index 168fd80..9bfead5 100644 (file)
@@ -1903,6 +1903,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
+                  QUIRK_FLAG_SET_IFACE_FIRST),
        DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
index 3bb1343..316917b 100644 (file)
@@ -75,9 +75,11 @@ struct kvm_regs {
 
 /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
 #define KVM_ARM_DEVICE_TYPE_SHIFT      0
-#define KVM_ARM_DEVICE_TYPE_MASK       (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
+#define KVM_ARM_DEVICE_TYPE_MASK       GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \
+                                               KVM_ARM_DEVICE_TYPE_SHIFT)
 #define KVM_ARM_DEVICE_ID_SHIFT                16
-#define KVM_ARM_DEVICE_ID_MASK         (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
+#define KVM_ARM_DEVICE_ID_MASK         GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \
+                                               KVM_ARM_DEVICE_ID_SHIFT)
 
 /* Supported device IDs */
 #define KVM_ARM_DEVICE_VGIC_V2         0
index 067e9ea..8727765 100644 (file)
@@ -722,6 +722,7 @@ print_all_levels(__maybe_unused enum libbpf_print_level level,
 
 static int prog_fd_by_nametag(void *nametag, int **fds, bool tag)
 {
+       char prog_name[MAX_PROG_FULL_NAME];
        unsigned int id = 0;
        int fd, nb_fds = 0;
        void *tmp;
@@ -754,12 +755,20 @@ static int prog_fd_by_nametag(void *nametag, int **fds, bool tag)
                        goto err_close_fd;
                }
 
-               if ((tag && memcmp(nametag, info.tag, BPF_TAG_SIZE)) ||
-                   (!tag && strncmp(nametag, info.name, BPF_OBJ_NAME_LEN))) {
+               if (tag && memcmp(nametag, info.tag, BPF_TAG_SIZE)) {
                        close(fd);
                        continue;
                }
 
+               if (!tag) {
+                       get_prog_full_name(&info, fd, prog_name,
+                                          sizeof(prog_name));
+                       if (strncmp(nametag, prog_name, sizeof(prog_name))) {
+                               close(fd);
+                               continue;
+                       }
+               }
+
                if (nb_fds > 0) {
                        tmp = realloc(*fds, (nb_fds + 1) * sizeof(int));
                        if (!tmp) {
@@ -820,7 +829,7 @@ int prog_parse_fds(int *argc, char ***argv, int **fds)
                NEXT_ARGP();
 
                name = **argv;
-               if (strlen(name) > BPF_OBJ_NAME_LEN - 1) {
+               if (strlen(name) > MAX_PROG_FULL_NAME - 1) {
                        p_err("can't parse name");
                        return -1;
                }
index 7ecabf7..36cf0f1 100644 (file)
@@ -1147,7 +1147,7 @@ exit_free:
        return res;
 #else
        /* Detection assumes user has specific privileges.
-        * We do not use libpcap so let's approximate, and restrict usage to
+        * We do not use libcap so let's approximate, and restrict usage to
         * root user only.
         */
        if (geteuid()) {
index 451cefc..ccd7457 100644 (file)
@@ -435,6 +435,16 @@ int main(int argc, char **argv)
 
        setlinebuf(stdout);
 
+#ifdef USE_LIBCAP
+       /* Libcap < 2.63 hooks before main() to compute the number of
+        * capabilities of the running kernel, and doing so it calls prctl()
+        * which may fail and set errno to non-zero.
+        * Let's reset errno to make sure this does not interfere with the
+        * batch mode.
+        */
+       errno = 0;
+#endif
+
        last_do_help = do_help;
        pretty_output = false;
        json_output = false;
index 59a217c..1d6085e 100644 (file)
@@ -2573,10 +2573,12 @@ union bpf_attr {
  *             There are two supported modes at this time:
  *
  *             * **BPF_ADJ_ROOM_MAC**: Adjust room at the mac layer
- *               (room space is added or removed below the layer 2 header).
+ *               (room space is added or removed between the layer 2 and
+ *               layer 3 headers).
  *
  *             * **BPF_ADJ_ROOM_NET**: Adjust room at the network layer
- *               (room space is added or removed below the layer 3 header).
+ *               (room space is added or removed between the layer 3 and
+ *               layer 4 headers).
  *
  *             The following flags are supported at this time:
  *
@@ -3008,8 +3010,18 @@ union bpf_attr {
  *             **BPF_F_USER_STACK**
  *                     Collect a user space stack instead of a kernel stack.
  *             **BPF_F_USER_BUILD_ID**
- *                     Collect buildid+offset instead of ips for user stack,
- *                     only valid if **BPF_F_USER_STACK** is also specified.
+ *                     Collect (build_id, file_offset) instead of ips for user
+ *                     stack, only valid if **BPF_F_USER_STACK** is also
+ *                     specified.
+ *
+ *                     *file_offset* is an offset relative to the beginning
+ *                     of the executable or shared object file backing the vma
+ *                     which the *ip* falls in. It is *not* an offset relative
+ *                     to that object's base address. Accordingly, it must be
+ *                     adjusted by adding (sh_addr - sh_offset), where
+ *                     sh_{addr,offset} correspond to the executable section
+ *                     containing *file_offset* in the object, for comparisons
+ *                     to symbols' st_value to be valid.
  *
  *             **bpf_get_stack**\ () can collect up to
  *             **PERF_MAX_STACK_DEPTH** both kernel and user frames, subject
@@ -5331,6 +5343,18 @@ union bpf_attr {
  *             **-EACCES** if the SYN cookie is not valid.
  *
  *             **-EPROTONOSUPPORT** if CONFIG_IPV6 is not builtin.
+ *
+ * u64 bpf_ktime_get_tai_ns(void)
+ *     Description
+ *             A nonsettable system-wide clock derived from wall-clock time but
+ *             ignoring leap seconds.  This clock does not experience
+ *             discontinuities and backwards jumps caused by NTP inserting leap
+ *             seconds as CLOCK_REALTIME does.
+ *
+ *             See: **clock_gettime**\ (**CLOCK_TAI**)
+ *     Return
+ *             Current *ktime*.
+ *
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
@@ -5541,6 +5565,7 @@ union bpf_attr {
        FN(tcp_raw_gen_syncookie_ipv6), \
        FN(tcp_raw_check_syncookie_ipv4),       \
        FN(tcp_raw_check_syncookie_ipv6),       \
+       FN(ktime_get_tai_ns),           \
        /* */
 
 /* integer value in 'imm' field of BPF_CALL instruction selects which helper
index efcc06d..1d49a03 100644 (file)
@@ -84,9 +84,7 @@ static inline int sys_bpf_fd(enum bpf_cmd cmd, union bpf_attr *attr,
        return ensure_good_fd(fd);
 }
 
-#define PROG_LOAD_ATTEMPTS 5
-
-static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
+int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts)
 {
        int fd;
 
@@ -107,7 +105,7 @@ static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int
  */
 int probe_memcg_account(void)
 {
-       const size_t prog_load_attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
+       const size_t attr_sz = offsetofend(union bpf_attr, attach_btf_obj_fd);
        struct bpf_insn insns[] = {
                BPF_EMIT_CALL(BPF_FUNC_ktime_get_coarse_ns),
                BPF_EXIT_INSN(),
@@ -117,13 +115,13 @@ int probe_memcg_account(void)
        int prog_fd;
 
        /* attempt loading freplace trying to use custom BTF */
-       memset(&attr, 0, prog_load_attr_sz);
+       memset(&attr, 0, attr_sz);
        attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
        attr.insns = ptr_to_u64(insns);
        attr.insn_cnt = insn_cnt;
        attr.license = ptr_to_u64("GPL");
 
-       prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, prog_load_attr_sz);
+       prog_fd = sys_bpf_fd(BPF_PROG_LOAD, &attr, attr_sz);
        if (prog_fd >= 0) {
                close(prog_fd);
                return 1;
@@ -183,7 +181,7 @@ int bpf_map_create(enum bpf_map_type map_type,
                return libbpf_err(-EINVAL);
 
        attr.map_type = map_type;
-       if (map_name)
+       if (map_name && kernel_supports(NULL, FEAT_PROG_NAME))
                libbpf_strlcpy(attr.map_name, map_name, sizeof(attr.map_name));
        attr.key_size = key_size;
        attr.value_size = value_size;
@@ -234,6 +232,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
                  const struct bpf_insn *insns, size_t insn_cnt,
                  const struct bpf_prog_load_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, fd_array);
        void *finfo = NULL, *linfo = NULL;
        const char *func_info, *line_info;
        __u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
@@ -253,7 +252,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
        if (attempts == 0)
                attempts = PROG_LOAD_ATTEMPTS;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
 
        attr.prog_type = prog_type;
        attr.expected_attach_type = OPTS_GET(opts, expected_attach_type, 0);
@@ -263,7 +262,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
        attr.prog_ifindex = OPTS_GET(opts, prog_ifindex, 0);
        attr.kern_version = OPTS_GET(opts, kern_version, 0);
 
-       if (prog_name)
+       if (prog_name && kernel_supports(NULL, FEAT_PROG_NAME))
                libbpf_strlcpy(attr.prog_name, prog_name, sizeof(attr.prog_name));
        attr.license = ptr_to_u64(license);
 
@@ -316,7 +315,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
                attr.log_level = log_level;
        }
 
-       fd = sys_bpf_prog_load(&attr, sizeof(attr), attempts);
+       fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
        if (fd >= 0)
                return fd;
 
@@ -356,7 +355,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
                        break;
                }
 
-               fd = sys_bpf_prog_load(&attr, sizeof(attr), attempts);
+               fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
                if (fd >= 0)
                        goto done;
        }
@@ -370,7 +369,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
                attr.log_size = log_size;
                attr.log_level = 1;
 
-               fd = sys_bpf_prog_load(&attr, sizeof(attr), attempts);
+               fd = sys_bpf_prog_load(&attr, attr_sz, attempts);
        }
 done:
        /* free() doesn't affect errno, so we don't need to restore it */
@@ -382,127 +381,136 @@ done:
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.value = ptr_to_u64(value);
        attr.flags = flags;
 
-       ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_UPDATE_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_lookup_elem(int fd, const void *key, void *value)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.value = ptr_to_u64(value);
 
-       ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_lookup_elem_flags(int fd, const void *key, void *value, __u64 flags)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.value = ptr_to_u64(value);
        attr.flags = flags;
 
-       ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_LOOKUP_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_lookup_and_delete_elem(int fd, const void *key, void *value)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.value = ptr_to_u64(value);
 
-       ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_lookup_and_delete_elem_flags(int fd, const void *key, void *value, __u64 flags)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.value = ptr_to_u64(value);
        attr.flags = flags;
 
-       ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_LOOKUP_AND_DELETE_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_delete_elem(int fd, const void *key)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
 
-       ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_delete_elem_flags(int fd, const void *key, __u64 flags)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.flags = flags;
 
-       ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_DELETE_ELEM, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_get_next_key(int fd, const void *key, void *next_key)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, next_key);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
        attr.key = ptr_to_u64(key);
        attr.next_key = ptr_to_u64(next_key);
 
-       ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_GET_NEXT_KEY, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_map_freeze(int fd)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, map_fd);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_fd = fd;
 
-       ret = sys_bpf(BPF_MAP_FREEZE, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_MAP_FREEZE, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
@@ -511,13 +519,14 @@ static int bpf_map_batch_common(int cmd, int fd, void  *in_batch,
                                __u32 *count,
                                const struct bpf_map_batch_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, batch);
        union bpf_attr attr;
        int ret;
 
        if (!OPTS_VALID(opts, bpf_map_batch_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.batch.map_fd = fd;
        attr.batch.in_batch = ptr_to_u64(in_batch);
        attr.batch.out_batch = ptr_to_u64(out_batch);
@@ -527,7 +536,7 @@ static int bpf_map_batch_common(int cmd, int fd, void  *in_batch,
        attr.batch.elem_flags  = OPTS_GET(opts, elem_flags, 0);
        attr.batch.flags = OPTS_GET(opts, flags, 0);
 
-       ret = sys_bpf(cmd, &attr, sizeof(attr));
+       ret = sys_bpf(cmd, &attr, attr_sz);
        *count = attr.batch.count;
 
        return libbpf_err_errno(ret);
@@ -566,14 +575,15 @@ int bpf_map_update_batch(int fd, const void *keys, const void *values, __u32 *co
 
 int bpf_obj_pin(int fd, const char *pathname)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, file_flags);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.pathname = ptr_to_u64((void *)pathname);
        attr.bpf_fd = fd;
 
-       ret = sys_bpf(BPF_OBJ_PIN, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_OBJ_PIN, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
@@ -584,17 +594,18 @@ int bpf_obj_get(const char *pathname)
 
 int bpf_obj_get_opts(const char *pathname, const struct bpf_obj_get_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, file_flags);
        union bpf_attr attr;
        int fd;
 
        if (!OPTS_VALID(opts, bpf_obj_get_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.pathname = ptr_to_u64((void *)pathname);
        attr.file_flags = OPTS_GET(opts, file_flags, 0);
 
-       fd = sys_bpf_fd(BPF_OBJ_GET, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_OBJ_GET, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
@@ -612,52 +623,50 @@ int bpf_prog_attach_opts(int prog_fd, int target_fd,
                          enum bpf_attach_type type,
                          const struct bpf_prog_attach_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, replace_bpf_fd);
        union bpf_attr attr;
        int ret;
 
        if (!OPTS_VALID(opts, bpf_prog_attach_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.target_fd     = target_fd;
        attr.attach_bpf_fd = prog_fd;
        attr.attach_type   = type;
        attr.attach_flags  = OPTS_GET(opts, flags, 0);
        attr.replace_bpf_fd = OPTS_GET(opts, replace_prog_fd, 0);
 
-       ret = sys_bpf(BPF_PROG_ATTACH, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_PROG_ATTACH, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
-__attribute__((alias("bpf_prog_attach_opts")))
-int bpf_prog_attach_xattr(int prog_fd, int target_fd,
-                         enum bpf_attach_type type,
-                         const struct bpf_prog_attach_opts *opts);
-
 int bpf_prog_detach(int target_fd, enum bpf_attach_type type)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, replace_bpf_fd);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.target_fd   = target_fd;
        attr.attach_type = type;
 
-       ret = sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_prog_detach2(int prog_fd, int target_fd, enum bpf_attach_type type)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, replace_bpf_fd);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.target_fd   = target_fd;
        attr.attach_bpf_fd = prog_fd;
        attr.attach_type = type;
 
-       ret = sys_bpf(BPF_PROG_DETACH, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_PROG_DETACH, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
@@ -665,6 +674,7 @@ int bpf_link_create(int prog_fd, int target_fd,
                    enum bpf_attach_type attach_type,
                    const struct bpf_link_create_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, link_create);
        __u32 target_btf_id, iter_info_len;
        union bpf_attr attr;
        int fd, err;
@@ -683,7 +693,7 @@ int bpf_link_create(int prog_fd, int target_fd,
                        return libbpf_err(-EINVAL);
        }
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.link_create.prog_fd = prog_fd;
        attr.link_create.target_fd = target_fd;
        attr.link_create.attach_type = attach_type;
@@ -727,7 +737,7 @@ int bpf_link_create(int prog_fd, int target_fd,
                break;
        }
 proceed:
-       fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_LINK_CREATE, &attr, attr_sz);
        if (fd >= 0)
                return fd;
        /* we'll get EINVAL if LINK_CREATE doesn't support attaching fentry
@@ -763,44 +773,47 @@ proceed:
 
 int bpf_link_detach(int link_fd)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, link_detach);
        union bpf_attr attr;
        int ret;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.link_detach.link_fd = link_fd;
 
-       ret = sys_bpf(BPF_LINK_DETACH, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_LINK_DETACH, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_link_update(int link_fd, int new_prog_fd,
                    const struct bpf_link_update_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, link_update);
        union bpf_attr attr;
        int ret;
 
        if (!OPTS_VALID(opts, bpf_link_update_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.link_update.link_fd = link_fd;
        attr.link_update.new_prog_fd = new_prog_fd;
        attr.link_update.flags = OPTS_GET(opts, flags, 0);
        attr.link_update.old_prog_fd = OPTS_GET(opts, old_prog_fd, 0);
 
-       ret = sys_bpf(BPF_LINK_UPDATE, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_LINK_UPDATE, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
 
 int bpf_iter_create(int link_fd)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, iter_create);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.iter_create.link_fd = link_fd;
 
-       fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_ITER_CREATE, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
@@ -808,13 +821,14 @@ int bpf_prog_query_opts(int target_fd,
                        enum bpf_attach_type type,
                        struct bpf_prog_query_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, query);
        union bpf_attr attr;
        int ret;
 
        if (!OPTS_VALID(opts, bpf_prog_query_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
 
        attr.query.target_fd    = target_fd;
        attr.query.attach_type  = type;
@@ -823,7 +837,7 @@ int bpf_prog_query_opts(int target_fd,
        attr.query.prog_ids     = ptr_to_u64(OPTS_GET(opts, prog_ids, NULL));
        attr.query.prog_attach_flags = ptr_to_u64(OPTS_GET(opts, prog_attach_flags, NULL));
 
-       ret = sys_bpf(BPF_PROG_QUERY, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_PROG_QUERY, &attr, attr_sz);
 
        OPTS_SET(opts, attach_flags, attr.query.attach_flags);
        OPTS_SET(opts, prog_cnt, attr.query.prog_cnt);
@@ -852,13 +866,14 @@ int bpf_prog_query(int target_fd, enum bpf_attach_type type, __u32 query_flags,
 
 int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, test);
        union bpf_attr attr;
        int ret;
 
        if (!OPTS_VALID(opts, bpf_test_run_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.test.prog_fd = prog_fd;
        attr.test.batch_size = OPTS_GET(opts, batch_size, 0);
        attr.test.cpu = OPTS_GET(opts, cpu, 0);
@@ -874,7 +889,7 @@ int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
        attr.test.data_in = ptr_to_u64(OPTS_GET(opts, data_in, NULL));
        attr.test.data_out = ptr_to_u64(OPTS_GET(opts, data_out, NULL));
 
-       ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, attr_sz);
 
        OPTS_SET(opts, data_size_out, attr.test.data_size_out);
        OPTS_SET(opts, ctx_size_out, attr.test.ctx_size_out);
@@ -886,13 +901,14 @@ int bpf_prog_test_run_opts(int prog_fd, struct bpf_test_run_opts *opts)
 
 static int bpf_obj_get_next_id(__u32 start_id, __u32 *next_id, int cmd)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
        union bpf_attr attr;
        int err;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.start_id = start_id;
 
-       err = sys_bpf(cmd, &attr, sizeof(attr));
+       err = sys_bpf(cmd, &attr, attr_sz);
        if (!err)
                *next_id = attr.next_id;
 
@@ -921,80 +937,84 @@ int bpf_link_get_next_id(__u32 start_id, __u32 *next_id)
 
 int bpf_prog_get_fd_by_id(__u32 id)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.prog_id = id;
 
-       fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_PROG_GET_FD_BY_ID, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
 int bpf_map_get_fd_by_id(__u32 id)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.map_id = id;
 
-       fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_MAP_GET_FD_BY_ID, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
 int bpf_btf_get_fd_by_id(__u32 id)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.btf_id = id;
 
-       fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_BTF_GET_FD_BY_ID, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
 int bpf_link_get_fd_by_id(__u32 id)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, open_flags);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.link_id = id;
 
-       fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_LINK_GET_FD_BY_ID, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
 int bpf_obj_get_info_by_fd(int bpf_fd, void *info, __u32 *info_len)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, info);
        union bpf_attr attr;
        int err;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.info.bpf_fd = bpf_fd;
        attr.info.info_len = *info_len;
        attr.info.info = ptr_to_u64(info);
 
-       err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, sizeof(attr));
-
+       err = sys_bpf(BPF_OBJ_GET_INFO_BY_FD, &attr, attr_sz);
        if (!err)
                *info_len = attr.info.info_len;
-
        return libbpf_err_errno(err);
 }
 
 int bpf_raw_tracepoint_open(const char *name, int prog_fd)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, raw_tracepoint);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.raw_tracepoint.name = ptr_to_u64(name);
        attr.raw_tracepoint.prog_fd = prog_fd;
 
-       fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_RAW_TRACEPOINT_OPEN, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
@@ -1050,16 +1070,18 @@ int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
                      __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset,
                      __u64 *probe_addr)
 {
-       union bpf_attr attr = {};
+       const size_t attr_sz = offsetofend(union bpf_attr, task_fd_query);
+       union bpf_attr attr;
        int err;
 
+       memset(&attr, 0, attr_sz);
        attr.task_fd_query.pid = pid;
        attr.task_fd_query.fd = fd;
        attr.task_fd_query.flags = flags;
        attr.task_fd_query.buf = ptr_to_u64(buf);
        attr.task_fd_query.buf_len = *buf_len;
 
-       err = sys_bpf(BPF_TASK_FD_QUERY, &attr, sizeof(attr));
+       err = sys_bpf(BPF_TASK_FD_QUERY, &attr, attr_sz);
 
        *buf_len = attr.task_fd_query.buf_len;
        *prog_id = attr.task_fd_query.prog_id;
@@ -1072,30 +1094,32 @@ int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len,
 
 int bpf_enable_stats(enum bpf_stats_type type)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, enable_stats);
        union bpf_attr attr;
        int fd;
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.enable_stats.type = type;
 
-       fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, sizeof(attr));
+       fd = sys_bpf_fd(BPF_ENABLE_STATS, &attr, attr_sz);
        return libbpf_err_errno(fd);
 }
 
 int bpf_prog_bind_map(int prog_fd, int map_fd,
                      const struct bpf_prog_bind_opts *opts)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, prog_bind_map);
        union bpf_attr attr;
        int ret;
 
        if (!OPTS_VALID(opts, bpf_prog_bind_opts))
                return libbpf_err(-EINVAL);
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, attr_sz);
        attr.prog_bind_map.prog_fd = prog_fd;
        attr.prog_bind_map.map_fd = map_fd;
        attr.prog_bind_map.flags = OPTS_GET(opts, flags, 0);
 
-       ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, sizeof(attr));
+       ret = sys_bpf(BPF_PROG_BIND_MAP, &attr, attr_sz);
        return libbpf_err_errno(ret);
 }
index 43ca3af..5fdb93d 100644 (file)
@@ -426,7 +426,7 @@ struct pt_regs;
  */
 #define BPF_PROG(name, args...)                                                    \
 name(unsigned long long *ctx);                                             \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(unsigned long long *ctx, ##args);                               \
 typeof(name(0)) name(unsigned long long *ctx)                              \
 {                                                                          \
@@ -435,7 +435,7 @@ typeof(name(0)) name(unsigned long long *ctx)                                   \
        return ____##name(___bpf_ctx_cast(args));                           \
        _Pragma("GCC diagnostic pop")                                       \
 }                                                                          \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(unsigned long long *ctx, ##args)
 
 struct pt_regs;
@@ -460,7 +460,7 @@ struct pt_regs;
  */
 #define BPF_KPROBE(name, args...)                                          \
 name(struct pt_regs *ctx);                                                 \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args);                                   \
 typeof(name(0)) name(struct pt_regs *ctx)                                  \
 {                                                                          \
@@ -469,7 +469,7 @@ typeof(name(0)) name(struct pt_regs *ctx)                               \
        return ____##name(___bpf_kprobe_args(args));                        \
        _Pragma("GCC diagnostic pop")                                       \
 }                                                                          \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args)
 
 #define ___bpf_kretprobe_args0()       ctx
@@ -484,7 +484,7 @@ ____##name(struct pt_regs *ctx, ##args)
  */
 #define BPF_KRETPROBE(name, args...)                                       \
 name(struct pt_regs *ctx);                                                 \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args);                                   \
 typeof(name(0)) name(struct pt_regs *ctx)                                  \
 {                                                                          \
@@ -540,7 +540,7 @@ static __always_inline typeof(name(0)) ____##name(struct pt_regs *ctx, ##args)
 #define BPF_KSYSCALL(name, args...)                                        \
 name(struct pt_regs *ctx);                                                 \
 extern _Bool LINUX_HAS_SYSCALL_WRAPPER __kconfig;                          \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args);                                   \
 typeof(name(0)) name(struct pt_regs *ctx)                                  \
 {                                                                          \
@@ -555,7 +555,7 @@ typeof(name(0)) name(struct pt_regs *ctx)                               \
                return ____##name(___bpf_syscall_args(args));               \
        _Pragma("GCC diagnostic pop")                                       \
 }                                                                          \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args)
 
 #define BPF_KPROBE_SYSCALL BPF_KSYSCALL
index 2d14f1a..3611315 100644 (file)
@@ -1225,8 +1225,6 @@ int btf__load_into_kernel(struct btf *btf)
        return btf_load_into_kernel(btf, NULL, 0, 0);
 }
 
-int btf__load(struct btf *) __attribute__((alias("btf__load_into_kernel")));
-
 int btf__fd(const struct btf *btf)
 {
        return btf->fd;
index 583760d..ae54314 100644 (file)
@@ -116,7 +116,6 @@ LIBBPF_API struct btf *btf__parse_raw_split(const char *path, struct btf *base_b
 
 LIBBPF_API struct btf *btf__load_vmlinux_btf(void);
 LIBBPF_API struct btf *btf__load_module_btf(const char *module_name, struct btf *vmlinux_btf);
-LIBBPF_API struct btf *libbpf_find_kernel_btf(void);
 
 LIBBPF_API struct btf *btf__load_from_kernel_by_id(__u32 id);
 LIBBPF_API struct btf *btf__load_from_kernel_by_id_split(__u32 id, struct btf *base_btf);
index 50d4181..3ad1392 100644 (file)
@@ -223,13 +223,18 @@ __printf(2, 3)
 void libbpf_print(enum libbpf_print_level level, const char *format, ...)
 {
        va_list args;
+       int old_errno;
 
        if (!__libbpf_pr)
                return;
 
+       old_errno = errno;
+
        va_start(args, format);
        __libbpf_pr(level, format, args);
        va_end(args);
+
+       errno = old_errno;
 }
 
 static void pr_perm_msg(int err)
@@ -412,6 +417,7 @@ struct bpf_program {
 
        int fd;
        bool autoload;
+       bool autoattach;
        bool mark_btf_static;
        enum bpf_prog_type type;
        enum bpf_attach_type expected_attach_type;
@@ -591,7 +597,6 @@ struct elf_state {
        size_t strtabidx;
        struct elf_sec_desc *secs;
        int sec_cnt;
-       int maps_shndx;
        int btf_maps_shndx;
        __u32 btf_maps_sec_btf_id;
        int text_shndx;
@@ -751,6 +756,8 @@ bpf_object__init_prog(struct bpf_object *obj, struct bpf_program *prog,
                prog->autoload = true;
        }
 
+       prog->autoattach = true;
+
        /* inherit object's log_level */
        prog->log_level = obj->log_level;
 
@@ -1272,7 +1279,6 @@ static struct bpf_object *bpf_object__new(const char *path,
         */
        obj->efile.obj_buf = obj_buf;
        obj->efile.obj_buf_sz = obj_buf_sz;
-       obj->efile.maps_shndx = -1;
        obj->efile.btf_maps_shndx = -1;
        obj->efile.st_ops_shndx = -1;
        obj->kconfig_map_idx = -1;
@@ -1642,6 +1648,10 @@ static int bpf_object__init_global_data_maps(struct bpf_object *obj)
        for (sec_idx = 1; sec_idx < obj->efile.sec_cnt; sec_idx++) {
                sec_desc = &obj->efile.secs[sec_idx];
 
+               /* Skip recognized sections with size 0. */
+               if (!sec_desc->data || sec_desc->data->d_size == 0)
+                       continue;
+
                switch (sec_desc->sec_type) {
                case SEC_DATA:
                        sec_name = elf_sec_name(obj, elf_sec_by_idx(obj, sec_idx));
@@ -3359,7 +3369,8 @@ static int bpf_object__elf_collect(struct bpf_object *obj)
                        if (err)
                                return err;
                } else if (strcmp(name, "maps") == 0) {
-                       obj->efile.maps_shndx = idx;
+                       pr_warn("elf: legacy map definitions in 'maps' section are not supported by libbpf v1.0+\n");
+                       return -ENOTSUP;
                } else if (strcmp(name, MAPS_ELF_SEC) == 0) {
                        obj->efile.btf_maps_shndx = idx;
                } else if (strcmp(name, BTF_ELF_SEC) == 0) {
@@ -3891,8 +3902,7 @@ static bool bpf_object__shndx_is_data(const struct bpf_object *obj,
 static bool bpf_object__shndx_is_maps(const struct bpf_object *obj,
                                      int shndx)
 {
-       return shndx == obj->efile.maps_shndx ||
-              shndx == obj->efile.btf_maps_shndx;
+       return shndx == obj->efile.btf_maps_shndx;
 }
 
 static enum libbpf_map_type
@@ -4277,11 +4287,12 @@ int bpf_map__set_autocreate(struct bpf_map *map, bool autocreate)
 
 int bpf_map__reuse_fd(struct bpf_map *map, int fd)
 {
-       struct bpf_map_info info = {};
+       struct bpf_map_info info;
        __u32 len = sizeof(info), name_len;
        int new_fd, err;
        char *new_name;
 
+       memset(&info, 0, len);
        err = bpf_obj_get_info_by_fd(fd, &info, &len);
        if (err && errno == EINVAL)
                err = bpf_get_map_info_from_fdinfo(fd, &info);
@@ -4408,14 +4419,23 @@ static int probe_fd(int fd)
 
 static int probe_kern_prog_name(void)
 {
+       const size_t attr_sz = offsetofend(union bpf_attr, prog_name);
        struct bpf_insn insns[] = {
                BPF_MOV64_IMM(BPF_REG_0, 0),
                BPF_EXIT_INSN(),
        };
-       int ret, insn_cnt = ARRAY_SIZE(insns);
+       union bpf_attr attr;
+       int ret;
+
+       memset(&attr, 0, attr_sz);
+       attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
+       attr.license = ptr_to_u64("GPL");
+       attr.insns = ptr_to_u64(insns);
+       attr.insn_cnt = (__u32)ARRAY_SIZE(insns);
+       libbpf_strlcpy(attr.prog_name, "libbpf_nametest", sizeof(attr.prog_name));
 
        /* make sure loading with name works */
-       ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "test", "GPL", insns, insn_cnt, NULL);
+       ret = sys_bpf_prog_load(&attr, attr_sz, PROG_LOAD_ATTEMPTS);
        return probe_fd(ret);
 }
 
@@ -4430,7 +4450,7 @@ static int probe_kern_global_data(void)
        };
        int ret, map, insn_cnt = ARRAY_SIZE(insns);
 
-       map = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(int), 32, 1, NULL);
+       map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_global", sizeof(int), 32, 1, NULL);
        if (map < 0) {
                ret = -errno;
                cp = libbpf_strerror_r(ret, errmsg, sizeof(errmsg));
@@ -4563,7 +4583,7 @@ static int probe_kern_array_mmap(void)
        LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_MMAPABLE);
        int fd;
 
-       fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(int), sizeof(int), 1, &opts);
+       fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_mmap", sizeof(int), sizeof(int), 1, &opts);
        return probe_fd(fd);
 }
 
@@ -4610,7 +4630,7 @@ static int probe_prog_bind_map(void)
        };
        int ret, map, prog, insn_cnt = ARRAY_SIZE(insns);
 
-       map = bpf_map_create(BPF_MAP_TYPE_ARRAY, NULL, sizeof(int), 32, 1, NULL);
+       map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_det_bind", sizeof(int), 32, 1, NULL);
        if (map < 0) {
                ret = -errno;
                cp = libbpf_strerror_r(ret, errmsg, sizeof(errmsg));
@@ -4814,13 +4834,12 @@ bool kernel_supports(const struct bpf_object *obj, enum kern_feature_id feat_id)
 
 static bool map_is_reuse_compat(const struct bpf_map *map, int map_fd)
 {
-       struct bpf_map_info map_info = {};
+       struct bpf_map_info map_info;
        char msg[STRERR_BUFSIZE];
-       __u32 map_info_len;
+       __u32 map_info_len = sizeof(map_info);
        int err;
 
-       map_info_len = sizeof(map_info);
-
+       memset(&map_info, 0, map_info_len);
        err = bpf_obj_get_info_by_fd(map_fd, &map_info, &map_info_len);
        if (err && errno == EINVAL)
                err = bpf_get_map_info_from_fdinfo(map_fd, &map_info);
@@ -7244,8 +7263,6 @@ static int bpf_object_unload(struct bpf_object *obj)
        return 0;
 }
 
-int bpf_object__unload(struct bpf_object *obj) __attribute__((alias("bpf_object_unload")));
-
 static int bpf_object__sanitize_maps(struct bpf_object *obj)
 {
        struct bpf_map *m;
@@ -8298,6 +8315,16 @@ int bpf_program__set_autoload(struct bpf_program *prog, bool autoload)
        return 0;
 }
 
+bool bpf_program__autoattach(const struct bpf_program *prog)
+{
+       return prog->autoattach;
+}
+
+void bpf_program__set_autoattach(struct bpf_program *prog, bool autoattach)
+{
+       prog->autoattach = autoattach;
+}
+
 const struct bpf_insn *bpf_program__insns(const struct bpf_program *prog)
 {
        return prog->insns;
@@ -8978,11 +9005,12 @@ int libbpf_find_vmlinux_btf_id(const char *name,
 
 static int libbpf_find_prog_btf_id(const char *name, __u32 attach_prog_fd)
 {
-       struct bpf_prog_info info = {};
+       struct bpf_prog_info info;
        __u32 info_len = sizeof(info);
        struct btf *btf;
        int err;
 
+       memset(&info, 0, info_len);
        err = bpf_obj_get_info_by_fd(attach_prog_fd, &info, &info_len);
        if (err) {
                pr_warn("failed bpf_obj_get_info_by_fd for FD %d: %d\n",
@@ -9810,13 +9838,16 @@ static int determine_uprobe_retprobe_bit(void)
 static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
                                 uint64_t offset, int pid, size_t ref_ctr_off)
 {
-       struct perf_event_attr attr = {};
+       const size_t attr_sz = sizeof(struct perf_event_attr);
+       struct perf_event_attr attr;
        char errmsg[STRERR_BUFSIZE];
        int type, pfd;
 
        if (ref_ctr_off >= (1ULL << PERF_UPROBE_REF_CTR_OFFSET_BITS))
                return -EINVAL;
 
+       memset(&attr, 0, attr_sz);
+
        type = uprobe ? determine_uprobe_perf_type()
                      : determine_kprobe_perf_type();
        if (type < 0) {
@@ -9837,7 +9868,7 @@ static int perf_event_open_probe(bool uprobe, bool retprobe, const char *name,
                }
                attr.config |= 1 << bit;
        }
-       attr.size = sizeof(attr);
+       attr.size = attr_sz;
        attr.type = type;
        attr.config |= (__u64)ref_ctr_off << PERF_UPROBE_REF_CTR_OFFSET_SHIFT;
        attr.config1 = ptr_to_u64(name); /* kprobe_func or uprobe_path */
@@ -9936,7 +9967,8 @@ static int determine_kprobe_perf_type_legacy(const char *probe_name, bool retpro
 static int perf_event_kprobe_open_legacy(const char *probe_name, bool retprobe,
                                         const char *kfunc_name, size_t offset, int pid)
 {
-       struct perf_event_attr attr = {};
+       const size_t attr_sz = sizeof(struct perf_event_attr);
+       struct perf_event_attr attr;
        char errmsg[STRERR_BUFSIZE];
        int type, pfd, err;
 
@@ -9955,7 +9987,9 @@ static int perf_event_kprobe_open_legacy(const char *probe_name, bool retprobe,
                        libbpf_strerror_r(err, errmsg, sizeof(errmsg)));
                goto err_clean_legacy;
        }
-       attr.size = sizeof(attr);
+
+       memset(&attr, 0, attr_sz);
+       attr.size = attr_sz;
        attr.config = type;
        attr.type = PERF_TYPE_TRACEPOINT;
 
@@ -10412,6 +10446,7 @@ static int determine_uprobe_perf_type_legacy(const char *probe_name, bool retpro
 static int perf_event_uprobe_open_legacy(const char *probe_name, bool retprobe,
                                         const char *binary_path, size_t offset, int pid)
 {
+       const size_t attr_sz = sizeof(struct perf_event_attr);
        struct perf_event_attr attr;
        int type, pfd, err;
 
@@ -10429,8 +10464,8 @@ static int perf_event_uprobe_open_legacy(const char *probe_name, bool retprobe,
                goto err_clean_legacy;
        }
 
-       memset(&attr, 0, sizeof(attr));
-       attr.size = sizeof(attr);
+       memset(&attr, 0, attr_sz);
+       attr.size = attr_sz;
        attr.config = type;
        attr.type = PERF_TYPE_TRACEPOINT;
 
@@ -10662,15 +10697,17 @@ static const char *arch_specific_lib_paths(void)
 static int resolve_full_path(const char *file, char *result, size_t result_sz)
 {
        const char *search_paths[3] = {};
-       int i;
+       int i, perm;
 
        if (str_has_sfx(file, ".so") || strstr(file, ".so.")) {
                search_paths[0] = getenv("LD_LIBRARY_PATH");
                search_paths[1] = "/usr/lib64:/usr/lib";
                search_paths[2] = arch_specific_lib_paths();
+               perm = R_OK;
        } else {
                search_paths[0] = getenv("PATH");
                search_paths[1] = "/usr/bin:/usr/sbin";
+               perm = R_OK | X_OK;
        }
 
        for (i = 0; i < ARRAY_SIZE(search_paths); i++) {
@@ -10689,8 +10726,8 @@ static int resolve_full_path(const char *file, char *result, size_t result_sz)
                        if (!seg_len)
                                continue;
                        snprintf(result, result_sz, "%.*s/%s", seg_len, s, file);
-                       /* ensure it is an executable file/link */
-                       if (access(result, R_OK | X_OK) < 0)
+                       /* ensure it has required permissions */
+                       if (access(result, perm) < 0)
                                continue;
                        pr_debug("resolved '%s' to '%s'\n", file, result);
                        return 0;
@@ -10967,7 +11004,8 @@ static int determine_tracepoint_id(const char *tp_category,
 static int perf_event_open_tracepoint(const char *tp_category,
                                      const char *tp_name)
 {
-       struct perf_event_attr attr = {};
+       const size_t attr_sz = sizeof(struct perf_event_attr);
+       struct perf_event_attr attr;
        char errmsg[STRERR_BUFSIZE];
        int tp_id, pfd, err;
 
@@ -10979,8 +11017,9 @@ static int perf_event_open_tracepoint(const char *tp_category,
                return tp_id;
        }
 
+       memset(&attr, 0, attr_sz);
        attr.type = PERF_TYPE_TRACEPOINT;
-       attr.size = sizeof(attr);
+       attr.size = attr_sz;
        attr.config = tp_id;
 
        pfd = syscall(__NR_perf_event_open, &attr, -1 /* pid */, 0 /* cpu */,
@@ -11600,12 +11639,15 @@ struct perf_buffer *perf_buffer__new(int map_fd, size_t page_cnt,
                                     void *ctx,
                                     const struct perf_buffer_opts *opts)
 {
+       const size_t attr_sz = sizeof(struct perf_event_attr);
        struct perf_buffer_params p = {};
-       struct perf_event_attr attr = {};
+       struct perf_event_attr attr;
 
        if (!OPTS_VALID(opts, perf_buffer_opts))
                return libbpf_err_ptr(-EINVAL);
 
+       memset(&attr, 0, attr_sz);
+       attr.size = attr_sz;
        attr.config = PERF_COUNT_SW_BPF_OUTPUT;
        attr.type = PERF_TYPE_SOFTWARE;
        attr.sample_type = PERF_SAMPLE_RAW;
@@ -12328,7 +12370,7 @@ int bpf_object__attach_skeleton(struct bpf_object_skeleton *s)
                struct bpf_program *prog = *s->progs[i].prog;
                struct bpf_link **link = s->progs[i].link;
 
-               if (!prog->autoload)
+               if (!prog->autoload || !prog->autoattach)
                        continue;
 
                /* auto-attaching not supported for this program */
index 61493c4..88a1ac3 100644 (file)
@@ -260,6 +260,8 @@ LIBBPF_API const char *bpf_program__name(const struct bpf_program *prog);
 LIBBPF_API const char *bpf_program__section_name(const struct bpf_program *prog);
 LIBBPF_API bool bpf_program__autoload(const struct bpf_program *prog);
 LIBBPF_API int bpf_program__set_autoload(struct bpf_program *prog, bool autoload);
+LIBBPF_API bool bpf_program__autoattach(const struct bpf_program *prog);
+LIBBPF_API void bpf_program__set_autoattach(struct bpf_program *prog, bool autoattach);
 
 struct bpf_insn;
 
index 119e6e1..2b928dc 100644 (file)
@@ -358,6 +358,8 @@ LIBBPF_1.0.0 {
                bpf_obj_get_opts;
                bpf_prog_query_opts;
                bpf_program__attach_ksyscall;
+               bpf_program__autoattach;
+               bpf_program__set_autoattach;
                btf__add_enum64;
                btf__add_enum64_value;
                libbpf_bpf_attach_type_str;
index 4135ae0..377642f 100644 (file)
@@ -573,4 +573,7 @@ static inline bool is_pow_of_2(size_t x)
        return x && (x & (x - 1)) == 0;
 }
 
+#define PROG_LOAD_ATTEMPTS 5
+int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size, int attempts);
+
 #endif /* __LIBBPF_LIBBPF_INTERNAL_H */
index 5b7e015..1e1be46 100644 (file)
@@ -125,6 +125,8 @@ struct bpf_map;
 struct btf;
 struct btf_ext;
 
+LIBBPF_API struct btf *libbpf_find_kernel_btf(void);
+
 LIBBPF_API enum bpf_prog_type bpf_program__get_type(const struct bpf_program *prog);
 LIBBPF_API enum bpf_attach_type bpf_program__get_expected_attach_type(const struct bpf_program *prog);
 LIBBPF_API const char *bpf_map__get_pin_path(const struct bpf_map *map);
index 0b53987..6d49565 100644 (file)
@@ -193,7 +193,7 @@ static int probe_map_create(enum bpf_map_type map_type)
        LIBBPF_OPTS(bpf_map_create_opts, opts);
        int key_size, value_size, max_entries;
        __u32 btf_key_type_id = 0, btf_value_type_id = 0;
-       int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err;
+       int fd = -1, btf_fd = -1, fd_inner = -1, exp_err = 0, err = 0;
 
        key_size        = sizeof(__u32);
        value_size      = sizeof(__u32);
index 6c01316..3510458 100644 (file)
@@ -587,11 +587,12 @@ static int get_tc_info(struct nlmsghdr *nh, libbpf_dump_nlmsg_t fn,
 
 static int tc_add_fd_and_name(struct libbpf_nla_req *req, int fd)
 {
-       struct bpf_prog_info info = {};
+       struct bpf_prog_info info;
        __u32 info_len = sizeof(info);
        char name[256];
        int len, ret;
 
+       memset(&info, 0, info_len);
        ret = bpf_obj_get_info_by_fd(fd, &info, &info_len);
        if (ret < 0)
                return ret;
index 70adf7b..00c5f94 100644 (file)
@@ -285,6 +285,8 @@ static inline int skel_link_create(int prog_fd, int target_fd,
 
 static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
 {
+       const size_t prog_load_attr_sz = offsetofend(union bpf_attr, fd_array);
+       const size_t test_run_attr_sz = offsetofend(union bpf_attr, test);
        int map_fd = -1, prog_fd = -1, key = 0, err;
        union bpf_attr attr;
 
@@ -302,7 +304,7 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
                goto out;
        }
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, prog_load_attr_sz);
        attr.prog_type = BPF_PROG_TYPE_SYSCALL;
        attr.insns = (long) opts->insns;
        attr.insn_cnt = opts->insns_sz / sizeof(struct bpf_insn);
@@ -313,18 +315,18 @@ static inline int bpf_load_and_run(struct bpf_load_and_run_opts *opts)
        attr.log_size = opts->ctx->log_size;
        attr.log_buf = opts->ctx->log_buf;
        attr.prog_flags = BPF_F_SLEEPABLE;
-       err = prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       err = prog_fd = skel_sys_bpf(BPF_PROG_LOAD, &attr, prog_load_attr_sz);
        if (prog_fd < 0) {
                opts->errstr = "failed to load loader prog";
                set_err;
                goto out;
        }
 
-       memset(&attr, 0, sizeof(attr));
+       memset(&attr, 0, test_run_attr_sz);
        attr.test.prog_fd = prog_fd;
        attr.test.ctx_in = (long) opts->ctx;
        attr.test.ctx_size_in = opts->ctx->sz;
-       err = skel_sys_bpf(BPF_PROG_RUN, &attr, sizeof(attr));
+       err = skel_sys_bpf(BPF_PROG_RUN, &attr, test_run_attr_sz);
        if (err < 0 || (int)attr.test.retval < 0) {
                opts->errstr = "failed to execute loader prog";
                if (err < 0) {
index 4f2adc0..fdfd235 100644 (file)
@@ -232,7 +232,7 @@ long bpf_usdt_cookie(struct pt_regs *ctx)
  */
 #define BPF_USDT(name, args...)                                                    \
 name(struct pt_regs *ctx);                                                 \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args);                                   \
 typeof(name(0)) name(struct pt_regs *ctx)                                  \
 {                                                                          \
@@ -241,7 +241,7 @@ typeof(name(0)) name(struct pt_regs *ctx)                               \
         return ____##name(___bpf_usdt_args(args));                         \
         _Pragma("GCC diagnostic pop")                                      \
 }                                                                          \
-static __attribute__((always_inline)) typeof(name(0))                      \
+static __always_inline typeof(name(0))                                     \
 ____##name(struct pt_regs *ctx, ##args)
 
 #endif /* __USDT_BPF_H__ */
index 9167825..e55fdf9 100644 (file)
@@ -162,32 +162,34 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
 
        /*
         * Unfortunately these have to be hard coded because the noreturn
-        * attribute isn't provided in ELF data.
+        * attribute isn't provided in ELF data. Keep 'em sorted.
         */
        static const char * const global_noreturns[] = {
+               "__invalid_creds",
+               "__module_put_and_kthread_exit",
+               "__reiserfs_panic",
                "__stack_chk_fail",
-               "panic",
+               "__ubsan_handle_builtin_unreachable",
+               "cpu_bringup_and_idle",
+               "cpu_startup_entry",
                "do_exit",
+               "do_group_exit",
                "do_task_dead",
-               "kthread_exit",
-               "make_task_dead",
-               "__module_put_and_kthread_exit",
+               "ex_handler_msr_mce",
+               "fortify_panic",
                "kthread_complete_and_exit",
-               "__reiserfs_panic",
+               "kthread_exit",
+               "kunit_try_catch_throw",
                "lbug_with_loc",
-               "fortify_panic",
-               "usercopy_abort",
                "machine_real_restart",
+               "make_task_dead",
+               "panic",
                "rewind_stack_and_make_dead",
-               "kunit_try_catch_throw",
-               "xen_start_kernel",
-               "cpu_bringup_and_idle",
-               "do_group_exit",
+               "sev_es_terminate",
+               "snp_abort",
                "stop_this_cpu",
-               "__invalid_creds",
-               "cpu_startup_entry",
-               "__ubsan_handle_builtin_unreachable",
-               "ex_handler_msr_mce",
+               "usercopy_abort",
+               "xen_start_kernel",
        };
 
        if (!func)
index c930209..e7a776a 100644 (file)
@@ -21,11 +21,6 @@ cat /sys/devices/cpu_atom/cpus
 
 It indicates cpu0-cpu15 are core cpus and cpu16-cpu23 are atom cpus.
 
-Quickstart
-
-List hybrid event
------------------
-
 As before, use perf-list to list the symbolic event.
 
 perf list
@@ -40,7 +35,6 @@ the event is belong to. Same event name but with different pmu can
 be supported.
 
 Enable hybrid event with a specific pmu
----------------------------------------
 
 To enable a core only event or atom only event, following syntax is supported:
 
@@ -53,7 +47,6 @@ For example, count the 'cycles' event on core cpus.
        perf stat -e cpu_core/cycles/
 
 Create two events for one hardware event automatically
-------------------------------------------------------
 
 When creating one event and the event is available on both atom and core,
 two events are created automatically. One is for atom, the other is for
@@ -132,7 +125,6 @@ For perf-stat result, it displays two events:
 The first 'cycles' is core event, the second 'cycles' is atom event.
 
 Thread mode example:
---------------------
 
 perf-stat reports the scaled counts for hybrid event and with a percentage
 displayed. The percentage is the event's running time/enabling time.
@@ -176,14 +168,12 @@ perf_event_attr:
        604,097,080      cpu_atom/cycles/                                              (99.57%)
 
 perf-record:
-------------
 
 If there is no '-e' specified in perf record, on hybrid platform,
 it creates two default 'cycles' and adds them to event list. One
 is for core, the other is for atom.
 
 perf-stat:
-----------
 
 If there is no '-e' specified in perf stat, on hybrid platform,
 besides of software events, following events are created and
index 099817e..0228efc 100644 (file)
@@ -397,6 +397,9 @@ following filters are defined:
        - abort_tx: only when the target is a hardware transaction abort
        - cond: conditional branches
        - save_type: save branch type during sampling in case binary is not available later
+                    For the platforms with Intel Arch LBR support (12th-Gen+ client or
+                    4th-Gen Xeon+ server), the save branch type is unconditionally enabled
+                    when the taken branch stack sampling is enabled.
 
 +
 The option requires at least one branch type among any, any_call, any_ret, ind_call, cond.
@@ -757,8 +760,6 @@ events in data directory files. Option specified with no or empty value
 defaults to CPU layout. Masks defined or provided by the option value are
 filtered through the mask provided by -C option.
 
-include::intel-hybrid.txt[]
-
 --debuginfod[=URLs]::
        Specify debuginfod URL to be used when cacheing perf.data binaries,
        it follows the same syntax as the DEBUGINFOD_URLS variable, like:
@@ -778,6 +779,8 @@ include::intel-hybrid.txt[]
        only, as of now.  So the applications built without the frame
        pointer might see bogus addresses.
 
+include::intel-hybrid.txt[]
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-intel-pt[1]
index 0661a1c..2171f02 100644 (file)
@@ -265,7 +265,7 @@ endif
 # defined. get-executable-or-default fails with an error if the first argument is supplied but
 # doesn't exist.
 override PYTHON_CONFIG := $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON_AUTO))
-override PYTHON := $(call get-executable-or-default,PYTHON,$(subst -config,,$(PYTHON_AUTO)))
+override PYTHON := $(call get-executable-or-default,PYTHON,$(subst -config,,$(PYTHON_CONFIG)))
 
 grep-libs  = $(filter -l%,$(1))
 strip-libs  = $(filter-out -l%,$(1))
index 2f6cd1b..a5cf243 100644 (file)
@@ -3355,7 +3355,8 @@ static bool schedstat_events_exposed(void)
 static int __cmd_record(int argc, const char **argv)
 {
        unsigned int rec_argc, i, j;
-       const char **rec_argv;
+       char **rec_argv;
+       const char **rec_argv_copy;
        const char * const record_args[] = {
                "record",
                "-a",
@@ -3384,6 +3385,7 @@ static int __cmd_record(int argc, const char **argv)
                ARRAY_SIZE(schedstat_args) : 0;
 
        struct tep_event *waking_event;
+       int ret;
 
        /*
         * +2 for either "-e", "sched:sched_wakeup" or
@@ -3391,14 +3393,18 @@ static int __cmd_record(int argc, const char **argv)
         */
        rec_argc = ARRAY_SIZE(record_args) + 2 + schedstat_argc + argc - 1;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
-
        if (rec_argv == NULL)
                return -ENOMEM;
+       rec_argv_copy = calloc(rec_argc + 1, sizeof(char *));
+       if (rec_argv_copy == NULL) {
+               free(rec_argv);
+               return -ENOMEM;
+       }
 
        for (i = 0; i < ARRAY_SIZE(record_args); i++)
                rec_argv[i] = strdup(record_args[i]);
 
-       rec_argv[i++] = "-e";
+       rec_argv[i++] = strdup("-e");
        waking_event = trace_event__tp_format("sched", "sched_waking");
        if (!IS_ERR(waking_event))
                rec_argv[i++] = strdup("sched:sched_waking");
@@ -3409,11 +3415,19 @@ static int __cmd_record(int argc, const char **argv)
                rec_argv[i++] = strdup(schedstat_args[j]);
 
        for (j = 1; j < (unsigned int)argc; j++, i++)
-               rec_argv[i] = argv[j];
+               rec_argv[i] = strdup(argv[j]);
 
        BUG_ON(i != rec_argc);
 
-       return cmd_record(i, rec_argv);
+       memcpy(rec_argv_copy, rec_argv, sizeof(char *) * rec_argc);
+       ret = cmd_record(rec_argc, rec_argv_copy);
+
+       for (i = 0; i < rec_argc; i++)
+               free(rec_argv[i]);
+       free(rec_argv);
+       free(rec_argv_copy);
+
+       return ret;
 }
 
 int cmd_sched(int argc, const char **argv)
index 7fb81a4..54cd29d 100644 (file)
@@ -826,6 +826,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        }
 
        evlist__for_each_entry(evsel_list, counter) {
+               counter->reset_group = false;
                if (bpf_counter__load(counter, &target))
                        return -1;
                if (!evsel__is_bpf(counter))
index 9313ef2..26a51b4 100755 (executable)
@@ -28,6 +28,24 @@ test_stat_record_report() {
   echo "stat record and report test [Success]"
 }
 
+test_stat_repeat_weak_groups() {
+  echo "stat repeat weak groups test"
+  if ! perf stat -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}' \
+     true 2>&1 | grep -q 'seconds time elapsed'
+  then
+    echo "stat repeat weak groups test [Skipped event parsing failed]"
+    return
+  fi
+  if ! perf stat -r2 -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}:W' \
+    true > /dev/null 2>&1
+  then
+    echo "stat repeat weak groups test [Failed]"
+    err=1
+    return
+  fi
+  echo "stat repeat weak groups test [Success]"
+}
+
 test_topdown_groups() {
   # Topdown events must be grouped with the slots event first. Test that
   # parse-events reorders this.
@@ -75,6 +93,7 @@ test_topdown_weak_groups() {
 
 test_default_stat
 test_stat_record_report
+test_stat_repeat_weak_groups
 test_topdown_groups
 test_topdown_weak_groups
 exit $err
index 979c8cb..788ce5e 100644 (file)
@@ -1193,7 +1193,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (retiring > 0.7)
                        color = PERF_COLOR_GREEN;
-               print_metric(config, ctxp, color, "%8.1f%%", "retiring",
+               print_metric(config, ctxp, color, "%8.1f%%", "Retiring",
                                retiring * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_FE_BOUND) &&
                   full_td(cpu_map_idx, st, &rsd)) {
@@ -1202,7 +1202,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (fe_bound > 0.2)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Frontend Bound",
                                fe_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BE_BOUND) &&
                   full_td(cpu_map_idx, st, &rsd)) {
@@ -1211,7 +1211,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (be_bound > 0.2)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "backend bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Backend Bound",
                                be_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BAD_SPEC) &&
                   full_td(cpu_map_idx, st, &rsd)) {
@@ -1220,7 +1220,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (bad_spec > 0.1)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
+               print_metric(config, ctxp, color, "%8.1f%%", "Bad Speculation",
                                bad_spec * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_HEAVY_OPS) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1234,13 +1234,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (retiring > 0.7 && heavy_ops > 0.1)
                        color = PERF_COLOR_GREEN;
-               print_metric(config, ctxp, color, "%8.1f%%", "heavy operations",
+               print_metric(config, ctxp, color, "%8.1f%%", "Heavy Operations",
                                heavy_ops * 100.);
                if (retiring > 0.7 && light_ops > 0.6)
                        color = PERF_COLOR_GREEN;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "light operations",
+               print_metric(config, ctxp, color, "%8.1f%%", "Light Operations",
                                light_ops * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BR_MISPREDICT) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1254,13 +1254,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (bad_spec > 0.1 && br_mis > 0.05)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "branch mispredict",
+               print_metric(config, ctxp, color, "%8.1f%%", "Branch Mispredict",
                                br_mis * 100.);
                if (bad_spec > 0.1 && m_clears > 0.05)
                        color = PERF_COLOR_RED;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "machine clears",
+               print_metric(config, ctxp, color, "%8.1f%%", "Machine Clears",
                                m_clears * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_LAT) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1274,13 +1274,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (fe_bound > 0.2 && fetch_lat > 0.15)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "fetch latency",
+               print_metric(config, ctxp, color, "%8.1f%%", "Fetch Latency",
                                fetch_lat * 100.);
                if (fe_bound > 0.2 && fetch_bw > 0.1)
                        color = PERF_COLOR_RED;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "fetch bandwidth",
+               print_metric(config, ctxp, color, "%8.1f%%", "Fetch Bandwidth",
                                fetch_bw * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_MEM_BOUND) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1294,13 +1294,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (be_bound > 0.2 && mem_bound > 0.2)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "memory bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Memory Bound",
                                mem_bound * 100.);
                if (be_bound > 0.2 && core_bound > 0.1)
                        color = PERF_COLOR_RED;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "Core bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Core Bound",
                                core_bound * 100.);
        } else if (evsel->metric_expr) {
                generic_metric(config, evsel->metric_expr, evsel->metric_events, NULL,
index e33cab3..5cadfbd 100644 (file)
@@ -43,7 +43,7 @@ test_bpffs                               # bpffs test  failed 255
 test_bprm_opts                           # failed to auto-attach program 'secure_exec': -524                           (trampoline)
 test_ima                                 # failed to auto-attach program 'ima': -524                                   (trampoline)
 test_local_storage                       # failed to auto-attach program 'unlink_hook': -524                           (trampoline)
-test_lsm                                 # failed to find kernel BTF type ID of '__x64_sys_setdomainname': -3          (?)
+test_lsm                                 # attach unexpected error: -524                                               (trampoline)
 test_overhead                            # attach_fentry unexpected error: -524                                        (trampoline)
 test_profiler                            # unknown func bpf_probe_read_str#45                                          (overlapping)
 timer                                    # failed to auto-attach program 'test1': -524                                 (trampoline)
@@ -65,3 +65,4 @@ send_signal                              # intermittently fails to receive signa
 select_reuseport                         # intermittently fails on new s390x setup
 xdp_synproxy                             # JIT does not support calling kernel function                                (kfunc)
 unpriv_bpf_disabled                      # fentry
+lru_bug                                  # prog 'printk': failed to auto-attach: -524
index fabf0c0..3fc46f9 100644 (file)
@@ -50,9 +50,11 @@ CONFIG_NET_SCHED=y
 CONFIG_NETDEVSIM=m
 CONFIG_NETFILTER=y
 CONFIG_NETFILTER_SYNPROXY=y
+CONFIG_NETFILTER_XT_CONNMARK=y
 CONFIG_NETFILTER_XT_MATCH_STATE=y
 CONFIG_NETFILTER_XT_TARGET_CT=y
 CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_MARK=y
 CONFIG_NF_DEFRAG_IPV4=y
 CONFIG_NF_DEFRAG_IPV6=y
 CONFIG_RC_CORE=y
index 0b899d2..9566d9d 100644 (file)
@@ -6,19 +6,19 @@
 volatile unsigned short uprobe_ref_ctr __attribute__((unused)) __attribute((section(".probes")));
 
 /* uprobe attach point */
-static void trigger_func(void)
+static noinline void trigger_func(void)
 {
        asm volatile ("");
 }
 
 /* attach point for byname uprobe */
-static void trigger_func2(void)
+static noinline void trigger_func2(void)
 {
        asm volatile ("");
 }
 
 /* attach point for byname sleepable uprobe */
-static void trigger_func3(void)
+static noinline void trigger_func3(void)
 {
        asm volatile ("");
 }
diff --git a/tools/testing/selftests/bpf/prog_tests/autoattach.c b/tools/testing/selftests/bpf/prog_tests/autoattach.c
new file mode 100644 (file)
index 0000000..dc5e01d
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Google */
+
+#include <test_progs.h>
+#include "test_autoattach.skel.h"
+
+void test_autoattach(void)
+{
+       struct test_autoattach *skel;
+
+       skel = test_autoattach__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+               goto cleanup;
+
+       /* disable auto-attach for prog2 */
+       bpf_program__set_autoattach(skel->progs.prog2, false);
+       ASSERT_TRUE(bpf_program__autoattach(skel->progs.prog1), "autoattach_prog1");
+       ASSERT_FALSE(bpf_program__autoattach(skel->progs.prog2), "autoattach_prog2");
+       if (!ASSERT_OK(test_autoattach__attach(skel), "skel_attach"))
+               goto cleanup;
+
+       usleep(1);
+
+       ASSERT_TRUE(skel->bss->prog1_called, "attached_prog1");
+       ASSERT_FALSE(skel->bss->prog2_called, "attached_prog2");
+
+cleanup:
+       test_autoattach__destroy(skel);
+}
+
index 2974b44..2be2d61 100644 (file)
@@ -13,7 +13,7 @@
 #include "kprobe_multi.skel.h"
 
 /* uprobe attach point */
-static void trigger_func(void)
+static noinline void trigger_func(void)
 {
        asm volatile ("");
 }
index 7a74a15..544bf90 100644 (file)
@@ -24,10 +24,34 @@ enum {
        TEST_TC_BPF,
 };
 
+#define TIMEOUT_MS 3000
+
+static int connect_to_server(int srv_fd)
+{
+       int fd = -1;
+
+       fd = socket(AF_INET, SOCK_STREAM, 0);
+       if (!ASSERT_GE(fd, 0, "socket"))
+               goto out;
+
+       if (!ASSERT_EQ(connect_fd_to_fd(fd, srv_fd, TIMEOUT_MS), 0, "connect_fd_to_fd")) {
+               close(fd);
+               fd = -1;
+       }
+out:
+       return fd;
+}
+
 static void test_bpf_nf_ct(int mode)
 {
+       const char *iptables = "iptables -t raw %s PREROUTING -j CONNMARK --set-mark 42/0";
+       int srv_fd = -1, client_fd = -1, srv_client_fd = -1;
+       struct sockaddr_in peer_addr = {};
        struct test_bpf_nf *skel;
        int prog_fd, err;
+       socklen_t len;
+       u16 srv_port;
+       char cmd[64];
        LIBBPF_OPTS(bpf_test_run_opts, topts,
                .data_in = &pkt_v4,
                .data_size_in = sizeof(pkt_v4),
@@ -38,6 +62,32 @@ static void test_bpf_nf_ct(int mode)
        if (!ASSERT_OK_PTR(skel, "test_bpf_nf__open_and_load"))
                return;
 
+       /* Enable connection tracking */
+       snprintf(cmd, sizeof(cmd), iptables, "-A");
+       if (!ASSERT_OK(system(cmd), "iptables"))
+               goto end;
+
+       srv_port = (mode == TEST_XDP) ? 5005 : 5006;
+       srv_fd = start_server(AF_INET, SOCK_STREAM, "127.0.0.1", srv_port, TIMEOUT_MS);
+       if (!ASSERT_GE(srv_fd, 0, "start_server"))
+               goto end;
+
+       client_fd = connect_to_server(srv_fd);
+       if (!ASSERT_GE(client_fd, 0, "connect_to_server"))
+               goto end;
+
+       len = sizeof(peer_addr);
+       srv_client_fd = accept(srv_fd, (struct sockaddr *)&peer_addr, &len);
+       if (!ASSERT_GE(srv_client_fd, 0, "accept"))
+               goto end;
+       if (!ASSERT_EQ(len, sizeof(struct sockaddr_in), "sockaddr len"))
+               goto end;
+
+       skel->bss->saddr = peer_addr.sin_addr.s_addr;
+       skel->bss->sport = peer_addr.sin_port;
+       skel->bss->daddr = peer_addr.sin_addr.s_addr;
+       skel->bss->dport = htons(srv_port);
+
        if (mode == TEST_XDP)
                prog_fd = bpf_program__fd(skel->progs.nf_xdp_ct_test);
        else
@@ -63,7 +113,17 @@ static void test_bpf_nf_ct(int mode)
        ASSERT_LE(skel->bss->test_delta_timeout, 10, "Test for max ct timeout update");
        /* expected status is IPS_SEEN_REPLY */
        ASSERT_EQ(skel->bss->test_status, 2, "Test for ct status update ");
+       ASSERT_EQ(skel->data->test_exist_lookup, 0, "Test existing connection lookup");
+       ASSERT_EQ(skel->bss->test_exist_lookup_mark, 43, "Test existing connection lookup ctmark");
 end:
+       if (srv_client_fd != -1)
+               close(srv_client_fd);
+       if (client_fd != -1)
+               close(client_fd);
+       if (srv_fd != -1)
+               close(srv_fd);
+       snprintf(cmd, sizeof(cmd), iptables, "-D");
+       system(cmd);
        test_bpf_nf__destroy(skel);
 }
 
index 3c7aa82..bcf80b9 100644 (file)
@@ -22,7 +22,8 @@ static struct {
        {"add_dynptr_to_map2", "invalid indirect read from stack"},
        {"data_slice_out_of_bounds_ringbuf", "value is outside of the allowed memory range"},
        {"data_slice_out_of_bounds_map_value", "value is outside of the allowed memory range"},
-       {"data_slice_use_after_release", "invalid mem access 'scalar'"},
+       {"data_slice_use_after_release1", "invalid mem access 'scalar'"},
+       {"data_slice_use_after_release2", "invalid mem access 'scalar'"},
        {"data_slice_missing_null_check1", "invalid mem access 'mem_or_null'"},
        {"data_slice_missing_null_check2", "invalid mem access 'mem_or_null'"},
        {"invalid_helper1", "invalid indirect read from stack"},
index c00eb97..351fafa 100644 (file)
@@ -5,6 +5,9 @@
 #include "kfunc_call_test.lskel.h"
 #include "kfunc_call_test_subprog.skel.h"
 #include "kfunc_call_test_subprog.lskel.h"
+#include "kfunc_call_destructive.skel.h"
+
+#include "cap_helpers.h"
 
 static void test_main(void)
 {
@@ -86,6 +89,36 @@ static void test_subprog_lskel(void)
        kfunc_call_test_subprog_lskel__destroy(skel);
 }
 
+static int test_destructive_open_and_load(void)
+{
+       struct kfunc_call_destructive *skel;
+       int err;
+
+       skel = kfunc_call_destructive__open();
+       if (!ASSERT_OK_PTR(skel, "prog_open"))
+               return -1;
+
+       err = kfunc_call_destructive__load(skel);
+
+       kfunc_call_destructive__destroy(skel);
+
+       return err;
+}
+
+static void test_destructive(void)
+{
+       __u64 save_caps = 0;
+
+       ASSERT_OK(test_destructive_open_and_load(), "succesful_load");
+
+       if (!ASSERT_OK(cap_disable_effective(1ULL << CAP_SYS_BOOT, &save_caps), "drop_caps"))
+               return;
+
+       ASSERT_EQ(test_destructive_open_and_load(), -13, "no_caps_failure");
+
+       cap_enable_effective(save_caps, NULL);
+}
+
 void test_kfunc_call(void)
 {
        if (test__start_subtest("main"))
@@ -96,4 +129,7 @@ void test_kfunc_call(void)
 
        if (test__start_subtest("subprog_lskel"))
                test_subprog_lskel();
+
+       if (test__start_subtest("destructive"))
+               test_destructive();
 }
index 61935e7..f000734 100644 (file)
@@ -4,7 +4,7 @@
 #include "test_task_pt_regs.skel.h"
 
 /* uprobe attach point */
-static void trigger_func(void)
+static noinline void trigger_func(void)
 {
        asm volatile ("");
 }
diff --git a/tools/testing/selftests/bpf/prog_tests/time_tai.c b/tools/testing/selftests/bpf/prog_tests/time_tai.c
new file mode 100644 (file)
index 0000000..a311198
--- /dev/null
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2022 Linutronix GmbH */
+
+#include <test_progs.h>
+#include <network_helpers.h>
+
+#include "test_time_tai.skel.h"
+
+#include <time.h>
+#include <stdint.h>
+
+#define TAI_THRESHOLD  1000000000ULL /* 1s */
+#define NSEC_PER_SEC   1000000000ULL
+
+static __u64 ts_to_ns(const struct timespec *ts)
+{
+       return ts->tv_sec * NSEC_PER_SEC + ts->tv_nsec;
+}
+
+void test_time_tai(void)
+{
+       struct __sk_buff skb = {
+               .cb[0] = 0,
+               .cb[1] = 0,
+               .tstamp = 0,
+       };
+       LIBBPF_OPTS(bpf_test_run_opts, topts,
+               .data_in = &pkt_v4,
+               .data_size_in = sizeof(pkt_v4),
+               .ctx_in = &skb,
+               .ctx_size_in = sizeof(skb),
+               .ctx_out = &skb,
+               .ctx_size_out = sizeof(skb),
+       );
+       struct test_time_tai *skel;
+       struct timespec now_tai;
+       __u64 ts1, ts2, now;
+       int ret, prog_fd;
+
+       /* Open and load */
+       skel = test_time_tai__open_and_load();
+       if (!ASSERT_OK_PTR(skel, "tai_open"))
+               return;
+
+       /* Run test program */
+       prog_fd = bpf_program__fd(skel->progs.time_tai);
+       ret = bpf_prog_test_run_opts(prog_fd, &topts);
+       ASSERT_OK(ret, "test_run");
+
+       /* Retrieve generated TAI timestamps */
+       ts1 = skb.tstamp;
+       ts2 = skb.cb[0] | ((__u64)skb.cb[1] << 32);
+
+       /* TAI != 0 */
+       ASSERT_NEQ(ts1, 0, "tai_ts1");
+       ASSERT_NEQ(ts2, 0, "tai_ts2");
+
+       /* TAI is moving forward only */
+       ASSERT_GT(ts2, ts1, "tai_forward");
+
+       /* Check for future */
+       ret = clock_gettime(CLOCK_TAI, &now_tai);
+       ASSERT_EQ(ret, 0, "tai_gettime");
+       now = ts_to_ns(&now_tai);
+
+       ASSERT_TRUE(now > ts1, "tai_future_ts1");
+       ASSERT_TRUE(now > ts2, "tai_future_ts2");
+
+       /* Check for reasonable range */
+       ASSERT_TRUE(now - ts1 < TAI_THRESHOLD, "tai_range_ts1");
+       ASSERT_TRUE(now - ts2 < TAI_THRESHOLD, "tai_range_ts2");
+
+       test_time_tai__destroy(skel);
+}
index 0a26c24..b0f08ff 100644 (file)
@@ -65,7 +65,7 @@ static int get_map_val_dynptr(struct bpf_dynptr *ptr)
 /* Every bpf_ringbuf_reserve_dynptr call must have a corresponding
  * bpf_ringbuf_submit/discard_dynptr call
  */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int ringbuf_missing_release1(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -77,7 +77,7 @@ int ringbuf_missing_release1(void *ctx)
        return 0;
 }
 
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int ringbuf_missing_release2(void *ctx)
 {
        struct bpf_dynptr ptr1, ptr2;
@@ -112,7 +112,7 @@ static int missing_release_callback_fn(__u32 index, void *data)
 }
 
 /* Any dynptr initialized within a callback must have bpf_dynptr_put called */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int ringbuf_missing_release_callback(void *ctx)
 {
        bpf_loop(10, missing_release_callback_fn, NULL, 0);
@@ -120,7 +120,7 @@ int ringbuf_missing_release_callback(void *ctx)
 }
 
 /* Can't call bpf_ringbuf_submit/discard_dynptr on a non-initialized dynptr */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int ringbuf_release_uninit_dynptr(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -132,7 +132,7 @@ int ringbuf_release_uninit_dynptr(void *ctx)
 }
 
 /* A dynptr can't be used after it has been invalidated */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int use_after_invalid(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -151,7 +151,7 @@ int use_after_invalid(void *ctx)
 }
 
 /* Can't call non-dynptr ringbuf APIs on a dynptr ringbuf sample */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int ringbuf_invalid_api(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -173,7 +173,7 @@ done:
 }
 
 /* Can't add a dynptr to a map */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int add_dynptr_to_map1(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -190,7 +190,7 @@ int add_dynptr_to_map1(void *ctx)
 }
 
 /* Can't add a struct with an embedded dynptr to a map */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int add_dynptr_to_map2(void *ctx)
 {
        struct test_info x;
@@ -207,7 +207,7 @@ int add_dynptr_to_map2(void *ctx)
 }
 
 /* A data slice can't be accessed out of bounds */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int data_slice_out_of_bounds_ringbuf(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -227,7 +227,7 @@ done:
        return 0;
 }
 
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int data_slice_out_of_bounds_map_value(void *ctx)
 {
        __u32 key = 0, map_val;
@@ -247,8 +247,8 @@ int data_slice_out_of_bounds_map_value(void *ctx)
 }
 
 /* A data slice can't be used after it has been released */
-SEC("?raw_tp/sys_nanosleep")
-int data_slice_use_after_release(void *ctx)
+SEC("?raw_tp")
+int data_slice_use_after_release1(void *ctx)
 {
        struct bpf_dynptr ptr;
        struct sample *sample;
@@ -272,8 +272,44 @@ done:
        return 0;
 }
 
+/* A data slice can't be used after it has been released.
+ *
+ * This tests the case where the data slice tracks a dynptr (ptr2)
+ * that is at a non-zero offset from the frame pointer (ptr1 is at fp,
+ * ptr2 is at fp - 16).
+ */
+SEC("?raw_tp")
+int data_slice_use_after_release2(void *ctx)
+{
+       struct bpf_dynptr ptr1, ptr2;
+       struct sample *sample;
+
+       bpf_ringbuf_reserve_dynptr(&ringbuf, 64, 0, &ptr1);
+       bpf_ringbuf_reserve_dynptr(&ringbuf, sizeof(*sample), 0, &ptr2);
+
+       sample = bpf_dynptr_data(&ptr2, 0, sizeof(*sample));
+       if (!sample)
+               goto done;
+
+       sample->pid = 23;
+
+       bpf_ringbuf_submit_dynptr(&ptr2, 0);
+
+       /* this should fail */
+       sample->pid = 23;
+
+       bpf_ringbuf_submit_dynptr(&ptr1, 0);
+
+       return 0;
+
+done:
+       bpf_ringbuf_discard_dynptr(&ptr2, 0);
+       bpf_ringbuf_discard_dynptr(&ptr1, 0);
+       return 0;
+}
+
 /* A data slice must be first checked for NULL */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int data_slice_missing_null_check1(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -293,7 +329,7 @@ int data_slice_missing_null_check1(void *ctx)
 }
 
 /* A data slice can't be dereferenced if it wasn't checked for null */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int data_slice_missing_null_check2(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -315,7 +351,7 @@ done:
 /* Can't pass in a dynptr as an arg to a helper function that doesn't take in a
  * dynptr argument
  */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_helper1(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -329,7 +365,7 @@ int invalid_helper1(void *ctx)
 }
 
 /* A dynptr can't be passed into a helper function at a non-zero offset */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_helper2(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -344,7 +380,7 @@ int invalid_helper2(void *ctx)
 }
 
 /* A bpf_dynptr is invalidated if it's been written into */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_write1(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -365,7 +401,7 @@ int invalid_write1(void *ctx)
  * A bpf_dynptr can't be used as a dynptr if it has been written into at a fixed
  * offset
  */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_write2(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -388,7 +424,7 @@ int invalid_write2(void *ctx)
  * A bpf_dynptr can't be used as a dynptr if it has been written into at a
  * non-const offset
  */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_write3(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -419,7 +455,7 @@ static int invalid_write4_callback(__u32 index, void *data)
 /* If the dynptr is written into in a callback function, it should
  * be invalidated as a dynptr
  */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_write4(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -436,7 +472,7 @@ int invalid_write4(void *ctx)
 
 /* A globally-defined bpf_dynptr can't be used (it must reside as a stack frame) */
 struct bpf_dynptr global_dynptr;
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int global(void *ctx)
 {
        /* this should fail */
@@ -448,7 +484,7 @@ int global(void *ctx)
 }
 
 /* A direct read should fail */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_read1(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -464,7 +500,7 @@ int invalid_read1(void *ctx)
 }
 
 /* A direct read at an offset should fail */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_read2(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -479,7 +515,7 @@ int invalid_read2(void *ctx)
 }
 
 /* A direct read at an offset into the lower stack slot should fail */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_read3(void *ctx)
 {
        struct bpf_dynptr ptr1, ptr2;
@@ -505,7 +541,7 @@ static int invalid_read4_callback(__u32 index, void *data)
 }
 
 /* A direct read within a callback function should fail */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_read4(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -520,7 +556,7 @@ int invalid_read4(void *ctx)
 }
 
 /* Initializing a dynptr on an offset should fail */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int invalid_offset(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -534,7 +570,7 @@ int invalid_offset(void *ctx)
 }
 
 /* Can't release a dynptr twice */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int release_twice(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -560,7 +596,7 @@ static int release_twice_callback_fn(__u32 index, void *data)
 /* Test that releasing a dynptr twice, where one of the releases happens
  * within a calback function, fails
  */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int release_twice_callback(void *ctx)
 {
        struct bpf_dynptr ptr;
@@ -575,7 +611,7 @@ int release_twice_callback(void *ctx)
 }
 
 /* Reject unsupported local mem types for dynptr_from_mem API */
-SEC("?raw_tp/sys_nanosleep")
+SEC("?raw_tp")
 int dynptr_from_mem_invalid_api(void *ctx)
 {
        struct bpf_dynptr ptr;
diff --git a/tools/testing/selftests/bpf/progs/kfunc_call_destructive.c b/tools/testing/selftests/bpf/progs/kfunc_call_destructive.c
new file mode 100644 (file)
index 0000000..767472b
--- /dev/null
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+
+extern void bpf_kfunc_call_test_destructive(void) __ksym;
+
+SEC("tc")
+int kfunc_destructive_test(void)
+{
+       bpf_kfunc_call_test_destructive();
+       return 0;
+}
+
+char _license[] SEC("license") = "GPL";
index 33694ef..d8d8af6 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright 2020 Google LLC.
  */
 
+#include "bpf_misc.h"
 #include "vmlinux.h"
 #include <bpf/bpf_helpers.h>
 #include <bpf/bpf_tracing.h>
@@ -160,7 +161,7 @@ int BPF_PROG(test_task_free, struct task_struct *task)
 
 int copy_test = 0;
 
-SEC("fentry.s/__x64_sys_setdomainname")
+SEC("fentry.s/" SYS_PREFIX "sys_setdomainname")
 int BPF_PROG(test_sys_setdomainname, struct pt_regs *regs)
 {
        void *ptr = (void *)PT_REGS_PARM1(regs);
diff --git a/tools/testing/selftests/bpf/progs/test_autoattach.c b/tools/testing/selftests/bpf/progs/test_autoattach.c
new file mode 100644 (file)
index 0000000..11a4449
--- /dev/null
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2022 Google */
+
+#include "vmlinux.h"
+#include <bpf/bpf_tracing.h>
+
+bool prog1_called = false;
+bool prog2_called = false;
+
+SEC("raw_tp/sys_enter")
+int prog1(const void *ctx)
+{
+       prog1_called = true;
+       return 0;
+}
+
+SEC("raw_tp/sys_exit")
+int prog2(const void *ctx)
+{
+       prog2_called = true;
+       return 0;
+}
+
index 22d0ac8..5a3a80f 100644 (file)
@@ -28,14 +28,14 @@ static void update(void *ctx, __u64 *res)
        *res |= bpf_get_attach_cookie(ctx);
 }
 
-SEC("kprobe/sys_nanosleep")
+SEC("kprobe")
 int handle_kprobe(struct pt_regs *ctx)
 {
        update(ctx, &kprobe_res);
        return 0;
 }
 
-SEC("kretprobe/sys_nanosleep")
+SEC("kretprobe")
 int handle_kretprobe(struct pt_regs *ctx)
 {
        update(ctx, &kretprobe_res);
index 196cd8d..2722441 100644 (file)
@@ -23,6 +23,12 @@ int test_insert_entry = -EAFNOSUPPORT;
 int test_succ_lookup = -ENOENT;
 u32 test_delta_timeout = 0;
 u32 test_status = 0;
+__be32 saddr = 0;
+__be16 sport = 0;
+__be32 daddr = 0;
+__be16 dport = 0;
+int test_exist_lookup = -ENOENT;
+u32 test_exist_lookup_mark = 0;
 
 struct nf_conn;
 
@@ -160,6 +166,21 @@ nf_ct_test(struct nf_conn *(*lookup_fn)(void *, struct bpf_sock_tuple *, u32,
                }
                test_alloc_entry = 0;
        }
+
+       bpf_tuple.ipv4.saddr = saddr;
+       bpf_tuple.ipv4.daddr = daddr;
+       bpf_tuple.ipv4.sport = sport;
+       bpf_tuple.ipv4.dport = dport;
+       ct = lookup_fn(ctx, &bpf_tuple, sizeof(bpf_tuple.ipv4), &opts_def,
+                      sizeof(opts_def));
+       if (ct) {
+               test_exist_lookup = 0;
+               if (ct->mark == 42)
+                       test_exist_lookup_mark = 43;
+               bpf_ct_release(ct);
+       } else {
+               test_exist_lookup = opts_def.error;
+       }
 }
 
 SEC("xdp")
index 20ef9d4..5715c56 100644 (file)
@@ -72,7 +72,7 @@ int tp_timer(void *ctx)
        return 0;
 }
 
-SEC("?kprobe/sys_nanosleep")
+SEC("?kprobe")
 int kprobe_timer(void *ctx)
 {
        timer_work();
@@ -104,7 +104,7 @@ int tp_spin_lock(void *ctx)
        return 0;
 }
 
-SEC("?kprobe/sys_nanosleep")
+SEC("?kprobe")
 int kprobe_spin_lock(void *ctx)
 {
        spin_lock_work();
diff --git a/tools/testing/selftests/bpf/progs/test_time_tai.c b/tools/testing/selftests/bpf/progs/test_time_tai.c
new file mode 100644 (file)
index 0000000..7ea0863
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (C) 2022 Linutronix GmbH */
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+char _license[] SEC("license") = "GPL";
+
+SEC("tc")
+int time_tai(struct __sk_buff *skb)
+{
+       __u64 ts1, ts2;
+
+       /* Get TAI timestamps */
+       ts1 = bpf_ktime_get_tai_ns();
+       ts2 = bpf_ktime_get_tai_ns();
+
+       /* Save TAI timestamps (Note: skb->hwtstamp is read-only) */
+       skb->tstamp = ts1;
+       skb->cb[0] = ts2 & 0xffffffff;
+       skb->cb[1] = ts2 >> 32;
+
+       return 0;
+}
index 9e75442..6c03a7d 100644 (file)
        .result = VERBOSE_ACCEPT,
        .retval = -1,
 },
+{
+       "precise: mark_chain_precision for ARG_CONST_ALLOC_SIZE_OR_ZERO",
+       .insns = {
+       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_1, offsetof(struct xdp_md, ingress_ifindex)),
+       BPF_LD_MAP_FD(BPF_REG_6, 0),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+       BPF_MOV64_IMM(BPF_REG_2, 1),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_4, 0, 1),
+       BPF_MOV64_IMM(BPF_REG_2, 0x1000),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ringbuf_reserve),
+       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+       BPF_EXIT_INSN(),
+       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+       BPF_LDX_MEM(BPF_DW, BPF_REG_2, BPF_REG_0, 42),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_ringbuf_submit),
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_map_ringbuf = { 1 },
+       .prog_type = BPF_PROG_TYPE_XDP,
+       .flags = BPF_F_TEST_STATE_FREQ,
+       .errstr = "invalid access to memory, mem_size=1 off=42 size=8",
+       .result = REJECT,
+},
index b86ae4a..a29aa05 100755 (executable)
@@ -307,6 +307,20 @@ update_kconfig()
        fi
 }
 
+catch()
+{
+       local exit_code=$1
+       local exit_status_file="${OUTPUT_DIR}/${EXIT_STATUS_FILE}"
+       # This is just a cleanup and the directory may
+       # have already been unmounted. So, don't let this
+       # clobber the error code we intend to return.
+       unmount_image || true
+       if [[ -f "${exit_status_file}" ]]; then
+               exit_code="$(cat ${exit_status_file})"
+       fi
+       exit ${exit_code}
+}
+
 main()
 {
        local script_dir="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
@@ -319,7 +333,7 @@ main()
        local exit_command="poweroff -f"
        local debug_shell="no"
 
-       while getopts 'hskid:j:' opt; do
+       while getopts ':hskid:j:' opt; do
                case ${opt} in
                i)
                        update_image="yes"
@@ -353,6 +367,8 @@ main()
        done
        shift $((OPTIND -1))
 
+       trap 'catch "$?"' EXIT
+
        if [[ $# -eq 0  && "${debug_shell}" == "no" ]]; then
                echo "No command specified, will run ${DEFAULT_COMMAND} in the vm"
        else
@@ -409,20 +425,4 @@ main()
        fi
 }
 
-catch()
-{
-       local exit_code=$1
-       local exit_status_file="${OUTPUT_DIR}/${EXIT_STATUS_FILE}"
-       # This is just a cleanup and the directory may
-       # have already been unmounted. So, don't let this
-       # clobber the error code we intend to return.
-       unmount_image || true
-       if [[ -f "${exit_status_file}" ]]; then
-               exit_code="$(cat ${exit_status_file})"
-       fi
-       exit ${exit_code}
-}
-
-trap 'catch "$?"' EXIT
-
 main "$@"
index 74d56d9..14b4737 100644 (file)
@@ -244,6 +244,11 @@ static void gen_udp_hdr(u32 payload, void *pkt, struct ifobject *ifobject,
        memset32_htonl(pkt + PKT_HDR_SIZE, payload, UDP_PKT_DATA_SIZE);
 }
 
+static bool is_umem_valid(struct ifobject *ifobj)
+{
+       return !!ifobj->umem->umem;
+}
+
 static void gen_udp_csum(struct udphdr *udp_hdr, struct iphdr *ip_hdr)
 {
        udp_hdr->check = 0;
@@ -817,12 +822,13 @@ static int complete_pkts(struct xsk_socket_info *xsk, int batch_size)
        return TEST_PASS;
 }
 
-static int receive_pkts(struct ifobject *ifobj, struct pollfd *fds)
+static int receive_pkts(struct test_spec *test, struct pollfd *fds)
 {
-       struct timeval tv_end, tv_now, tv_timeout = {RECV_TMOUT, 0};
+       struct timeval tv_end, tv_now, tv_timeout = {THREAD_TMOUT, 0};
+       struct pkt_stream *pkt_stream = test->ifobj_rx->pkt_stream;
        u32 idx_rx = 0, idx_fq = 0, rcvd, i, pkts_sent = 0;
-       struct pkt_stream *pkt_stream = ifobj->pkt_stream;
-       struct xsk_socket_info *xsk = ifobj->xsk;
+       struct xsk_socket_info *xsk = test->ifobj_rx->xsk;
+       struct ifobject *ifobj = test->ifobj_rx;
        struct xsk_umem_info *umem = xsk->umem;
        struct pkt *pkt;
        int ret;
@@ -843,17 +849,28 @@ static int receive_pkts(struct ifobject *ifobj, struct pollfd *fds)
                }
 
                kick_rx(xsk);
+               if (ifobj->use_poll) {
+                       ret = poll(fds, 1, POLL_TMOUT);
+                       if (ret < 0)
+                               exit_with_error(-ret);
+
+                       if (!ret) {
+                               if (!is_umem_valid(test->ifobj_tx))
+                                       return TEST_PASS;
+
+                               ksft_print_msg("ERROR: [%s] Poll timed out\n", __func__);
+                               return TEST_FAILURE;
 
-               rcvd = xsk_ring_cons__peek(&xsk->rx, BATCH_SIZE, &idx_rx);
-               if (!rcvd) {
-                       if (xsk_ring_prod__needs_wakeup(&umem->fq)) {
-                               ret = poll(fds, 1, POLL_TMOUT);
-                               if (ret < 0)
-                                       exit_with_error(-ret);
                        }
-                       continue;
+
+                       if (!(fds->revents & POLLIN))
+                               continue;
                }
 
+               rcvd = xsk_ring_cons__peek(&xsk->rx, BATCH_SIZE, &idx_rx);
+               if (!rcvd)
+                       continue;
+
                if (ifobj->use_fill_ring) {
                        ret = xsk_ring_prod__reserve(&umem->fq, rcvd, &idx_fq);
                        while (ret != rcvd) {
@@ -900,13 +917,35 @@ static int receive_pkts(struct ifobject *ifobj, struct pollfd *fds)
        return TEST_PASS;
 }
 
-static int __send_pkts(struct ifobject *ifobject, u32 *pkt_nb)
+static int __send_pkts(struct ifobject *ifobject, u32 *pkt_nb, struct pollfd *fds,
+                      bool timeout)
 {
        struct xsk_socket_info *xsk = ifobject->xsk;
-       u32 i, idx, valid_pkts = 0;
+       bool use_poll = ifobject->use_poll;
+       u32 i, idx = 0, ret, valid_pkts = 0;
+
+       while (xsk_ring_prod__reserve(&xsk->tx, BATCH_SIZE, &idx) < BATCH_SIZE) {
+               if (use_poll) {
+                       ret = poll(fds, 1, POLL_TMOUT);
+                       if (timeout) {
+                               if (ret < 0) {
+                                       ksft_print_msg("ERROR: [%s] Poll error %d\n",
+                                                      __func__, ret);
+                                       return TEST_FAILURE;
+                               }
+                               if (ret == 0)
+                                       return TEST_PASS;
+                               break;
+                       }
+                       if (ret <= 0) {
+                               ksft_print_msg("ERROR: [%s] Poll error %d\n",
+                                              __func__, ret);
+                               return TEST_FAILURE;
+                       }
+               }
 
-       while (xsk_ring_prod__reserve(&xsk->tx, BATCH_SIZE, &idx) < BATCH_SIZE)
                complete_pkts(xsk, BATCH_SIZE);
+       }
 
        for (i = 0; i < BATCH_SIZE; i++) {
                struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx, idx + i);
@@ -933,11 +972,27 @@ static int __send_pkts(struct ifobject *ifobject, u32 *pkt_nb)
 
        xsk_ring_prod__submit(&xsk->tx, i);
        xsk->outstanding_tx += valid_pkts;
-       if (complete_pkts(xsk, i))
-               return TEST_FAILURE;
 
-       usleep(10);
-       return TEST_PASS;
+       if (use_poll) {
+               ret = poll(fds, 1, POLL_TMOUT);
+               if (ret <= 0) {
+                       if (ret == 0 && timeout)
+                               return TEST_PASS;
+
+                       ksft_print_msg("ERROR: [%s] Poll error %d\n", __func__, ret);
+                       return TEST_FAILURE;
+               }
+       }
+
+       if (!timeout) {
+               if (complete_pkts(xsk, i))
+                       return TEST_FAILURE;
+
+               usleep(10);
+               return TEST_PASS;
+       }
+
+       return TEST_CONTINUE;
 }
 
 static void wait_for_tx_completion(struct xsk_socket_info *xsk)
@@ -948,29 +1003,19 @@ static void wait_for_tx_completion(struct xsk_socket_info *xsk)
 
 static int send_pkts(struct test_spec *test, struct ifobject *ifobject)
 {
+       bool timeout = !is_umem_valid(test->ifobj_rx);
        struct pollfd fds = { };
-       u32 pkt_cnt = 0;
+       u32 pkt_cnt = 0, ret;
 
        fds.fd = xsk_socket__fd(ifobject->xsk->xsk);
        fds.events = POLLOUT;
 
        while (pkt_cnt < ifobject->pkt_stream->nb_pkts) {
-               int err;
-
-               if (ifobject->use_poll) {
-                       int ret;
-
-                       ret = poll(&fds, 1, POLL_TMOUT);
-                       if (ret <= 0)
-                               continue;
-
-                       if (!(fds.revents & POLLOUT))
-                               continue;
-               }
-
-               err = __send_pkts(ifobject, &pkt_cnt);
-               if (err || test->fail)
+               ret = __send_pkts(ifobject, &pkt_cnt, &fds, timeout);
+               if ((ret || test->fail) && !timeout)
                        return TEST_FAILURE;
+               else if (ret == TEST_PASS && timeout)
+                       return ret;
        }
 
        wait_for_tx_completion(ifobject->xsk);
@@ -1235,7 +1280,7 @@ static void *worker_testapp_validate_rx(void *arg)
 
        pthread_barrier_wait(&barr);
 
-       err = receive_pkts(ifobject, &fds);
+       err = receive_pkts(test, &fds);
 
        if (!err && ifobject->validation_func)
                err = ifobject->validation_func(ifobject);
@@ -1251,6 +1296,33 @@ static void *worker_testapp_validate_rx(void *arg)
        pthread_exit(NULL);
 }
 
+static int testapp_validate_traffic_single_thread(struct test_spec *test, struct ifobject *ifobj,
+                                                 enum test_type type)
+{
+       pthread_t t0;
+
+       if (pthread_barrier_init(&barr, NULL, 2))
+               exit_with_error(errno);
+
+       test->current_step++;
+       if (type  == TEST_TYPE_POLL_RXQ_TMOUT)
+               pkt_stream_reset(ifobj->pkt_stream);
+       pkts_in_flight = 0;
+
+       /*Spawn thread */
+       pthread_create(&t0, NULL, ifobj->func_ptr, test);
+
+       if (type != TEST_TYPE_POLL_TXQ_TMOUT)
+               pthread_barrier_wait(&barr);
+
+       if (pthread_barrier_destroy(&barr))
+               exit_with_error(errno);
+
+       pthread_join(t0, NULL);
+
+       return !!test->fail;
+}
+
 static int testapp_validate_traffic(struct test_spec *test)
 {
        struct ifobject *ifobj_tx = test->ifobj_tx;
@@ -1548,12 +1620,30 @@ static void run_pkt_test(struct test_spec *test, enum test_mode mode, enum test_
 
                pkt_stream_restore_default(test);
                break;
-       case TEST_TYPE_POLL:
-               test->ifobj_tx->use_poll = true;
+       case TEST_TYPE_RX_POLL:
                test->ifobj_rx->use_poll = true;
-               test_spec_set_name(test, "POLL");
+               test_spec_set_name(test, "POLL_RX");
                testapp_validate_traffic(test);
                break;
+       case TEST_TYPE_TX_POLL:
+               test->ifobj_tx->use_poll = true;
+               test_spec_set_name(test, "POLL_TX");
+               testapp_validate_traffic(test);
+               break;
+       case TEST_TYPE_POLL_TXQ_TMOUT:
+               test_spec_set_name(test, "POLL_TXQ_FULL");
+               test->ifobj_tx->use_poll = true;
+               /* create invalid frame by set umem frame_size and pkt length equal to 2048 */
+               test->ifobj_tx->umem->frame_size = 2048;
+               pkt_stream_replace(test, 2 * DEFAULT_PKT_CNT, 2048);
+               testapp_validate_traffic_single_thread(test, test->ifobj_tx, type);
+               pkt_stream_restore_default(test);
+               break;
+       case TEST_TYPE_POLL_RXQ_TMOUT:
+               test_spec_set_name(test, "POLL_RXQ_EMPTY");
+               test->ifobj_rx->use_poll = true;
+               testapp_validate_traffic_single_thread(test, test->ifobj_rx, type);
+               break;
        case TEST_TYPE_ALIGNED_INV_DESC:
                test_spec_set_name(test, "ALIGNED_INV_DESC");
                testapp_invalid_desc(test);
index 3d17053..ee97576 100644 (file)
@@ -27,6 +27,7 @@
 
 #define TEST_PASS 0
 #define TEST_FAILURE -1
+#define TEST_CONTINUE 1
 #define MAX_INTERFACES 2
 #define MAX_INTERFACE_NAME_CHARS 7
 #define MAX_INTERFACES_NAMESPACE_CHARS 10
@@ -48,7 +49,7 @@
 #define SOCK_RECONF_CTR 10
 #define BATCH_SIZE 64
 #define POLL_TMOUT 1000
-#define RECV_TMOUT 3
+#define THREAD_TMOUT 3
 #define DEFAULT_PKT_CNT (4 * 1024)
 #define DEFAULT_UMEM_BUFFERS (DEFAULT_PKT_CNT / 4)
 #define UMEM_SIZE (DEFAULT_UMEM_BUFFERS * XSK_UMEM__DEFAULT_FRAME_SIZE)
@@ -68,7 +69,10 @@ enum test_type {
        TEST_TYPE_RUN_TO_COMPLETION,
        TEST_TYPE_RUN_TO_COMPLETION_2K_FRAME,
        TEST_TYPE_RUN_TO_COMPLETION_SINGLE_PKT,
-       TEST_TYPE_POLL,
+       TEST_TYPE_RX_POLL,
+       TEST_TYPE_TX_POLL,
+       TEST_TYPE_POLL_RXQ_TMOUT,
+       TEST_TYPE_POLL_TXQ_TMOUT,
        TEST_TYPE_UNALIGNED,
        TEST_TYPE_ALIGNED_INV_DESC,
        TEST_TYPE_ALIGNED_INV_DESC_2K_FRAME,
index 2a731d5..c393e7b 100644 (file)
@@ -8,9 +8,10 @@ TEST_PROGS = bridge_locked_port.sh \
        bridge_vlan_unaware.sh \
        local_termination.sh \
        no_forwarding.sh \
+       tc_actions.sh \
        test_bridge_fdb_stress.sh
 
-TEST_PROGS_EXTENDED := lib.sh
+TEST_PROGS_EXTENDED := lib.sh tc_common.sh
 
 TEST_FILES := forwarding.config
 
diff --git a/tools/testing/selftests/drivers/net/dsa/tc_actions.sh b/tools/testing/selftests/drivers/net/dsa/tc_actions.sh
new file mode 120000 (symlink)
index 0000000..306213d
--- /dev/null
@@ -0,0 +1 @@
+../../../net/forwarding/tc_actions.sh
\ No newline at end of file
diff --git a/tools/testing/selftests/drivers/net/dsa/tc_common.sh b/tools/testing/selftests/drivers/net/dsa/tc_common.sh
new file mode 120000 (symlink)
index 0000000..bc3465b
--- /dev/null
@@ -0,0 +1 @@
+../../../net/forwarding/tc_common.sh
\ No newline at end of file
diff --git a/tools/testing/selftests/drivers/net/mlxsw/egress_vid_classification.sh b/tools/testing/selftests/drivers/net/mlxsw/egress_vid_classification.sh
new file mode 100755 (executable)
index 0000000..0cf9e47
--- /dev/null
@@ -0,0 +1,273 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Test VLAN classification after routing and verify that the order of
+# configuration does not impact switch behavior. Verify that {RIF, Port}->VID
+# mapping is added correctly for existing {Port, VID}->FID mapping and that
+# {RIF, Port}->VID mapping is added correctly for new {Port, VID}->FID mapping.
+
+# +-------------------+                   +--------------------+
+# | H1                |                   | H2                 |
+# |                   |                   |                    |
+# |         $h1.10 +  |                   |  + $h2.10          |
+# |   192.0.2.1/28 |  |                   |  | 192.0.2.3/28    |
+# |                |  |                   |  |                 |
+# |            $h1 +  |                   |  + $h2             |
+# +----------------|--+                   +--|-----------------+
+#                  |                         |
+# +----------------|-------------------------|-----------------+
+# | SW             |                         |                 |
+# | +--------------|-------------------------|---------------+ |
+# | |        $swp1 +                         + $swp2         | |
+# | |              |                         |               | |
+# | |     $swp1.10 +                         + $swp2.10      | |
+# | |                                                        | |
+# | |                           br0                          | |
+# | |                       192.0.2.2/28                     | |
+# | +--------------------------------------------------------+ |
+# |                                                            |
+# |      $swp3.20 +                                            |
+# | 192.0.2.17/28 |                                            |
+# |               |                                            |
+# |         $swp3 +                                            |
+# +---------------|--------------------------------------------+
+#                 |
+# +---------------|--+
+# |           $h3 +  |
+# |               |  |
+# |        $h3.20 +  |
+# | 192.0.2.18/28    |
+# |                  |
+# | H3               |
+# +------------------+
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+       port_vid_map_rif
+       rif_port_vid_map
+"
+
+NUM_NETIFS=6
+source $lib_dir/lib.sh
+source $lib_dir/tc_common.sh
+source $lib_dir/devlink_lib.sh
+
+h1_create()
+{
+       simple_if_init $h1
+       vlan_create $h1 10 v$h1 192.0.2.1/28
+
+       ip route add 192.0.2.16/28 vrf v$h1 nexthop via 192.0.2.2
+}
+
+h1_destroy()
+{
+       ip route del 192.0.2.16/28 vrf v$h1 nexthop via 192.0.2.2
+
+       vlan_destroy $h1 10
+       simple_if_fini $h1
+}
+
+h2_create()
+{
+       simple_if_init $h2
+       vlan_create $h2 10 v$h2 192.0.2.3/28
+}
+
+h2_destroy()
+{
+       vlan_destroy $h2 10
+       simple_if_fini $h2
+}
+
+h3_create()
+{
+       simple_if_init $h3
+       vlan_create $h3 20 v$h3 192.0.2.18/28
+
+       ip route add 192.0.2.0/28 vrf v$h3 nexthop via 192.0.2.17
+}
+
+h3_destroy()
+{
+       ip route del 192.0.2.0/28 vrf v$h3 nexthop via 192.0.2.17
+
+       vlan_destroy $h3 20
+       simple_if_fini $h3
+}
+
+switch_create()
+{
+       ip link set dev $swp1 up
+       tc qdisc add dev $swp1 clsact
+
+       ip link add dev br0 type bridge mcast_snooping 0
+
+       # By default, a link-local address is generated when netdevice becomes
+       # up. Adding an address to the bridge will cause creating a RIF for it.
+       # Prevent generating link-local address to be able to control when the
+       # RIF is added.
+       sysctl_set net.ipv6.conf.br0.addr_gen_mode 1
+       ip link set dev br0 up
+
+       ip link set dev $swp2 up
+       vlan_create $swp2 10
+       ip link set dev $swp2.10 master br0
+
+       ip link set dev $swp3 up
+       vlan_create $swp3 20 "" 192.0.2.17/28
+
+       # Replace neighbor to avoid 1 packet which is forwarded in software due
+       # to "unresolved neigh".
+       ip neigh replace dev $swp3.20 192.0.2.18 lladdr $(mac_get $h3.20)
+}
+
+switch_destroy()
+{
+       vlan_destroy $swp3 20
+       ip link set dev $swp3 down
+
+       ip link set dev $swp2.10 nomaster
+       vlan_destroy $swp2 10
+       ip link set dev $swp2 down
+
+       ip link set dev br0 down
+       sysctl_restore net.ipv6.conf.br0.addr_gen_mode
+       ip link del dev br0
+
+       tc qdisc del dev $swp1 clsact
+       ip link set dev $swp1 down
+}
+
+setup_prepare()
+{
+       h1=${NETIFS[p1]}
+       swp1=${NETIFS[p2]}
+
+       swp2=${NETIFS[p3]}
+       h2=${NETIFS[p4]}
+
+       swp3=${NETIFS[p5]}
+       h3=${NETIFS[p6]}
+
+       vrf_prepare
+       forwarding_enable
+
+       h1_create
+       h2_create
+       h3_create
+
+       switch_create
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       switch_destroy
+
+       h3_destroy
+       h2_destroy
+       h1_destroy
+
+       forwarding_restore
+       vrf_cleanup
+}
+
+bridge_rif_add()
+{
+       rifs_occ_t0=$(devlink_resource_occ_get rifs)
+       __addr_add_del br0 add 192.0.2.2/28
+       rifs_occ_t1=$(devlink_resource_occ_get rifs)
+
+       expected_rifs=$((rifs_occ_t0 + 1))
+
+       [[ $expected_rifs -eq $rifs_occ_t1 ]]
+       check_err $? "Expected $expected_rifs RIFs, $rifs_occ_t1 are used"
+
+       sleep 1
+}
+
+bridge_rif_del()
+{
+       __addr_add_del br0 del 192.0.2.2/28
+}
+
+port_vid_map_rif()
+{
+       RET=0
+
+       # First add {port, VID}->FID for swp1.10, then add a RIF and verify that
+       # packets get the correct VID after routing.
+       vlan_create $swp1 10
+       ip link set dev $swp1.10 master br0
+       bridge_rif_add
+
+       # Replace neighbor to avoid 1 packet which is forwarded in software due
+       # to "unresolved neigh".
+       ip neigh replace dev br0 192.0.2.1 lladdr $(mac_get $h1.10)
+
+       # The hardware matches on the first ethertype which is not VLAN,
+       # so the protocol should be IP.
+       tc filter add dev $swp1 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.1 action pass
+
+       ping_do $h1.10 192.0.2.18
+       check_err $? "Ping failed"
+
+       tc_check_at_least_x_packets "dev $swp1 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add RIF for existing {port, VID}->FID mapping"
+
+       tc filter del dev $swp1 egress
+
+       bridge_rif_del
+       ip link set dev $swp1.10 nomaster
+       vlan_destroy $swp1 10
+}
+
+rif_port_vid_map()
+{
+       RET=0
+
+       # First add an address to the bridge, which will create a RIF on top of
+       # it, then add a new {port, VID}->FID mapping and verify that packets
+       # get the correct VID after routing.
+       bridge_rif_add
+       vlan_create $swp1 10
+       ip link set dev $swp1.10 master br0
+
+       # Replace neighbor to avoid 1 packet which is forwarded in software due
+       # to "unresolved neigh".
+       ip neigh replace dev br0 192.0.2.1 lladdr $(mac_get $h1.10)
+
+       # The hardware matches on the first ethertype which is not VLAN,
+       # so the protocol should be IP.
+       tc filter add dev $swp1 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.1 action pass
+
+       ping_do $h1.10 192.0.2.18
+       check_err $? "Ping failed"
+
+       tc_check_at_least_x_packets "dev $swp1 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add {port, VID}->FID mapping for FID with a RIF"
+
+       tc filter del dev $swp1 egress
+
+       ip link set dev $swp1.10 nomaster
+       vlan_destroy $swp1 10
+       bridge_rif_del
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_1d.sh b/tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_1d.sh
new file mode 100755 (executable)
index 0000000..df2b099
--- /dev/null
@@ -0,0 +1,264 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Test routing over bridge and verify that the order of configuration does not
+# impact switch behavior. Verify that RIF is added correctly for existing
+# mappings and that new mappings use the correct RIF.
+
+# +-------------------+                   +--------------------+
+# | H1                |                   | H2                 |
+# |                   |                   |                    |
+# |         $h1.10 +  |                   |  + $h2.10          |
+# |   192.0.2.1/28 |  |                   |  | 192.0.2.3/28    |
+# |                |  |                   |  |                 |
+# |            $h1 +  |                   |  + $h2             |
+# +----------------|--+                   +--|-----------------+
+#                  |                         |
+# +----------------|-------------------------|-----------------+
+# | SW             |                         |                 |
+# | +--------------|-------------------------|---------------+ |
+# | |        $swp1 +                         + $swp2         | |
+# | |              |                         |               | |
+# | |     $swp1.10 +                         + $swp2.10      | |
+# | |                                                        | |
+# | |                           br0                          | |
+# | |                       192.0.2.2/28                     | |
+# | +--------------------------------------------------------+ |
+# |                                                            |
+# |      $swp3.10 +                                            |
+# | 192.0.2.17/28 |                                            |
+# |               |                                            |
+# |         $swp3 +                                            |
+# +---------------|--------------------------------------------+
+#                 |
+# +---------------|--+
+# |           $h3 +  |
+# |               |  |
+# |        $h3.10 +  |
+# | 192.0.2.18/28    |
+# |                  |
+# | H3               |
+# +------------------+
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+       port_vid_map_rif
+       rif_port_vid_map
+"
+
+NUM_NETIFS=6
+source $lib_dir/lib.sh
+source $lib_dir/tc_common.sh
+source $lib_dir/devlink_lib.sh
+
+h1_create()
+{
+       simple_if_init $h1
+       vlan_create $h1 10 v$h1 192.0.2.1/28
+
+       ip route add 192.0.2.16/28 vrf v$h1 nexthop via 192.0.2.2
+}
+
+h1_destroy()
+{
+       ip route del 192.0.2.16/28 vrf v$h1 nexthop via 192.0.2.2
+
+       vlan_destroy $h1 10
+       simple_if_fini $h1
+}
+
+h2_create()
+{
+       simple_if_init $h2
+       vlan_create $h2 10 v$h2 192.0.2.3/28
+}
+
+h2_destroy()
+{
+       vlan_destroy $h2 10
+       simple_if_fini $h2
+}
+
+h3_create()
+{
+       simple_if_init $h3
+       vlan_create $h3 10 v$h3 192.0.2.18/28
+
+       ip route add 192.0.2.0/28 vrf v$h3 nexthop via 192.0.2.17
+}
+
+h3_destroy()
+{
+       ip route del 192.0.2.0/28 vrf v$h3 nexthop via 192.0.2.17
+
+       vlan_destroy $h3 10
+       simple_if_fini $h3
+}
+
+switch_create()
+{
+       ip link set dev $swp1 up
+
+       ip link add dev br0 type bridge mcast_snooping 0
+
+       # By default, a link-local address is generated when netdevice becomes
+       # up. Adding an address to the bridge will cause creating a RIF for it.
+       # Prevent generating link-local address to be able to control when the
+       # RIF is added.
+       sysctl_set net.ipv6.conf.br0.addr_gen_mode 1
+       ip link set dev br0 up
+
+       ip link set dev $swp2 up
+       vlan_create $swp2 10
+       ip link set dev $swp2.10 master br0
+
+       ip link set dev $swp3 up
+       vlan_create $swp3 10 "" 192.0.2.17/28
+       tc qdisc add dev $swp3 clsact
+
+       # Replace neighbor to avoid 1 packet which is forwarded in software due
+       # to "unresolved neigh".
+       ip neigh replace dev $swp3.10 192.0.2.18 lladdr $(mac_get $h3.10)
+}
+
+switch_destroy()
+{
+       tc qdisc del dev $swp3 clsact
+       vlan_destroy $swp3 10
+       ip link set dev $swp3 down
+
+       ip link set dev $swp2.10 nomaster
+       vlan_destroy $swp2 10
+       ip link set dev $swp2 down
+
+       ip link set dev br0 down
+       sysctl_restore net.ipv6.conf.br0.addr_gen_mode
+       ip link del dev br0
+
+       ip link set dev $swp1 down
+}
+
+setup_prepare()
+{
+       h1=${NETIFS[p1]}
+       swp1=${NETIFS[p2]}
+
+       swp2=${NETIFS[p3]}
+       h2=${NETIFS[p4]}
+
+       swp3=${NETIFS[p5]}
+       h3=${NETIFS[p6]}
+
+       vrf_prepare
+       forwarding_enable
+
+       h1_create
+       h2_create
+       h3_create
+
+       switch_create
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       switch_destroy
+
+       h3_destroy
+       h2_destroy
+       h1_destroy
+
+       forwarding_restore
+       vrf_cleanup
+}
+
+bridge_rif_add()
+{
+       rifs_occ_t0=$(devlink_resource_occ_get rifs)
+       __addr_add_del br0 add 192.0.2.2/28
+       rifs_occ_t1=$(devlink_resource_occ_get rifs)
+
+       expected_rifs=$((rifs_occ_t0 + 1))
+
+       [[ $expected_rifs -eq $rifs_occ_t1 ]]
+       check_err $? "Expected $expected_rifs RIFs, $rifs_occ_t1 are used"
+
+       sleep 1
+}
+
+bridge_rif_del()
+{
+       __addr_add_del br0 del 192.0.2.2/28
+}
+
+port_vid_map_rif()
+{
+       RET=0
+
+       # First add {port, VID}->FID for $swp1.10, then add a RIF and verify
+       # that packets can be routed via the existing mapping.
+       vlan_create $swp1 10
+       ip link set dev $swp1.10 master br0
+       bridge_rif_add
+
+       # The hardware matches on the first ethertype which is not VLAN,
+       # so the protocol should be IP.
+       tc filter add dev $swp3 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.18 action pass
+
+       ping_do $h1.10 192.0.2.18
+       check_err $? "Ping failed"
+
+       tc_check_at_least_x_packets "dev $swp3 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add RIF for existing {port, VID}->FID mapping"
+
+       tc filter del dev $swp3 egress
+
+       bridge_rif_del
+       ip link set dev $swp1.10 nomaster
+       vlan_destroy $swp1 10
+}
+
+rif_port_vid_map()
+{
+       RET=0
+
+       # First add an address to the bridge, which will create a RIF on top of
+       # it, then add a new {port, VID}->FID mapping and verify that packets
+       # can be routed via the new mapping.
+       bridge_rif_add
+       vlan_create $swp1 10
+       ip link set dev $swp1.10 master br0
+
+       # The hardware matches on the first ethertype which is not VLAN,
+       # so the protocol should be IP.
+       tc filter add dev $swp3 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.18 action pass
+
+       ping_do $h1.10 192.0.2.18
+       check_err $? "Ping failed"
+
+       tc_check_at_least_x_packets "dev $swp3 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add {port, VID}->FID mapping for FID with a RIF"
+
+       tc filter del dev $swp3 egress
+
+       ip link set dev $swp1.10 nomaster
+       vlan_destroy $swp1 10
+       bridge_rif_del
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_1q.sh b/tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_1q.sh
new file mode 100755 (executable)
index 0000000..577293b
--- /dev/null
@@ -0,0 +1,264 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Test routing over bridge and verify that the order of configuration does not
+# impact switch behavior. Verify that RIF is added correctly for existing
+# mapping and that packets can be routed via port which is added after the FID
+# already has a RIF.
+
+# +-------------------+                   +--------------------+
+# | H1                |                   | H2                 |
+# |                   |                   |                    |
+# |         $h1.10 +  |                   |  + $h2.10          |
+# |   192.0.2.1/28 |  |                   |  | 192.0.2.3/28    |
+# |                |  |                   |  |                 |
+# |            $h1 +  |                   |  + $h2             |
+# +----------------|--+                   +--|-----------------+
+#                  |                         |
+# +----------------|-------------------------|-----------------+
+# | SW             |                         |                 |
+# | +--------------|-------------------------|---------------+ |
+# | |        $swp1 +                         + $swp2         | |
+# | |                                                        | |
+# | |                           br0                          | |
+# | +--------------------------------------------------------+ |
+# |                              |                             |
+# |                           br0.10                           |
+# |                        192.0.2.2/28                        |
+# |                                                            |
+# |                                                            |
+# |          $swp3 +                                           |
+# |  192.0.2.17/28 |                                           |
+# +----------------|-------------------------------------------+
+#                  |
+# +----------------|--+
+# |            $h3 +  |
+# |  192.0.2.18/28    |
+# |                   |
+# | H3                |
+# +-------------------+
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+       vid_map_rif
+       rif_vid_map
+"
+
+NUM_NETIFS=6
+source $lib_dir/lib.sh
+source $lib_dir/tc_common.sh
+source $lib_dir/devlink_lib.sh
+
+h1_create()
+{
+       simple_if_init $h1
+       vlan_create $h1 10 v$h1 192.0.2.1/28
+
+       ip route add 192.0.2.16/28 vrf v$h1 nexthop via 192.0.2.2
+}
+
+h1_destroy()
+{
+       ip route del 192.0.2.16/28 vrf v$h1 nexthop via 192.0.2.2
+
+       vlan_destroy $h1 10
+       simple_if_fini $h1
+}
+
+h2_create()
+{
+       simple_if_init $h2
+       vlan_create $h2 10 v$h2 192.0.2.3/28
+}
+
+h2_destroy()
+{
+       vlan_destroy $h2 10
+       simple_if_fini $h2
+}
+
+h3_create()
+{
+       simple_if_init $h3 192.0.2.18/28
+       ip route add 192.0.2.0/28 vrf v$h3 nexthop via 192.0.2.17
+}
+
+h3_destroy()
+{
+       ip route del 192.0.2.0/28 vrf v$h3 nexthop via 192.0.2.17
+       simple_if_fini $h3 192.0.2.18/28
+}
+
+switch_create()
+{
+       ip link set dev $swp1 up
+
+       ip link add dev br0 type bridge vlan_filtering 1 mcast_snooping 0
+
+       # By default, a link-local address is generated when netdevice becomes
+       # up. Adding an address to the bridge will cause creating a RIF for it.
+       # Prevent generating link-local address to be able to control when the
+       # RIF is added.
+       sysctl_set net.ipv6.conf.br0.addr_gen_mode 1
+       ip link set dev br0 up
+
+       ip link set dev $swp2 up
+       ip link set dev $swp2 master br0
+       bridge vlan add vid 10 dev $swp2
+
+       ip link set dev $swp3 up
+       __addr_add_del $swp3 add 192.0.2.17/28
+       tc qdisc add dev $swp3 clsact
+
+       # Replace neighbor to avoid 1 packet which is forwarded in software due
+       # to "unresolved neigh".
+       ip neigh replace dev $swp3 192.0.2.18 lladdr $(mac_get $h3)
+}
+
+switch_destroy()
+{
+       tc qdisc del dev $swp3 clsact
+       __addr_add_del $swp3 del 192.0.2.17/28
+       ip link set dev $swp3 down
+
+       bridge vlan del vid 10 dev $swp2
+       ip link set dev $swp2 nomaster
+       ip link set dev $swp2 down
+
+       ip link set dev br0 down
+       sysctl_restore net.ipv6.conf.br0.addr_gen_mode
+       ip link del dev br0
+
+       ip link set dev $swp1 down
+}
+
+setup_prepare()
+{
+       h1=${NETIFS[p1]}
+       swp1=${NETIFS[p2]}
+
+       swp2=${NETIFS[p3]}
+       h2=${NETIFS[p4]}
+
+       swp3=${NETIFS[p5]}
+       h3=${NETIFS[p6]}
+
+       vrf_prepare
+       forwarding_enable
+
+       h1_create
+       h2_create
+       h3_create
+
+       switch_create
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       switch_destroy
+
+       h3_destroy
+       h2_destroy
+       h1_destroy
+
+       forwarding_restore
+       vrf_cleanup
+}
+
+bridge_rif_add()
+{
+       rifs_occ_t0=$(devlink_resource_occ_get rifs)
+       vlan_create br0 10 "" 192.0.2.2/28
+       rifs_occ_t1=$(devlink_resource_occ_get rifs)
+
+       expected_rifs=$((rifs_occ_t0 + 1))
+
+       [[ $expected_rifs -eq $rifs_occ_t1 ]]
+       check_err $? "Expected $expected_rifs RIFs, $rifs_occ_t1 are used"
+
+       sleep 1
+}
+
+bridge_rif_del()
+{
+       vlan_destroy br0 10
+}
+
+vid_map_rif()
+{
+       RET=0
+
+       # First add VID->FID for vlan 10, then add a RIF and verify that
+       # packets can be routed via the existing mapping.
+       bridge vlan add vid 10 dev br0 self
+       ip link set dev $swp1 master br0
+       bridge vlan add vid 10 dev $swp1
+
+       bridge_rif_add
+
+       tc filter add dev $swp3 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.18 action pass
+
+       ping_do $h1.10 192.0.2.18
+       check_err $? "Ping failed"
+
+       tc_check_at_least_x_packets "dev $swp3 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add RIF for existing VID->FID mapping"
+
+       tc filter del dev $swp3 egress
+
+       bridge_rif_del
+
+       bridge vlan del vid 10 dev $swp1
+       ip link set dev $swp1 nomaster
+       bridge vlan del vid 10 dev br0 self
+}
+
+rif_vid_map()
+{
+       RET=0
+
+       # Using 802.1Q, there is only one VID->FID map for each VID. That means
+       # that we cannot really check adding a new map for existing FID with a
+       # RIF. Verify that packets can be routed via port which is added after
+       # the FID already has a RIF, although in practice there is no new
+       # mapping in the hardware.
+       bridge vlan add vid 10 dev br0 self
+       bridge_rif_add
+
+       ip link set dev $swp1 master br0
+       bridge vlan add vid 10 dev $swp1
+
+       tc filter add dev $swp3 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.18 action pass
+
+       ping_do $h1.10 192.0.2.18
+       check_err $? "Ping failed"
+
+       tc_check_at_least_x_packets "dev $swp3 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add port to VID->FID mapping for FID with a RIF"
+
+       tc filter del dev $swp3 egress
+
+       bridge vlan del vid 10 dev $swp1
+       ip link set dev $swp1 nomaster
+
+       bridge_rif_del
+       bridge vlan del vid 10 dev br0 self
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_vxlan.sh b/tools/testing/selftests/drivers/net/mlxsw/ingress_rif_conf_vxlan.sh
new file mode 100755 (executable)
index 0000000..9045021
--- /dev/null
@@ -0,0 +1,311 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# Test routing after VXLAN decapsulation and verify that the order of
+# configuration does not impact switch behavior. Verify that RIF is added
+# correctly for existing mapping and that new mapping uses the correct RIF.
+
+# +---------------------------+
+# |                        H1 |
+# |    + $h1                  |
+# |    | 192.0.2.1/28         |
+# +----|----------------------+
+#      |
+# +----|----------------------------------------------------------------------+
+# | SW |                                                                      |
+# | +--|--------------------------------------------------------------------+ |
+# | |  + $swp1                         br1                                  | |
+# | |     vid 10 pvid untagged                                              | |
+# | |                                                                       | |
+# | |                                                                       | |
+# | |                                            + vx4001                   | |
+# | |                                              local 192.0.2.17         | |
+# | |                                              remote 192.0.2.18        | |
+# | |                                              id 104001                | |
+# | |                                              dstport $VXPORT          | |
+# | |                                              vid 4001 pvid untagged   | |
+# | |                                                                       | |
+# | +----------------------------------+------------------------------------+ |
+# |                                    |                                      |
+# | +----------------------------------|------------------------------------+ |
+# | |                                  |                                    | |
+# | |  +-------------------------------+---------------------------------+  | |
+# | |  |                                                                 |  | |
+# | |  + vlan10                                                 vlan4001 +  | |
+# | |    192.0.2.2/28                                                       | |
+# | |                                                                       | |
+# | |                               vrf-green                               | |
+# | +-----------------------------------------------------------------------+ |
+# |                                                                           |
+# |    + $rp1                                       +lo                       |
+# |    | 198.51.100.1/24                             192.0.2.17/32            |
+# +----|----------------------------------------------------------------------+
+#      |
+# +----|--------------------------------------------------------+
+# |    |                                             v$rp2      |
+# |    + $rp2                                                   |
+# |      198.51.100.2/24                                        |
+# |                                                             |
+# +-------------------------------------------------------------+
+
+lib_dir=$(dirname $0)/../../../net/forwarding
+
+ALL_TESTS="
+       vni_fid_map_rif
+       rif_vni_fid_map
+"
+
+NUM_NETIFS=4
+source $lib_dir/lib.sh
+source $lib_dir/tc_common.sh
+source $lib_dir/devlink_lib.sh
+
+: ${VXPORT:=4789}
+export VXPORT
+
+h1_create()
+{
+       simple_if_init $h1 192.0.2.1/28
+}
+
+h1_destroy()
+{
+       simple_if_fini $h1 192.0.2.1/28
+}
+
+switch_create()
+{
+       ip link add name br1 type bridge vlan_filtering 1 vlan_default_pvid 0 \
+               mcast_snooping 0
+       # Make sure the bridge uses the MAC address of the local port and not
+       # that of the VxLAN's device.
+       ip link set dev br1 address $(mac_get $swp1)
+       ip link set dev br1 up
+
+       ip link set dev $rp1 up
+       ip address add dev $rp1 198.51.100.1/24
+
+       ip link set dev $swp1 master br1
+       ip link set dev $swp1 up
+       bridge vlan add vid 10 dev $swp1 pvid untagged
+
+       tc qdisc add dev $swp1 clsact
+
+       ip link add name vx4001 type vxlan id 104001 \
+               local 192.0.2.17 dstport $VXPORT \
+               nolearning noudpcsum tos inherit ttl 100
+       ip link set dev vx4001 up
+
+       ip link set dev vx4001 master br1
+
+       ip address add 192.0.2.17/32 dev lo
+
+       # Create SVIs.
+       vrf_create "vrf-green"
+       ip link set dev vrf-green up
+
+       ip link add link br1 name vlan10 up master vrf-green type vlan id 10
+
+       # Replace neighbor to avoid 1 packet which is forwarded in software due
+       # to "unresolved neigh".
+       ip neigh replace dev vlan10 192.0.2.1 lladdr $(mac_get $h1)
+
+       ip address add 192.0.2.2/28 dev vlan10
+
+       bridge vlan add vid 10 dev br1 self
+       bridge vlan add vid 4001 dev br1 self
+
+       sysctl_set net.ipv4.conf.all.rp_filter 0
+}
+
+switch_destroy()
+{
+       sysctl_restore net.ipv4.conf.all.rp_filter
+
+       bridge vlan del vid 4001 dev br1 self
+       bridge vlan del vid 10 dev br1 self
+
+       ip link del dev vlan10
+
+       vrf_destroy "vrf-green"
+
+       ip address del 192.0.2.17/32 dev lo
+
+       tc qdisc del dev $swp1 clsact
+
+       bridge vlan del vid 10 dev $swp1
+       ip link set dev $swp1 down
+       ip link set dev $swp1 nomaster
+
+       ip link set dev vx4001 nomaster
+
+       ip link set dev vx4001 down
+       ip link del dev vx4001
+
+       ip address del dev $rp1 198.51.100.1/24
+       ip link set dev $rp1 down
+
+       ip link set dev br1 down
+       ip link del dev br1
+}
+
+vrp2_create()
+{
+       simple_if_init $rp2 198.51.100.2/24
+
+       ip route add 192.0.2.17/32 vrf v$rp2 nexthop via 198.51.100.1
+}
+
+vrp2_destroy()
+{
+       ip route del 192.0.2.17/32 vrf v$rp2 nexthop via 198.51.100.1
+
+       simple_if_fini $rp2 198.51.100.2/24
+}
+
+setup_prepare()
+{
+       h1=${NETIFS[p1]}
+       swp1=${NETIFS[p2]}
+
+       rp1=${NETIFS[p3]}
+       rp2=${NETIFS[p4]}
+
+       vrf_prepare
+       forwarding_enable
+
+       h1_create
+       switch_create
+
+       vrp2_create
+}
+
+cleanup()
+{
+       pre_cleanup
+
+       vrp2_destroy
+
+       switch_destroy
+       h1_destroy
+
+       forwarding_restore
+       vrf_cleanup
+}
+
+payload_get()
+{
+       local dest_mac=$(mac_get vlan4001)
+       local src_mac=$(mac_get $rp1)
+
+       p=$(:
+               )"08:"$(                      : VXLAN flags
+               )"00:00:00:"$(                : VXLAN reserved
+               )"01:96:41:"$(                : VXLAN VNI : 104001
+               )"00:"$(                      : VXLAN reserved
+               )"$dest_mac:"$(               : ETH daddr
+               )"$src_mac:"$(                : ETH saddr
+               )"08:00:"$(                   : ETH type
+               )"45:"$(                      : IP version + IHL
+               )"00:"$(                      : IP TOS
+               )"00:54:"$(                   : IP total length
+               )"3f:49:"$(                   : IP identification
+               )"00:00:"$(                   : IP flags + frag off
+               )"3f:"$(                      : IP TTL
+               )"01:"$(                      : IP proto
+               )"50:21:"$(                   : IP header csum
+               )"c6:33:64:0a:"$(             : IP saddr: 198.51.100.10
+               )"c0:00:02:01:"$(             : IP daddr: 192.0.2.1
+       )
+       echo $p
+}
+
+vlan_rif_add()
+{
+       rifs_occ_t0=$(devlink_resource_occ_get rifs)
+
+       ip link add link br1 name vlan4001 up master vrf-green \
+               type vlan id 4001
+
+       rifs_occ_t1=$(devlink_resource_occ_get rifs)
+       expected_rifs=$((rifs_occ_t0 + 1))
+
+       [[ $expected_rifs -eq $rifs_occ_t1 ]]
+       check_err $? "Expected $expected_rifs RIFs, $rifs_occ_t1 are used"
+}
+
+vlan_rif_del()
+{
+       ip link del dev vlan4001
+}
+
+vni_fid_map_rif()
+{
+       local rp1_mac=$(mac_get $rp1)
+
+       RET=0
+
+       # First add VNI->FID mapping to the FID of VLAN 4001
+       bridge vlan add vid 4001 dev vx4001 pvid untagged
+
+       # Add a RIF to the FID with VNI->FID mapping
+       vlan_rif_add
+
+       tc filter add dev $swp1 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.1 action pass
+
+       payload=$(payload_get)
+       ip vrf exec v$rp2 $MZ $rp2 -c 10 -d 1msec -b $rp1_mac \
+               -B 192.0.2.17 -A 192.0.2.18 \
+               -t udp sp=12345,dp=$VXPORT,p=$payload -q
+
+       tc_check_at_least_x_packets "dev $swp1 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add RIF for existing VNI->FID mapping"
+
+       tc filter del dev $swp1 egress
+
+       bridge vlan del vid 4001 dev vx4001 pvid untagged
+       vlan_rif_del
+}
+
+rif_vni_fid_map()
+{
+       local rp1_mac=$(mac_get $rp1)
+
+       RET=0
+
+       # First add a RIF to the FID of VLAN 4001
+       vlan_rif_add
+
+       # Add VNI->FID mapping to FID with a RIF
+       bridge vlan add vid 4001 dev vx4001 pvid untagged
+
+       tc filter add dev $swp1 egress protocol ip pref 1 handle 101 \
+               flower skip_sw dst_ip 192.0.2.1 action pass
+
+       payload=$(payload_get)
+       ip vrf exec v$rp2 $MZ $rp2 -c 10 -d 1msec -b $rp1_mac \
+               -B 192.0.2.17 -A 192.0.2.18 \
+               -t udp sp=12345,dp=$VXPORT,p=$payload -q
+
+       tc_check_at_least_x_packets "dev $swp1 egress" 101 10
+       check_err $? "Packets were not routed in hardware"
+
+       log_test "Add VNI->FID mapping for FID with a RIF"
+
+       tc filter del dev $swp1 egress
+
+       bridge vlan del vid 4001 dev vx4001 pvid untagged
+       vlan_rif_del
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+
+tests_run
+
+exit $EXIT_STATUS
index 0e5751a..3d7adee 100644 (file)
@@ -1,42 +1,45 @@
 # SPDX-License-Identifier: GPL-2.0-only
+bind_bhash
+cmsg_sender
+fin_ack_lat
+gro
+hwtstamp_config
+ioam6_parser
+ip_defrag
 ipsec
+ipv6_flowlabel
+ipv6_flowlabel_mgr
 msg_zerocopy
-socket
+nettest
 psock_fanout
 psock_snd
 psock_tpacket
-stress_reuseport_listen
+reuseaddr_conflict
+reuseaddr_ports_exhausted
 reuseport_addr_any
 reuseport_bpf
 reuseport_bpf_cpu
 reuseport_bpf_numa
 reuseport_dualstack
-reuseaddr_conflict
-tcp_mmap
-udpgso
-udpgso_bench_rx
-udpgso_bench_tx
-tcp_inq
-tls
-txring_overwrite
-ip_defrag
-ipv6_flowlabel
-ipv6_flowlabel_mgr
-so_txtime
-tcp_fastopen_backup_key
-nettest
-fin_ack_lat
-reuseaddr_ports_exhausted
-hwtstamp_config
 rxtimestamp
-timestamping
-txtimestamp
+sk_bind_sendto_listen
+sk_connect_zero_addr
+socket
 so_netns_cookie
+so_txtime
+stress_reuseport_listen
+tap
+tcp_fastopen_backup_key
+tcp_inq
+tcp_mmap
 test_unix_oob
-gro
-ioam6_parser
+timestamping
+tls
 toeplitz
 tun
-cmsg_sender
+txring_overwrite
+txtimestamp
+udpgso
+udpgso_bench_rx
+udpgso_bench_tx
 unix_connect
-tap
\ No newline at end of file
index c0ee295..f5ac143 100644 (file)
@@ -42,6 +42,8 @@ TEST_PROGS += arp_ndisc_evict_nocarrier.sh
 TEST_PROGS += ndisc_unsolicited_na_test.sh
 TEST_PROGS += arp_ndisc_untracked_subnets.sh
 TEST_PROGS += stress_reuseport_listen.sh
+TEST_PROGS += l2_tos_ttl_inherit.sh
+TEST_PROGS += bind_bhash.sh
 TEST_PROGS_EXTENDED := in_netns.sh setup_loopback.sh setup_veth.sh
 TEST_PROGS_EXTENDED += toeplitz_client.sh toeplitz.sh
 TEST_GEN_FILES =  socket nettest
@@ -63,6 +65,9 @@ TEST_GEN_FILES += cmsg_sender
 TEST_GEN_FILES += stress_reuseport_listen
 TEST_PROGS += test_vxlan_vnifiltering.sh
 TEST_GEN_FILES += io_uring_zerocopy_tx
+TEST_GEN_FILES += bind_bhash
+TEST_GEN_PROGS += sk_bind_sendto_listen
+TEST_GEN_PROGS += sk_connect_zero_addr
 
 TEST_FILES := settings
 
@@ -73,3 +78,4 @@ include bpf/Makefile
 $(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
 $(OUTPUT)/tcp_mmap: LDLIBS += -lpthread
 $(OUTPUT)/tcp_inq: LDLIBS += -lpthread
+$(OUTPUT)/bind_bhash: LDLIBS += -lpthread
diff --git a/tools/testing/selftests/net/bind_bhash.c b/tools/testing/selftests/net/bind_bhash.c
new file mode 100644 (file)
index 0000000..57ff67a
--- /dev/null
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * This times how long it takes to bind to a port when the port already
+ * has multiple sockets in its bhash table.
+ *
+ * In the setup(), we populate the port's bhash table with
+ * MAX_THREADS * MAX_CONNECTIONS number of entries.
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <pthread.h>
+#include <string.h>
+#include <stdbool.h>
+
+#define MAX_THREADS 600
+#define MAX_CONNECTIONS 40
+
+static const char *setup_addr_v6 = "::1";
+static const char *setup_addr_v4 = "127.0.0.1";
+static const char *setup_addr;
+static const char *bind_addr;
+static const char *port;
+bool use_v6;
+int ret;
+
+static int fd_array[MAX_THREADS][MAX_CONNECTIONS];
+
+static int bind_socket(int opt, const char *addr)
+{
+       struct addrinfo *res, hint = {};
+       int sock_fd, reuse = 1, err;
+       int domain = use_v6 ? AF_INET6 : AF_INET;
+
+       sock_fd = socket(domain, SOCK_STREAM, 0);
+       if (sock_fd < 0) {
+               perror("socket fd err");
+               return sock_fd;
+       }
+
+       hint.ai_family = domain;
+       hint.ai_socktype = SOCK_STREAM;
+
+       err = getaddrinfo(addr, port, &hint, &res);
+       if (err) {
+               perror("getaddrinfo failed");
+               goto cleanup;
+       }
+
+       if (opt) {
+               err = setsockopt(sock_fd, SOL_SOCKET, opt, &reuse, sizeof(reuse));
+               if (err) {
+                       perror("setsockopt failed");
+                       goto cleanup;
+               }
+       }
+
+       err = bind(sock_fd, res->ai_addr, res->ai_addrlen);
+       if (err) {
+               perror("failed to bind to port");
+               goto cleanup;
+       }
+
+       return sock_fd;
+
+cleanup:
+       close(sock_fd);
+       return err;
+}
+
+static void *setup(void *arg)
+{
+       int sock_fd, i;
+       int *array = (int *)arg;
+
+       for (i = 0; i < MAX_CONNECTIONS; i++) {
+               sock_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, setup_addr);
+               if (sock_fd < 0) {
+                       ret = sock_fd;
+                       pthread_exit(&ret);
+               }
+               array[i] = sock_fd;
+       }
+
+       return NULL;
+}
+
+int main(int argc, const char *argv[])
+{
+       int listener_fd, sock_fd, i, j;
+       pthread_t tid[MAX_THREADS];
+       clock_t begin, end;
+
+       if (argc != 4) {
+               printf("Usage: listener <port> <ipv6 | ipv4> <bind-addr>\n");
+               return -1;
+       }
+
+       port = argv[1];
+       use_v6 = strcmp(argv[2], "ipv6") == 0;
+       bind_addr = argv[3];
+
+       setup_addr = use_v6 ? setup_addr_v6 : setup_addr_v4;
+
+       listener_fd = bind_socket(SO_REUSEADDR | SO_REUSEPORT, setup_addr);
+       if (listen(listener_fd, 100) < 0) {
+               perror("listen failed");
+               return -1;
+       }
+
+       /* Set up threads to populate the bhash table entry for the port */
+       for (i = 0; i < MAX_THREADS; i++)
+               pthread_create(&tid[i], NULL, setup, fd_array[i]);
+
+       for (i = 0; i < MAX_THREADS; i++)
+               pthread_join(tid[i], NULL);
+
+       if (ret)
+               goto done;
+
+       begin = clock();
+
+       /* Bind to the same port on a different address */
+       sock_fd  = bind_socket(0, bind_addr);
+       if (sock_fd < 0)
+               goto done;
+
+       end = clock();
+
+       printf("time spent = %f\n", (double)(end - begin) / CLOCKS_PER_SEC);
+
+       /* clean up */
+       close(sock_fd);
+
+done:
+       close(listener_fd);
+       for (i = 0; i < MAX_THREADS; i++) {
+               for (j = 0; i < MAX_THREADS; i++)
+                       close(fd_array[i][j]);
+       }
+
+       return 0;
+}
diff --git a/tools/testing/selftests/net/bind_bhash.sh b/tools/testing/selftests/net/bind_bhash.sh
new file mode 100755 (executable)
index 0000000..ca0292d
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+NR_FILES=32768
+SAVED_NR_FILES=$(ulimit -n)
+
+# default values
+port=443
+addr_v6="2001:0db8:0:f101::1"
+addr_v4="10.8.8.8"
+use_v6=true
+addr=""
+
+usage() {
+    echo "Usage: $0 [-6 | -4] [-p port] [-a address]"
+    echo -e "\t6: use ipv6"
+    echo -e "\t4: use ipv4"
+    echo -e "\tport: Port number"
+    echo -e "\taddress: ip address"
+}
+
+while getopts "ha:p:64" opt; do
+    case ${opt} in
+       h)
+           usage $0
+           exit 0
+           ;;
+       a)  addr=$OPTARG;;
+       p)
+           port=$OPTARG;;
+       6)
+           use_v6=true;;
+       4)
+           use_v6=false;;
+    esac
+done
+
+setup() {
+    if [[ "$use_v6" == true ]]; then
+       ip addr add $addr_v6 nodad dev eth0
+    else
+       ip addr add $addr_v4 dev lo
+    fi
+       ulimit -n $NR_FILES
+}
+
+cleanup() {
+    if [[ "$use_v6" == true ]]; then
+       ip addr del $addr_v6 dev eth0
+    else
+       ip addr del $addr_v4/32 dev lo
+    fi
+    ulimit -n $SAVED_NR_FILES
+}
+
+if [[ "$addr" != "" ]]; then
+    addr_v4=$addr;
+    addr_v6=$addr;
+fi
+setup
+if [[ "$use_v6" == true ]] ; then
+    ./bind_bhash $port "ipv6" $addr_v6
+else
+    ./bind_bhash $port "ipv4" $addr_v4
+fi
+cleanup
index 03b5867..31c3b6e 100755 (executable)
@@ -1466,6 +1466,13 @@ ipv4_udp_novrf()
                run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP}
                log_test_addr ${a} $? 0 "Client, device bind via IP_UNICAST_IF"
 
+               log_start
+               run_cmd_nsb nettest -D -s &
+               sleep 1
+               run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -0 ${NSA_IP} -U
+               log_test_addr ${a} $? 0 "Client, device bind via IP_UNICAST_IF, with connect()"
+
+
                log_start
                show_hint "Should fail 'Connection refused'"
                run_cmd nettest -D -r ${a}
@@ -1525,6 +1532,13 @@ ipv4_udp_novrf()
        run_cmd nettest -D -d ${NSA_DEV} -S -r ${a}
        log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection"
 
+       log_start
+       run_cmd nettest -s -D &
+       sleep 1
+       run_cmd nettest -D -d ${NSA_DEV} -S -r ${a} -U
+       log_test_addr ${a} $? 0 "Global server, device client via IP_UNICAST_IF, local connection, with connect()"
+
+
        # IPv4 with device bind has really weird behavior - it overrides the
        # fib lookup, generates an rtable and tries to send the packet. This
        # causes failures for local traffic at different places
@@ -1550,6 +1564,15 @@ ipv4_udp_novrf()
                sleep 1
                run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S
                log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection"
+
+               log_start
+               show_hint "Should fail since addresses on loopback are out of device scope"
+               run_cmd nettest -D -s &
+               sleep 1
+               run_cmd nettest -D -r ${a} -d ${NSA_DEV} -S -U
+               log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection, with connect()"
+
+
        done
 
        a=${NSA_IP}
@@ -3157,6 +3180,13 @@ ipv6_udp_novrf()
                sleep 1
                run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S
                log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection"
+
+               log_start
+               show_hint "Should fail 'No route to host' since addresses on loopback are out of device scope"
+               run_cmd nettest -6 -D -s &
+               sleep 1
+               run_cmd nettest -6 -D -r ${a} -d ${NSA_DEV} -S -U
+               log_test_addr ${a} $? 1 "Global server, device client via IP_UNICAST_IF, local connection, with connect()"
        done
 
        a=${NSA_IP6}
diff --git a/tools/testing/selftests/net/l2_tos_ttl_inherit.sh b/tools/testing/selftests/net/l2_tos_ttl_inherit.sh
new file mode 100755 (executable)
index 0000000..dca1e6f
--- /dev/null
@@ -0,0 +1,390 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+# Author: Matthias May <matthias.may@westermo.com>
+#
+# This script evaluates ip tunnels that are capable of carrying L2 traffic
+# if they inherit or set the inheritable fields.
+# Namely these tunnels are: 'gretap', 'vxlan' and 'geneve'.
+# Checked inheritable fields are: TOS and TTL.
+# The outer tunnel protocol of 'IPv4' or 'IPv6' is verified-
+# As payload frames of type 'IPv4', 'IPv6' and 'other'(ARP) are verified.
+# In addition this script also checks if forcing a specific field in the
+# outer header is working.
+
+if [ "$(id -u)" != "0" ]; then
+       echo "Please run as root."
+       exit 0
+fi
+if ! which tcpdump > /dev/null 2>&1; then
+       echo "No tcpdump found. Required for this test."
+       exit 0
+fi
+
+expected_tos="0x00"
+expected_ttl="0"
+failed=false
+
+get_random_tos() {
+       # Get a random hex tos value between 0x00 and 0xfc, a multiple of 4
+       echo "0x$(tr -dc '0-9a-f' < /dev/urandom | head -c 1)\
+$(tr -dc '048c' < /dev/urandom | head -c 1)"
+}
+get_random_ttl() {
+       # Get a random dec value between 0 and 255
+       printf "%d" "0x$(tr -dc '0-9a-f' < /dev/urandom | head -c 2)"
+}
+get_field() {
+       # Expects to get the 'head -n 1' of a captured frame by tcpdump.
+       # Parses this first line and returns the specified field.
+       local field="$1"
+       local input="$2"
+       local found=false
+       input="$(echo "$input" | tr -d '(),')"
+       for input_field in $input; do
+               if $found; then
+                       echo "$input_field"
+                       return
+               fi
+               # The next field that we iterate over is the looked for value
+               if [ "$input_field" = "$field" ]; then
+                       found=true
+               fi
+       done
+       echo "0"
+}
+setup() {
+       local type="$1"
+       local outer="$2"
+       local inner="$3"
+       local tos_ttl="$4"
+       local vlan="$5"
+       local test_tos="0x00"
+       local test_ttl="0"
+       local ns="ip netns exec testing"
+
+       # We don't want a test-tos of 0x00,
+       # because this is the value that we get when no tos is set.
+       expected_tos="$(get_random_tos)"
+       while [ "$expected_tos" = "0x00" ]; do
+               expected_tos="$(get_random_tos)"
+       done
+       if [ "$tos_ttl" = "random" ]; then
+               test_tos="$expected_tos"
+               tos="fixed $test_tos"
+       elif [ "$tos_ttl" = "inherit" ]; then
+               test_tos="$tos_ttl"
+               tos="inherit $expected_tos"
+       fi
+
+       # We don't want a test-ttl of 64 or 0,
+       # because 64 is when no ttl is set and 0 is not a valid ttl.
+       expected_ttl="$(get_random_ttl)"
+       while [ "$expected_ttl" = "64" ] || [ "$expected_ttl" = "0" ]; do
+               expected_ttl="$(get_random_ttl)"
+       done
+
+       if [ "$tos_ttl" = "random" ]; then
+               test_ttl="$expected_ttl"
+               ttl="fixed $test_ttl"
+       elif [ "$tos_ttl" = "inherit" ]; then
+               test_ttl="$tos_ttl"
+               ttl="inherit $expected_ttl"
+       fi
+       printf "│%7s │%6s │%6s │%13s │%13s │%6s │" \
+       "$type" "$outer" "$inner" "$tos" "$ttl" "$vlan"
+
+       # Create 'testing' netns, veth pair and connect main ns with testing ns
+       ip netns add testing
+       ip link add type veth
+       ip link set veth1 netns testing
+       ip link set veth0 up
+       $ns ip link set veth1 up
+       ip addr flush dev veth0
+       $ns ip addr flush dev veth1
+
+       local local_addr1=""
+       local local_addr2=""
+       if [ "$type" = "gre" ] || [ "$type" = "vxlan" ]; then
+               if [ "$outer" = "4" ]; then
+                       local_addr1="local 198.18.0.1"
+                       local_addr2="local 198.18.0.2"
+               elif [ "$outer" = "6" ]; then
+                       local_addr1="local fdd1:ced0:5d88:3fce::1"
+                       local_addr2="local fdd1:ced0:5d88:3fce::2"
+               fi
+       fi
+       local vxlan=""
+       if [ "$type" = "vxlan" ]; then
+               vxlan="vni 100 dstport 4789"
+       fi
+       local geneve=""
+       if [ "$type" = "geneve" ]; then
+               geneve="vni 100"
+       fi
+       # Create tunnel and assign outer IPv4/IPv6 addresses
+       if [ "$outer" = "4" ]; then
+               if [ "$type" = "gre" ]; then
+                       type="gretap"
+               fi
+               ip addr add 198.18.0.1/24 dev veth0
+               $ns ip addr add 198.18.0.2/24 dev veth1
+               ip link add name tep0 type $type $local_addr1 remote \
+               198.18.0.2 tos $test_tos ttl $test_ttl $vxlan $geneve
+               $ns ip link add name tep1 type $type $local_addr2 remote \
+               198.18.0.1 tos $test_tos ttl $test_ttl $vxlan $geneve
+       elif [ "$outer" = "6" ]; then
+               if [ "$type" = "gre" ]; then
+                       type="ip6gretap"
+               fi
+               ip addr add fdd1:ced0:5d88:3fce::1/64 dev veth0
+               $ns ip addr add fdd1:ced0:5d88:3fce::2/64 dev veth1
+               ip link add name tep0 type $type $local_addr1 \
+               remote fdd1:ced0:5d88:3fce::2 tos $test_tos ttl $test_ttl \
+               $vxlan $geneve
+               $ns ip link add name tep1 type $type $local_addr2 \
+               remote fdd1:ced0:5d88:3fce::1 tos $test_tos ttl $test_ttl \
+               $vxlan $geneve
+       fi
+
+       # Bring L2-tunnel link up and create VLAN on top
+       ip link set tep0 up
+       $ns ip link set tep1 up
+       ip addr flush dev tep0
+       $ns ip addr flush dev tep1
+       local parent
+       if $vlan; then
+               parent="vlan99-"
+               ip link add link tep0 name ${parent}0 type vlan id 99
+               $ns ip link add link tep1 name ${parent}1 type vlan id 99
+               ip link set ${parent}0 up
+               $ns ip link set ${parent}1 up
+               ip addr flush dev ${parent}0
+               $ns ip addr flush dev ${parent}1
+       else
+               parent="tep"
+       fi
+
+       # Assign inner IPv4/IPv6 addresses
+       if [ "$inner" = "4" ] || [ "$inner" = "other" ]; then
+               ip addr add 198.19.0.1/24 brd + dev ${parent}0
+               $ns ip addr add 198.19.0.2/24 brd + dev ${parent}1
+       elif [ "$inner" = "6" ]; then
+               ip addr add fdd4:96cf:4eae:443b::1/64 dev ${parent}0
+               $ns ip addr add fdd4:96cf:4eae:443b::2/64 dev ${parent}1
+       fi
+}
+
+verify() {
+       local outer="$1"
+       local inner="$2"
+       local tos_ttl="$3"
+       local vlan="$4"
+
+       local ping_pid out captured_tos captured_ttl result
+
+       local ping_dst
+       if [ "$inner" = "4" ]; then
+               ping_dst="198.19.0.2"
+       elif [ "$inner" = "6" ]; then
+               ping_dst="fdd4:96cf:4eae:443b::2"
+       elif [ "$inner" = "other" ]; then
+               ping_dst="198.19.0.3" # Generates ARPs which are not IPv4/IPv6
+       fi
+       if [ "$tos_ttl" = "inherit" ]; then
+               ping -i 0.1 $ping_dst -Q "$expected_tos" -t "$expected_ttl" \
+               2>/dev/null 1>&2 & ping_pid="$!"
+       else
+               ping -i 0.1 $ping_dst 2>/dev/null 1>&2 & ping_pid="$!"
+       fi
+       local tunnel_type_offset tunnel_type_proto req_proto_offset req_offset
+       if [ "$type" = "gre" ]; then
+               tunnel_type_proto="0x2f"
+       elif [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+               tunnel_type_proto="0x11"
+       fi
+       if [ "$outer" = "4" ]; then
+               tunnel_type_offset="9"
+               if [ "$inner" = "4" ]; then
+                       req_proto_offset="47"
+                       req_offset="58"
+                       if [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                               req_proto_offset="$((req_proto_offset + 12))"
+                               req_offset="$((req_offset + 12))"
+                       fi
+                       if $vlan; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+                       ip[$tunnel_type_offset] = $tunnel_type_proto and \
+                       ip[$req_proto_offset] = 0x01 and \
+                       ip[$req_offset] = 0x08 2>/dev/null | head -n 1)"
+               elif [ "$inner" = "6" ]; then
+                       req_proto_offset="44"
+                       req_offset="78"
+                       if [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                               req_proto_offset="$((req_proto_offset + 12))"
+                               req_offset="$((req_offset + 12))"
+                       fi
+                       if $vlan; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+                       ip[$tunnel_type_offset] = $tunnel_type_proto and \
+                       ip[$req_proto_offset] = 0x3a and \
+                       ip[$req_offset] = 0x80 2>/dev/null | head -n 1)"
+               elif [ "$inner" = "other" ]; then
+                       req_proto_offset="36"
+                       req_offset="45"
+                       if [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                               req_proto_offset="$((req_proto_offset + 12))"
+                               req_offset="$((req_offset + 12))"
+                       fi
+                       if $vlan; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       if [ "$tos_ttl" = "inherit" ]; then
+                               expected_tos="0x00"
+                               expected_ttl="64"
+                       fi
+                       out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+                       ip[$tunnel_type_offset] = $tunnel_type_proto and \
+                       ip[$req_proto_offset] = 0x08 and \
+                       ip[$((req_proto_offset + 1))] = 0x06 and \
+                       ip[$req_offset] = 0x01 2>/dev/null | head -n 1)"
+               fi
+       elif [ "$outer" = "6" ]; then
+               if [ "$type" = "gre" ]; then
+                       tunnel_type_offset="40"
+               elif [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                       tunnel_type_offset="6"
+               fi
+               if [ "$inner" = "4" ]; then
+                       local req_proto_offset="75"
+                       local req_offset="86"
+                       if [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       if $vlan; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+                       ip6[$tunnel_type_offset] = $tunnel_type_proto and \
+                       ip6[$req_proto_offset] = 0x01 and \
+                       ip6[$req_offset] = 0x08 2>/dev/null | head -n 1)"
+               elif [ "$inner" = "6" ]; then
+                       local req_proto_offset="72"
+                       local req_offset="106"
+                       if [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       if $vlan; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+                       ip6[$tunnel_type_offset] = $tunnel_type_proto and \
+                       ip6[$req_proto_offset] = 0x3a and \
+                       ip6[$req_offset] = 0x80 2>/dev/null | head -n 1)"
+               elif [ "$inner" = "other" ]; then
+                       local req_proto_offset="64"
+                       local req_offset="73"
+                       if [ "$type" = "vxlan" ] || [ "$type" = "geneve" ]; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       if $vlan; then
+                               req_proto_offset="$((req_proto_offset + 4))"
+                               req_offset="$((req_offset + 4))"
+                       fi
+                       if [ "$tos_ttl" = "inherit" ]; then
+                               expected_tos="0x00"
+                               expected_ttl="64"
+                       fi
+                       out="$(tcpdump --immediate-mode -p -c 1 -v -i veth0 -n \
+                       ip6[$tunnel_type_offset] = $tunnel_type_proto and \
+                       ip6[$req_proto_offset] = 0x08 and \
+                       ip6[$((req_proto_offset + 1))] = 0x06 and \
+                       ip6[$req_offset] = 0x01 2>/dev/null | head -n 1)"
+               fi
+       fi
+       kill -9 $ping_pid
+       wait $ping_pid 2>/dev/null
+       result="FAIL"
+       if [ "$outer" = "4" ]; then
+               captured_ttl="$(get_field "ttl" "$out")"
+               captured_tos="$(printf "0x%02x" "$(get_field "tos" "$out")")"
+               if [ "$captured_tos" = "$expected_tos" ] &&
+                  [ "$captured_ttl" = "$expected_ttl" ]; then
+                       result="OK"
+               fi
+       elif [ "$outer" = "6" ]; then
+               captured_ttl="$(get_field "hlim" "$out")"
+               captured_tos="$(printf "0x%02x" "$(get_field "class" "$out")")"
+               if [ "$captured_tos" = "$expected_tos" ] &&
+                  [ "$captured_ttl" = "$expected_ttl" ]; then
+                       result="OK"
+               fi
+       fi
+
+       printf "%7s │\n" "$result"
+       if [ "$result" = "FAIL" ]; then
+               failed=true
+               if [ "$captured_tos" != "$expected_tos" ]; then
+                       printf "│%43s%27s │\n" \
+                       "Expected TOS value: $expected_tos" \
+                       "Captured TOS value: $captured_tos"
+               fi
+               if [ "$captured_ttl" != "$expected_ttl" ]; then
+                       printf "│%43s%27s │\n" \
+                       "Expected TTL value: $expected_ttl" \
+                       "Captured TTL value: $captured_ttl"
+               fi
+               printf "│%71s│\n" " "
+       fi
+}
+
+cleanup() {
+       ip link del veth0 2>/dev/null
+       ip netns del testing 2>/dev/null
+       ip link del tep0 2>/dev/null
+}
+
+printf "┌────────┬───────┬───────┬──────────────┬"
+printf "──────────────┬───────┬────────┐\n"
+for type in gre vxlan geneve; do
+       if ! $(modprobe "$type" 2>/dev/null); then
+               continue
+       fi
+       for outer in 4 6; do
+               printf "├────────┼───────┼───────┼──────────────┼"
+               printf "──────────────┼───────┼────────┤\n"
+               printf "│  Type  │ outer | inner │     tos      │"
+               printf "      ttl     │  vlan │ result │\n"
+               for inner in 4 6 other; do
+                       printf "├────────┼───────┼───────┼──────────────┼"
+                       printf "──────────────┼───────┼────────┤\n"
+                       for tos_ttl in inherit random; do
+                               for vlan in false true; do
+                                       setup "$type" "$outer" "$inner" \
+                                       "$tos_ttl" "$vlan"
+                                       verify "$outer" "$inner" "$tos_ttl" \
+                                       "$vlan"
+                                       cleanup
+                               done
+                       done
+               done
+       done
+done
+printf "└────────┴───────┴───────┴──────────────┴"
+printf "──────────────┴───────┴────────┘\n"
+
+if $failed; then
+       exit 1
+fi
index d9a6fd2..7900fa9 100644 (file)
@@ -127,6 +127,9 @@ struct sock_args {
 
        /* ESP in UDP encap test */
        int use_xfrm;
+
+       /* use send() and connect() instead of sendto */
+       int datagram_connect;
 };
 
 static int server_mode;
@@ -979,6 +982,11 @@ static int send_msg(int sd, void *addr, socklen_t alen, struct sock_args *args)
                        log_err_errno("write failed sending msg to peer");
                        return 1;
                }
+       } else if (args->datagram_connect) {
+               if (send(sd, msg, msglen, 0) < 0) {
+                       log_err_errno("send failed sending msg to peer");
+                       return 1;
+               }
        } else if (args->ifindex && args->use_cmsg) {
                if (send_msg_cmsg(sd, addr, alen, args->ifindex, args->version))
                        return 1;
@@ -1659,7 +1667,7 @@ static int connectsock(void *addr, socklen_t alen, struct sock_args *args)
        if (args->has_local_ip && bind_socket(sd, args))
                goto err;
 
-       if (args->type != SOCK_STREAM)
+       if (args->type != SOCK_STREAM && !args->datagram_connect)
                goto out;
 
        if (args->password && tcp_md5sig(sd, addr, alen, args))
@@ -1854,7 +1862,7 @@ static int ipc_parent(int cpid, int fd, struct sock_args *args)
        return client_status;
 }
 
-#define GETOPT_STR  "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SCi6xL:0:1:2:3:Fbqf"
+#define GETOPT_STR  "sr:l:c:p:t:g:P:DRn:M:X:m:d:I:BN:O:SUCi6xL:0:1:2:3:Fbqf"
 #define OPT_FORCE_BIND_KEY_IFINDEX 1001
 #define OPT_NO_BIND_KEY_IFINDEX 1002
 
@@ -1891,6 +1899,7 @@ static void print_usage(char *prog)
        "    -I dev        bind socket to given device name - server mode\n"
        "    -S            use setsockopt (IP_UNICAST_IF or IP_MULTICAST_IF)\n"
        "                  to set device binding\n"
+       "    -U            Use connect() and send() for datagram sockets\n"
        "    -f            bind socket with the IP[V6]_FREEBIND option\n"
        "    -C            use cmsg and IP_PKTINFO to specify device binding\n"
        "\n"
@@ -2074,6 +2083,9 @@ int main(int argc, char *argv[])
                case 'x':
                        args.use_xfrm = 1;
                        break;
+               case 'U':
+                       args.datagram_connect = 1;
+                       break;
                default:
                        print_usage(argv[0]);
                        return 1;
diff --git a/tools/testing/selftests/net/sk_bind_sendto_listen.c b/tools/testing/selftests/net/sk_bind_sendto_listen.c
new file mode 100644 (file)
index 0000000..b420d83
--- /dev/null
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <arpa/inet.h>
+#include <error.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main(void)
+{
+       int fd1, fd2, one = 1;
+       struct sockaddr_in6 bind_addr = {
+               .sin6_family = AF_INET6,
+               .sin6_port = htons(20000),
+               .sin6_flowinfo = htonl(0),
+               .sin6_addr = {},
+               .sin6_scope_id = 0,
+       };
+
+       inet_pton(AF_INET6, "::", &bind_addr.sin6_addr);
+
+       fd1 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
+       if (fd1 < 0) {
+               error(1, errno, "socket fd1");
+               return -1;
+       }
+
+       if (setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+               error(1, errno, "setsockopt(SO_REUSEADDR) fd1");
+               goto out_err1;
+       }
+
+       if (bind(fd1, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
+               error(1, errno, "bind fd1");
+               goto out_err1;
+       }
+
+       if (sendto(fd1, NULL, 0, MSG_FASTOPEN, (struct sockaddr *)&bind_addr,
+                  sizeof(bind_addr))) {
+               error(1, errno, "sendto fd1");
+               goto out_err1;
+       }
+
+       fd2 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
+       if (fd2 < 0) {
+               error(1, errno, "socket fd2");
+               goto out_err1;
+       }
+
+       if (setsockopt(fd2, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+               error(1, errno, "setsockopt(SO_REUSEADDR) fd2");
+               goto out_err2;
+       }
+
+       if (bind(fd2, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
+               error(1, errno, "bind fd2");
+               goto out_err2;
+       }
+
+       if (sendto(fd2, NULL, 0, MSG_FASTOPEN, (struct sockaddr *)&bind_addr,
+                  sizeof(bind_addr)) != -1) {
+               error(1, errno, "sendto fd2");
+               goto out_err2;
+       }
+
+       if (listen(fd2, 0)) {
+               error(1, errno, "listen");
+               goto out_err2;
+       }
+
+       close(fd2);
+       close(fd1);
+       return 0;
+
+out_err2:
+       close(fd2);
+
+out_err1:
+       close(fd1);
+       return -1;
+}
diff --git a/tools/testing/selftests/net/sk_connect_zero_addr.c b/tools/testing/selftests/net/sk_connect_zero_addr.c
new file mode 100644 (file)
index 0000000..4be418a
--- /dev/null
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <arpa/inet.h>
+#include <error.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main(void)
+{
+       int fd1, fd2, one = 1;
+       struct sockaddr_in6 bind_addr = {
+               .sin6_family = AF_INET6,
+               .sin6_port = htons(20000),
+               .sin6_flowinfo = htonl(0),
+               .sin6_addr = {},
+               .sin6_scope_id = 0,
+       };
+
+       inet_pton(AF_INET6, "::", &bind_addr.sin6_addr);
+
+       fd1 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
+       if (fd1 < 0) {
+               error(1, errno, "socket fd1");
+               return -1;
+       }
+
+       if (setsockopt(fd1, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one))) {
+               error(1, errno, "setsockopt(SO_REUSEADDR) fd1");
+               goto out_err1;
+       }
+
+       if (bind(fd1, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
+               error(1, errno, "bind fd1");
+               goto out_err1;
+       }
+
+       if (listen(fd1, 0)) {
+               error(1, errno, "listen");
+               goto out_err1;
+       }
+
+       fd2 = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
+       if (fd2 < 0) {
+               error(1, errno, "socket fd2");
+               goto out_err1;
+       }
+
+       if (connect(fd2, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) {
+               error(1, errno, "bind fd2");
+               goto out_err2;
+       }
+
+       close(fd2);
+       close(fd1);
+       return 0;
+
+out_err2:
+       close(fd2);
+out_err1:
+       close(fd1);
+       return -1;
+}
index dc57746..bb6d691 100644 (file)
@@ -18,6 +18,7 @@
 #include <sys/socket.h>
 #include <time.h>
 #include <sys/mman.h>
+#include <poll.h>
 
 #include "timeout.h"
 #include "control.h"
@@ -596,6 +597,108 @@ static void test_seqpacket_invalid_rec_buffer_server(const struct test_opts *opt
        close(fd);
 }
 
+#define RCVLOWAT_BUF_SIZE 128
+
+static void test_stream_poll_rcvlowat_server(const struct test_opts *opts)
+{
+       int fd;
+       int i;
+
+       fd = vsock_stream_accept(VMADDR_CID_ANY, 1234, NULL);
+       if (fd < 0) {
+               perror("accept");
+               exit(EXIT_FAILURE);
+       }
+
+       /* Send 1 byte. */
+       send_byte(fd, 1, 0);
+
+       control_writeln("SRVSENT");
+
+       /* Wait until client is ready to receive rest of data. */
+       control_expectln("CLNSENT");
+
+       for (i = 0; i < RCVLOWAT_BUF_SIZE - 1; i++)
+               send_byte(fd, 1, 0);
+
+       /* Keep socket in active state. */
+       control_expectln("POLLDONE");
+
+       close(fd);
+}
+
+static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
+{
+       unsigned long lowat_val = RCVLOWAT_BUF_SIZE;
+       char buf[RCVLOWAT_BUF_SIZE];
+       struct pollfd fds;
+       ssize_t read_res;
+       short poll_flags;
+       int fd;
+
+       fd = vsock_stream_connect(opts->peer_cid, 1234);
+       if (fd < 0) {
+               perror("connect");
+               exit(EXIT_FAILURE);
+       }
+
+       if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT,
+                      &lowat_val, sizeof(lowat_val))) {
+               perror("setsockopt");
+               exit(EXIT_FAILURE);
+       }
+
+       control_expectln("SRVSENT");
+
+       /* At this point, server sent 1 byte. */
+       fds.fd = fd;
+       poll_flags = POLLIN | POLLRDNORM;
+       fds.events = poll_flags;
+
+       /* Try to wait for 1 sec. */
+       if (poll(&fds, 1, 1000) < 0) {
+               perror("poll");
+               exit(EXIT_FAILURE);
+       }
+
+       /* poll() must return nothing. */
+       if (fds.revents) {
+               fprintf(stderr, "Unexpected poll result %hx\n",
+                       fds.revents);
+               exit(EXIT_FAILURE);
+       }
+
+       /* Tell server to send rest of data. */
+       control_writeln("CLNSENT");
+
+       /* Poll for data. */
+       if (poll(&fds, 1, 10000) < 0) {
+               perror("poll");
+               exit(EXIT_FAILURE);
+       }
+
+       /* Only these two bits are expected. */
+       if (fds.revents != poll_flags) {
+               fprintf(stderr, "Unexpected poll result %hx\n",
+                       fds.revents);
+               exit(EXIT_FAILURE);
+       }
+
+       /* Use MSG_DONTWAIT, if call is going to wait, EAGAIN
+        * will be returned.
+        */
+       read_res = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
+       if (read_res != RCVLOWAT_BUF_SIZE) {
+               fprintf(stderr, "Unexpected recv result %zi\n",
+                       read_res);
+               exit(EXIT_FAILURE);
+       }
+
+       control_writeln("POLLDONE");
+
+       close(fd);
+}
+
 static struct test_case test_cases[] = {
        {
                .name = "SOCK_STREAM connection reset",
@@ -646,6 +749,11 @@ static struct test_case test_cases[] = {
                .run_client = test_seqpacket_invalid_rec_buffer_client,
                .run_server = test_seqpacket_invalid_rec_buffer_server,
        },
+       {
+               .name = "SOCK_STREAM poll() + SO_RCVLOWAT",
+               .run_client = test_stream_poll_rcvlowat_client,
+               .run_server = test_stream_poll_rcvlowat_server,
+       },
        {},
 };